├── Procfile ├── requirements.txt ├── .gitignore ├── bot ├── vars.py ├── bot_status.py ├── translate │ ├── languages_list.py │ ├── translate.py │ └── settings.py ├── database.py ├── cb_data.py ├── admin.py └── commands.py ├── main.py ├── LICENSE └── README.md /Procfile: -------------------------------------------------------------------------------- 1 | worker: python3 main.py 2 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pyrogram 2 | tgcrypto 3 | googletrans==4.0.0-rc1 4 | motor 5 | aiofiles 6 | dnspython 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/__pycache__ 2 | **/venv 3 | *.session 4 | *.session-journal 5 | *.pyc 6 | *.env 7 | test.py 8 | -------------------------------------------------------------------------------- /bot/vars.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | ADMINS = set(int(x) for x in os.environ.get("ADMINS", "").split()) 5 | DATABASE_URL = os.environ.get("DATABASE_URL") 6 | DATABASE_NAME = os.environ.get("DATABASE_NAME", "Translator-Bot") 7 | DEFAULT_LANGUAGE = os.environ.get("DEFAULT_LANGUAGE", "en") 8 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | # Author: Fayas (https://github.com/FayasNoushad) (@FayasNoushad) 2 | 3 | import os 4 | from pyrogram import Client 5 | 6 | 7 | Bot = Client( 8 | "Translator Bot", 9 | bot_token = os.environ["BOT_TOKEN"], 10 | api_id = int(os.environ["API_ID"]), 11 | api_hash = os.environ["API_HASH"], 12 | plugins = dict(root="bot") 13 | ) 14 | 15 | 16 | Bot.run() 17 | -------------------------------------------------------------------------------- /bot/bot_status.py: -------------------------------------------------------------------------------- 1 | from .database import db 2 | from .admin import add_user 3 | from pyrogram import Client, filters 4 | 5 | 6 | @Client.on_message(filters.private & filters.command(["status", "bot_status"])) 7 | async def status(bot, message): 8 | await add_user(message.from_user.id) 9 | total_users = await db.total_users_count() 10 | text = "**Bot Status**\n" 11 | text += f"\n**Total Users:** `{total_users}`" 12 | await message.reply_text( 13 | text=text, 14 | quote=True, 15 | disable_web_page_preview=True 16 | ) -------------------------------------------------------------------------------- /bot/translate/languages_list.py: -------------------------------------------------------------------------------- 1 | from googletrans import constants 2 | from .translate import BUTTONS 3 | from pyrogram import Client, filters 4 | 5 | 6 | @Client.on_message(filters.command(["list", "languages", "langs", "languages_list"])) 7 | async def languages_list(bot, message): 8 | languages = constants.LANGUAGES 9 | languages_text = "**Languages**\n" 10 | for language in languages: 11 | languages_text += f"\n`{languages[language].capitalize()}` -> `{language}`" 12 | await message.reply_text( 13 | text=languages_text, 14 | disable_web_page_preview=True, 15 | reply_markup=BUTTONS, 16 | quote=True 17 | ) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021-2024 Fayas 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Translator Bot V3 2 | An advanced telegram language translator bot 3 | 4 | --- 5 | 6 | ## Features 7 | 8 | - Database ( MongoDB ) Support 9 | - Broadcast Support 10 | - Set default language support 11 | - Direct languages updation from Python Translation Library 12 | 13 | --- 14 | 15 | ## Deploy 16 | 17 | ```sh 18 | git clone https://github.com/FayasNoushad/Translator-Bot-V3.git 19 | cd Translator-Bot 20 | python3 -m venv venv 21 | . ./venv/bin/activate 22 | pip3 install -r requirements.txt 23 | # 24 | python3 main.py 25 | ``` 26 | 27 | --- 28 | 29 | ## Variables 30 | 31 | ### Required 32 | 33 | - `API_HASH` Your API Hash from my.telegram.org 34 | - `API_ID` Your API ID from my.telegram.org 35 | - `BOT_TOKEN` Your bot token from @BotFather 36 | - `DATABASE_URL` MongoDB URL 37 | 38 | ### Optional 39 | 40 | - `ADMINS` Administrators IDs seperated by whitespace 41 | - `DATABASE_NAME` MongoDB Database Name 42 | - `DEFAULT_LANGUAGE` Default language code 43 | 44 | --- 45 | 46 | ## Old Versions 47 | 48 | - [Translator-Bot](https://github.com/FayasNoushad/Translator-Bot) 49 | - [Translator-Bot-V2](https://github.com/FayasNoushad/Translator-Bot-V2) 50 | 51 | --- 52 | -------------------------------------------------------------------------------- /bot/database.py: -------------------------------------------------------------------------------- 1 | import motor.motor_asyncio 2 | from .vars import DEFAULT_LANGUAGE, DATABASE_URL, DATABASE_NAME 3 | 4 | 5 | class Database: 6 | def __init__(self, uri=DATABASE_URL, database_name=DATABASE_NAME): 7 | self._client = motor.motor_asyncio.AsyncIOMotorClient(uri) 8 | self.db = self._client[database_name] 9 | self.col = self.db.users 10 | self.cache = {} 11 | 12 | def new_user(self, id): 13 | return {"id": id, "language": DEFAULT_LANGUAGE} 14 | 15 | async def add_user(self, id): 16 | user = self.new_user(id) 17 | await self.col.insert_one(user) 18 | 19 | async def get_user(self, id): 20 | user = self.cache.get(id) 21 | if user is not None: 22 | return user 23 | 24 | user = await self.col.find_one({"id": int(id)}) 25 | self.cache[id] = user 26 | return user 27 | 28 | async def is_user_exist(self, id): 29 | user = await self.col.find_one({'id': int(id)}) 30 | return True if user else False 31 | 32 | async def total_users_count(self): 33 | count = await self.col.count_documents({}) 34 | return count 35 | 36 | async def get_all_users(self): 37 | all_users = self.col.find({}) 38 | return all_users 39 | 40 | async def delete_user(self, user_id): 41 | await self.col.delete_many({'id': int(user_id)}) 42 | 43 | async def get_lang(self, id): 44 | user = await self.col.find_one({'id': int(id)}) 45 | if user: 46 | return user.get("language", DEFAULT_LANGUAGE) 47 | 48 | async def update_lang(self, id, language): 49 | await self.col.update_one( 50 | {"id": id}, {"$set": {"language": language}} 51 | ) 52 | 53 | 54 | db = Database() 55 | -------------------------------------------------------------------------------- /bot/cb_data.py: -------------------------------------------------------------------------------- 1 | from .database import db 2 | from .admin import add_user 3 | from pyrogram import Client 4 | from pyrogram.types import InlineKeyboardMarkup 5 | from .commands import start, help, about 6 | from googletrans.constants import LANGUAGES 7 | from .translate.settings import language_buttons, SETTINGS_TEXT 8 | 9 | 10 | @Client.on_callback_query() 11 | async def cb_data(_, message): 12 | await add_user(message.from_user.id) 13 | if message.data == "home": 14 | await start(_, message, cb=True) 15 | elif message.data == "help": 16 | await help(_, message, cb=True) 17 | elif message.data == "about": 18 | await about(_, message, cb=True) 19 | elif message.data == "close": 20 | await message.message.delete() 21 | elif message.data.startswith("page+"): 22 | await message.answer("Processing") 23 | page_no = int(message.data.split("+")[1]) - 1 24 | await message.message.edit_reply_markup( 25 | InlineKeyboardMarkup( 26 | language_buttons()[page_no] 27 | ) 28 | ) 29 | elif message.data.startswith("set+"): 30 | try: 31 | language = message.data.split("+")[1] 32 | await db.update_lang(message.from_user.id, language) 33 | lang_text = f"{LANGUAGES[language].capitalize()} ({language})" 34 | alert_text = f"Language changed to {lang_text}" 35 | await message.answer(text=alert_text, show_alert=True) 36 | await message.message.edit_text( 37 | text=SETTINGS_TEXT.format(await db.get_lang(message.from_user.id)), 38 | disable_web_page_preview=True, 39 | reply_markup=message.message.reply_markup 40 | ) 41 | except Exception as error: 42 | if 'MESSAGE_NOT_MODIFIED' in str(error): 43 | return 44 | print(error) 45 | await message.message.edit_text("Something wrong.") 46 | -------------------------------------------------------------------------------- /bot/translate/translate.py: -------------------------------------------------------------------------------- 1 | # Author: Fayas (https://github.com/FayasNoushad) (@FayasNoushad) 2 | 3 | import os 4 | from ..vars import DEFAULT_LANGUAGE 5 | from ..admin import db 6 | from io import BytesIO 7 | from pyrogram import Client, filters, enums 8 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton 9 | from googletrans import Translator 10 | 11 | 12 | BUTTONS = InlineKeyboardMarkup( 13 | [[InlineKeyboardButton('⚙ Feedback ⚙', url='https://telegram.me/FayasNoushad')]] 14 | ) 15 | 16 | @Client.on_message(filters.group & filters.command(["tr", "translate"])) 17 | async def command_filter(bot, update): 18 | if update.reply_to_message: 19 | if update.reply_to_message.text: 20 | text = update.reply_to_message.text 21 | elif update.reply_to_message.caption: 22 | text = update.reply_to_message.caption 23 | else: 24 | return 25 | else: 26 | if update.text: 27 | text = update.text.split(" ", 1)[1] 28 | elif update.caption: 29 | text = update.caption.split(" ", 1)[1] 30 | else: 31 | return 32 | await translate(bot, update, text) 33 | 34 | 35 | @Client.on_message(filters.private & (filters.text | filters.caption)) 36 | async def get_message(_, message): 37 | text = message.text if message.text else message.caption 38 | await translate(message, text) 39 | 40 | 41 | async def translate(update, text): 42 | await update.reply_chat_action(enums.ChatAction.TYPING) 43 | message = await update.reply_text("`Translating...`", quote=True) 44 | try: 45 | language = await db.get_lang(update.from_user.id) 46 | except: 47 | language = DEFAULT_LANGUAGE 48 | translator = Translator() 49 | try: 50 | translate = translator.translate(text, dest=language) 51 | translate_text = f"**Translated to {language}**" 52 | translate_text += f"\n\n`{translate.text}`" 53 | if len(translate_text) < 4096: 54 | await message.edit_text( 55 | text=translate_text, 56 | disable_web_page_preview=True, 57 | reply_markup=BUTTONS 58 | ) 59 | else: 60 | with BytesIO(str.encode(str(translate_text))) as translate_file: 61 | translate_file.name = language + ".txt" 62 | await update.reply_document( 63 | document=translate_file, 64 | quote=True, 65 | reply_markup=BUTTONS 66 | ) 67 | await message.delete() 68 | try: 69 | os.remove(translate_file) 70 | except: 71 | pass 72 | except Exception as error: 73 | print(error) 74 | await message.edit_text("Something wrong. Contact developer.") 75 | return 76 | -------------------------------------------------------------------------------- /bot/admin.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | import string 4 | import random 5 | import traceback 6 | import asyncio 7 | import datetime 8 | import aiofiles 9 | from .database import db 10 | from pyrogram import Client, filters 11 | from pyrogram.errors import FloodWait, InputUserDeactivated, UserIsBlocked, PeerIdInvalid 12 | from pyrogram.errors.exceptions.bad_request_400 import PeerIdInvalid 13 | from .vars import ADMINS 14 | 15 | 16 | async def add_user(id): 17 | if not await db.is_user_exist(id): 18 | await db.add_user(id) 19 | return 20 | 21 | 22 | async def send_msg(user_id, message): 23 | try: 24 | await message.copy(chat_id=user_id) 25 | return 200, None 26 | except FloodWait as e: 27 | await asyncio.sleep(e.x) 28 | return send_msg(user_id, message) 29 | except InputUserDeactivated: 30 | return 400, f"{user_id} : deactivated\n" 31 | except UserIsBlocked: 32 | return 400, f"{user_id} : blocked the bot\n" 33 | except PeerIdInvalid: 34 | return 400, f"{user_id} : user id invalid\n" 35 | except Exception as e: 36 | return 500, f"{user_id} : {traceback.format_exc()}\n" 37 | 38 | 39 | @Client.on_message(filters.private & filters.command("broadcast") & filters.reply) 40 | async def broadcast(bot, message): 41 | 42 | # Checking user is admin or not 43 | if message.from_user.id not in ADMINS: 44 | return 45 | 46 | broadcast_ids={} 47 | all_users = await db.get_all_users() 48 | broadcast_msg = message.reply_to_message 49 | 50 | while True: 51 | broadcast_id = ''.join([random.choice(string.ascii_letters) for i in range(3)]) 52 | if not broadcast_ids.get(broadcast_id): 53 | break 54 | 55 | out = await message.reply_text( 56 | text=f"Broadcast Started! You will be notified with log file when all the users are notified." 57 | ) 58 | 59 | start_time = time.time() 60 | total_users = await db.total_users_count() 61 | done = 0 62 | failed = 0 63 | success = 0 64 | broadcast_ids[broadcast_id] = dict(total=total_users, current=done, failed=failed, success=success) 65 | 66 | async with aiofiles.open('broadcast.txt', 'w') as broadcast_log_file: 67 | async for user in all_users: 68 | sts, msg = await send_msg(user_id=int(user['id']), message=broadcast_msg) 69 | if msg is not None: 70 | await broadcast_log_file.write(msg) 71 | if sts == 200: 72 | success += 1 73 | else: 74 | failed += 1 75 | if sts == 400: 76 | await db.delete_user(user['id']) 77 | done += 1 78 | if broadcast_ids.get(broadcast_id) is None: 79 | break 80 | else: 81 | broadcast_ids[broadcast_id].update(dict(current=done, failed=failed, success=success)) 82 | 83 | if broadcast_ids.get(broadcast_id): 84 | broadcast_ids.pop(broadcast_id) 85 | 86 | completed_in = datetime.timedelta(seconds=int(time.time()-start_time)) 87 | await asyncio.sleep(3) 88 | await out.delete() 89 | 90 | broadcast_text = f"Broadcast completed in `{completed_in}`\n" \ 91 | f"\nTotal users {total_users}.\nTotal done {done}," \ 92 | f"{success} success and {failed} failed." 93 | if failed == 0: 94 | await message.reply_text(text=broadcast_text, quote=True) 95 | else: 96 | await message.reply_document(document='broadcast.txt', caption=broadcast_text) 97 | os.remove('broadcast.txt') 98 | -------------------------------------------------------------------------------- /bot/translate/settings.py: -------------------------------------------------------------------------------- 1 | from ..database import db 2 | from ..admin import add_user 3 | from ..vars import DEFAULT_LANGUAGE 4 | from googletrans.constants import LANGUAGES 5 | from pyrogram import Client, filters, enums 6 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton 7 | 8 | 9 | def language_buttons(): 10 | pages = [] 11 | button_limit = 2 12 | line_limit = 8 13 | for language in LANGUAGES: 14 | button = InlineKeyboardButton(text=LANGUAGES[language].capitalize(), callback_data="set+"+language) 15 | if len(pages) == 0 or len(pages[-1]) >= line_limit and len(pages[-1][-1]) >= button_limit: 16 | pages.append([[button]]) 17 | elif len(pages[-1]) == 0 or len(pages[-1][-1]) >= button_limit: 18 | pages[-1].append([button]) 19 | else: 20 | pages[-1][-1].append(button) 21 | page_no = 0 22 | no_buttons = [] 23 | if len(pages) == 1: 24 | return pages 25 | for page in pages: 26 | page_no += 1 27 | page_buttons = [] 28 | if page == pages[0]: 29 | page_buttons.append( 30 | InlineKeyboardButton( 31 | text="-->", 32 | callback_data="page+"+str(page_no+1) 33 | ) 34 | ) 35 | elif page == pages[-1]: 36 | page_buttons.append( 37 | InlineKeyboardButton( 38 | text="<--", 39 | callback_data="page+"+str(page_no-1) 40 | ) 41 | ) 42 | else: 43 | page_buttons.append( 44 | InlineKeyboardButton( 45 | text="<--", 46 | callback_data="page+"+str(page_no-1) 47 | ) 48 | ) 49 | page_buttons.append( 50 | InlineKeyboardButton( 51 | text="-->", 52 | callback_data="page+"+str(page_no+1) 53 | ) 54 | ) 55 | pages[page_no-1].append(page_buttons) 56 | no_buttons.append( 57 | InlineKeyboardButton( 58 | text=str(page_no), 59 | callback_data="page+"+str(page_no) 60 | ) 61 | ) 62 | pages[page_no-1].append(no_buttons) 63 | return pages 64 | 65 | 66 | SETTINGS_TEXT = "Select your language for translating. Current default language is `{}`." 67 | SETTINGS_BUTTONS = InlineKeyboardMarkup( 68 | language_buttons()[0] 69 | ) 70 | 71 | 72 | @Client.on_message(filters.command(["set", "settings"])) 73 | async def settings(bot, message): 74 | if message.chat.type != enums.ChatType.PRIVATE: 75 | reply_markup = InlineKeyboardMarkup( 76 | [ 77 | [ 78 | InlineKeyboardButton( 79 | text="Click here", 80 | url=f"https://telegram.me/{(await bot.get_me()).username}?start=set" 81 | ) 82 | ] 83 | ] 84 | ) 85 | await message.reply_text( 86 | text="Set your language via private", 87 | disable_web_page_preview=True, 88 | reply_markup=reply_markup, 89 | quote=True 90 | ) 91 | return 92 | await add_user(message.from_user.id) 93 | await message.reply_text( 94 | text=SETTINGS_TEXT.format(await db.get_lang(message.from_user.id)), 95 | disable_web_page_preview=True, 96 | reply_markup=SETTINGS_BUTTONS, 97 | quote=True 98 | ) 99 | 100 | 101 | @Client.on_message(filters.private & filters.command(["reset", "unset"])) 102 | async def reset(bot, message): 103 | await add_user(message.from_user.id) 104 | await db.update_lang(message.from_user.id, DEFAULT_LANGUAGE) 105 | await message.reply_text( 106 | text="Language reset successfully", 107 | disable_web_page_preview=True, 108 | quote=True 109 | ) 110 | -------------------------------------------------------------------------------- /bot/commands.py: -------------------------------------------------------------------------------- 1 | from .database import db 2 | from .admin import add_user 3 | from .translate.settings import settings 4 | from pyrogram import Client, filters 5 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton 6 | 7 | 8 | START_TEXT = """**Hello {} 😌 9 | I am a google translator telegram bot.** 10 | 11 | >> `I can translate from any languages to any languages.` 12 | 13 | Made by @FayasNoushad""" 14 | 15 | HELP_TEXT = """**Hey, Follow these steps:** 16 | 17 | - Send /set or /settings for set a translate language 18 | - Send /reset for resetting current translate language 19 | - Send /list or /languages for languages list 20 | - Just send a text for translation 21 | - Add me your group and send /tr or /translate command for translation in group 22 | 23 | **Available Commands** 24 | 25 | /start - Checking bot online 26 | /help - For more help 27 | /about - For more about me 28 | /status - For bot status 29 | /list - For language list 30 | /set - For set translate language 31 | /reset - For reset translate language 32 | 33 | Made by @FayasNoushad""" 34 | 35 | ABOUT_TEXT = """--**About Me 😎**-- 36 | 37 | 🤖 **Name :** [Translator Bot](https://telegram.me/{}) 38 | 39 | 👨‍💻 **Developer :** [GitHub](https://github.com/FayasNoushad) | [Telegram](https://telegram.me/FayasNoushad) 40 | 41 | 🌐 **Source :** [👉 Click here](https://github.com/FayasNoushad/Translator-Bot-V3) 42 | 43 | 📝 **Language :** [Python3](https://python.org) 44 | 45 | 🧰 **Framework :** [Pyrogram](https://pyrogram.org)""" 46 | 47 | 48 | START_BUTTONS = InlineKeyboardMarkup( 49 | [ 50 | [ 51 | InlineKeyboardButton('⚙ Help', callback_data='help'), 52 | InlineKeyboardButton('About 🔰', callback_data='about'), 53 | InlineKeyboardButton('Close ✖️', callback_data='close') 54 | ] 55 | ] 56 | ) 57 | 58 | HELP_BUTTONS = InlineKeyboardMarkup( 59 | [ 60 | [ 61 | InlineKeyboardButton('🏘 Home', callback_data='home'), 62 | InlineKeyboardButton('About 🔰', callback_data='about'), 63 | InlineKeyboardButton('Close ✖️', callback_data='close') 64 | ] 65 | ] 66 | ) 67 | 68 | ABOUT_BUTTONS = InlineKeyboardMarkup( 69 | [ 70 | [ 71 | InlineKeyboardButton('🏘 Home', callback_data='home'), 72 | InlineKeyboardButton('Help ⚙', callback_data='help'), 73 | InlineKeyboardButton('Close ✖️', callback_data='close') 74 | ] 75 | ] 76 | ) 77 | 78 | CLOSE_BUTTON = InlineKeyboardMarkup([[InlineKeyboardButton('Close', callback_data='close')]]) 79 | 80 | 81 | @Client.on_message(filters.private & filters.command(["start"])) 82 | async def start(bot, message, cb=False): 83 | await add_user(message.from_user.id) 84 | if cb or (message and message.text and (message.text == "/start")): 85 | text = START_TEXT.format(message.from_user.mention) 86 | buttons = START_BUTTONS 87 | if cb: 88 | await message.message.edit_text( 89 | text=text, 90 | reply_markup=buttons, 91 | disable_web_page_preview=True 92 | ) 93 | return 94 | await message.reply_text( 95 | text=text, 96 | disable_web_page_preview=True, 97 | reply_markup=buttons, 98 | quote=True 99 | ) 100 | else: 101 | command = message.text.split(" ", 1)[1] 102 | if command == "set": 103 | await settings(bot, message) 104 | 105 | 106 | @Client.on_message(filters.private & filters.command(["help"])) 107 | async def help(bot, message, cb=False): 108 | await add_user(message.from_user.id) 109 | if cb: 110 | await message.message.edit_text( 111 | text=HELP_TEXT, 112 | reply_markup=HELP_BUTTONS, 113 | disable_web_page_preview=True 114 | ) 115 | else: 116 | await message.reply_text( 117 | text=HELP_TEXT, 118 | reply_markup=HELP_BUTTONS, 119 | disable_web_page_preview=True, 120 | quote=True 121 | ) 122 | 123 | 124 | @Client.on_message(filters.private & filters.command(["about"])) 125 | async def about(bot, message, cb=False): 126 | await add_user(message.from_user.id) 127 | text = ABOUT_TEXT.format((await bot.get_me()).username) 128 | if cb: 129 | await message.message.edit_text( 130 | text=text, 131 | reply_markup=ABOUT_BUTTONS, 132 | disable_web_page_preview=True 133 | ) 134 | else: 135 | await message.reply_text( 136 | text=text, 137 | reply_markup=ABOUT_BUTTONS, 138 | disable_web_page_preview=True, 139 | quote=True 140 | ) --------------------------------------------------------------------------------