def decrypt(bot, update): config = Configuration() uid = update.message.from_user.id try: application_key = update.message.text application_key = application_key.strip() if not application_key: message = "Enter a proper key!\nDo you want to try again? (Yes/No)" update.message.reply_text(message, parse_mode="Markdown") return ENTERKEY else: print(uid) user_in_db = db_interface.get_user(uid) print(user_in_db) username = user_in_db.user_name decrypted_password = Encrypt( user_in_db.encrypted_pass, application_key ).decrypt() if not decrypted_password: message = "A wrong application key has been entered\nDo you want to try again? (Yes/No)" update.message.reply_text(message, parse_mode="Markdown") return ENTERKEY # passes into celery. No longer my problem. config = Configuration() update_class = config.CELERY_INSTANCE.signature( "Controllers.celery_queue.update_user" ) """ def update_user( telegram_id:str, user_name:str, password:str, bot ): """ r = config.REDIS_INSTANCE r.set(uid, 1) update_class.delay( uid, username, decrypted_password, jsonpickle.encode(bot) ) message = "Your details have been enqueued for scraping!\nThis process might take up to 5 minutes, please wait for the results." update.message.reply_text(message, parse_mode="Markdown") return ConversationHandler.END except Exception as e: update.message.reply_text("Unknown error occured", parse_mode="Markdown") local = arrow.utcnow().to("Asia/Singapore") local_time = local.format("YYYY-MM-DD HH:mm:ss ZZ") bot.send_message( chat_id=config.ERROR_CHANNEL, text=f"An error occured at {local_time}" ) bot.send_message( chat_id=config.ERROR_CHANNEL, text=f"The error was: {traceback.format_exc()}", ) bot.send_message( chat_id=config.ERROR_CHANNEL, text=f"This message was triggered in get timetable by {uid}.", ) return ConversationHandler.END
def megaphone(bot, update): uid = update.message.from_user.id config = Configuration() try: message = update.message.text[6:] if str(uid) in config.ADMIN_LIST: list_of_ids = db_interface.get_all_telegram_ids() count = 0 for id in list_of_ids: try: bot.send_message(chat_id=id, text=message, parse_mode="HTML") count += 1 except Unauthorized: pass bot.send_message(chat_id=config.ERROR_CHANNEL, text=f"{count} messages megaphoned") else: update.message.reply_text("You are not an administrator!") except Exception as e: local = arrow.utcnow().to("Asia/Singapore") local_time = local.format("YYYY-MM-DD HH:mm:ss ZZ") bot.send_message(chat_id=config.ERROR_CHANNEL, text=f"An error occured at {local_time}") bot.send_message( chat_id=config.ERROR_CHANNEL, text=f"The error was: {traceback.format_exc()}", ) bot.send_message( chat_id=config.ERROR_CHANNEL, text=f"This message was triggered in megaphone.", )
def help(bot, update): config = Configuration() try: cid = update.message.chat_id message_id = update.message.message_id hm = HelpMessage() msg = hm.get_help_message() print(f"hm:{msg}") bot.send_message( chat_id=cid, text=msg, disable_web_page_preview=True, reply_to_message_id=message_id, parse_mode="Markdown", ) except Exception as e: local = arrow.utcnow().to("Asia/Singapore") local_time = local.format("YYYY-MM-DD HH:mm:ss ZZ") bot.send_message( chat_id=config.ERROR_CHANNEL, text=f"An error occured at {local_time}" ) bot.send_message( chat_id=config.ERROR_CHANNEL, text=f"The error was: {traceback.format_exc()}", ) bot.send_message( chat_id=config.ERROR_CHANNEL, text=f"This message was triggered in help." )
def morning_alert(bot, update): config = Configuration() try: user_list = db_interface.get_all_users_alert("morning") for user in user_list: # cur_dt = datetime.now().replace(hour=0, minute=0, second=0) list_of_cur_classes = user.get_list_of_class_by_date( datetime.now().date()) rm = ReminderMessage( list_of_cur_classes, "Morning", user.name, datetime.strftime(datetime.now(), "%b %d %Y"), ) msg = rm.get_message() bot.send_message(chat_id=user.telegram_id, text=msg, parse_mode="Markdown") except Exception as e: local = arrow.utcnow().to("Asia/Singapore") local_time = local.format("YYYY-MM-DD HH:mm:ss ZZ") bot.send_message(chat_id=config.ERROR_CHANNEL, text=f"An error occured at {local_time}") bot.send_message( chat_id=config.ERROR_CHANNEL, text=f"The error was: {traceback.format_exc()}", ) bot.send_message( chat_id=config.ERROR_CHANNEL, text=f"This message was triggered in morning reminder.", )
def toggle_night(bot, update): uid = update.message.from_user.id config = Configuration() try: if db_interface.user_exist(uid): if db_interface.toggle_alert(uid, False): message = "Nightly alert has been sucessfully *enabled*!" else: message = "Nightly alert has been sucessfully *disabled*!" update.message.reply_text(message, parse_mode="Markdown") else: message_array = ["You are not registered!\n"] message_array.append("Would you like to register using /register?") message = "".join(message_array) update.message.reply_text(message, parse_mode="Markdown") except Exception as e: local = arrow.utcnow().to("Asia/Singapore") local_time = local.format("YYYY-MM-DD HH:mm:ss ZZ") bot.send_message(chat_id=config.ERROR_CHANNEL, text=f"An error occured at {local_time}") bot.send_message( chat_id=config.ERROR_CHANNEL, text=f"The error was: {traceback.format_exc()}", ) bot.send_message( chat_id=config.ERROR_CHANNEL, text= f"This message was triggered in nightly reminder toggle. Triggered by: {uid}", )
def get_today(bot, update): uid = update.message.from_user.id config = Configuration() try: if db_interface.user_exist(uid): current_date = datetime.now(pytz.timezone("Asia/Singapore")).date() # sets time to midnight. current_date = datetime.combine(current_date, time()) # gets a list of IndividualClassStructure objects. classes_list = db_interface.get_current_class( uid, current_date, current_date) # sorts by start time classes_list.sort(key=lambda x: x.start_time) lsd = db_interface.get_last_sync_date(uid) mt = MessageTimetable(None, lsd) for c in classes_list: mt.add_class_list(c.class_numeric_day, c) formatted_message = mt.get_today() update.message.reply_text( formatted_message, disable_web_page_preview=True, quote=True, parse_mode="Markdown", ) else: message_array = [ f"Unable to find telegram ID {uid} in our database\n" ] message_array.append( "Kindly register using /register before attempting to retrieve a timetable." ) message = "".join(message_array) update.message.reply_text(message, parse_mode="Markdown") except Exception as e: print(str(e)) local = arrow.utcnow().to("Asia/Singapore") local_time = local.format("YYYY-MM-DD HH:mm:ss ZZ") bot.send_message(chat_id=config.ERROR_CHANNEL, text=f"An error occured at {local_time}") bot.send_message( chat_id=config.ERROR_CHANNEL, text=f"The error was: {traceback.format_exc()}", ) bot.send_message( chat_id=config.ERROR_CHANNEL, text=f"This message was triggered in get today timetable by {uid}.", )
def start_register(bot, update): """ Kickstarts registeration process. Gets name and subsequently passes it to the next handler in process. """ try: config = Configuration() # gets the telegram ID tg_id = update.message.from_user.id # Checks the database for the user ID message_array = [] if not db_interface.user_exist(tg_id): r = config.REDIS_INSTANCE if not r.get(tg_id): message_array.append( "Hi! Let's get started by registering with this bot\n" ) message_array.append( "❇️By using this bot, you hereby declare that you have read the documentation and disclaimer on github.\n" ) message_array.append( "❇️*As such, you release the author from any responsibilities of events incurred by the usage of this bot*\n" ) message_array.append( "❇️At any point of time during this process, you can stop the bot by typing /cancel\n" ) message_array.append("Now, can I have your *name*?") message = "".join(message_array) update.message.reply_text(message, parse_mode="Markdown") # instructs the chatbox to move to the next method. return NAME else: message_array.append("You are already enqueued!\n") message_array.append( "If you are encountering issues, please pm @fatalityx directly." ) message = "".join(message_array) update.message.reply_text(message, parse_mode="Markdown") return ConversationHandler.END else: message_array.append("You are already registered!\n") message_array.append( "If you have forgotten your application key, please use /forget to clear your information and re-register." ) message = "".join(message_array) update.message.reply_text(message, parse_mode="Markdown") return ConversationHandler.END except Exception as e: print(str(e)) # To be changed. return ConversationHandler.END
def get_ics(bot, update): print("Get ICS method called") config = Configuration() is_callback = False if not update.message: uid = update.callback_query.from_user.id is_callback = True else: uid = update.message.from_user.id try: if db_interface.user_exist(uid): print("DB Interface exists") filepath = f"./ics/{uid}.ics" # Gets a list of classes classes_list = db_interface.get_all_classes(uid) print(classes_list) ics_model = ICSParser(classes_list) ics_model.convert_to_event() with open(filepath, "w") as f: f.writelines(ics_model.calendar) # sends the message bot.send_document(chat_id=uid, document=open(filepath, "rb")) else: message_array = [ f"Unable to find telegram ID {uid} in our database\n" ] message_array.append( "Kindly register using /register before attempting to retrieve a timetable." ) message = "".join(message_array) update.message.reply_text(message, parse_mode="Markdown") except Exception as e: print(str(e)) local = arrow.utcnow().to("Asia/Singapore") local_time = local.format("YYYY-MM-DD HH:mm:ss ZZ") bot.send_message(chat_id=config.ERROR_CHANNEL, text=f"An error occured at {local_time}") bot.send_message( chat_id=config.ERROR_CHANNEL, text=f"The error was: {traceback.format_exc()}", ) bot.send_message( chat_id=config.ERROR_CHANNEL, text=f"This message was triggered in get timetable by {uid}.", )
def application_key(bot, update, user_data): try: user_input_application_key = update.message.text user_input_application_key = user_input_application_key.strip() if len(user_input_application_key) <= 16: user_data["application_key"] = user_input_application_key config = Configuration() """ci = Celery( 'queue', broker='amqp://', backend='rpc://', include=['Controllers.celery_queue'] )""" cel_reg = config.CELERY_INSTANCE.signature( "Controllers.celery_queue.register_user" ) # marks the user as already using the queue in redis. r = config.REDIS_INSTANCE r.set(user_data["user_id"], 1) # Starts a celery task cel_reg.delay(user_data, jsonpickle.encode(bot)) message_array = ["Your details have been enqueued for scraping!\n"] message_array.append( f"You are currently position {len(r.keys())} in the queue.\n" ) message_array.append( "This process might take up to 5 minutes, please wait for the results." ) message = "".join(message_array) update.message.reply_text(message, parse_mode="Markdown") return ConversationHandler.END else: if not user_input_application_key: message = "Please enter an application key" else: message = "Please enter an encryption key that is under 17 characters." update.message.reply_text(message, parse_mode="Markdown") return KEY except Exception as e: print(str(e)) return ConversationHandler.END
def update_user(telegram_id: str, user_name: str, password: str, bot): config = Configuration() r = config.REDIS_INSTANCE bot = jsonpickle.decode(bot) try: list_of_classes = get_timetable(user_name, password, telegram_id, bot) dbInterface.update_classes(list_of_classes, telegram_id) message = ( f"A total of *{len(list_of_classes)}* records were resynced to the database" ) r.delete(telegram_id) bot.send_message(chat_id=telegram_id, text=message, parse_mode="Markdown") except UnableToLogin: # Unable to login with given credentials. # new_ripper attempts to login and raises an UnableToLogin exception # if it cant be logged in. error_message = ["Unable to login with your credentials!\n"] error_message.append( "Please try to wipe your details and register again using /register" ) err = "".join(error_message) r.delete(telegram_id) bot.send_message(chat_id=telegram_id, text=err, parse_mode="Markdown") except Exception as e: local = arrow.utcnow().to("Asia/Singapore") local_time = local.format("YYYY-MM-DD HH:mm:ss ZZ") bot.send_message(chat_id=config.ERROR_CHANNEL, text=f"An error occured at {local_time}") bot.send_message( chat_id=config.ERROR_CHANNEL, text=f"The error was: {traceback.format_exc()}", ) bot.send_message( chat_id=config.ERROR_CHANNEL, text= f"This message was triggered in celery. Triggered by: {telegram_id}", ) r.delete(telegram_id) pass
def enter_key(bot, update): config = Configuration() try: message = "Please enter your decryption key\n" update.message.reply_text(message, parse_mode="Markdown") return DECRYPT except Exception as e: local = arrow.utcnow().to("Asia/Singapore") local_time = local.format("YYYY-MM-DD HH:mm:ss ZZ") bot.send_message( chat_id=config.ERROR_CHANNEL, text=f"An error occured at {local_time}" ) bot.send_message( chat_id=config.ERROR_CHANNEL, text=f"The error was: {traceback.format_exc()}", ) bot.send_message( chat_id=config.ERROR_CHANNEL, text=f"This message was triggered in enter your decryption key.", ) return ConversationHandler.END
def update(bot, update): """ confirms that the update is meant to be handled. """ config = Configuration() try: uid = update.message.from_user.id if not db_interface.user_exist(uid): update.message.reply_text("You are not registered! Please register first") return ConversationHandler.END r = config.REDIS_INSTANCE if r.get(uid): update.message.reply_text("You are already enqueued in the queue!") return ConversationHandler.END message_array = ["Do you want to update your timetable?\n"] message_array.append("❇️This will erase *all* previous timetable schedules\n") message_array.append("❇️Please reply with a yes or no\n") message_array.append("❇️To exit this state, please use /cancel\n") message = "".join(message_array) update.message.reply_text(message, parse_mode="Markdown") return ENTERKEY except Exception as e: local = arrow.utcnow().to("Asia/Singapore") local_time = local.format("YYYY-MM-DD HH:mm:ss ZZ") bot.send_message( chat_id=config.ERROR_CHANNEL, text=f"An error occured at {local_time}" ) bot.send_message( chat_id=config.ERROR_CHANNEL, text=f"The error was: {traceback.format_exc()}", ) bot.send_message( chat_id=config.ERROR_CHANNEL, text=f"This message was triggered in get timetable by {uid}.", ) return ConversationHandler.END
def __init__(self): self.__config = Configuration() self.__flush_redis_cache() q = mq.MessageQueue( all_burst_limit=30, all_time_limit_ms=1000, group_burst_limit=20, group_time_limit_ms=60000, exc_route=None, autostart=True, ) # set connection pool size for bot request = Request(con_pool_size=8) self.__queue_bot = MQBot(self.__config.BOT_API_KEY, request=request, mqueue=q) self.__updater = Updater(bot=self.__queue_bot) self.__dp = self.__updater.dispatcher self.__jq = self.__updater.job_queue self.__reg() self.__update() self.__forget() self.__timetable() self.__ics() self.__fuck() self.__cbq() self.__mega() self.__alert() self.__nightly() self.__toggles() self.__help() self.__today() self.__test_alert() self.start_webhooks() # must always come last. print("Bot online") print(f"Current Time: {datetime.now()}")
def register_user(user_data: Dict, bot): config = Configuration() r = config.REDIS_INSTANCE user_id = user_data["user_id"] try: bot = jsonpickle.decode(bot) username = user_data["username"] password = user_data["password"] name = user_data["name"] user_input_application_key = user_data["application_key"] encrypted_password = Encrypt(user_data["password"], user_input_application_key).encrypt() try: timetable_result = get_timetable(username, password, user_id, bot) print(f"Classes retrieved: {len(timetable_result)}") # Now, let us begin constructing our database insertion object. obj_to_insert = UserObject(user_id, username, name, encrypted_password) obj_to_insert.add_classes(timetable_result) dbInterface.insert_new_user(obj_to_insert) success_message = [ f"A total of {obj_to_insert.get_class_leng()} records have been synced to the database\n" ] success_message.append( "You can now use /timetable to retrieve your timetable\n") success_message.append( "In addition, please take note of the following handlers:\n") success_message.append( "```Daily reminder at 7am in the morning - /alert ```\n") success_message.append( "```Nightly reminder at 10pm at night - /nightly ```\n") success_message.append("Both of these handlers act as a toggle.") message = "".join(success_message) r.delete(user_id) bot.send_message(chat_id=user_id, text=message, parse_mode="Markdown") except UnableToLogin: # Unable to login with given credentials. # new_ripper attempts to login and raises an UnableToLogin exception # if it cant be logged in. error_message = ["Unable to login with your credentials!\n"] error_message.append( "Please try to register again using /register") err = "".join(error_message) r.delete(user_id) bot.send_message(chat_id=user_id, text=err, parse_mode="Markdown") except Exception as e: # to send to github local = arrow.utcnow().to("Asia/Singapore") local_time = local.format("YYYY-MM-DD HH:mm:ss ZZ") bot.send_message(chat_id=config.ERROR_CHANNEL, text=f"An error occured at {local_time}") bot.send_message( chat_id=config.ERROR_CHANNEL, text=f"The error was: {traceback.format_exc()}", ) bot.send_message( chat_id=config.ERROR_CHANNEL, text= f"This message was triggered in celery. User data: {str(user_data)}", ) r.delete(user_id) pass
def get_timetable(bot, update): config = Configuration() is_callback = False if not update.message: uid = update.callback_query.from_user.id is_callback = True else: uid = update.message.from_user.id try: if db_interface.user_exist(uid): # if its not a callback type: if not is_callback: current_date = date.today() # sets time to midnight. current_date = datetime.combine(current_date, time()) else: # if it is a callback query = update.callback_query current_date = datetime.strptime(query.data[2:], "%b%d%Y") start_date = current_date - timedelta(days=current_date.weekday()) end_date = start_date + timedelta(days=6) # gets a list of IndividualClassStructure objects. classes_list = db_interface.get_current_class( uid, start_date, end_date) # sorts by start time classes_list.sort(key=lambda x: x.start_time) lsd = db_interface.get_last_sync_date(uid) # prepares the message timetable object cur_week = datetime.strftime( (current_date - timedelta(days=current_date.weekday())), "%b %d %Y") print(cur_week) mt = MessageTimetable(cur_week, lsd) for c in classes_list: mt.add_class_list(c.class_numeric_day, c) formatted_message = mt.get_message() # prepares the keyboard. reply_kb = get_keyboard(uid, current_date, start_date, end_date) reply_markup = InlineKeyboardMarkup(reply_kb) # sends the message if is_callback: bot.edit_message_text( text=formatted_message, chat_id=update.callback_query.message.chat_id, message_id=update.callback_query.message.message_id, disable_web_page_preview=True, reply_markup=reply_markup, parse_mode="Markdown", ) else: update.message.reply_text( formatted_message, reply_markup=reply_markup, disable_web_page_preview=True, quote=True, parse_mode="Markdown", ) else: message_array = [ f"Unable to find telegram ID {uid} in our database\n" ] message_array.append( "Kindly register using /register before attempting to retrieve a timetable." ) message = "".join(message_array) update.message.reply_text(message, parse_mode="Markdown") except Exception as e: print(str(e)) local = arrow.utcnow().to("Asia/Singapore") local_time = local.format("YYYY-MM-DD HH:mm:ss ZZ") bot.send_message(chat_id=config.ERROR_CHANNEL, text=f"An error occured at {local_time}") bot.send_message( chat_id=config.ERROR_CHANNEL, text=f"The error was: {traceback.format_exc()}", ) bot.send_message( chat_id=config.ERROR_CHANNEL, text=f"This message was triggered in get timetable by {uid}.", )
def __init__(self): self.__cfg = Configuration() # Instantiated only ONCE will reuse throughout connection self.__mongo = MongoClient(self.__cfg.MONGOURI) self.__db = self.__mongo.timetable
def __init__(self): self.__cfg = Configuration()