diff --git a/README.md b/README.md index 8d97cfb..7f9cdb0 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ You can deploy your own bot, or use mine: [@chatgpt_karfly_bot](https://t.me/cha - No request limits - Message streaming (watch demo) - GPT-4 support +- Group Chat support (/help_group_chat to get instructions) - DALLE 2 (choose ๐Ÿ‘ฉโ€๐ŸŽจ Artist mode to generate images) - Voice message recognition - Code highlighting @@ -48,10 +49,10 @@ You can deploy your own bot, or use mine: [@chatgpt_karfly_bot](https://t.me/cha - [ะฎMoney](https://yoomoney.ru) - and [many-many other](https://core.telegram.org/bots/payments#supported-payment-providers) -If you want to add payments to your bot โ€“ write me on Telegram ([@karfly](https://t.me/karfly)). +If you want to add payments to your bot and create profitable business โ€“ write me on Telegram ([@karfly](https://t.me/karfly)). ## News -- *21 Apr 2023*: DALLE 2 support +- *21 Apr 2023*: DALLE 2 support, Group Chat support (/help_group_chat to get instructions) - *24 Mar 2023*: GPT-4 support. Run `/settings` command to choose model - *15 Mar 2023*: Added message streaming. Now you don't have to wait until the whole message is ready, it's streamed to Telegram part-by-part (watch demo) - *9 Mar 2023*: Now you can easily create your own Chat Modes by editing `config/chat_modes.yml` diff --git a/bot/bot.py b/bot/bot.py index 2b70cd3..49ed2d8 100644 --- a/bot/bot.py +++ b/bot/bot.py @@ -49,6 +49,21 @@ HELP_MESSAGE = """Commands: โšช /settings โ€“ Show settings โšช /balance โ€“ Show balance โšช /help โ€“ Show help + +๐ŸŽจ Generate images from text prompts in ๐Ÿ‘ฉโ€๐ŸŽจ Artist /mode +๐Ÿ‘ฅ Add bot to group chat: /help_group_chat +๐ŸŽค You can send Voice Messages instead of text +""" + +HELP_GROUP_CHAT_MESSAGE = """You can add bot to any group chat to help and entertain its participants! + +Instructions (see video below): +1. Add the bot to the group chat +2. Make it an admin, so that it can see messages (all other rights can be restricted) +3. You're awesome! + +To get a reply from the bot in the chat โ€“ @ tag it or reply to its message. +For example: "{bot_username} write a poem about Telegram" """ @@ -97,6 +112,25 @@ async def register_user_if_not_exists(update: Update, context: CallbackContext, db.set_user_attribute(user.id, "n_generated_images", 0) +async def is_bot_mentioned(update: Update, context: CallbackContext): + try: + message = update.message + + if message.chat.type == "private": + return True + + if message.text is not None and config.bot_username in message.text: + return True + + if message.reply_to_message is not None: + if message.reply_to_message.from_user.id == context.bot.id: + return True + except: + return True + else: + return False + + async def start_handle(update: Update, context: CallbackContext): await register_user_if_not_exists(update, context, update.message.from_user) user_id = update.message.from_user.id @@ -119,6 +153,17 @@ async def help_handle(update: Update, context: CallbackContext): await update.message.reply_text(HELP_MESSAGE, parse_mode=ParseMode.HTML) +async def help_group_chat_handle(update: Update, context: CallbackContext): + await register_user_if_not_exists(update, context, update.message.from_user) + user_id = update.message.from_user.id + db.set_user_attribute(user_id, "last_interaction", datetime.now()) + + text = HELP_GROUP_CHAT_MESSAGE.format(bot_username="@" + context.bot.username) + + await update.message.reply_text(text, parse_mode=ParseMode.HTML) + await update.message.reply_video(config.help_group_chat_video_path) + + async def retry_handle(update: Update, context: CallbackContext): await register_user_if_not_exists(update, context, update.message.from_user) if await is_previous_message_not_answered_yet(update, context): return @@ -138,11 +183,21 @@ async def retry_handle(update: Update, context: CallbackContext): async def message_handle(update: Update, context: CallbackContext, message=None, use_new_dialog_timeout=True): + # check if bot was mentioned (for group chats) + if not await is_bot_mentioned(update, context): + return + # check if message is edited if update.edited_message is not None: await edited_message_handle(update, context) return + _message = message or update.message.text + + # remove bot mention (in group chats) + if update.message.chat.type != "private": + _message = _message.replace("@" + context.bot.username, "").strip() + await register_user_if_not_exists(update, context, update.message.from_user) if await is_previous_message_not_answered_yet(update, context): return @@ -172,7 +227,6 @@ async def message_handle(update: Update, context: CallbackContext, message=None, # send typing action await update.message.chat.send_action(action="typing") - _message = message or update.message.text if _message is None or len(_message) == 0: await update.message.reply_text("๐Ÿฅฒ You sent empty message. Please, try again!", parse_mode=ParseMode.HTML) return @@ -278,6 +332,10 @@ async def is_previous_message_not_answered_yet(update: Update, context: Callback async def voice_message_handle(update: Update, context: CallbackContext): + # check if bot was mentioned (for group chats) + if not await is_bot_mentioned(update, context): + return + await register_user_if_not_exists(update, context, update.message.from_user) if await is_previous_message_not_answered_yet(update, context): return @@ -561,6 +619,7 @@ def run_bot() -> None: application.add_handler(CommandHandler("start", start_handle, filters=user_filter)) application.add_handler(CommandHandler("help", help_handle, filters=user_filter)) + application.add_handler(CommandHandler("help_group_chat", help_group_chat_handle, filters=user_filter)) application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND & user_filter, message_handle)) application.add_handler(CommandHandler("retry", retry_handle, filters=user_filter)) diff --git a/bot/config.py b/bot/config.py index 2fb4c9a..a768006 100644 --- a/bot/config.py +++ b/bot/config.py @@ -28,3 +28,6 @@ with open(config_dir / "chat_modes.yml", 'r') as f: # models with open(config_dir / "models.yml", 'r') as f: models = yaml.safe_load(f) + +# files +help_group_chat_video_path = Path(__file__).parent.parent.resolve() / "static" / "help_group_chat.mp4" diff --git a/static/help_group_chat.mp4 b/static/help_group_chat.mp4 new file mode 100644 index 0000000..2af627e Binary files /dev/null and b/static/help_group_chat.mp4 differ