Example #1
0
async def _print_comic(bot, event, num=None):
    info = await _get_comic(bot, num)
    image_id = info['image_id']

    context = {
        "parser": False,
    }

    msg1 = [
        ChatMessageSegment("xkcd #%s: " % info['num']),
        ChatMessageSegment(info["title"], is_bold=True),
    ]
    msg2 = [
        ChatMessageSegment(info["alt"]),
    ] + ChatMessageSegment.from_str(
        '\n- <i><a href="https://xkcd.com/%s">CC-BY-SA xkcd</a></i>' %
        info['num'])
    if "link" in info and info["link"]:
        msg2.extend(
            ChatMessageSegment.from_str("\n* see also %s" % info["link"]))

    await bot.coro_send_message(event.conv.id_, msg1, context)
    await bot.coro_send_message(
        event.conv.id_, msg2, context, image_id=image_id
    )  # image appears above text, so order is [msg1, image, msg2]
Example #2
0
    async def _async_send_message(self, message, targets):
        conversations = []
        for target in targets:
            conversation = None
            if 'id' in target:
                conversation = self._conversation_list.get(target['id'])
            elif 'name' in target:
                conversation = self._resolve_conversation_name(target['name'])
            if conversation is not None:
                conversations.append(conversation)

        if not conversations:
            return False

        from hangups import ChatMessageSegment, hangouts_pb2
        messages = []
        for segment in message:
            if 'parse_str' in segment and segment['parse_str']:
                messages.extend(ChatMessageSegment.from_str(segment['text']))
            else:
                if 'parse_str' in segment:
                    del segment['parse_str']
                messages.append(ChatMessageSegment(**segment))
            messages.append(ChatMessageSegment('',
                                               segment_type=hangouts_pb2.
                                               SEGMENT_TYPE_LINE_BREAK))

        if not messages:
            return False
        for conv in conversations:
            await conv.send_message(messages)
Example #3
0
    async def _async_send_message(self, message, targets, data):
        conversations = []
        for target in targets:
            conversation = None
            if CONF_CONVERSATION_ID in target:
                conversation = self._conversation_list.get(target[CONF_CONVERSATION_ID])
            elif CONF_CONVERSATION_NAME in target:
                conversation = self._resolve_conversation_name(
                    target[CONF_CONVERSATION_NAME]
                )
            if conversation is not None:
                conversations.append(conversation)

        if not conversations:
            return False

        from hangups import ChatMessageSegment, hangouts_pb2

        messages = []
        for segment in message:
            if messages:
                messages.append(
                    ChatMessageSegment(
                        "", segment_type=hangouts_pb2.SEGMENT_TYPE_LINE_BREAK
                    )
                )
            if "parse_str" in segment and segment["parse_str"]:
                messages.extend(ChatMessageSegment.from_str(segment["text"]))
            else:
                if "parse_str" in segment:
                    del segment["parse_str"]
                messages.append(ChatMessageSegment(**segment))

        image_file = None
        if data:
            if data.get("image_url"):
                uri = data.get("image_url")
                try:
                    websession = async_get_clientsession(self.hass)
                    async with websession.get(uri, timeout=5) as response:
                        if response.status != 200:
                            _LOGGER.error(
                                "Fetch image failed, %s, %s", response.status, response
                            )
                            image_file = None
                        else:
                            image_data = await response.read()
                            image_file = io.BytesIO(image_data)
                            image_file.name = "image.png"
                except (asyncio.TimeoutError, aiohttp.ClientError) as error:
                    _LOGGER.error("Failed to fetch image, %s", type(error))
                    image_file = None
            elif data.get("image_file"):
                uri = data.get("image_file")
                if self.hass.config.is_allowed_path(uri):
                    try:
                        image_file = open(uri, "rb")
                    except OSError as error:
                        _LOGGER.error(
                            "Image file I/O error(%s): %s", error.errno, error.strerror
                        )
                else:
                    _LOGGER.error('Path "%s" not allowed', uri)

        if not messages:
            return False
        for conv in conversations:
            await conv.send_message(messages, image_file)
Example #4
0
 def convert(self, source, slack):
     if isinstance(source, str):
         # Parse, then convert reparser.Segment to hangups.ChatMessageSegment.
         segments = [
             ChatMessageSegment(seg.text, **seg.params)
             for seg in self.parse(source)
         ]
     else:
         # We'll assume it's already a ChatMessageSegment list.
         segments = source
     formatted = ""
     current = []
     for seg in segments:
         if seg.type_ == hangouts_pb2.SEGMENT_TYPE_LINE_BREAK:
             # Insert closing tags for all current formatting, in reverse order.
             for chars in reversed(current):
                 formatted += chars
             # Start a new line.
             formatted += "\n"
             # Now reinsert the current formatting.
             for chars in current:
                 formatted += chars
             continue
         if self.from_slack:
             text = seg.text.replace("&gt;", ">").replace("&lt;",
                                                          "<").replace(
                                                              "&amp;", "&")
             if seg.link_target:
                 if seg.link_target[0] == "@":
                     # User link, just replace with the plain username.
                     user = seg.link_target[1:]
                     if user in slack.users:
                         user = slack.users[user]["name"]
                     text = "@{}".format(user)
                 elif seg.link_target[0] == "#":
                     # Channel link, just replace with the plain channel name.
                     channel = seg.link_target[1:]
                     if channel in slack.channels:
                         channel = slack.channels[channel]["name"]
                     text = "#{}".format(channel)
                 else:
                     # Markdown link: [label](target)
                     text = "[{}]({})".format(
                         text, message_parser.url_complete(seg.link_target))
         else:
             text = seg.text.replace("&", "&amp;").replace(">",
                                                           "&gt;").replace(
                                                               "<", "&lt;")
             if seg.link_target:
                 if text == seg.link_target:
                     # Slack implicit link: <target>
                     text = "<{}>".format(seg.link_target)
                 else:
                     # Slack link with label: <target|label>
                     text = "<{}|{}>".format(seg.link_target, text)
         # Compare formatting of the previous segment to the current one.
         formatting = {
             self.bold: seg.is_bold,
             self.italic: seg.is_italic,
             self.strike: seg.is_strikethrough
         }
         # Insert closing tags for any formatting that ends here.
         # Apply in reverse order to opened tags.
         for chars in reversed(current):
             if not formatting[chars]:
                 formatted += chars
                 current.remove(chars)
         # Insert opening tags for any formatting that starts here.
         for chars, condition in formatting.items():
             if condition and chars not in current:
                 formatted += chars
                 current.append(chars)
         # XXX: May generate tags closed in the wrong order: *bold _bold+italic* italic_
         # Testing suggests both Slack and Hangouts can cope with this though.
         formatted += text
     # Close any remaining format tags.
     formatted += "".join(reversed(current))
     return formatted