From 0742e0ab04519fb9e22ef5dd04ae68c2b782ae3b Mon Sep 17 00:00:00 2001 From: F33RNI Date: Sat, 9 Sep 2023 01:39:01 +0300 Subject: [PATCH 1/6] Make Bing image gen works (finally) --- BingImageGenModule.py | 31 +++++++++++++++++++++++----- BotHandler.py | 48 ++++++++++++++++++++++++++++++++++--------- QueueHandler.py | 27 +++++++++++++++--------- config.json | 9 +++++--- requirements.txt | 2 +- 5 files changed, 88 insertions(+), 29 deletions(-) diff --git a/BingImageGenModule.py b/BingImageGenModule.py index 0b1dbe3c..2092ee3d 100644 --- a/BingImageGenModule.py +++ b/BingImageGenModule.py @@ -24,6 +24,7 @@ import BotHandler import UsersHandler +from JSONReaderWriter import load_json from RequestResponseContainer import RequestResponseContainer @@ -60,8 +61,30 @@ def initialize(self, proxy=None) -> None: logging.warning("Bing ImageGen module disabled in config file!") raise Exception("Bing ImageGen module disabled in config file!") + # Parse cookies + auth_cookie = "" + auth_cookie_SRCHHPGUSR = "" + try: + cookies = load_json(self.config["bing_imagegen"]["cookies_file"]) + if not cookies or len(cookies) < 1: + raise "Error reading bing cookies!" + for cookie in cookies: + if cookie["name"] == "_U": + auth_cookie = cookie["value"] + elif cookie["name"] == "SRCHHPGUSR": + auth_cookie_SRCHHPGUSR = cookie["value"] + if not auth_cookie: + raise "No _U cookie!" + if not auth_cookie_SRCHHPGUSR: + raise "No SRCHHPGUSR cookie!" + except Exception as e: + raise e + # Initialize Bing ImageGen - self._image_generator = ImageGen(self.config["bing_imagegen"]["cookies_file"], quiet=True) + self._image_generator = ImageGen(auth_cookie=auth_cookie, + auth_cookie_SRCHHPGUSR=auth_cookie_SRCHHPGUSR, + quiet=True, + all_cookies=cookies) # Set proxy if proxy: @@ -99,19 +122,17 @@ def process_request(self, request_response: RequestResponseContainer) -> None: self.users_handler.save_user(request_response.user) # Generate images - # TODO: Make it work logging.info("Requesting images from Bing ImageGen") response_urls = self._image_generator.get_images(request_response.request) - print(response_urls) # Check response if not response_urls or len(response_urls) < 1: raise Exception("Wrong Bing ImageGen response!") - # TODO: Use all generated images (for now it's the first one) + # Use all generated images logging.info("Response successfully processed for user {0} ({1})" .format(request_response.user["user_name"], request_response.user["user_id"])) - request_response.response = response_urls[0] + request_response.response = response_urls # Exit requested except KeyboardInterrupt: diff --git a/BotHandler.py b/BotHandler.py index 9d5d7197..649a30e3 100644 --- a/BotHandler.py +++ b/BotHandler.py @@ -26,7 +26,7 @@ from typing import List, Dict import telegram -from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup +from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup, InputMediaPhoto from telegram.ext import ApplicationBuilder, ContextTypes, CommandHandler, MessageHandler, filters, CallbackQueryHandler import LoggingHandler @@ -128,8 +128,11 @@ async def send_message_async(config: dict, messages: List[Dict], lang = UsersHandler.get_key_or_none(request_response.user, "lang", 0) # Fix empty message - if len(request_response.response.strip()) <= 0 and end: - request_response.response = messages[lang]["empty_message"] + if end: + if not request_response.response \ + or (type(request_response.response) == list and len(request_response.response) == 0) \ + or (type(request_response.response) == str and len(request_response.response.strip()) <= 0): + request_response.response = messages[lang]["empty_message"] # The last message if end: @@ -180,13 +183,38 @@ async def send_message_async(config: dict, messages: List[Dict], if (request_response.request_type == RequestResponseContainer.REQUEST_TYPE_DALLE or request_response.request_type == RequestResponseContainer.REQUEST_TYPE_BING_IMAGEGEN) \ and not request_response.error: - request_response.message_id = (await (telegram.Bot(config["telegram"]["api_key"]).sendPhoto( - chat_id=request_response.user["user_id"], - photo=request_response.response, - reply_to_message_id=request_response - .reply_message_id, - reply_markup=request_response.reply_markup))) \ - .message_id + # Single photo + if type(request_response.response) == str: + request_response.message_id = (await (telegram.Bot(config["telegram"]["api_key"]).sendPhoto( + chat_id=request_response.user["user_id"], + photo=request_response.response, + reply_to_message_id=request_response + .reply_message_id, + reply_markup=request_response.reply_markup))) \ + .message_id + + # Multiple photos (send media group + markup as seperate messages) + else: + # Collect media group + media_group = [] + for url in request_response.response: + media_group.append(InputMediaPhoto(media=url)) + + # Send it + await (telegram.Bot(config["telegram"]["api_key"]).sendMediaGroup( + chat_id=request_response.user["user_id"], + media=media_group, + reply_to_message_id=request_response.reply_message_id)) + + # Send reply markup and get message ID + request_response.message_id = await send_reply(config["telegram"]["api_key"], + request_response.user["user_id"], + config["telegram"]["empty_message_symbol"], + request_response.reply_message_id, + markdown=False, + reply_markup=request_response.reply_markup, + edit_message_id=request_response.message_id) + # Send message as text else: request_response.message_id = await send_reply(config["telegram"]["api_key"], diff --git a/QueueHandler.py b/QueueHandler.py index 03bdf6eb..3b942b9e 100644 --- a/QueueHandler.py +++ b/QueueHandler.py @@ -675,16 +675,23 @@ def _collect_data(self, request_response: RequestResponseContainer, log_request= # Log response else: - # DALL-E or BingImageGen response without error - if (request_response.request_type == RequestResponseContainer.REQUEST_TYPE_DALLE - or request_response.request_type == RequestResponseContainer.REQUEST_TYPE_BING_IMAGEGEN) \ - and not request_response.error: - response = base64.b64encode(requests.get(request_response.response, timeout=120).content) \ - .decode("utf-8") - - # Text response (ChatGPT, EdgeGPT, Bard) - else: - response = request_response.response + response = "None" + try: + # DALL-E or BingImageGen response without error + if (request_response.request_type == RequestResponseContainer.REQUEST_TYPE_DALLE + or request_response.request_type == RequestResponseContainer.REQUEST_TYPE_BING_IMAGEGEN) \ + and not request_response.error: + response_url = request_response.response if type(request_response.response) == str\ + else request_response.response[0] + response = base64.b64encode(requests.get(response_url, timeout=120).content) \ + .decode("utf-8") + + # Text response (ChatGPT, EdgeGPT, Bard) + else: + response = request_response.response + except Exception as e: + logging.warning("Can't parse response for data logging!", exc_info=e) + response = str(response) # Log response response_str_to_format = self.config["data_collecting"]["response_format"].replace("\\n", "\n") \ diff --git a/config.json b/config.json index 97cab4d6..f7c409e7 100644 --- a/config.json +++ b/config.json @@ -5,7 +5,7 @@ "edgegpt": true, "dalle": true, "bard": true, - "bing_imagegen": false, + "bing_imagegen": true, "__comment04__": "Default (initial) module for handling user messages (see RequestResponseContainer.py)", "default_module": 0 @@ -95,7 +95,7 @@ "user_cooldown_seconds": 600 }, - "__comment05__": "BING IMAGEGEN SETTINGS (CURRENTLY NOT WORKING)", + "__comment05__": "BING IMAGEGEN SETTINGS", "bing_imagegen": { "__comment01__": "PATH TO COOKIES FILE (JSON) https://github.com/acheong08/EdgeGPT#collect-cookies", "cookies_file": "EdgeGPT_cookies.json", @@ -151,7 +151,10 @@ "add_cursor_symbol": true, "cursor_symbol": "▯", - "__comment07__": "SET TO true FOR THE BOT TO REPLY TO PLAIN MESSAGES AS WELL AS DIRECT MODULE COMMANDS", + "__comment07__": "EMPTY SYMBOL FOR REPLY MARKUP WITHOUT TEXT (FOR SENDING MULTIPLE PHOTOS)", + "empty_message_symbol": "ㅤ", + + "__comment08__": "SET TO true FOR THE BOT TO REPLY TO PLAIN MESSAGES AS WELL AS DIRECT MODULE COMMANDS", "reply_to_messages": true }, diff --git a/requirements.txt b/requirements.txt index 13b7fedd..89616f8f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,4 +9,4 @@ asyncio>=3.4.3 requests>=2.28.1 telegram>=0.0.1 psutil>=5.9.4 -BingImageCreator>=0.4.4 \ No newline at end of file +BingImageCreator>=0.5.0 \ No newline at end of file From 69ffe3d11f88e66c67331da53b8449fef63c58af Mon Sep 17 00:00:00 2001 From: F33RNI Date: Sat, 9 Sep 2023 01:40:06 +0300 Subject: [PATCH 2/6] Update version --- main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.py b/main.py index 18d10430..d92c05cd 100644 --- a/main.py +++ b/main.py @@ -34,7 +34,7 @@ from JSONReaderWriter import load_json # GPT-Telegramus version -__version__ = "3.2.1" +__version__ = "3.3.0" # Logging level LOGGING_LEVEL = logging.INFO From cec9d37e2d492cac9298844125b59aa1e0b1dcd5 Mon Sep 17 00:00:00 2001 From: F33RNI Date: Sat, 9 Sep 2023 01:42:17 +0300 Subject: [PATCH 3/6] Update TODO list --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 928393ff..759848f9 100644 --- a/README.md +++ b/README.md @@ -174,8 +174,7 @@ You can enable and configure data collection in config in `data_collecting` bloc ## 📝 TODO - Add some free GPT-4 model -- Make Bing ImageGet work -- Add rate limit +- Add list of commands ---------- From d6b452fc333e3e73d420a985c9e9faed03a36bf2 Mon Sep 17 00:00:00 2001 From: F33RNI Date: Sat, 9 Sep 2023 17:37:42 +0300 Subject: [PATCH 4/6] Change Bing Image gen reply --- BotHandler.py | 9 +++++---- config.json | 9 +++------ messages.json | 3 +++ 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/BotHandler.py b/BotHandler.py index 649a30e3..52328640 100644 --- a/BotHandler.py +++ b/BotHandler.py @@ -201,16 +201,17 @@ async def send_message_async(config: dict, messages: List[Dict], media_group.append(InputMediaPhoto(media=url)) # Send it - await (telegram.Bot(config["telegram"]["api_key"]).sendMediaGroup( + media_group_message_id = (await (telegram.Bot(config["telegram"]["api_key"]).sendMediaGroup( chat_id=request_response.user["user_id"], media=media_group, - reply_to_message_id=request_response.reply_message_id)) + reply_to_message_id=request_response.reply_message_id)))[0].message_id # Send reply markup and get message ID request_response.message_id = await send_reply(config["telegram"]["api_key"], request_response.user["user_id"], - config["telegram"]["empty_message_symbol"], - request_response.reply_message_id, + messages[lang]["media_group_response"] + .format(request_response.request), + media_group_message_id, markdown=False, reply_markup=request_response.reply_markup, edit_message_id=request_response.message_id) diff --git a/config.json b/config.json index f7c409e7..21f15229 100644 --- a/config.json +++ b/config.json @@ -73,7 +73,7 @@ "timeout_seconds": 240, "__comment07__": "HOW OFTEN EACH USER CAN SEND REQUESTS TO THIS MODULE (SPECIFY 0 TO REMOVE THE RESTRICTION)", - "user_cooldown_seconds": 0 + "user_cooldown_seconds": 120 }, "__comment04__": "DALL-E SETTINGS", @@ -92,7 +92,7 @@ "timeout_seconds": 120, "__comment15__": "HOW OFTEN EACH USER CAN SEND REQUESTS TO THIS MODULE (SPECIFY 0 TO REMOVE THE RESTRICTION)", - "user_cooldown_seconds": 600 + "user_cooldown_seconds": 120 }, "__comment05__": "BING IMAGEGEN SETTINGS", @@ -151,10 +151,7 @@ "add_cursor_symbol": true, "cursor_symbol": "▯", - "__comment07__": "EMPTY SYMBOL FOR REPLY MARKUP WITHOUT TEXT (FOR SENDING MULTIPLE PHOTOS)", - "empty_message_symbol": "ㅤ", - - "__comment08__": "SET TO true FOR THE BOT TO REPLY TO PLAIN MESSAGES AS WELL AS DIRECT MODULE COMMANDS", + "__comment07__": "SET TO true FOR THE BOT TO REPLY TO PLAIN MESSAGES AS WELL AS DIRECT MODULE COMMANDS", "reply_to_messages": true }, diff --git a/messages.json b/messages.json index 5af603c6..838d2949 100644 --- a/messages.json +++ b/messages.json @@ -8,6 +8,7 @@ "help_message": "📄 /start - Welcome message and bot version\\n❓ /help - Show this message\\n↕ /module - Change module to chat with\\n🧹 /clear - Clear chat history\\n🌎 /lang - Change the language\\n🆔 /chatid - Show your chat_id\\n\\nNow to get started send me any message 💬", "help_message_admin": "Admin commands:\\n\\n💬 /queue - Show requests queue\\n🔃 /restart - Restart proxies and telegram bot\\n👤 /users - Show list of all users\\n🔨 /ban [reason] - Ban a user by their id with reason (optional)\\n🔓 /unban - Unban a user by their id\\n📢 /broadcast - Send text message to everyone except banned users", "empty_request_module_changed": "✅ Your module has been changed to {0}\\nNow send me your request as a message", + "media_group_response": "Generated images for \"{}\" request", "permissions_deny": "❌ You do not have permission for this command!", "queue_overflow": "Queue is full. Try again later ⏳", "queue_empty": "🗑 Queue is empty", @@ -66,6 +67,7 @@ "help_message": "📄 /start - Приветственное сообщение и версия бота\\n❓ /help - Показать это сообщение\\n↕ /module - Изменить модуль для чата\\n🧹 /clear - Очистить историю чата\\n🌎 /lang - Изменить язык\\n🆔 /chatid - Показать ваш chat_id\\n\\nТеперь, чтобы начать, отправьте мне любое сообщение 💬", "help_message_admin": "Команды администратора:\\n\\n💬 /queue - Показать очередь запросов\\n🔃 /restart - Перезапустить прокси и телеграм-бота\\n👤 /users - Показать список всех пользователей\\n🔨 /ban [reason] - Заблокировать пользователя по его id с указанием причины (опционально)\\n🔓 /unban - Разблокировать пользователя по id\\n📢 /broadcast - Отправить текстовое сообщение всем, кроме заблокированных пользователей", "empty_request_module_changed": "✅ Модуль был изменен на {0}\\nТеперь пришлите мне ваш запрос в виде сообщения", + "media_group_response": "Сгенерированные изображения по запросу: \"{}\"", "permissions_deny": "❌ У вас нет разрешения на эту команду!", "queue_overflow": "Очередь заполнена. Попробуйте позже ⏳", "queue_empty": "🗑 Очередь пуста", @@ -124,6 +126,7 @@ "help_message": "📄 /start - Приветствене сообщенне и версия ботба\\n❓ /help - Показатб этоб сообщенне\\n↕ /module - Изменитб модуль для тчата\\n🧹 /clear - Очиститб истоию чатба\\n🌎 /lang - Изменитб языкб\\n🆔 /chatid - Показатб ваш chat_id\\n\\nТеперб, чтобы начать, начырыкайте мне любое сообщенне 💬", "help_message_admin": "Команды админаб:\\n\\n💬 /queue - Показатб очередб запрософ\\n🔃 /restart - Перезапуститб прокси и телеграм-боба\\n👤 /users - Показатб списох всех польбзователей\\n🔨 /ban [reason] - Заблокировать полбзоватебля по его id с указанием причиныб (оптсыоинально)\\n🔓 /unban - Разблокироватб полбзоватебля по id\\n📢 /broadcast - Начырыкатб текбстовое сообщенне всем, кроме заблокированне пользователе", "empty_request_module_changed": "✅ Модулб был изменен на {0}\\nТеперб начырыкайте мне ваш запросб в виде сообщення", + "media_group_response": "Нарисованне кортинбки по зомпросуб: \"{}\"", "permissions_deny": "❌ Вам низзя, у вас нет правб на енту команбду!", "queue_overflow": "Очередб заполнена. Попробувайте пожже ⏳", "queue_empty": "🗑 Очередб пуста", From 0a9c4a0e3d4ea272af24434145ece4c648c0dea4 Mon Sep 17 00:00:00 2001 From: F33RNI Date: Sat, 9 Sep 2023 17:41:31 +0300 Subject: [PATCH 5/6] Change Bing Image gen reply --- RequestResponseContainer.py | 3 +++ config.json | 4 ++-- messages.json | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/RequestResponseContainer.py b/RequestResponseContainer.py index f8c785b8..6312b67a 100644 --- a/RequestResponseContainer.py +++ b/RequestResponseContainer.py @@ -82,5 +82,8 @@ def __init__(self, self.processing_start_timestamp = 0. self.error = False + # Used by BotHandler to split large message into smaller ones + self.response_parts = [] + # Unique ID for container to get it from queue (address) self.id = -1 diff --git a/config.json b/config.json index 21f15229..84fef858 100644 --- a/config.json +++ b/config.json @@ -73,7 +73,7 @@ "timeout_seconds": 240, "__comment07__": "HOW OFTEN EACH USER CAN SEND REQUESTS TO THIS MODULE (SPECIFY 0 TO REMOVE THE RESTRICTION)", - "user_cooldown_seconds": 120 + "user_cooldown_seconds": 0 }, "__comment04__": "DALL-E SETTINGS", @@ -108,7 +108,7 @@ "timeout_seconds": 120, "__comment15__": "HOW OFTEN EACH USER CAN SEND REQUESTS TO THIS MODULE (SPECIFY 0 TO REMOVE THE RESTRICTION)", - "user_cooldown_seconds": 0 + "user_cooldown_seconds": 120 }, "__comment06__": "BARD SETTINGS", diff --git a/messages.json b/messages.json index 838d2949..8e1d4249 100644 --- a/messages.json +++ b/messages.json @@ -67,7 +67,7 @@ "help_message": "📄 /start - Приветственное сообщение и версия бота\\n❓ /help - Показать это сообщение\\n↕ /module - Изменить модуль для чата\\n🧹 /clear - Очистить историю чата\\n🌎 /lang - Изменить язык\\n🆔 /chatid - Показать ваш chat_id\\n\\nТеперь, чтобы начать, отправьте мне любое сообщение 💬", "help_message_admin": "Команды администратора:\\n\\n💬 /queue - Показать очередь запросов\\n🔃 /restart - Перезапустить прокси и телеграм-бота\\n👤 /users - Показать список всех пользователей\\n🔨 /ban [reason] - Заблокировать пользователя по его id с указанием причины (опционально)\\n🔓 /unban - Разблокировать пользователя по id\\n📢 /broadcast - Отправить текстовое сообщение всем, кроме заблокированных пользователей", "empty_request_module_changed": "✅ Модуль был изменен на {0}\\nТеперь пришлите мне ваш запрос в виде сообщения", - "media_group_response": "Сгенерированные изображения по запросу: \"{}\"", + "media_group_response": "Сгенерированные изображения по запросу \"{}\"", "permissions_deny": "❌ У вас нет разрешения на эту команду!", "queue_overflow": "Очередь заполнена. Попробуйте позже ⏳", "queue_empty": "🗑 Очередь пуста", @@ -126,7 +126,7 @@ "help_message": "📄 /start - Приветствене сообщенне и версия ботба\\n❓ /help - Показатб этоб сообщенне\\n↕ /module - Изменитб модуль для тчата\\n🧹 /clear - Очиститб истоию чатба\\n🌎 /lang - Изменитб языкб\\n🆔 /chatid - Показатб ваш chat_id\\n\\nТеперб, чтобы начать, начырыкайте мне любое сообщенне 💬", "help_message_admin": "Команды админаб:\\n\\n💬 /queue - Показатб очередб запрософ\\n🔃 /restart - Перезапуститб прокси и телеграм-боба\\n👤 /users - Показатб списох всех польбзователей\\n🔨 /ban [reason] - Заблокировать полбзоватебля по его id с указанием причиныб (оптсыоинально)\\n🔓 /unban - Разблокироватб полбзоватебля по id\\n📢 /broadcast - Начырыкатб текбстовое сообщенне всем, кроме заблокированне пользователе", "empty_request_module_changed": "✅ Модулб был изменен на {0}\\nТеперб начырыкайте мне ваш запросб в виде сообщення", - "media_group_response": "Нарисованне кортинбки по зомпросуб: \"{}\"", + "media_group_response": "Нарисованне кортинбки по зомпросуб \"{}\"", "permissions_deny": "❌ Вам низзя, у вас нет правб на енту команбду!", "queue_overflow": "Очередб заполнена. Попробувайте пожже ⏳", "queue_empty": "🗑 Очередб пуста", From 70813d7a2ad508961619a1e9b0c5d14f7ba4d03a Mon Sep 17 00:00:00 2001 From: F33RNI Date: Sat, 9 Sep 2023 20:10:08 +0300 Subject: [PATCH 6/6] Add large response splitting into several messages --- BotHandler.py | 103 ++++++++++++++++++++++++++++-------- RequestResponseContainer.py | 5 +- config.json | 5 +- main.py | 2 +- 4 files changed, 88 insertions(+), 27 deletions(-) diff --git a/BotHandler.py b/BotHandler.py index 52328640..6071dc35 100644 --- a/BotHandler.py +++ b/BotHandler.py @@ -134,6 +134,17 @@ async def send_message_async(config: dict, messages: List[Dict], or (type(request_response.response) == str and len(request_response.response.strip()) <= 0): request_response.response = messages[lang]["empty_message"] + # Split large response into parts (by index) + if type(request_response.response) == str and len(request_response.response) > 0: + while True: + index_start = request_response.response_part_positions[-1] + response_part_length = len(request_response.response[index_start:-1]) + if response_part_length > config["telegram"]["one_message_limit"]: + request_response.response_part_positions\ + .append(index_start + config["telegram"]["one_message_limit"]) + else: + break + # The last message if end: # Generate regenerate button @@ -218,15 +229,9 @@ async def send_message_async(config: dict, messages: List[Dict], # Send message as text else: - request_response.message_id = await send_reply(config["telegram"]["api_key"], - request_response.user["user_id"], - request_response.response.strip(), - request_response.reply_message_id, - markdown=True, - reply_markup=request_response.reply_markup, - edit_message_id=request_response.message_id) + await _send_text_async_split(config, request_response, end) - # First or any other message + # First or any other message (text only) else: # Get current time time_current = time.time() @@ -238,28 +243,15 @@ async def send_message_async(config: dict, messages: List[Dict], and (request_response.response_len_last <= 0 or len(request_response.response.strip()) != request_response.response_len_last): - # Is it first message? + # Generate stop button if it's the first message if request_response.message_id is None or request_response.message_id < 0: - # Generate stop button button_stop = InlineKeyboardButton(messages[lang]["button_stop_generating"], callback_data="{0}_stop_{1}".format( request_response.request_type, request_response.reply_message_id)) request_response.reply_markup = InlineKeyboardMarkup(build_menu([button_stop])) - # Add cursor symbol? - response_text = request_response.response.strip() - if config["telegram"]["add_cursor_symbol"]: - response_text += config["telegram"]["cursor_symbol"] - - # Send message - request_response.message_id = await send_reply(config["telegram"]["api_key"], - request_response.user["user_id"], - response_text, - request_response.reply_message_id, - markdown=True, - reply_markup=request_response.reply_markup, - edit_message_id=request_response.message_id) + await _send_text_async_split(config, request_response, end) # Save new data request_response.response_len_last = len(request_response.response.strip()) @@ -273,6 +265,71 @@ async def send_message_async(config: dict, messages: List[Dict], request_response.response_timestamp = time.time() +async def _send_text_async_split(config: dict, + request_response: RequestResponseContainer.RequestResponseContainer, + end=False): + """ + Sends text in multiple messages if needed (must be previously split) + :param config: + :param request_response: + :param end: + :return: + """ + # Send all parts of message + response_part_counter_init = request_response.response_part_counter + while True: + # Get current part of response + response_part_index_start \ + = request_response.response_part_positions[request_response.response_part_counter] + response_part_index_stop = -1 + if request_response.response_part_counter < len(request_response.response_part_positions) - 1: + response_part_index_stop \ + = request_response.response_part_positions[request_response.response_part_counter + 1] + response_part \ + = request_response.response[response_part_index_start:response_part_index_stop].strip() + + # Get message ID to reply to + reply_to_id = request_response.reply_message_id + if request_response.message_id >= 0 and request_response.response_part_counter > 0: + reply_to_id = request_response.message_id + + edit_id = None + # Edit last message if first loop enter + if response_part_counter_init == request_response.response_part_counter: + edit_id = request_response.message_id + + # Check if it is not empty + if len(response_part) > 0: + # Send with markup and exit from loop if it's the last part + if response_part_index_stop == -1: + # Add cursor symbol? + if not end and config["telegram"]["add_cursor_symbol"]: + response_part += config["telegram"]["cursor_symbol"] + + request_response.message_id = await send_reply(config["telegram"]["api_key"], + request_response.user["user_id"], + response_part, + reply_to_id, + markdown=True, + reply_markup=request_response.reply_markup, + edit_message_id=edit_id) + break + # Send as new message without markup and increment counter + else: + request_response.message_id = await send_reply(config["telegram"]["api_key"], + request_response.user["user_id"], + response_part, + reply_to_id, + markdown=True, + reply_markup=None, + edit_message_id=edit_id) + request_response.response_part_counter += 1 + + # Exit from loop if no response in current part + else: + break + + async def send_reply(api_key: str, chat_id: int, message: str, reply_to_message_id: int | None, markdown=False, reply_markup=None, edit_message_id=None): """ diff --git a/RequestResponseContainer.py b/RequestResponseContainer.py index 6312b67a..c5d72f1e 100644 --- a/RequestResponseContainer.py +++ b/RequestResponseContainer.py @@ -82,8 +82,9 @@ def __init__(self, self.processing_start_timestamp = 0. self.error = False - # Used by BotHandler to split large message into smaller ones - self.response_parts = [] + # Used by BotHandler to split large message into smaller ones (list of indexes of text in response) + self.response_part_positions = [0] + self.response_part_counter = 0 # Unique ID for container to get it from queue (address) self.id = -1 diff --git a/config.json b/config.json index 84fef858..316b72d3 100644 --- a/config.json +++ b/config.json @@ -151,7 +151,10 @@ "add_cursor_symbol": true, "cursor_symbol": "▯", - "__comment07__": "SET TO true FOR THE BOT TO REPLY TO PLAIN MESSAGES AS WELL AS DIRECT MODULE COMMANDS", + "__comment07__": "IF RESPONSE IS LARGER THAN THIS NUMBER (IN CHARS), IT WILL BE SPLIT INTO MULTIPLE MESSAGES", + "one_message_limit": 3000, + + "__comment08__": "SET TO true FOR THE BOT TO REPLY TO PLAIN MESSAGES AS WELL AS DIRECT MODULE COMMANDS", "reply_to_messages": true }, diff --git a/main.py b/main.py index d92c05cd..56560a8f 100644 --- a/main.py +++ b/main.py @@ -34,7 +34,7 @@ from JSONReaderWriter import load_json # GPT-Telegramus version -__version__ = "3.3.0" +__version__ = "3.4.0" # Logging level LOGGING_LEVEL = logging.INFO