├── .gitignore ├── LICENSE ├── Procfile ├── README.md ├── main.py ├── requirements.txt └── vars.py /.gitignore: -------------------------------------------------------------------------------- 1 | **/__pycache__ 2 | **/venv 3 | *.session 4 | *.session-journal 5 | *.pyc 6 | *.env 7 | test.py 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 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 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | worker: python3 main.py 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Translator Bot V2 2 | A telegram language translator bot version 2 3 | 4 | --- 5 | 6 | ## Advanced Features 7 | 8 | - Change in user interface (Totally different) 9 | - Language selection after sending message for translating 10 | 11 | --- 12 | 13 | ## Variables 14 | 15 | ### Required 16 | 17 | - `API_HASH` Your API Hash from my.telegram.org 18 | - `API_ID` Your API ID from my.telegram.org 19 | - `BOT_TOKEN` Your bot token from @BotFather 20 | 21 | ### Optional 22 | 23 | - `CUSTOM` Custom buttons or not for translating 24 | 25 | --- 26 | 27 | ### Use [Translator-Bot-V3](https://github.com/FayasNoushad/Translator-Bot-V3), it is the latest and best version with more features. 28 | 29 | --- 30 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import os 2 | from vars import * 3 | from googletrans import Translator 4 | from googletrans.constants import LANGUAGES 5 | from pyrogram import Client, filters 6 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton 7 | 8 | 9 | Bot = Client( 10 | "Translator Bot", 11 | bot_token=BOT_TOKEN, 12 | api_id=API_ID, 13 | api_hash=API_HASH 14 | ) 15 | 16 | 17 | START_TEXT = """Hello {}, 18 | 19 | I am a google translator telegram bot. I can translate text to any language.""" 20 | 21 | HELP_TEXT = """**More Help** 22 | 23 | - Just send a text/message to translate. 24 | - And select a language for translating""" 25 | 26 | ABOUT_TEXT = """**About Me** 27 | 28 | - **Bot :** `Translator Bot V2` 29 | - **Creator :** [GitHub](https://github.com/FayasNoushad) | [Telegram](https://telegram.me/FayasNoushad) 30 | - **Source :** [Click here](https://github.com/FayasNoushad/Translator-Bot-V2) 31 | - **Language :** [Python3](https://python.org) 32 | - **Library :** [Pyrogram](https://pyrogram.org)""" 33 | 34 | START_BUTTONS = InlineKeyboardMarkup( 35 | [ 36 | [ 37 | InlineKeyboardButton('Help', callback_data='help'), 38 | InlineKeyboardButton('About', callback_data='about'), 39 | InlineKeyboardButton('Close', callback_data='close') 40 | ] 41 | ] 42 | ) 43 | HELP_BUTTONS = InlineKeyboardMarkup( 44 | [ 45 | [ 46 | InlineKeyboardButton('Home', callback_data='home'), 47 | InlineKeyboardButton('About', callback_data='about'), 48 | InlineKeyboardButton('Close', callback_data='close') 49 | ] 50 | ] 51 | ) 52 | ABOUT_BUTTONS = InlineKeyboardMarkup( 53 | [ 54 | [ 55 | InlineKeyboardButton('Feedback', url='https://telegram.me/FayasNoushad') 56 | ], 57 | [ 58 | InlineKeyboardButton('Home', callback_data='home'), 59 | InlineKeyboardButton('Help', callback_data='help'), 60 | InlineKeyboardButton('Close', callback_data='close') 61 | ] 62 | ] 63 | ) 64 | CLOSE_BUTTON = InlineKeyboardMarkup( 65 | [[InlineKeyboardButton('Close', callback_data='close')]] 66 | ) 67 | TRANSLATE_BUTTON = InlineKeyboardMarkup( 68 | [[InlineKeyboardButton('⚙ Feedback ⚙', url='https://telegram.me/FayasNoushad')]] 69 | ) 70 | 71 | 72 | def language_buttons(): 73 | pages = [] 74 | button_limit = 2 75 | line_limit = 8 76 | for language in LANGUAGES: 77 | button = InlineKeyboardButton(text=LANGUAGES[language].capitalize(), callback_data=language) 78 | if len(pages) == 0 or len(pages[-1]) >= line_limit and len(pages[-1][-1]) >= button_limit: 79 | pages.append([[button]]) 80 | elif len(pages[-1]) == 0 or len(pages[-1][-1]) >= button_limit: 81 | pages[-1].append([button]) 82 | else: 83 | pages[-1][-1].append(button) 84 | page_no = 0 85 | no_buttons = [] 86 | if len(pages) == 1: 87 | return pages 88 | for page in pages: 89 | page_no += 1 90 | page_buttons = [] 91 | if page == pages[0]: 92 | page_buttons.append( 93 | InlineKeyboardButton( 94 | text="-->", 95 | callback_data="page+"+str(page_no+1) 96 | ) 97 | ) 98 | elif page == pages[-1]: 99 | page_buttons.append( 100 | InlineKeyboardButton( 101 | text="<--", 102 | callback_data="page+"+str(page_no-1) 103 | ) 104 | ) 105 | else: 106 | page_buttons.append( 107 | InlineKeyboardButton( 108 | text="<--", 109 | callback_data="page+"+str(page_no-1) 110 | ) 111 | ) 112 | page_buttons.append( 113 | InlineKeyboardButton( 114 | text="-->", 115 | callback_data="page+"+str(page_no+1) 116 | ) 117 | ) 118 | pages[page_no-1].append(page_buttons) 119 | no_buttons.append( 120 | InlineKeyboardButton( 121 | text=str(page_no), 122 | callback_data="page+"+str(page_no) 123 | ) 124 | ) 125 | pages[page_no-1].append(no_buttons) 126 | return pages 127 | 128 | 129 | CUSTOM_LANGUAGE_BUTTONS = InlineKeyboardMarkup( 130 | [ 131 | [ 132 | InlineKeyboardButton("മലയാളം", callback_data="Malayalam"), 133 | InlineKeyboardButton("தமிழ்", callback_data="Tamil"), 134 | InlineKeyboardButton("हिन्दी", callback_data="Hindi") 135 | ], 136 | [ 137 | InlineKeyboardButton("ಕನ್ನಡ", callback_data="Kannada"), 138 | InlineKeyboardButton("తెలుగు", callback_data="Telugu"), 139 | InlineKeyboardButton("मराठी", callback_data="Marathi") 140 | ], 141 | [ 142 | InlineKeyboardButton("ગુજરાતી", callback_data="Gujarati"), 143 | InlineKeyboardButton("ଓଡ଼ିଆ", callback_data="Odia"), 144 | InlineKeyboardButton("বাংলা", callback_data="bn") 145 | ], 146 | [ 147 | InlineKeyboardButton("ਪੰਜਾਬੀ", callback_data="Punjabi"), 148 | InlineKeyboardButton("فارسی", callback_data="Persian"), 149 | InlineKeyboardButton("English", callback_data="English") 150 | ], 151 | [ 152 | InlineKeyboardButton("español", callback_data="Spanish"), 153 | InlineKeyboardButton("français", callback_data="French"), 154 | InlineKeyboardButton("русский", callback_data="Russian") 155 | ], 156 | [ 157 | InlineKeyboardButton("עִברִית", callback_data="hebrew"), 158 | InlineKeyboardButton("العربية", callback_data="arabic") 159 | ] 160 | ] 161 | ) 162 | 163 | LANGUAGE_BUTTONS = InlineKeyboardMarkup( 164 | language_buttons()[0] 165 | ) 166 | 167 | @Bot.on_callback_query() 168 | async def cb_data(bot, message): 169 | if message.data == "home": 170 | await message.message.edit_text( 171 | text=START_TEXT.format(message.from_user.mention), 172 | disable_web_page_preview=True, 173 | reply_markup=START_BUTTONS 174 | ) 175 | elif message.data == "help": 176 | await message.message.edit_text( 177 | text=HELP_TEXT, 178 | disable_web_page_preview=True, 179 | reply_markup=HELP_BUTTONS 180 | ) 181 | elif message.data == "about": 182 | await message.message.edit_text( 183 | text=ABOUT_TEXT, 184 | disable_web_page_preview=True, 185 | reply_markup=ABOUT_BUTTONS 186 | ) 187 | elif message.data == "close": 188 | await message.message.delete() 189 | elif message.data.startswith("page+"): 190 | await message.answer("Processing") 191 | page_no = int(message.data.split("+")[1]) - 1 192 | await message.message.edit_reply_markup( 193 | InlineKeyboardMarkup( 194 | language_buttons()[page_no] 195 | ) 196 | ) 197 | else: 198 | await message.message.edit_text("`Translating...`") 199 | text = message.message.reply_to_message.text 200 | language = message.data 201 | translator = Translator() 202 | try: 203 | translate = translator.translate(text, dest=language) 204 | lang_text = f"{LANGUAGES[language].capitalize()} ({language})" 205 | translate_text = f"**Translated to {lang_text}**" 206 | translate_text += f"\n\n{translate.text}" 207 | if len(translate_text) < 4096: 208 | await message.message.edit_text( 209 | text=translate_text, 210 | disable_web_page_preview=True, 211 | reply_markup=TRANSLATE_BUTTON 212 | ) 213 | else: 214 | with BytesIO(str.encode(str(translate_text))) as translate_file: 215 | translate_file.name = language + ".txt" 216 | await message.reply_document( 217 | document=translate_file, 218 | reply_markup=TRANSLATE_BUTTON 219 | ) 220 | await message.delete() 221 | except Exception as error: 222 | print(error) 223 | await message.edit_text("Something wrong.") 224 | 225 | 226 | @Bot.on_message(filters.command(["start"])) 227 | async def start(bot, message): 228 | text = START_TEXT.format(message.from_user.mention) 229 | reply_markup = START_BUTTONS 230 | await message.reply_text( 231 | text=text, 232 | disable_web_page_preview=True, 233 | reply_markup=reply_markup 234 | ) 235 | 236 | 237 | @Bot.on_message(filters.command(["help"])) 238 | async def help(bot, message): 239 | text = HELP_TEXT 240 | reply_markup = HELP_BUTTONS 241 | await message.reply_text( 242 | text=text, 243 | disable_web_page_preview=True, 244 | reply_markup=reply_markup 245 | ) 246 | 247 | 248 | @Bot.on_message(filters.command(["about"])) 249 | async def about(bot, message): 250 | text = ABOUT_TEXT 251 | reply_markup = ABOUT_BUTTONS 252 | await message.reply_text( 253 | text=text, 254 | disable_web_page_preview=True, 255 | reply_markup=reply_markup 256 | ) 257 | 258 | 259 | # Language list 260 | @Bot.on_message(filters.command(["list", "languages", "langs", "languages_list"])) 261 | async def languages_list(bot, message): 262 | languages = LANGUAGES 263 | languages_text = "**Languages**\n" 264 | for language in languages: 265 | languages_text += f"\n`{languages[language].capitalize()}` -> `{language}`" 266 | await message.reply_text( 267 | text=languages_text, 268 | disable_web_page_preview=True, 269 | reply_markup=TRANSLATE_BUTTON, 270 | quote=True 271 | ) 272 | 273 | 274 | @Bot.on_message(filters.private & filters.text) 275 | async def translate(bot, message): 276 | # to avoid command only messages 277 | if message.text.startswith("/") and len(message.text) == 1: 278 | return 279 | buttons = CUSTOM_LANGUAGE_BUTTONS if CUSTOM else LANGUAGE_BUTTONS 280 | await message.reply_text( 281 | text="Select a language below for translating", 282 | disable_web_page_preview=True, 283 | reply_markup=buttons, 284 | quote=True 285 | ) 286 | 287 | 288 | Bot.run() 289 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pyrogram 2 | tgcrypto 3 | googletrans==4.0.0-rc1 4 | -------------------------------------------------------------------------------- /vars.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | API_ID = int(os.environ.get("API_ID")) 4 | API_HASH = os.environ.get("API_HASH") 5 | BOT_TOKEN = os.environ.get("BOT_TOKEN") 6 | 7 | # Custom language buttons or not 8 | CUSTOM = bool(os.environ.get("CUSTOM", False)) 9 | --------------------------------------------------------------------------------