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]
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)
def post(self, request, format=None): serializer = MessageSerializer(data=request.data) serializer.is_valid() message = serializer.data m = Members client = m.get_client(message.get('user_id')) if client: conversation = client._conv_list.get(message.get('conv_id')) loop = m.get_loop(message.get('user_id')) if conversation: # testできたら移動 text = message.get('message') image_file = None segments = ChatMessageSegment.from_str(text) asyncio.async( conversation.send_message(segments, image_file=image_file), loop=loop ).add_done_callback(self._on_message_sent) return HttpResponse("ok") # 該当するuser, conv_idがない場合 raise Http404
async def _async_send_message(self, message, targets): 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 '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)
def _print_comic(bot, event, num=None): info = yield from _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('<br/>- <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("<br/>* see also %s" % info["link"])) yield from bot.coro_send_message(event.conv.id_, msg1, context) yield from bot.coro_send_message(event.conv.id_, msg2, context, image_id=image_id) # image appears above text, so order is [msg1, image, msg2]
def _update(self, data) -> None: self.reachable = getattr(data, 'reachable', None) self.available = getattr(data, 'available', None) device_status = getattr(data, 'device_status', None) self.mobile = getattr(device_status, 'mobile', None) self.desktop = getattr(device_status, 'desktop', None) self.tablet = getattr(device_status, 'tablet', None) mood_message = getattr(data, 'mood_message', None) mood_content = getattr(mood_message, 'mood_content', None) segment = getattr(mood_content, 'segment', None) mood_segment = [ChatMessageSegment.deserialize(segment) for segment in segment] self.mood_message = [segment.text for segment in mood_segment] last_seen = getattr(data, 'last_seen', None) self.last_seen = parsers.from_timestamp(getattr(last_seen, 'last_seen_timestamp_usec', None)) self.since_last_seen = getattr(last_seen, 'usec_since_last_seen', None) // 1000000
def get(self, request): m = Members client = m.get_client('test') if client: conversation = client._conv_list.get('UgyUUHcz02x_EFXA-Ht4AaABAagB_N-DBw') if conversation: # testできたら移動 text = 'メッセージ送信テスト' image_file = None segments = ChatMessageSegment.from_str(text) loop = m.get_loop('test') asyncio.async( conversation.send_message(segments, image_file=image_file), loop=loop ).add_done_callback(self._on_message_sent) # 成功したら最新のconversationを返却 # 若干遅延するからやめておきたい serializer = ConversationSerializer(conversation) return JSONResponse(serializer.data) # 該当するuser, conv_idがない場合 raise Http404
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 IOError 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)
def text_to_segments(text): """Create list of message segments from text""" return ChatMessageSegment.from_str(text)
def receive(self, msg, conv, user): clients = [] for userObject in conv.users: nick = name_to_nick(userObject.full_name) clients.append(nick) sender = name_to_nick(user.full_name) imageLinks = re.findall("((?:https?:\/\/)?(?:[\da-z\.-]+)\.(?:[a-z\.]{2,6})(?:[\/\w\.-]+)(\.jpg|\.png|\.jpeg|\.gif)\/?)", msg) for link in imageLinks: if link[0].find("https://lh3.googleusercontent") == -1: tmp_file = "/home/lshetron/.monopoly/tmp/" + str(random.randint(0,100)) + link[1] try: with urllib.request.urlopen(link[0]) as response, open(tmp_file, "wb") as out: data = response.read() out.write(data) self.message("", open(tmp_file, "rb")) except urllib.error.URLError as e: print("Error opening file: ", e) except Exception as e: print("Exception encountered: ", e) for subscriber, conv_id in self.swift.subscribers: re_mentions = re.compile('{0}|{1}|{2}'.format(name_to_nick(subscriber), *subscriber.split()), re.IGNORECASE) if (re.search(re_mentions, msg) and user.full_name != subscriber and len(clients) > 2 and name_to_nick(subscriber) in clients): highlighted = re.sub(re_mentions, lambda x: '<b>' + x.group(0) + '</b>', msg) yield from self.swift.notify('<b>{0}</b> mentioned you in <i>{1}</i>:\n"{2}"' .format(user.full_name, conv.name, highlighted), conv_id) print("Forwarded hangouts mention to {0}".format(subscriber)) if re.search("!subscribe", msg, re.IGNORECASE): if user.full_name not in [name for name, id in self.swift.subscribers]: client_id = self.client.get_client_generated_id() inviteeID = hangouts_pb2.InviteeID(gaia_id=user.id_.gaia_id) conversation_request = hangouts_pb2.CreateConversationRequest( request_header = self.client.get_request_header(), type = CONVERSATION_TYPE_ONE_TO_ONE, client_generated_id = client_id, invitee_id = [inviteeID]) res = yield from self.client.create_conversation(conversation_request) conv_id = res.conversation.conversation_id.id welcome_msg = ChatMessageSegment.from_str( '<b>Welcome to Monopoly Swift Notifications!</b>\n' + '<i>This channel will be used to receive alerts for IRC private ' + 'messages, channel mentions, and hangouts mentions.</i>\n\n' + 'To unsubscribe,\njust say <b><i>!unsubscribe</i></b>') new_conv = self.conv_list.get(conv_id) asyncio.async(new_conv.send_message(welcome_msg, image_file=None)) if conv_id == conv.id_: self.subscribe(user.full_name, conv_id, True) else: self.subscribe(user.full_name, conv_id) else: self.message("<b>{0}</b> is already subscribed to receive alerts." .format(user.full_name)) elif re.search("!unsubscribe", msg, re.IGNORECASE): if user.full_name in [name for name, id in self.swift.subscribers]: for subscriber, id in self.swift.subscribers: if user.full_name == subscriber: self.unsubscribe(user.full_name, id) else: self.message("<b>{0}</b> is not currently subscribed to receive alerts." .format(user.full_name)) # Avoid outputting twice if re.search("trumpism", msg, re.IGNORECASE): if self.g_ratelimiter.queue(sender): self.message("<i>{0}</i>".format(self.donald.trumpism())) else: # TODO should ratelimit provoked = self.donald.provoke(msg) if provoked: self.message("<i>{0}</i>".format(provoked)) buffer = super().receive(msg, sender, clients) self.send(buffer, conv)
def _segments(self): """List of :class:`ChatMessageSegment` in message (:class:`list`).""" seg_list = self._event.chat_message.message_content.segment return [ChatMessageSegment.deserialize(seg) for seg in seg_list]
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(">", ">").replace("<", "<").replace( "&", "&") 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("&", "&").replace(">", ">").replace( "<", "<") 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
def notify(self, message, conv_id): segment = ChatMessageSegment.from_str(message) conv = self.h_conv_list.get(conv_id) asyncio.async(conv.send_message(segment, image_file=None))
def send(self, buffer, conv): for msg in buffer: segments = ChatMessageSegment.from_str(msg[0]) asyncio.async(conv.send_message(segments, image_file=msg[1]))
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)
def __init__(self, text: str): self.text: str = text self._segment: List[ChatMessageSegment] = ChatMessageSegment.from_str(text)