На основе прошлой статьи пришло несколько отзывов, что поддерживается только латиница. Ну давайте добавлять кириллицу, и заодно поддержку эмодзи.
Создаем файл app.py. Вводим:
Код |
---|
import smpplib.clientimport smpplib.constsimport smpplib.gsmimport smpplib.exceptionsfrom flask import Flask, jsonify, render_templatefrom flask_sqlalchemy import SQLAlchemyimport threadingimport atexit # Настройки Flask и базы данныхapp = Flask(__name__)app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///sms.db'app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = Falsedb = SQLAlchemy(app) # Модель для хранения SMS сообщенийclass SMSMessage(db.Model): id = db.Column(db.Integer, primary_key=True) source = db.Column(db.String(20)) destination = db.Column(db.String(20)) message = db.Column(db.String(160)) timestamp = db.Column(db.DateTime, default=db.func.current_timestamp()) # Создаем таблицы в базе данныхwith app.app_context(): db.create_all() # Данные для подключения к SMPP серверуSMPP_SERVER = "smpp.exolve.ru"SMPP_PORT = 2775SYSTEM_ID = "логин"PASSWORD = "пароль" # Функция для обработки входящих сообщенийdef handle_message(pdu): try: # Попытка декодировать сообщение с разными кодировками try: if pdu.data_coding == 0x08: # UCS2 кодировка message = pdu.short_message.decode('utf-16-be') else: message = pdu.short_message.decode('utf-8') except UnicodeDecodeError: # Если не удалось, пробуем GSM 7-бит (возможные латинские символы) try: message = smpplib.gsm.decode(pdu.short_message) except: # Если ничего не помогло, сохраняем как есть message = pdu.short_message.decode('latin1') source = pdu.source_addr.decode('utf-8') if isinstance(pdu.source_addr, bytes) else pdu.source_addr destination = pdu.destination_addr.decode('utf-8') if isinstance(pdu.destination_addr, bytes) else pdu.destination_addr # Создаем контекст приложения Flask with app.app_context(): # Сохраняем сообщение в базе данных sms = SMSMessage(source=source, destination=destination, message=message) db.session.add(sms) db.session.commit() print(f"Received message: {message}") print(f"From: {source}") print(f"To: {destination}") except UnicodeDecodeError as e: print(f"Ошибка декодирования сообщения: {e}") except smpplib.exceptions.ConnectionError as e: print("Connection lost with SMPP server:", e) # Создаем клиента SMPPclient = smpplib.client.Client(SMPP_SERVER, SMPP_PORT) # Включаем логирование (опционально)client.set_message_received_handler(handle_message) # Функция для корректного закрытия SMPP клиентаdef close_smpp_client(): if client: try: client.unbind() finally: client.disconnect() # Регистрация функции закрытия соединения при завершении работы приложенияatexit.register(close_smpp_client) # Подключаемся и регистрируемся как приемник (только для получения сообщений)client.connect()client.bind_receiver(system_id=SYSTEM_ID, password=PASSWORD) # Запуск прослушивания SMPP сообщений в отдельном потокеlistener_thread = threading.Thread(target=client.listen, daemon=True)listener_thread.start() # Веб-интерфейс для отображения полученных SMS@app.route('/')def index(): return render_template('index.html') # Маршрут для получения сообщений в формате JSON@app.route('/get_messages', methods=['GET'])def get_messages(): messages = SMSMessage.query.order_by(SMSMessage.timestamp.desc()).all() messages_data = [] for sms in messages: messages_data.append({ "source": sms.source.decode('utf-8') if isinstance(sms.source, bytes) else sms.source, "destination": sms.destination.decode('utf-8') if isinstance(sms.destination, bytes) else sms.destination, "message": sms.message, "timestamp": sms.timestamp.strftime('%Y-%m-%d %H:%M:%S') }) return jsonify(messages_data) # Запуск веб-приложения на порту 5001if __name__ == '__main__': try: app.run(debug=True, port=5001) finally: close_smpp_client()
|
И тут давайте сразу напишем обновленный index.html
Код |
---|
<!DO CTYPE html><ht ml lang="ru"><head> <met a charset="UTF-8"> <met a name="viewport" content="width=device-width, initial-scale=1.0"> <title>Полученные SMS сообщения</title> <st yle> .message-text { color: green; font-weight: bold; } </style> <sc ript> // Функция для загрузки сообщений function loadMessages() { fetch('/get_messages') .then(response => response.json()) .then(data => { const messageList = document.getElementById('message-list'); messageList.innerHTML = ''; // Очищаем список сообщений data.forEach(sms => { const listItem = document.createElement('li'); listItem.innerHTML = `<span class="message-text">${sms.message}</span> <strong>От:</strong> ${sms.source} <strong>Кому:</strong> ${sms.destination} <strong>Получено в:</strong> ${sms.timestamp}`; messageList.appendChild(listItem); }); }) .catch(error => console.error('Error loading messages:', error)); } // Обновляем сообщения каждые 5 секунд setInterval(loadMessages, 5000); // Загрузка сообщений при загрузке страницы window.onl oad = loadMessages; </sc ript></head><body> <h1>Полученные SMS сообщения</h1> <h2>Сообщения</h2> <ul id="message-list"> <!-- Сообщения будут динамически добавляться сюда --> </ul></body></html>
|
Объяснение работы кода
app.py
1. Инициализация Flask и SQLAlchemy:
- Приложение Flask и база данных SQLAlchemy инициализируются в начале кода.
- Создается модель SMSMessage, которая определяет структуру данных для хранения SMS-сообщений в базе данных.
2. Подключение к SMPP серверу:
- Устанавливается подключение к SMPP серверу с использованием предоставленных учетных данных (IP-адрес, порт, SYSTEM_ID, PASSWORD).
- Клиент регистрируется как приемник сообщений с использованием методаbind_receiver.
3. Обработка входящих сообщений:
- Функция handle_message обрабатывает входящие сообщения.
- В зависимости от кодировки (data_coding) определяется, как декодировать сообщение.
- Декодированные сообщения сохраняются в базе данных.
4. Запуск прослушивания сообщений:
- Прослушивание входящих сообщений выполняется в отдельном потоке, чтобы не блокировать работу веб-сервера Flask.
- В случае завершения работы приложения, соединение с SMPP сервером корректно закрывается с помощью функции close_smpp_client.
5. Веб-маршруты:
- Главная страница (/) возвращает HTML-шаблон.
- Маршрут /get_messages возвращает список сообщений в формате JSON, которые затем отображаются на веб-странице.
index.html
1. Интерфейс пользователя:
- Страница содержит заголовок и список сообщений, который будет динамически обновляться.
2. CSS стили:
- Сообщение (sms.message) отображается первым и выделено зеленым цветом с использованием класса message-text.
3. Jav * aScript:
- Вызов функции loadMessages происходит каждые 5 секунд для загрузки новых сообщений с сервера.
- Сообщения отображаются на странице без необходимости перезагрузки страницы.
Как это работает:
- Когда приходит новое SMS-сообщение, оно декодируется и сохраняется в базе данных.
- Веб-интерфейс каждые 5 секунд отправляет запрос на сервер для получения списка сообщений и обновляет отображение.
- Если SMS-сообщение содержит кириллические символы, они корректно декодируются и отображаются благодаря обработке в функции handle_message.
Этот подход обеспечивает стабильную работу с SMS-сообщениями, содержащими символы на разных языках, включая кириллицу и латиницу.
Для того, чтобы оставлять комментарии, необходимо пройти авторизацию
Авторизоваться