def authorize_admin(update, CallbackContext) -> None: global bot args = CallbackContext.args chatid = update.message.chat_id if len(args) != 1: send_message( chatid, "You need to specify the admin password, use the command like /authorize_admin <b>password</b>", bot, html=True ) return elif admin_pw == "": send_message( chatid, "The admin is disabled, check your telegram bot configuration", bot ) return if Utils.admin_check(chatid): send_message(chatid, "You already are an admin", bot) elif args[0] == admin_pw: Utils.exec_query(f"""INSERT INTO ADMIN VALUES ({chatid})""") send_message(chatid, "Admin enabled", bot) send_message(chatid, "Remember to disable the --admin-password if you want to avoid people trying to bruteforce this command", bot) logging.info(f"{chatid} got admin authorization") else: send_message(chatid, "The password is wrong", bot)
def send_message_to_everyone(update, CallbackContext) -> None: global bot args = CallbackContext.args chatid = update.message.chat_id if Utils.admin_check(chatid) == False: send_message(chatid, "You're not authorized to do this", bot) return chatid_list = [] message = "" start_time = datetime.datetime.now() logging.info(f"{chatid} started sending a message to everyone") results = Utils.retrieve_query_results("SELECT DISTINCT CHAT_ID FROM CHATURBATE") for row in results: chatid_list.append(row[0]) for word in args: message += f"{word} " message = message[:-1] for x in chatid_list: send_message(x, message, bot) logging.info( f"{chatid} finished sending a message to everyone, took {(datetime.datetime.now() - start_time).total_seconds()} seconds")
def settings(update, context): global bot global settings_menu_keyboard chatid = update.effective_chat.id message_markup = InlineKeyboardMarkup(settings_menu_keyboard) Link_preview_setting = Preferences.get_user_link_preview_preference(chatid) Link_preview_setting = Utils.bool_to_status(Link_preview_setting) Notifications_sound_setting = Preferences.get_user_notifications_sound_preference( chatid) Notifications_sound_setting = Utils.bool_to_status( Notifications_sound_setting) settings_message = f"Here are your settings:\nLink preview: <b>{Link_preview_setting}</b>\nNotifications: <b>{Notifications_sound_setting}</b>" if update.callback_query: update.callback_query.edit_message_text( text=settings_message, reply_markup=message_markup, parse_mode=telegram.ParseMode.HTML) else: send_message(chatid, settings_message, bot, markup=message_markup, html=True)
def remove_user_from_preferences(chatid: str) -> None: """ Remove the chatid from the preference table :param chatid: The chatid of the user who will be removed """ Utils.exec_query(f"DELETE FROM PREFERENCES WHERE CHAT_ID='{chatid}'") logging.info(f'{chatid} has been removed from preferences')
def add_user_to_preferences(chatid: str) -> None: """ Add user to the preference table :param chatid: The chatid of the user who will be tested """ Utils.exec_query(f"INSERT INTO PREFERENCES VALUES ('{chatid}', '1', '1')") logging.info(f'{chatid} has been added to preferences')
def view_stream_image_callback(update, CallbackContext): username = CallbackContext.match.string.replace("view_stream_image_callback_", "") chatid = update.callback_query.message.chat_id messageid = update.callback_query.message.message_id if Utils.is_chatid_temp_banned(chatid): return model_instance = Model(username) keyboard = [[InlineKeyboardButton("Watch the live", url=f'http://chaturbate.com/{username}'), InlineKeyboardButton("Update stream image", callback_data='view_stream_image_callback_' + username)]] markup = InlineKeyboardMarkup(keyboard) try: bot.edit_message_media(chat_id=chatid, message_id=messageid, media=telegram.InputMediaPhoto(model_instance.model_image,caption=f"{username} is now <b>online</b>!",parse_mode=telegram.ParseMode.HTML), reply_markup=markup) except Exceptions.ModelPrivate: send_message(chatid, f"The model {username} is in private now, try again later", bot) logging.warning(f'{chatid} could not view {username} image update because is private') except Exceptions.ModelAway: send_message(chatid, f"The model {username} is away, try again later", bot) logging.warning(f'{chatid} could not view {username} image update because is away') except Exceptions.ModelPassword: send_message(chatid, f"The model {username} cannot be seen because is password protected", bot) logging.warning(f'{chatid} could not view {username} image update because is password protected') except (Exceptions.ModelDeleted, Exceptions.ModelBanned, Exceptions.ModelGeoblocked, Exceptions.ModelCanceled, Exceptions.ModelOffline): keyboard = [[InlineKeyboardButton("Watch the live", url=f'http://chaturbate.com/{username}')]] markup = InlineKeyboardMarkup(keyboard) bot.edit_message_reply_markup(chat_id=chatid, message_id=messageid, reply_markup=markup) #remove update image button send_message(chatid, f"The model {username} cannot be seen because is {model_instance.status}", bot) logging.warning(f'{chatid} could not view {username} image update because is {model_instance.status}') except Exceptions.ModelNotViewable: send_message(chatid, f"The model {username} is not visible", bot) logging.warning(f'{chatid} could not view {username} image update') except ConnectionError: send_message(chatid, f"The model {username} cannot be seen because of connection issues, try again later", bot) logging.warning(f'{chatid} could not view {username} image update because of connection issues') except Exception as e: if hasattr(e, 'message'): if "Message is not modified" in e.message: send_message(chatid, f"This is the latest update of {username}", bot) if not Utils.admin_check(chatid): if Utils.get_last_spam_date(chatid)==None: Utils.set_last_spam_date(chatid, datetime.datetime.now()) elif (datetime.datetime.now()-Utils.get_last_spam_date(chatid)).total_seconds() <= 3: Utils.temp_ban_chatid(chatid, 25) send_message(chatid, "You have been temporarily banned for spamming, try again later", bot) logging.warning(f"Soft banned {chatid} for 25 seconds for spamming image updates") else: Utils.set_last_spam_date(chatid, datetime.datetime.now())
def active_models(update, CallbackContext) -> None: global bot chatid = update.message.chat_id if Utils.admin_check(chatid) == False: send_message(chatid, "You're not authorized to do this", bot) return models_count = Utils.retrieve_query_results("SELECT COUNT(DISTINCT USERNAME) FROM CHATURBATE")[0][0] send_message(chatid,f"The active models are {models_count}",bot)
def active_users(update, CallbackContext) -> None: global bot chatid = update.message.chat_id if Utils.admin_check(chatid) == False: send_message(chatid, "You're not authorized to do this", bot) return users_count = Utils.retrieve_query_results("SELECT COUNT(CHAT_ID) FROM PREFERENCES")[0][0] send_message(chatid,f"The active users are {users_count}",bot)
def update_model_image(self): """ Updates self.image :raise ModelOffline if self.status is 'offline' :raise ModelAway if self.status is 'away' :raise ModelPrivate if self.status is 'private' or 'hidden' :raise ModelPassword if self.status is 'password' :raise ModelDeleted if self.status is 'deleted' :raise ModelBanned if self.status is 'banned' :raise ModelGeoblocked if self.status is 'geoblocked' :raise ModelCanceled if self.status is 'canceled' :raise ModelNotViewable if any other error happens """ if self.online and self.status not in { "away", "private", "hidden", "password" }: attempt_count = 0 for attempt in range(5): try: data = requests.get( f'https://roomimg.stream.highwebmedia.com/ri/{self.username}.jpg' ).content bio_data = io.BytesIO(data) self.model_image = bio_data except Exception as e: Utils.handle_exception(e) attempt_count += 1 logging.info(self.username + " has failed to obtain image on attempt " + str(attempt)) time.sleep(1) # sleep and retry else: break if attempt_count == 5: logging.info(self.username + " has failed to obtain image after all attempts") raise ConnectionError elif self.status == "offline": raise Exceptions.ModelOffline elif self.status == "away": raise Exceptions.ModelAway elif self.status in {"private", "hidden"}: raise Exceptions.ModelPrivate elif self.status == "password": raise Exceptions.ModelPassword elif self.status == "deleted": raise Exceptions.ModelDeleted elif self.status == "banned": raise Exceptions.ModelBanned elif self.status == "geoblocked": raise Exceptions.ModelGeoblocked elif self.status == "canceled": raise Exceptions.ModelCanceled else: raise Exceptions.ModelNotViewable
def update_link_preview_preference(chatid: str, value: bool) -> None: """ Update the link_preview preference of the user :param chatid: The chatid of the user who will be tested :param value: The boolean value that will be converted to int and inserted in the table """ if value: value = 1 else: value = 0 Utils.exec_query( f"UPDATE PREFERENCES SET LINK_PREVIEW='{value}' WHERE CHAT_ID='{chatid}'" )
def update_notifications_sound_preference(chatid: str, value: bool) -> None: """ Update the notifications preference of the user :param chatid: The chatid of the user who will be tested :param value: The boolean value that will be converted to int and inserted in the table """ if value: value = 1 else: value = 0 Utils.exec_query( f"UPDATE PREFERENCES SET NOTIFICATIONS_SOUND='{value}' WHERE CHAT_ID='{chatid}'" )
def remove(update, context) -> None: global bot args = context.args chatid = update.message.chat_id username_message_list = [] usernames_in_database = [] if len(args) < 1: send_message( chatid, "You need to specify an username to follow, use the command like /remove <b>test</b>\n You can also remove multiple users at the same time by separating them using a comma, like /remove <b>username1</b>,<b>username2</b>", bot, html=True) return if len(args) > 1: for username in args: if username != "": username_message_list.append( Utils.sanitize_username(username).replace(",", "")) # len(args)==0 -> only one username or all in one line elif "," in args[0].lower(): for splitted_username in args[0].lower().replace( " ", "").rstrip().split(","): if splitted_username != "": username_message_list.append( Utils.sanitize_username(splitted_username)) else: username_message_list.append(Utils.sanitize_username(args[0])) usernames_in_database = Utils.alchemy_instance.session.query( ChaturbateUser).filter_by(chat_id=str(chatid)).all() if "all" in username_message_list: Utils.alchemy_instance.session.query(ChaturbateUser).filter_by( chat_id=str(chatid)).all().delete(synchronize_session=False) Utils.alchemy_instance.session.commit() send_message(chatid, "All usernames have been removed", bot) logging.info(f"{chatid} removed all usernames") else: for username in username_message_list: if username in usernames_in_database: Utils.alchemy_instance.session.query(ChaturbateUser).filter_by( chat_id=str(chatid), username=str(username)).delete(synchronize_session=False) send_message(chatid, f"{username} has been removed", bot) logging.info(f"{chatid} removed {username}") else: send_message(chatid, f"You aren't following {username}", bot)
def send_message_to_everyone(update, context) -> None: global bot args = context.args chatid = update.message.chat_id if not Utils.admin_check(chatid): send_message(chatid, "You're not authorized to do this", bot) return chatid_list = [] message = "" start_time = datetime.datetime.now() logging.info(f"{chatid} started sending a message to everyone") chatid_list = Utils.alchemy_instance.session.query( PreferenceUser).filter_by(chat_id=str(chatid)).all() for word in args: message += f"{word} " message = message[:-1] for x in chatid_list: send_message(x.chat_id, message, bot) logging.info( f"{chatid} finished sending a message to everyone, took {(datetime.datetime.now() - start_time).total_seconds()} seconds" )
def list_command(update, CallbackContext) -> None: global bot chatid = update.message.chat_id username_dict = {} followed_users = "" results = Utils.retrieve_query_results(f"SELECT USERNAME, ONLINE FROM CHATURBATE WHERE CHAT_ID='{chatid}'") if results != []: # an exception didn't happen for row in results: username=row[0] status=row[1] username_dict[username]=status for username, status in sorted(username_dict.items()): followed_users += f"{username}: " if status == "T": followed_users += "<b>online</b>\n" else: followed_users += "offline\n" if followed_users == "": send_message(chatid, "You aren't following any user", bot) else: send_message( chatid, f"You are currently following these {len(username_dict)} users:\n" + followed_users, bot, html=True)
def send_image(chatid: str, image, bot: updater.bot, html: bool = False, markup=None, caption=None) -> None: """ Sends an image to a telegram user and sends "sending image" action :param chatid: The chatid of the user who will receive the message :param image: The image to send :param bot: telegram bot instance :param html: Enable html markdown parsing in the message :param markup: The reply_markup to use when sending the message """ notification = not Preferences.get_user_notifications_sound_preference( chatid) # the setting is opposite of preference try: bot.send_chat_action(chatid, action="upload_photo") if html and markup != None and caption != None: bot.send_photo(chat_id=chatid, photo=image, parse_mode=telegram.ParseMode.HTML, reply_markup=markup, disable_notification=notification, caption=caption) elif html and markup != None: bot.send_photo(chat_id=chatid, photo=image, parse_mode=telegram.ParseMode.HTML, reply_markup=markup, disable_notification=notification) elif markup != None and caption != None: bot.send_photo(chat_id=chatid, photo=image, reply_markup=markup, disable_notification=notification, caption=caption) elif html and caption != None: bot.send_photo(chat_id=chatid, photo=image, parse_mode=telegram.ParseMode.HTML, disable_notification=notification, caption=caption) elif html: bot.send_photo(chat_id=chatid, photo=image, parse_mode=telegram.ParseMode.HTML, disable_notification=notification) elif markup != None: bot.send_photo(chat_id=chatid, photo=image, reply_markup=markup, disable_notification=notification) elif caption != None: bot.send_photo(chat_id=chatid, photo=image, disable_notification=notification, caption=caption) else: bot.send_photo(chat_id=chatid, photo=image, disable_notification=notification) except Unauthorized: # user blocked the bot if auto_remove == True: logging.info(f"{chatid} blocked the bot, he's been removed from the database") Utils.exec_query(f"DELETE FROM CHATURBATE WHERE CHAT_ID='{chatid}'") Preferences.remove_user_from_preferences(chatid) except Exception as e: Utils.handle_exception(e)
def active_models(update, context) -> None: global bot chatid = update.message.chat_id if not Utils.admin_check(chatid): send_message(chatid, "You're not authorized to do this", bot) return models_count = Utils.alchemy_instance.session.query( ChaturbateUser.username).distinct().count() send_message(chatid, f"The active models are {models_count}", bot)
def active_users(update, context) -> None: global bot chatid = update.message.chat_id if not Utils.admin_check(chatid): send_message(chatid, "You're not authorized to do this", bot) return users_count = Utils.alchemy_instance.session.query( PreferenceUser).filter_by(chat_id=str(chatid)).count() send_message(chatid, f"The active users are {users_count}", bot)
def send_message(chatid: str, messaggio: str, bot: updater.bot, html: bool = False, markup=None) -> None: """ Sends a message to a telegram user and sends "typing" action :param chatid: The chatid of the user who will receive the message :param messaggio: The message who the user will receive :param bot: telegram bot instance :param html: Enable html markdown parsing in the message :param markup: The reply_markup to use when sending the message """ disable_webpage_preview = not Preferences.get_user_link_preview_preference( chatid) # the setting is opposite of preference notification = not Preferences.get_user_notifications_sound_preference( chatid) # the setting is opposite of preference try: bot.send_chat_action(chat_id=chatid, action="typing") if html and markup != None: bot.send_message(chat_id=chatid, text=messaggio, parse_mode=telegram.ParseMode.HTML, disable_web_page_preview=disable_webpage_preview, reply_markup=markup, disable_notification=notification) elif html: bot.send_message(chat_id=chatid, text=messaggio, parse_mode=telegram.ParseMode.HTML, disable_web_page_preview=disable_webpage_preview, disable_notification=notification) elif markup != None: bot.send_message(chat_id=chatid, text=messaggio, disable_web_page_preview=disable_webpage_preview, reply_markup=markup, disable_notification=notification) else: bot.send_message(chat_id=chatid, text=messaggio, disable_web_page_preview=disable_webpage_preview, disable_notification=notification) except Unauthorized: # user blocked the bot if auto_remove == True: logging.info(f"{chatid} blocked the bot, he's been removed from the database") Utils.exec_query(f"DELETE FROM CHATURBATE WHERE CHAT_ID='{chatid}'") Preferences.remove_user_from_preferences(chatid) except Exception as e: Utils.handle_exception(e)
def crawl(q, model_instances_dict): while not q.empty(): username = Utils.sanitize_username(q.get()[1].username) model_instance = Model(username, autoupdate=False) model_instance.update_model_status() try: model_instance.update_model_image() except Exception: model_instance.model_image = None # set to None just to be secure Todo: this may be extra model_instances_dict[username] = model_instance # signal to the queue that task has been processed q.task_done() return True
def user_has_preferences(chatid: str) -> bool: """ Checks if user exists in the preferences table :param chatid: The chatid of the user who will be tested :return: True if it exists, False if it doesn't exist """ results = Utils.retrieve_query_results( f"SELECT * FROM PREFERENCES WHERE CHAT_ID={chatid}") if not results: return False else: return True
def get_user_link_preview_preference(chatid: str) -> bool: """ Retrieve the link_preview preference of the user :param chatid: The chatid of the user who will be tested :return: The boolean value of the preference """ if not user_has_preferences(chatid): add_user_to_preferences(chatid) results = Utils.retrieve_query_results( f"SELECT LINK_PREVIEW FROM PREFERENCES WHERE CHAT_ID={chatid}") if results[0][0] == 0: return False else: return True
def get_user_notifications_sound_preference(chatid: str) -> bool: """ Retrieve the notifications preference of the user :param chatid: The chatid of the user who will be tested :return: The boolean value of the preference """ if not user_has_preferences(chatid): add_user_to_preferences(chatid) results = Utils.retrieve_query_results( f"SELECT NOTIFICATIONS_SOUND FROM PREFERENCES WHERE CHAT_ID={chatid}") if results[0][0] == 0: return False else: return True
def remove(update, CallbackContext) -> None: global bot args = CallbackContext.args chatid = update.message.chat_id username_message_list = [] usernames_in_database = [] if len(args) < 1: send_message( chatid, "You need to specify an username to follow, use the command like /remove <b>test</b>\n You can also remove multiple users at the same time by separating them using a comma, like /remove <b>username1</b>,<b>username2</b>", bot, html=True ) return if len(args) > 1: for username in args: if username != "": username_message_list.append(Utils.sanitize_username(username).replace(",", "")) # len(args)==0 -> only one username or all in one line elif "," in args[0].lower(): for splitted_username in args[0].lower().replace(" ", "").rstrip().split(","): if splitted_username != "": username_message_list.append(Utils.sanitize_username(splitted_username)) else: username_message_list.append(Utils.sanitize_username(args[0])) results = Utils.retrieve_query_results(f"SELECT * FROM CHATURBATE WHERE CHAT_ID='{chatid}'") for row in results: usernames_in_database.append(row[0]) if "all" in username_message_list: Utils.exec_query( f"DELETE FROM CHATURBATE WHERE CHAT_ID='{chatid}'") send_message(chatid, "All usernames have been removed", bot) logging.info(f"{chatid} removed all usernames") else: for username in username_message_list: if username in usernames_in_database: Utils.exec_query(f"DELETE FROM CHATURBATE WHERE USERNAME='******' AND CHAT_ID='{chatid}'") send_message(chatid, f"{username} has been removed", bot) logging.info(f"{chatid} removed {username}") else: send_message(chatid, f"You aren't following {username}", bot)
def notifications_sound_callback_update_value(update, CallbackContext): query = update.callback_query chatid = query.message.chat.id keyboard = [[InlineKeyboardButton("Settings", callback_data='settings_menu')]] keyboard = InlineKeyboardMarkup(keyboard) if query.data == "notifications_sound_callback_True": setting = True else: setting = False Preferences.update_notifications_sound_preference(chatid, setting) setting = Utils.bool_to_status(setting) logging.info(f'{chatid} has set notifications sound to {setting}') query.edit_message_text(text=f"The notifications sound preference has been set to <b>{setting}</b>", reply_markup=keyboard, parse_mode=telegram.ParseMode.HTML)
# Create and configure logger LOG_FORMAT = "%(asctime)s : %(levelname)s - %(message)s" logging.basicConfig(filename="logs/start.py.log", level=logging.DEBUG, format=LOG_FORMAT) # Check the environment env = os.environ.get('ENVIRONMENT') if env == None: logging.info('No environment supplied. Hence defaulting to dev') env = 'dev' # Source environment specific settings file _settingsFile = os.path.join("settings", "app.settings." + env + ".json") util = Utils() settings = util.getSettings(_settingsFile) api = BooksAPI(settings) # Get Books from API print( "#############################################################################" ) print( "#################### Get Ratings List #######################################" ) print( "#############################################################################" ) logging.info('Starting request to API to get list of ratings') apiBookRatingsUrl = settings['apiUrl'] + 'bookrating/'
def add(update, context) -> None: global bot args = context.args chatid = update.message.chat_id username_message_list = [] if len(args) < 1: send_message( chatid, "You need to specify an username to follow, use the command like /add <b>username</b>\n You can also add multiple users at the same time by separating them using a comma, like /add <b>username1</b>,<b>username2</b>", bot, html=True) return # not lowercase usernames bug the api calls if len(args) > 1: for username in args: if username != "": username_message_list.append( Utils.sanitize_username(username).replace(",", "")) # len(args)==0 -> only one username or all in one line elif "," in args[0].lower(): for splitted_username in args[0].lower().replace( " ", "").rstrip().split(","): if splitted_username != "": username_message_list.append( Utils.sanitize_username(splitted_username)) else: username_message_list.append(Utils.sanitize_username(args[0])) username_message_list = list( dict.fromkeys(username_message_list)) # remove duplicate usernames usernames_in_database = Utils.alchemy_instance.session.query( ChaturbateUser).filter_by(chat_id=str(chatid)).all() # 0 is unlimited usernames if len(usernames_in_database) + len( username_message_list) > user_limit and ( Utils.admin_check(chatid) == False != user_limit != 0): send_message( chatid, "You are trying to add more usernames than your limit permits, which is " + str(user_limit), bot) logging.info( f'{chatid} tried to add more usernames than his limit permits') return for username in username_message_list: model_instance = Model(username) if model_instance.status not in ('deleted', 'banned', 'geoblocked', 'canceled', 'error'): if username not in usernames_in_database: Utils.alchemy_instance.session.add( ChaturbateUser(username=username, chat_id=chatid, online=False)) Utils.alchemy_instance.session.commit() send_message(chatid, f"{username} has been added", bot) logging.info(f'{chatid} added {username}') else: send_message(chatid, f"{username} has already been added", bot) elif model_instance.status == 'deleted': send_message(chatid, f"{username} has not been added because is deleted", bot) logging.info( f"{chatid} could not add {username} because is deleted") elif model_instance.status == 'banned': send_message(chatid, f"{username} has not been added because is banned", bot) logging.info( f"{chatid} could not add {username} because is banned") elif model_instance.status == 'geoblocked': send_message( chatid, f"{username} has not been added because is geoblocked", bot) logging.info( f"{chatid} could not add {username} because is geoblocked") elif model_instance.status == 'canceled': send_message(chatid, f"{username} was not added because it doesn't exist", bot) logging.info( f'{chatid} tried to add {username}, which does not exist') elif model_instance.status == 'error': send_message( chatid, f"{username} was not added because an error happened", bot) logging.info( f'{chatid} could not add {username} because an error happened')
def stream_image(update, context) -> None: global bot args = context.args chatid = update.message.chat_id if len(args) < 1: send_message( chatid, "You didn't specify a model to get the stream image of\nUse the command like this: /stream_image <b>username</b>", bot, html=True) return username = Utils.sanitize_username(args[0]) model_instance = Model(username) if not Utils.admin_check(chatid): if Utils.is_chatid_temp_banned(chatid): return if Utils.get_last_spam_date(chatid) == None: Utils.set_last_spam_date(chatid, datetime.datetime.now()) elif (datetime.datetime.now() - Utils.get_last_spam_date(chatid)).total_seconds() <= 3: Utils.temp_ban_chatid(chatid, 10) send_message( chatid, "You have been temporarily banned for spamming, try again later", bot) logging.warning( f"Soft banned {chatid} for 10 seconds for spamming image updates" ) else: Utils.set_last_spam_date(chatid, datetime.datetime.now()) try: send_image(chatid, model_instance.model_image, bot) logging.info(f'{chatid} viewed {username} stream image') except Exceptions.ModelPrivate: send_message( chatid, f"The model {username} is in private now, try again later", bot) logging.warning( f'{chatid} could not view {username} stream image because is private' ) except Exceptions.ModelAway: send_message(chatid, f"The model {username} is away, try again later", bot) logging.warning( f'{chatid} could not view {username} stream image because is away') except Exceptions.ModelPassword: send_message( chatid, f"The model {username} cannot be seen because is password protected", bot) logging.warning( f'{chatid} could not view {username} stream image because is password protected' ) except (Exceptions.ModelDeleted, Exceptions.ModelBanned, Exceptions.ModelGeoblocked, Exceptions.ModelCanceled, Exceptions.ModelOffline): send_message( chatid, f"The model {username} cannot be seen because is {model_instance.status}", bot) logging.warning( f'{chatid} could not view {username} image update because is {model_instance.status}' ) except Exceptions.ModelNotViewable: send_message(chatid, f"The model {username} is not visible", bot) logging.warning(f'{chatid} could not view {username} stream image') except ConnectionError: send_message( chatid, f"The model {username} cannot be seen because of connection issues, try again later", bot) logging.warning( f'{chatid} could not view {username} stream image because of connection issues' )
def send_message(chatid: str, messaggio: str, bot_p: updater.bot, html: bool = False, markup=None) -> None: """ Sends a message to a telegram user and sends "typing" action :param chatid: The chatid of the user who will receive the message :param messaggio: The message who the user will receive :param bot_p: telegram bot instance :param html: Enable html markdown parsing in the message :param markup: The reply_markup to use when sending the message """ disable_webpage_preview = not Preferences.get_user_link_preview_preference( chatid) # the setting is opposite of preference notification = not Preferences.get_user_notifications_sound_preference( chatid) # the setting is opposite of preference try: bot_p.send_chat_action(chat_id=chatid, action="typing") if html and markup is not None: bot_p.send_message( chat_id=chatid, text=messaggio, parse_mode=telegram.ParseMode.HTML, disable_web_page_preview=disable_webpage_preview, reply_markup=markup, disable_notification=notification) elif html: bot_p.send_message( chat_id=chatid, text=messaggio, parse_mode=telegram.ParseMode.HTML, disable_web_page_preview=disable_webpage_preview, disable_notification=notification) elif markup is not None: bot_p.send_message( chat_id=chatid, text=messaggio, disable_web_page_preview=disable_webpage_preview, reply_markup=markup, disable_notification=notification) else: bot_p.send_message( chat_id=chatid, text=messaggio, disable_web_page_preview=disable_webpage_preview, disable_notification=notification) except Unauthorized: # user blocked the bot if auto_remove: logging.info( f"{chatid} blocked the bot, he's been removed from the database" ) Utils.alchemy_instance.session.query(ChaturbateUser).filter_by( chat_id=str(chatid)).delete(synchronize_session=False) Preferences.remove_user_from_preferences(chatid) except Exception as e: Utils.handle_exception(e)
def update_status() -> None: username_list = [] chat_and_online_dict = {} # create a dictionary with usernames and online using distinct username_list = Utils.alchemy_instance.session.query( ChaturbateUser.username).distinct().all() # obtain chatid for username in username_list: results: List[ ChaturbateUser] = Utils.alchemy_instance.session.query( ChaturbateUser).filter_by(username=username).all() chat_and_online_dict[ username] = results # assign (chatid,online) to every model # Threaded function for queue processing. def crawl(q, model_instances_dict): while not q.empty(): username = Utils.sanitize_username(q.get()[1].username) model_instance = Model(username, autoupdate=False) model_instance.update_model_status() try: model_instance.update_model_image() except Exception: model_instance.model_image = None # set to None just to be secure Todo: this may be extra model_instances_dict[username] = model_instance # signal to the queue that task has been processed q.task_done() return True q = Queue(maxsize=0) # Populating Queue with tasks model_instances_dict = {} # load up the queue with the username_list to fetch and the index for each job (as a tuple): for index, value in enumerate(username_list): # need the index and the username in each queue item. q.put((index, value)) # Starting worker threads on queue processing for i in range(http_threads): worker = threading.Thread(target=crawl, args=(q, model_instances_dict), daemon=True) worker.start() time.sleep( wait_time ) # avoid server spamming by time-limiting the start of requests # now we wait until the queue has been processed q.join() for username in username_list: model_instance = model_instances_dict[username] keyboard_with_link_preview = [[ InlineKeyboardButton("Watch the live", url=f'http://chaturbate.com/{username}'), InlineKeyboardButton( "Update stream image", callback_data='view_stream_image_callback_' + username) ]] keyboard_without_link_preview = [[ InlineKeyboardButton("Watch the live", url=f'http://chaturbate.com/{username}') ]] markup_with_link_preview = InlineKeyboardMarkup( keyboard_with_link_preview) markup_without_link_preview = InlineKeyboardMarkup( keyboard_without_link_preview) try: if model_instance.status != "error": for chatid_tuple in chat_and_online_dict[username]: chat_id = chatid_tuple.chat_id db_status = chatid_tuple.online if model_instance.online and db_status == False: if model_instance.status in { "away", "private", "hidden", "password" }: # assuming the user knows the password Utils.alchemy_instance.session.query( ChaturbateUser).filter( ChaturbateUser.username == username and ChaturbateUser.chat_id == chat_id).update( {ChaturbateUser.online: True}, synchronize_session=False) send_message( chat_id, f"{username} is now <b>online</b>!\n<i>No link preview can be provided</i>", bot, html=True, markup=markup_without_link_preview) else: Utils.alchemy_instance.session.query( ChaturbateUser).filter( ChaturbateUser.username == username and ChaturbateUser.chat_id == chat_id).update( {ChaturbateUser.online: True}, synchronize_session=False) if Preferences.get_user_link_preview_preference( chat_id ) and model_instance.model_image is not None: send_image( chat_id, model_instance.model_image, bot, markup=markup_with_link_preview, caption= f"{username} is now <b>online</b>!", html=True) else: send_message( chat_id, f"{username} is now <b>online</b>!", bot, html=True, markup=markup_without_link_preview) elif model_instance.online == False and db_status: Utils.alchemy_instance.session.query( ChaturbateUser).filter( ChaturbateUser.username == username and ChaturbateUser.chat_id == chat_id).update( {ChaturbateUser.online: False}, synchronize_session=False) send_message(chat_id, f"{username} is now <b>offline</b>", bot, html=True) if model_instance.status == "deleted": Utils.alchemy_instance.session.query( ChaturbateUser).filter_by( username=username, chat_id=chat_id).delete( synchronize_session=False) send_message( chat_id, f"{username} has been removed because room has been deleted", bot) logging.info( f"{username} has been removed from {chat_id} because room has been deleted" ) elif model_instance.status == "banned": Utils.alchemy_instance.session.query( ChaturbateUser).filter_by( username=username, chat_id=chat_id).delete( synchronize_session=False) send_message( chat_id, f"{username} has been removed because room has been banned", bot) logging.info( f"{username} has been removed from {chat_id} because has been banned" ) elif model_instance.status == "canceled": Utils.alchemy_instance.session.query( ChaturbateUser).filter_by( username=username, chat_id=chat_id).delete( synchronize_session=False) send_message( chat_id, f"{username} has been removed because room has been canceled", bot) logging.info( f"{username} has been removed from {chat_id} because has been canceled" ) elif model_instance.status == "geoblocked": Utils.alchemy_instance.session.query( ChaturbateUser).filter_by( username=username, chat_id=chat_id).delete( synchronize_session=False) send_message( chat_id, f"{username} has been removed because of geoblocking", bot) logging.info( f"{username} has been removed from {chat_id} because of geoblocking" ) except Exception as e: Utils.handle_exception(e)
def test_getSettings(self): _settingsFile = os.path.join("../settings", "app.settings." + env + ".json") util = Utils() settings = util.getSettings(_settingsFile) assert 'apiUrl' in settings