def wrapper(bot, update): session = get_session() try: user = get_user(session, update) if not is_allowed( user, update, admin_only=admin_only, check_ban=check_ban): return func(bot, update, session, user) session.commit() except BadRequest as e: # An update for a reply keyboard has failed (Probably due to button spam) if str(e) == 'Message is not modified': # noqa print(e) return # It took to long to send the inline query response. # Probably due to slow network on client side. elif str(e) == 'Query_id_invalid': # noqa print(e) return traceback.print_exc() sentry.captureException() # Ignore network related errors except (TimedOut, NetworkError): pass except BaseException: traceback.print_exc() sentry.captureException() finally: session.close()
def extract_text(tg_sticker): """Extract the text from a telegram sticker.""" text = None logger = logging.getLogger() try: # Get Image and preprocess it tg_file = call_tg_func(tg_sticker, "get_file") image_bytes = call_tg_func(tg_file, "download_as_bytearray") with Image.open(io.BytesIO(image_bytes)).convert("RGB") as image: image = preprocess_image(image) # Extract text text = image_to_string(image).strip().lower() # Only allow chars and remove multiple spaces to single spaces text = re.sub("[^a-zA-Z\ ]+", "", text) text = re.sub(" +", " ", text) text = text.strip() if text == "": text = None except TimedOut: logger.info(f"Finally failed on file {tg_sticker.file_id}") pass except BadRequest: logger.info(f"Failed to get image of {tg_sticker.file_id}") pass except OSError: logger.info(f"Failed to open image {tg_sticker.file_id}") pass except: sentry.captureException() pass return text
def extract_text(tg_sticker): """Extract the text from a telegram sticker.""" text = None logger = logging.getLogger() try: # Get Image and preprocess it tg_file = call_tg_func(tg_sticker, 'get_file') image_bytes = call_tg_func(tg_file, 'download_as_bytearray') image = Image.open(io.BytesIO(image_bytes)).convert('RGB') image = preprocess_image(image) # Extract text text = image_to_string(image).strip().lower() # Only allow chars and remove multiple spaces to single spaces text = re.sub('[^a-zA-Z\ ]+', '', text) text = re.sub(' +', ' ', text) text = text.strip() if text == '': text = None except TimedOut: logger.info(f'Finally failed on file {tg_sticker.file_id}') pass except BadRequest: logger.info(f'Failed to get image of f{tg_sticker.file_id}') pass except BaseException: sentry.captureException() pass return text
def wrapper(update, context): session = get_session() chat = None try: if hasattr(update, "message") and update.message: message = update.message elif hasattr(update, "edited_message") and update.edited_message: message = update.edited_message user = get_user(session, update) if config["mode"]["authorized_only"] and not user.authorized: text = "StickerFinder is officially offline. Access will still be granted for [Patreons](https://www.patreon.com/nukesor).\n" text += "Check the repository for the latest database dump in case you want to host your own bot." message.chat.send_message(text, parse_mode="Markdown") session.commit() return if not is_allowed( user, update, admin_only=admin_only, check_ban=check_ban): return chat_id = message.chat_id chat_type = message.chat.type chat = Chat.get_or_create(session, chat_id, chat_type) if not is_allowed(user, update, chat=chat, private=private): return response = func(context.bot, update, session, chat, user) session.commit() # Respond to user if hasattr(update, "message") and response is not None: message.chat.send_message(response) # A user banned the bot except Unauthorized: if chat is not None: session.delete(chat) # A group chat has been converted to a super group. except ChatMigrated: if chat is not None: session.delete(chat) # Handle all not telegram relatated exceptions except Exception as e: if not ignore_exception(e): traceback.print_exc() sentry.captureException() if send_message and message: session.close() call_tg_func(message.chat, "send_message", args=[error_text]) raise finally: session.close()
def wrapper(context): session = get_session() try: func(context, session) session.commit() except: # Capture all exceptions from jobs. We need to handle those inside the jobs traceback.print_exc() sentry.captureException() finally: session.close()
def wrapper(update, context): session = get_session() try: user = get_user(session, update) if not is_allowed( user, update, admin_only=admin_only, check_ban=check_ban): return if hasattr(update, 'message') and update.message: message = update.message elif hasattr(update, 'edited_message') and update.edited_message: message = update.edited_message chat_id = message.chat_id chat_type = message.chat.type chat = Chat.get_or_create(session, chat_id, chat_type) if not is_allowed(user, update, chat=chat, private=private): return response = func(context.bot, update, session, chat, user) session.commit() # Respond to user if hasattr(update, 'message') and response is not None: call_tg_func(message.chat, 'send_message', args=[response]) # A user banned the bot except Unauthorized: session.delete(chat) # A group chat has been converted to a super group. except ChatMigrated: session.delete(chat) # Raise all telegram errors and let the generic error_callback handle it except TelegramError as e: raise e # Handle all not telegram relatated exceptions except: traceback.print_exc() sentry.captureException() if send_message: session.close() call_tg_func(message.chat, 'send_message', args=[error_text]) raise finally: session.close()
def call_tg_func(tg_object: object, function_name: str, args: list = None, kwargs: dict = None): """Call a tg object member function. We need to handle those calls in case we get rate limited. """ current_try = 1 tries = 4 exception = None while current_try < tries: try: args = args if args else [] kwargs = kwargs if kwargs else {} breadcrumbs.record(data={"action": f"Starting: {datetime.now()}"}, category="info") retrieved_object = getattr(tg_object, function_name)(*args, **kwargs) return retrieved_object except (TimedOut, NetworkError) as e: # Can't update message. just ignore it if "Message to edit not found" in str( e) or "Message is not modified" in str(e): raise e timeout = 2 * current_try breadcrumbs.record(data={"action": f"Exception: {datetime.now()}"}, category="info") logger = logging.getLogger() logger.info( f"Try {current_try}: Got telegram exception waiting {timeout} secs." ) logger.info(e.message) if config["logging"]["debug"]: sentry.captureException() time.sleep(timeout) current_try += 1 exception = e pass raise exception
def call_tg_func(tg_object: object, function_name: str, args: list = None, kwargs: dict = None): """Call a tg object member function. We need to handle those calls in case we get rate limited. """ _try = 0 tries = 2 exception = None while _try < tries: try: args = args if args else [] kwargs = kwargs if kwargs else {} breadcrumbs.record(data={'action': f'Starting: {datetime.now()}'}, category='info') retrieved_object = getattr(tg_object, function_name)(*args, **kwargs) return retrieved_object except (TimedOut, NetworkError) as e: # Can't update message. just ignore it if 'Message to edit not found' in str(e) or \ 'Message is not modified' in str(e): raise e breadcrumbs.record(data={'action': f'Exception: {datetime.now()}'}, category='info') logger = logging.getLogger() logger.info(f'Got telegram exception waiting 4 secs.') logger.info(e) if config.DEBUG: sentry.captureException() time.sleep(4) _try += 1 exception = e pass raise exception
def error_callback(update, context): """Handle generic errors from telegram.""" try: raise context.error except BadRequest as e: # It took to long to send the inline query response. # Probably due to slow network on client side. if str(e) == "Query_id_invalid": # noqa return traceback.print_exc() sentry.captureException() # A user banned the bot Just ignore this. # This probably happens due to sending a message during maintenance work except Unauthorized: pass except (TimedOut, NetworkError): pass except: traceback.print_exc() sentry.captureException()
def wrapper(update, context): session = get_session() try: user = get_user(session, update) if not is_allowed( user, update, admin_only=admin_only, check_ban=check_ban): return if config['mode']['authorized_only'] and not user.authorized: return func(context.bot, update, session, user) session.commit() # Handle all not telegram relatated exceptions except Exception as e: if not ignore_exception(e): traceback.print_exc() sentry.captureException() finally: session.close()
def wrapper(update, context): session = get_session() try: user = get_user(session, update) if not is_allowed( user, update, admin_only=admin_only, check_ban=check_ban): return func(context.bot, update, session, user) session.commit() # Raise all telegram errors and let the generic error_callback handle it except TelegramError as e: raise e # Handle all not telegram relatated exceptions except: traceback.print_exc() sentry.captureException() finally: session.close()
def refresh_stickers(self, session, bot, refresh_ocr=False, chat=None): """Refresh stickers and set data from telegram.""" # Get sticker set from telegram and create new a Sticker for each sticker stickers = [] logger = logging.getLogger() try: tg_sticker_set = call_tg_func(bot, 'get_sticker_set', args=[self.name]) except BadRequest as e: if e.message == 'Stickerset_invalid': self.deleted = True return raise e for tg_sticker in tg_sticker_set.stickers: # Ignore already existing stickers if we don't need to rescan images sticker = session.query(Sticker).get(tg_sticker.file_id) text = None if sticker is None or refresh_ocr: # Download the image for text recognition # This sometimes fail. Thereby we implement a retry # If the retry failes 5 times, we ignore the image text = None try: # Get Image and preprocess it tg_file = call_tg_func(tg_sticker, 'get_file') image_bytes = call_tg_func(tg_file, 'download_as_bytearray') image = Image.open(io.BytesIO(image_bytes)).convert('RGB') image = preprocess_image(image) # Extract text text = image_to_string(image).strip().lower() # Only allow chars text = re.sub('[^a-zA-Z\ ]+', '', text) if text == '': text = None except TimedOut: logger.info(f'Finally failed on file {tg_sticker.file_id}') pass except BadRequest: logger.info( f'Failed to get image of f{tg_sticker.file_id}') pass except BaseException: sentry.captureException() pass # Create new Sticker. if sticker is None: sticker = Sticker(tg_sticker.file_id) # Only set text, if we got some text from the ocr recognition if text is not None: sticker.text = text sticker.add_emojis(session, tg_sticker.emoji) stickers.append(sticker) session.commit() self.name = tg_sticker_set.name.lower() self.title = tg_sticker_set.title.lower() self.stickers = stickers self.complete = True session.commit()
def wrapper(bot, update): session = get_session() try: user = get_user(session, update) if not is_allowed( user, update, admin_only=admin_only, check_ban=check_ban): return chat_id = update.message.chat_id chat_type = update.message.chat.type chat = Chat.get_or_create(session, chat_id, chat_type) if not is_allowed(user, update, chat=chat, private=private): return response = func(bot, update, session, chat, user) # Respond to user if hasattr(update, 'message') and response is not None: session.commit() call_tg_func(update.message.chat, 'send_message', args=[response]) return session.commit() except BadRequest as e: # An update for a reply keyboard has failed (Probably due to button spam) if str(e) == 'Message is not modified': # noqa print(e) return # We are on dev db or a user deleted a chat. if str(e) == 'Chat not found': # noqa print(e) session.delete(chat) traceback.print_exc() sentry.captureException() # A user banned the bot except Unauthorized: session.delete(chat) return # A group chat has been converted to a super group. except ChatMigrated: session.delete(chat) return # Ignore network related errors except (TimedOut, NetworkError) as e: print(e) pass except BaseException: traceback.print_exc() sentry.captureException() if send_message: session.close() call_tg_func(update.message.chat, 'send_message', args=[error_text]) finally: session.close()