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()
Esempio n. 2
0
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
Esempio n. 3
0
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
Esempio n. 4
0
        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()
Esempio n. 5
0
        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()
Esempio n. 6
0
        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()
Esempio n. 7
0
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
Esempio n. 8
0
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
Esempio n. 9
0
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()
Esempio n. 10
0
        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()
Esempio n. 11
0
        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()
Esempio n. 13
0
        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()