Esempio n. 1
0
 async def send_bot_response(self, user: str, response: BotResponse):
     if response.message:
         images = response.images
         disable_unicode = not self.bot.get_user_setting(
             user, BotUserSettings.FORMATTING)
         max_chars = 2000
         if response.choices:
             max_chars = 640
         messages = split_message(adapt_text(str(response),
                                             just_strip=disable_unicode),
                                  max_chars=max_chars)
         for i in range(0, len(messages)):
             buttons = None
             if response.choices and i == len(messages) - 1:
                 buttons = []
                 if len(response.choices) > 3:
                     response.choices = response.choices[:3]
                 for choice in response.choices:
                     buttons.append(
                         PostbackButton(choice.label, choice.callback_data))
             await self.fb_messenger.send_message(user,
                                                  messages[i],
                                                  images=images,
                                                  buttons=buttons)
             images = None
             SENT_MESSAGE_COUNT.inc()
Esempio n. 2
0
    async def handle_messenger_msg(self, message: Message):
        RECV_MESSAGE_COUNT.inc()
        try:
            user_input = message.text
            if message.payload:
                user_input = message.payload
            responses = self.bot.handle_input(user_input, message.sender_id)
            for response in responses:
                await self.send_bot_response(message.sender_id, response)
        except Exception as e:
            self.log.exception(
                "An error happened while handling a FB Messenger message",
                exc_info=e)
            self.log.exception(
                f"Message from {message.sender_id}: {message.text}")
            self.log.exception("Exiting!")
            await self.fb_messenger.send_reply(
                message, adapt_text(self.bot.get_error_message().message))

            try:
                tb_list = traceback.format_exception(None, e, e.__traceback__)
                tb_string = ''.join(tb_list)

                await self.sendMessageToDev(
                    f"An exception occurred: {tb_string}\n"
                    f"Message from {message.sender_id}: {message.text}")
            except Exception:
                self.log.error(f"Could not send message to developers")

            # Just exit on exception
            os.kill(os.getpid(), signal.SIGINT)
Esempio n. 3
0
    async def send_message_to_users(self, message: str,
                                    users: List[Union[str, int]]):
        if not users:
            users = map(lambda x: x.platform_id, self.bot.get_all_users())

        message = UserHintService.format_commands(message,
                                                  self.bot.command_formatter)

        for user in users:
            await TextMessage(self.connection,
                              text=adapt_text(message, True),
                              to_id=user).send()
            self.log.warning(f"Sent message to {user}")
Esempio n. 4
0
    async def send_message_to_users(self, message: str,
                                    users: List[Union[str, int]]):
        if not users:
            users = map(lambda x: x.platform_id, self.bot.get_all_users())

        message = UserHintService.format_commands(message,
                                                  self.bot.command_formatter)

        for user in users:
            disable_unicode = not self.bot.get_user_setting(
                user, BotUserSettings.FORMATTING)
            await self.fb_messenger.send_message(
                user, adapt_text(message, just_strip=disable_unicode))
            self.log.warning(f"Sent message to {user}")
Esempio n. 5
0
    async def handle_threema_msg(self, message: Message):
        if type(message) == TextMessage:
            RECV_MESSAGE_COUNT.inc()
            message: TextMessage
            try:
                responses = self.bot.handle_input(message.text,
                                                  message.from_id)
                for response in responses:
                    await self.send_bot_response(message.from_id, response)
            except Exception as e:
                self.log.exception(
                    "An error happened while handling a Threema message",
                    exc_info=e)
                self.log.exception(
                    f"Message from {message.from_id}: {message.text}")
                self.log.exception("Exiting!")

                try:
                    response_msg = TextMessage(
                        self.connection,
                        text=adapt_text(self.bot.get_error_message().message,
                                        True),
                        to_id=message.from_id)
                    await response_msg.send()
                except Exception:
                    self.log.error(
                        f"Could not send message to {message.from_id}")

                try:
                    tb_list = traceback.format_exception(
                        None, e, e.__traceback__)
                    tb_string = ''.join(tb_list)

                    await self.sendMessageToDev(
                        f"An exception occurred: {tb_string}\n"
                        f"Message from {message.from_id}: {message.text}")
                except Exception:
                    self.log.error(f"Could not send message to developers")

                # Just exit on exception
                os.kill(os.getpid(), signal.SIGINT)
        elif type(message) == DeliveryReceipt:
            pass
        else:
            self.log.warning(
                f"Received unknown message type {type(message)}: {message}")
Esempio n. 6
0
    async def send_bot_response(self, user: str, response: BotResponse):
        if response.images:
            for image in response.images:
                response_img = ImageMessage(self.connection,
                                            image_path=image,
                                            to_id=user)
                await response_img.send()
                SENT_IMAGES_COUNT.inc()

        if response.message:
            message_parts = split_message(adapt_text(str(response),
                                                     threema_format=True),
                                          max_bytes=3500)
            for m in message_parts:
                response_msg = TextMessage(self.connection, text=m, to_id=user)
                await response_msg.send()
                SENT_MESSAGE_COUNT.inc()
Esempio n. 7
0
    async def send_message_to_users(self, message: str, users: List[str]) -> None:
        """
        Send a message to specific or all users
        Args:
            message: Message to send
            users: List of user ids or None for all signal users
        """
        if not users:
            users = map(lambda x: x.platform_id, self.bot.get_all_users())

        message = UserHintService.format_commands(message, self.bot.command_formatter)

        async with semaphore.Bot(self.phone_number, socket_path=self.socket,
                                 profile_name=self.profile_name,
                                 profile_picture=self.profile_picture,
                                 raise_errors=True) as bot:
            for user in users:
                disable_unicode = not self.bot.get_user_setting(user,
                                                                BotUserSettings.FORMATTING)
                await bot.send_message(user, adapt_text(str(message),
                                                        just_strip=disable_unicode))
Esempio n. 8
0
    def update(self) -> bool:
        last_update = self.get_last_update()
        if last_update and datetime.now() - last_update < timedelta(hours=12):
            return False

        new_data = False
        response = self.get_resource(self.URL)
        if response:
            self.log.debug("Got RulesGermany Data")
            data = json.loads(response)
            updated = datetime.now()
            with self.connection.cursor() as cursor:
                from covidbot.utils import adapt_text
                for bl in data:
                    district_id = self.get_district_id(bl['Bundesland'])
                    if not district_id:
                        self.log.warning(f"Could not get ID of {bl['Bundesland']}")
                        continue

                    text = bl['Überblick']
                    text = adapt_text(text, just_strip=True)
                    link = f'https://tourismus-wegweiser.de/detail/?bl={bl["Kürzel"]}'

                    cursor.execute("SELECT text, link FROM district_rules WHERE district_id=%s", [district_id])
                    row = cursor.fetchone()
                    if row:
                        if row[0] == text and row[1] == link:
                            continue
                        cursor.execute("UPDATE district_rules SET text=%s, link=%s, updated=%s WHERE district_id=%s",
                                       [text, link, updated, district_id])
                    else:
                        cursor.execute("INSERT INTO district_rules (district_id, text, link, updated) "
                                       "VALUES (%s, %s, %s, %s)", [district_id, text, link, updated])
                    new_data = True
            self.connection.commit()
        return new_data
Esempio n. 9
0
    async def send_response(self, room_id: str, responses: List[BotResponse]):
        # Check if device is verified
        # if self.matrix.room_contains_unverified(room.room_id):
        #    devices = self.matrix.room_devices(room.room_id)
        #    for user in devices:
        #        for device in devices[user]:
        #            self.matrix.verify_device(devices[user][device])
        #            self.log.debug(f"Verified {device} of {user}")

        if self.debug:
            return

        for message in responses:
            if message.images:
                for image in message.images:
                    # Calculate metadata
                    mime_type = "image/jpeg"
                    file_stat = os.stat(image)

                    im = Image.open(image)
                    (width, height) = im.size

                    url = await self.upload_file(image, mime_type)

                    image = {
                        "body": os.path.basename(image),
                        "msgtype": "m.image",
                        "url": url,
                        "info": {
                            "size": file_stat.st_size,
                            "mimetype": mime_type,
                            "w": width,  # width in pixel
                            "h": height,  # height in pixel
                        },
                    }

                    resp = await self.matrix.room_send(
                        room_id=room_id,
                        message_type="m.room.message",
                        content=image,
                        ignore_unverified_devices=True)
                    if isinstance(resp, ErrorResponse):
                        self.log.error(f"Could not send image: {resp}")
                    else:
                        SENT_IMAGES_COUNT.inc()

            resp = await self.matrix.room_send(room_id=room_id,
                                               message_type="m.room.message",
                                               content={
                                                   "msgtype":
                                                   "m.text",
                                                   "body":
                                                   adapt_text(str(message),
                                                              just_strip=True),
                                                   "format":
                                                   "org.matrix.custom.html",
                                                   "formatted_body":
                                                   str(message).replace(
                                                       "\n", "<br />")
                                               },
                                               ignore_unverified_devices=True)
            if isinstance(resp, ErrorResponse):
                self.log.error(f"Could not send message: {resp}")
                FAILED_MESSAGE_COUNT.inc()
            else:
                SENT_MESSAGE_COUNT.inc()
Esempio n. 10
0
def format_response(bot_response: BotResponse, just_strip: bool):
    bot_response.message = adapt_text(str(bot_response), just_strip=just_strip)
    return bot_response
Esempio n. 11
0
 async def send_to_dev(self, message: str, bot: semaphore.Bot):
     await bot.send_message(self.dev_chat, adapt_text(message))
Esempio n. 12
0
    async def send_unconfirmed_reports(self) -> None:
        """
        Send unconfirmed daily reports to the specific users
        """
        if not self.bot.user_messages_available():
            return

        async with semaphore.Bot(self.phone_number, socket_path=self.socket,
                                 profile_name=self.profile_name,
                                 profile_picture=self.profile_picture,
                                 raise_errors=True) as bot:
            backoff_time = random.uniform(2, 6)
            message_counter = 0
            for report_type, userid, message in self.bot.get_available_user_messages():
                self.log.info(f"Try to send report {message_counter}")
                disable_unicode = not self.bot.get_user_setting(userid,
                                                                BotUserSettings.FORMATTING)
                for elem in message:
                    success = False
                    rate_limited = False
                    try:
                        success = await bot.send_message(userid, adapt_text(elem.message,
                                                                            just_strip=disable_unicode),
                                                         attachments=elem.images)
                    except InternalError as e:
                        if "org.whispersystems.signalservice.api.push.exceptions.RateLimitException" in e.exceptions:
                            rate_limited = True
                            break
                        elif "org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException" in e.exceptions \
                                or "org.whispersystems.signalservice.api.push.exceptions.NotFoundException" in e.exceptions:
                            self.log.warning(
                                f"Account does not exist anymore, delete it: {userid}")
                            self.bot.delete_user(userid)
                            break
                        elif "org.whispersystems.signalservice.api.push.exceptions.ProofRequiredException" in e.exceptions:
                            self.log.warning(f"ProofRequired for {userid}")
                            break
                        else:
                            raise e
                    except RateLimitError as e:
                        self.log.error(f"Invalid Send Request: {e.message}")
                        rate_limited = True
                        break
                    except NoSuchAccountError as e:
                        self.log.warning(
                            f"Account does not exist anymore, delete it: {e.account}")
                        self.bot.delete_user(userid)
                        break
                    except UnknownGroupError:
                        self.log.warning(
                            f"Group does not exist anymore, delete it: {userid}")
                        self.bot.delete_user(userid)
                        break
                    except (NoSendPermissionError, InvalidRecipientError) as e:
                        self.log.warning(
                            f"We cant send to {userid}, disabling user: {e.message}")
                        self.bot.disable_user(userid)
                        break
                    except UnknownError as e:
                        self.log.error(f"Unknown Signald Error {e.error_type}: {e.error}")
                        raise e
                    except SignaldError as e:
                        self.log.error(f"Unknown Signald Error {e}")
                        raise e

                if success:
                    self.log.warning(f"({message_counter}) Sent daily report to {userid}")
                    self.bot.confirm_message_send(report_type, userid)
                else:
                    self.log.error(
                        f"({message_counter}) Error sending daily report to {userid}")

                backoff_time = self.backoff_timer(backoff_time, rate_limited)
                message_counter += 1
Esempio n. 13
0
 async def sendMessageToDev(self, message: str):
     await TextMessage(self.connection,
                       text=adapt_text(message, True),
                       to_id=self.dev_chat).send()