├── .gitignore ├── app.py ├── database.py ├── info.py ├── readme.md └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea/ 3 | __pycache__/ 4 | temp.py -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | from database import DataBase 2 | from info import * 3 | from telegram.ext import * 4 | from telegram import * 5 | import telegram 6 | 7 | class ChatBot: 8 | def __init__(self, bot_name, bot_key): 9 | self.boys = [] 10 | self.girls = [] 11 | self.chat_pair = {} 12 | 13 | self.bot_name, self.bot_key = bot_name, bot_key 14 | 15 | # Calling database 16 | self.record = DataBase() 17 | 18 | # Bot command handler 19 | self.command_handler() 20 | 21 | def common_args(self, update, context): 22 | if update.message.chat.type != "private": 23 | user_id = update.message.chat.id 24 | name = context.bot.get_chat(chat_id=user_id).title 25 | username = context.bot.get_chat(chat_id=user_id).username 26 | 27 | else: 28 | user_id = update.message.from_user.id 29 | name = update.message.from_user.first_name 30 | username = update.message.from_user.username 31 | 32 | return user_id, name, username 33 | 34 | def start(self, update, context): 35 | user_id, name, username = self.common_args(update, context) 36 | 37 | # chat type (group or private) 38 | chat_type = update.message.chat.type 39 | 40 | if chat_type == "private": 41 | try: 42 | check_user = self.record.search(user_id) 43 | if not check_user: 44 | # record insertion 45 | self.record.insert(user_id, name, username) 46 | 47 | # Typing Action 48 | context.bot.send_chat_action(chat_id=user_id, action=ChatAction.TYPING, timeout=1) 49 | # User welcome 50 | update.message.reply_text(text=welcome(name), parse_mode='Markdown') 51 | 52 | if check_user and not check_user.get('gender') and not check_user.get('partner_gender'): 53 | self.settings(update, context) 54 | 55 | # if user stop the bot 56 | except telegram.error.Unauthorized: 57 | pass 58 | 59 | def help(self, update, context): 60 | user_id, name, username = self.common_args(update, context) 61 | 62 | # chat type (group or private) 63 | chat_type = update.message.chat.type 64 | 65 | if chat_type == "private": 66 | try: 67 | # Typing Action 68 | context.bot.send_chat_action(chat_id=user_id, action=ChatAction.TYPING, timeout=1) 69 | 70 | # Help user 71 | update.message.reply_text(text=user_help(), parse_mode='Markdown') 72 | 73 | # if user stop the bot 74 | except telegram.error.Unauthorized: 75 | pass 76 | 77 | def settings(self, update, context): 78 | user_id, name, username = self.common_args(update, context) 79 | 80 | # chat type (group or private) 81 | chat_type = update.message.chat.type 82 | 83 | if chat_type == "private": 84 | try: 85 | # Typing Action 86 | context.bot.send_chat_action(chat_id=user_id, action=ChatAction.TYPING, timeout=1) 87 | 88 | reply_markup = InlineKeyboardMarkup([ 89 | [InlineKeyboardButton(text="🤴🏻 Gender 👸🏻", callback_data='SetGender')] 90 | ]) 91 | 92 | # User info 93 | update.message.reply_text(text="🛠Settings", reply_markup=reply_markup) 94 | 95 | # if user stop the bot 96 | except telegram.error.Unauthorized: 97 | pass 98 | 99 | def partner_selection(self, context, gender_list, opp_gender_list, user_id, gender1, gender2): 100 | 101 | # precaution for same gender 102 | if gender1 == gender2: 103 | if gender_list[0] != user_id: 104 | partner = gender_list[0] 105 | else: 106 | partner = gender_list[1] 107 | else: 108 | partner = opp_gender_list[0] 109 | 110 | # updating user list 111 | gender_list.remove(user_id) 112 | opp_gender_list.remove(partner) 113 | 114 | # updating chat pairs 115 | self.chat_pair.update({user_id: partner}) 116 | self.chat_pair.update({partner: user_id}) 117 | 118 | context.bot.send_message(chat_id=user_id, text=partner_match(gender1)) 119 | context.bot.send_message(chat_id=partner, text=partner_match(gender2)) 120 | 121 | def find_partner(self, update, context): 122 | user_id, name, username = self.common_args(update, context) 123 | 124 | # chat type (group or private) 125 | chat_type = update.message.chat.type 126 | 127 | if chat_type == "private": 128 | # Updating name & username 129 | self.record.update(user_id, {"name": name, "username": username}) 130 | 131 | # user preference 132 | data = self.record.search(user_id) 133 | my_gender = data.get("gender") 134 | partner_gender = data.get("partner_gender") 135 | 136 | if my_gender is None or partner_gender is None: 137 | self.settings(update, context) 138 | else: 139 | try: 140 | # ending previous dialog if any 141 | if user_id in self.chat_pair: 142 | self.end_conversation(update, context) 143 | 144 | if my_gender == "🤴🏻 Boy": 145 | if user_id not in self.boys: 146 | self.boys.append(user_id) 147 | 148 | if partner_gender == "👸🏻 Girl": 149 | if len(self.girls) >= 1: 150 | self.partner_selection(context, gender_list=self.boys, opp_gender_list=self.girls, 151 | user_id=user_id, gender1="Girl", gender2="Boy") 152 | # if NO GIRL is available 153 | elif len(self.boys) >= 2: 154 | self.partner_selection(context, gender_list=self.boys, opp_gender_list=self.boys, 155 | user_id=user_id, gender1="Boy", gender2="Boy") 156 | else: 157 | context.bot.send_message(chat_id=user_id, text=partner_not_found()) 158 | 159 | elif partner_gender == "🤴🏻 Boy": 160 | if len(self.boys) >= 2: 161 | self.partner_selection(context, gender_list=self.boys, opp_gender_list=self.boys, 162 | user_id=user_id, gender1="Boy", gender2="Boy") 163 | # if NO BOY is available 164 | elif len(self.girls) >= 1: 165 | self.partner_selection(context, gender_list=self.boys, opp_gender_list=self.girls, 166 | user_id=user_id, gender1="Girl", gender2="Boy") 167 | else: 168 | context.bot.send_message(chat_id=user_id, text=partner_not_found()) 169 | 170 | elif my_gender == "👸🏻 Girl": 171 | if user_id not in self.girls: 172 | self.girls.append(user_id) 173 | 174 | if partner_gender == "🤴🏻 Boy": 175 | if len(self.boys) >= 1: 176 | self.partner_selection(context, gender_list=self.girls, opp_gender_list=self.boys, 177 | user_id=user_id, gender1="Boy", gender2="Girl") 178 | # if NO BOY is available 179 | elif len(self.girls) >= 2: 180 | self.partner_selection(context, gender_list=self.girls, opp_gender_list=self.girls, 181 | user_id=user_id, gender1="Girl", gender2="Girl") 182 | else: 183 | context.bot.send_message(chat_id=user_id, text=partner_not_found()) 184 | 185 | elif partner_gender == "👸🏻 Girl": 186 | if len(self.girls) >= 2: 187 | self.partner_selection(context, gender_list=self.girls, opp_gender_list=self.girls, 188 | user_id=user_id, gender1="Girl", gender2="Girl") 189 | # if NO GIRL is available 190 | if len(self.boys) >= 1: 191 | self.partner_selection(context, gender_list=self.girls, opp_gender_list=self.boys, 192 | user_id=user_id, gender1="Boy", gender2="Girl") 193 | else: 194 | context.bot.send_message(chat_id=user_id, text=partner_not_found()) 195 | 196 | # if user stop the bot 197 | except telegram.error.Unauthorized: 198 | pass 199 | 200 | def end_conversation(self, update, context): 201 | user_id, name, username = self.common_args(update, context) 202 | 203 | # chat type (group or private) 204 | chat_type = update.message.chat.type 205 | 206 | if chat_type == "private": 207 | try: 208 | # getting user info 209 | data = self.record.search(user_id) 210 | my_gender = data.get("gender") 211 | 212 | if user_id not in self.chat_pair: 213 | # remove instance from list 214 | if my_gender == "🤴🏻 Boy" and user_id in self.boys: 215 | self.boys.remove(user_id) 216 | elif my_gender == "👸🏻 Girl" and user_id in self.girls: 217 | self.girls.remove(user_id) 218 | 219 | # user reply 220 | context.bot.send_message(chat_id=user_id, text=invalid_destroy()) 221 | else: 222 | partner_id = self.chat_pair.get(user_id) 223 | 224 | # update chat pair 225 | del self.chat_pair[user_id] 226 | del self.chat_pair[partner_id] 227 | 228 | context.bot.send_message(chat_id=user_id, text=destroy(who="You")) 229 | context.bot.send_message(chat_id=partner_id, text=destroy(who="Your")) 230 | 231 | # if user stop the bot 232 | except telegram.error.Unauthorized: 233 | pass 234 | 235 | def message_handler(self, update, context): 236 | user_id, name, username = self.common_args(update, context) 237 | 238 | # chat type (group or private) 239 | chat_type = update.message.chat.type 240 | 241 | if chat_type == "private": 242 | try: 243 | if user_id not in self.chat_pair: 244 | # Typing Action 245 | context.bot.send_chat_action(chat_id=user_id, action=ChatAction.TYPING, timeout=1) 246 | context.bot.send_message(chat_id=user_id, text=invalid_destroy()) 247 | else: 248 | partner_id = self.chat_pair.get(user_id) 249 | msg = update.message.text 250 | 251 | # Typing Action 252 | context.bot.send_chat_action(chat_id=partner_id, action=ChatAction.TYPING, timeout=1) 253 | context.bot.send_message(chat_id=partner_id, text=msg) 254 | 255 | # if user stop the bot 256 | except telegram.error.Unauthorized: 257 | self.end_conversation(update, context) 258 | 259 | def media_handler(self, update, context): 260 | # print(update) 261 | user_id, name, username = self.common_args(update, context) 262 | 263 | # chat type (group or private) 264 | chat_type = update.message.chat.type 265 | 266 | if chat_type == "private": 267 | try: 268 | if user_id not in self.chat_pair: 269 | # Typing Action 270 | context.bot.send_chat_action(chat_id=user_id, action=ChatAction.TYPING, timeout=1) 271 | context.bot.send_message(chat_id=user_id, text=invalid_destroy()) 272 | else: 273 | partner_id = self.chat_pair.get(user_id) 274 | caption = update.message.caption 275 | 276 | if update.message.sticker: 277 | # sticker send action 278 | context.bot.send_chat_action(chat_id=partner_id, action=ChatAction.CHOOSE_STICKER, timeout=1) 279 | context.bot.send_sticker(chat_id=partner_id, sticker=update.message.sticker) 280 | 281 | elif update.message.photo: 282 | # image send action 283 | context.bot.send_chat_action(chat_id=partner_id, action=ChatAction.UPLOAD_PHOTO, timeout=1) 284 | if caption: 285 | context.bot.send_photo(chat_id=partner_id, photo=update.message.photo[-1], caption=caption) 286 | else: 287 | context.bot.send_photo(chat_id=partner_id, photo=update.message.photo[-1]) 288 | 289 | elif update.message.video: 290 | # video send action 291 | context.bot.send_chat_action(chat_id=partner_id, action=telegram.ChatAction.UPLOAD_VIDEO) 292 | if caption: 293 | context.bot.send_video(chat_id=partner_id, video=update.message.video, caption=caption) 294 | else: 295 | context.bot.send_video(chat_id=partner_id, video=update.message.video) 296 | 297 | elif update.message.video_note: 298 | # video note send action 299 | context.bot.send_chat_action(chat_id=partner_id, action=ChatAction.RECORD_VIDEO_NOTE, timeout=1) 300 | context.bot.send_video_note(chat_id=partner_id, video_note=update.message.video_note) 301 | 302 | elif update.message.voice: 303 | # voice send action 304 | context.bot.send_chat_action(chat_id=partner_id, action=ChatAction.RECORD_VOICE, timeout=1) 305 | context.bot.send_voice(chat_id=partner_id, voice=update.message.voice) 306 | 307 | elif update.message.audio: 308 | # audio send action 309 | context.bot.send_chat_action(chat_id=partner_id, action=ChatAction.UPLOAD_AUDIO, timeout=1) 310 | context.bot.send_audio(chat_id=partner_id, audio=update.message.audio) 311 | 312 | elif update.message.document: 313 | # document send action 314 | context.bot.send_chat_action(chat_id=partner_id, action=ChatAction.UPLOAD_DOCUMENT, timeout=1) 315 | context.bot.send_document(chat_id=partner_id, document=update.message.document) 316 | 317 | # if user stop the bot 318 | except telegram.error.Unauthorized: 319 | self.end_conversation(update, context) 320 | 321 | def button_handler(self, update, context): 322 | """Parses the CallbackQuery and updates the message text.""" 323 | query = update.callback_query 324 | query.answer() 325 | 326 | # chat info 327 | user_id = update.callback_query.message.chat.id 328 | chat_type = update.callback_query.message.chat.type 329 | 330 | if chat_type == "private": 331 | if "SetGender" in query.data: 332 | 333 | # removing user previous state if present 334 | if user_id in self.boys: 335 | self.boys.remove(user_id) 336 | elif user_id in self.girls: 337 | self.girls.remove(user_id) 338 | 339 | # normal flow 340 | data = self.record.search(user_id) 341 | 342 | my_gender = data.get("gender") 343 | partner_gender = data.get("partner_gender") 344 | 345 | reply_markup = InlineKeyboardMarkup([ 346 | [InlineKeyboardButton(text="👤 Your Gender", callback_data=f'SetMine')], 347 | [InlineKeyboardButton(text="🗣️ Partner's Gender", callback_data=f'SetPartner')], 348 | ]) 349 | 350 | query.edit_message_text( 351 | text=f"Edit your gender or your partner's gender\nyou: {my_gender}\npartner: {partner_gender}", 352 | reply_markup=reply_markup) 353 | 354 | elif "SetMine" in query.data: 355 | data = self.record.search(user_id) 356 | 357 | my_gender = data.get("gender") 358 | 359 | reply_markup = InlineKeyboardMarkup([ 360 | [InlineKeyboardButton(text="🤴🏻 Boy", callback_data=f'SetBoy_M')], 361 | [InlineKeyboardButton(text="👸🏻 Girl", callback_data=f'SetGirl_M')], 362 | ]) 363 | 364 | query.edit_message_text(text=f"Select your gender\nCurrent: {my_gender}", reply_markup=reply_markup) 365 | 366 | elif "SetPartner" in query.data: 367 | data = self.record.search(user_id) 368 | 369 | partner_gender = data.get("partner_gender") 370 | 371 | reply_markup = InlineKeyboardMarkup([ 372 | [InlineKeyboardButton(text="🤴🏻 Boy", callback_data=f'SetBoy_P')], 373 | [InlineKeyboardButton(text="👸🏻 Girl", callback_data=f'SetGirl_P')], 374 | ]) 375 | 376 | query.edit_message_text(text=f"Select partner gender\nCurrent: {partner_gender}", 377 | reply_markup=reply_markup) 378 | 379 | elif "SetBoy" in query.data: 380 | # checking request for user or partner 381 | if str(query.data).split("_")[1] == "M": 382 | new_data = {"gender": "🤴🏻 Boy"} 383 | else: 384 | new_data = {"partner_gender": "🤴🏻 Boy"} 385 | 386 | # update user info 387 | self.record.update(user_id, new_data) 388 | 389 | data = self.record.search(user_id) 390 | my_gender = data.get("gender") 391 | partner_gender = data.get("partner_gender") 392 | 393 | reply_markup = InlineKeyboardMarkup([ 394 | [InlineKeyboardButton(text="👤 Your Gender", callback_data=f'SetMine')], 395 | [InlineKeyboardButton(text="🗣️ Partner's Gender", callback_data=f'SetPartner')], 396 | ]) 397 | 398 | query.edit_message_text( 399 | text=f"Edit your gender or your partner's gender\nyou: {my_gender}\npartner: {partner_gender}", 400 | reply_markup=reply_markup) 401 | 402 | elif "SetGirl" in query.data: 403 | # checking request for user or partner 404 | if str(query.data).split("_")[1] == "M": 405 | new_data = {"gender": "👸🏻 Girl"} 406 | else: 407 | new_data = {"partner_gender": "👸🏻 Girl"} 408 | 409 | # update user info 410 | self.record.update(user_id, new_data) 411 | 412 | data = self.record.search(user_id) 413 | my_gender = data.get("gender") 414 | partner_gender = data.get("partner_gender") 415 | 416 | reply_markup = InlineKeyboardMarkup([ 417 | [InlineKeyboardButton(text="👤 Your Gender", callback_data=f'SetMine')], 418 | [InlineKeyboardButton(text="🗣️ Partner's Gender", callback_data=f'SetPartner')], 419 | ]) 420 | 421 | query.edit_message_text( 422 | text=f"Edit your gender or your partner's gender\nyou: {my_gender}\npartner: {partner_gender}", 423 | reply_markup=reply_markup) 424 | 425 | def sharelink(self, update, context): 426 | user_id, name, username = self.common_args(update, context) 427 | 428 | # chat type (group or private) 429 | chat_type = update.message.chat.type 430 | 431 | if chat_type == "private": 432 | try: 433 | if user_id not in self.chat_pair: 434 | # Typing Action 435 | context.bot.send_chat_action(chat_id=user_id, action=ChatAction.TYPING, timeout=1) 436 | context.bot.send_message(chat_id=user_id, text=invalid_destroy()) 437 | else: 438 | partner_id = self.chat_pair.get(user_id) 439 | 440 | if username is not None: 441 | context.bot.send_message(chat_id=user_id, text=f"Profile shared") 442 | context.bot.send_message(chat_id=partner_id, text=f"@{username}") 443 | else: 444 | context.bot.send_message(chat_id=user_id, text=f"Error: Username not found") 445 | 446 | # if user stop the bot 447 | except telegram.error.Unauthorized: 448 | self.end_conversation(update, context) 449 | 450 | def command_handler(self): 451 | updater = Updater(self.bot_key, use_context=True) 452 | 453 | dp = updater.dispatcher 454 | 455 | dp.add_handler(CommandHandler("start", self.start, run_async=True)) 456 | dp.add_handler(CommandHandler("help", self.help, run_async=True)) 457 | dp.add_handler(CommandHandler("settings", self.settings, run_async=True)) 458 | 459 | dp.add_handler(CommandHandler("next", self.find_partner, run_async=True)) 460 | dp.add_handler(CommandHandler("stop", self.end_conversation, run_async=True)) 461 | 462 | dp.add_handler(CommandHandler("sharelink", self.sharelink, run_async=True)) 463 | 464 | dp.add_handler(MessageHandler(Filters.all, self.media_handler, run_async=True)) 465 | dp.add_handler(CallbackQueryHandler(self.button_handler, run_async=True)) 466 | 467 | updater.start_polling() 468 | updater.idle() 469 | 470 | 471 | if __name__ == '__main__': 472 | bot_name = "Bot" 473 | bot_key = "SECRET KEY" 474 | 475 | ChatBot(bot_name, bot_key) -------------------------------------------------------------------------------- /database.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | import pymongo 3 | import gridfs 4 | import pytz 5 | 6 | 7 | class DataBase: 8 | def __init__(self): 9 | self.dataset, self.storage, self.database = self.connect() 10 | 11 | def connect(self): 12 | mongod = pymongo.MongoClient( 13 | "DataBase URL") 14 | 15 | database = mongod["TABLE"] 16 | 17 | dataset = database["COLLECTION"] 18 | 19 | storage = gridfs.GridFS(database) 20 | 21 | return dataset, storage, database 22 | 23 | def search(self, user_id=None, allEntry=None): 24 | if allEntry: 25 | result = self.dataset.find() 26 | else: 27 | result = self.dataset.find_one({"_id": user_id}) 28 | 29 | return result 30 | 31 | def insert(self, user_id, name, username): 32 | # time-stamp 33 | IST = pytz.timezone('Asia/Kolkata') 34 | time_stamp = datetime.now(IST).strftime('%Y-%m-%d || %H:%M:%S') 35 | 36 | self.dataset.insert_one({"_id": user_id, 37 | "name": name, 38 | "username": username, 39 | "timestamp": time_stamp}) 40 | 41 | def update(self, user_id, new_data): 42 | self.dataset.update_one({"_id": user_id}, {"$set": new_data}) -------------------------------------------------------------------------------- /info.py: -------------------------------------------------------------------------------- 1 | def welcome(name): 2 | return f"""Hey {name}🖐\n 3 | Send me text, links, gifs, stickers, photos, videos or voice messages and I will anonymously forward them to your partner 4 | 5 | Commands 6 | /start - start the bot 7 | /help - show help guide 8 | /next — find a new partner 9 | /stop — stop the dialog 10 | /settings - settings menu 11 | /report - Report a message 12 | """ 13 | 14 | 15 | def user_help(): 16 | return """With this bot you can chat with Guys and Girls anonymously based on your preferences of age, gender. 17 | 18 | Commands 19 | /start - start the bot 20 | /next — find a new partner 21 | /stop — stop this dialog 22 | /settings - settings menu 23 | /sharelink - share profile to partner 24 | /report - Report a message 25 | /help - show the guide 26 | 27 | """ 28 | 29 | 30 | def partner_match(gender): 31 | if gender == "Boy": 32 | partner = "🤴🏻 Boy" 33 | else: 34 | partner = "👸🏻 Girl" 35 | 36 | return f"""Partner: {partner} 37 | /next — find a new partner 38 | /stop — stop this dialog""" 39 | 40 | 41 | def partner_not_found(): 42 | return """🔎 Searching for a partner""" 43 | 44 | 45 | def destroy(who=None): 46 | if who == "You": 47 | return """You stopped the dialog 🙄 48 | Type /next to find a new partner 49 | """ 50 | elif who == "Your": 51 | return """Your partner has stopped the dialog 😞 52 | Type /next to find a new partner 53 | """ 54 | 55 | 56 | def invalid_destroy(): 57 | return """You have no partner 🤔 58 | Type /next to find a new partner""" 59 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # TeleGram AnonymousChatBot 2 | 3 | Intro 4 | -------- 5 | This ChatBot is Telegram version of [omegle](http://www.omegle.com) 6 | 7 | Dependancies 8 | ------------- 9 | In order to run this code you're supposed to have **python-telegram-bot**, **pymongo** and **pytz** libary installed 10 | on your machine, you can just use *pip* command to this. 11 | 12 | ```bash 13 | -> pip3 install -r requirements.txt 14 | ``` 15 | 16 | Bot WorkFlow 17 | ----------- 18 | 19 | ```mermaid 20 | graph TD; 21 | A((Start)):::entryPoint --> |Bot Welcome Text|B{Action} 22 | 23 | B --> C1[Help] 24 | B --> C2{Settings} 25 | B --> C3{Find Partner} 26 | B --> C4{Share Profile} 27 | 28 | C1 --> C1A{{List of commands with usage}} 29 | 30 | C2 --> D[Set Gender] 31 | D --> D1[Set Your Gender] 32 | D --> D2[Set Partner's Gender] 33 | 34 | D1 --> E1[Male] 35 | D1 --> E2[Female] 36 | 37 | D2 --> E1[Male] 38 | D2 --> E2[Female] 39 | 40 | C3 --> |If: Gender selection done| C3A{Condition} 41 | C3A --> C3B1[NO] 42 | C3A --> C3B2[YES] 43 | 44 | C3B1 --> D 45 | C3B2 --> |Random partner based on prefrence| C3B2A{Condition} 46 | C3B2A --> |Not Available|C3B2A1[NO] 47 | C3B2A --> |Available|C3B2A2[YES] 48 | 49 | C3B2A1 --> C3B2A1A{{Temp Msg: Looking for partner's}} 50 | C3B2A2 --> |Partner Choosen|C3B2A2A{{Conversation started}} 51 | 52 | C3B2A2A --> C3B2A2A1((End)):::termination 53 | 54 | C4 -->C4A{Condition} 55 | C4A --> |Not Connected|C4B1[NO] 56 | C4A --> |Connected|C4B2[YES] 57 | 58 | C4B1 --> C4B1A{{Error: User not connected}} 59 | C4B2 --> C4B1B{{Profile Shared}} 60 | 61 | 62 | classDef entryPoint fill:#009c11, stroke:#42FF57, color:#ffffff 63 | classDef termination fill:#bb0007, stroke:#E60109, color:#ffffff 64 | ``` 65 | 66 | ## Project Structure 67 | ``` 68 | |-- app.py 69 | |-- info.py 70 | |-- database.py 71 | |-- readme.md 72 | |-- requirements.txt 73 | ``` 74 | 75 | Give it a star 76 | -------------- 77 | Did you find this information useful, then give it a star 78 | 79 | 80 | Credits 81 | ----------- 82 | All the credits to [mramitdas](https://github.com/mramitdas) 83 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | APScheduler==3.6.3 2 | cachetools==4.2.2 3 | certifi==2022.6.15 4 | dnspython==2.2.1 5 | pymongo==4.1.1 6 | python-telegram-bot==13.13 7 | pytz==2022.1 8 | pytz-deprecation-shim==0.1.0.post0 9 | six==1.16.0 10 | tornado==6.2 11 | tzdata==2022.1 12 | tzlocal==4.2 13 | --------------------------------------------------------------------------------