def handle_message(event_data): message = event_data["event"] if members.search(Q.id.matches(message["user"])) == []: return user = members.search(Q.id.matches(message["user"]))[0] if user != config.BOT_ID: if user["convState"] == 0: if message["text"] != "yes" and message["text"] != "Yes": slack_client.chat_postMessage( text= "Sorry you can only answer by yes :) please try again!", token=config.SLACK_BOT_TOKEN, channel=user["imChannelID"]) return user["convState"] = user["convState"] + 1 members.update({"convState": user["convState"]}, Q.id == user["id"]) slack_client.chat_postMessage( text=config.QUESTIONS[user["convState"]], token=config.SLACK_BOT_TOKEN, channel=user["imChannelID"]) return if user["convState"] == 1: user["convState"] = user["convState"] + 1 members.update( { "yesterday": slackdown.render(message['text']), "convState": user["convState"] }, Q.id == user["id"]) slack_client.chat_postMessage( text=config.QUESTIONS[user["convState"]], token=config.SLACK_BOT_TOKEN, channel=user["imChannelID"]) return if user["convState"] == 2: user["convState"] = user["convState"] + 1 members.update( { "today": slackdown.render(message['text']), "convState": user["convState"] }, Q.id == user["id"]) slack_client.chat_postMessage( text=config.QUESTIONS[user["convState"]], token=config.SLACK_BOT_TOKEN, channel=user["imChannelID"]) return if user["convState"] == 3: user["convState"] = user["convState"] + 1 members.update( { "blockers": slackdown.render(message['text']), "convState": user["convState"] }, Q.id == user["id"]) slack_client.chat_postMessage( text=config.QUESTIONS[user["convState"]], token=config.SLACK_BOT_TOKEN, channel=user["imChannelID"]) return return
def test_multiple_parents(self): txt = slackdown.render( 'A blockquote looks like this:\n> Someone else said this.') self.assertEqual( txt, '<p>A blockquote looks like this:</p><blockquote>Someone else said this.</blockquote>' )
def test_multiple_blockquotes(self): txt = slackdown.render( '> A couple of\n>>> Blockquotes until\nthe end of the message.' ) self.assertEqual( txt, '\ <blockquote>A couple of</blockquote><blockquote>Blockquotes until<br />the end of the message.</blockquote>' )
def test_multiple_same_lists(self): txt = slackdown.render('- item 1\n- item 2\n\n- item 3\n- item 4') self.assertEqual( txt, '\ <ul class="list-container-dash">\ <li>item 1</li>\ <li>item 2</li>\ </ul>\ <ul class="list-container-dash">\ <li>item 3</li>\ <li>item 4</li>\ </ul>\ ')
def test_multiple_diff_lists(self): txt = slackdown.render( 'These are *two* lists.\n- item 1\n- item 2\n1. item 3\n2. item 4\nRight?' ) self.maxDiff = None self.assertEqual( txt, '\ <p>These are <b>two</b> lists.</p>\ <ul class="list-container-dash">\ <li>item 1</li>\ <li>item 2</li>\ </ul>\ <ol class="list-container-numbered">\ <li>item 3</li>\ <li>item 4</li>\ </ol>\ <p>Right?</p>\ ')
def test_single_line_blockquote(self): txt = slackdown.render('> Someone else said this.') self.assertEqual(txt, '<blockquote>Someone else said this.</blockquote>')
def test_hyphen_list(self): txt = slackdown.render(u'- item 1\n- item 2') self.assertEqual( txt, '<ul class="list-container-dash"><li>item 1</li><li>item 2</li></ul>' )
def test_numbered_list(self): txt = slackdown.render(u'1. item 1\n24. item 2') self.assertEqual( txt, '<ol class="list-container-numbered"><li>item 1</li><li>item 2</li></ol>' )
def test_multi_line_code(self): txt = slackdown.render('```multiple\n*lines* of\ncode```') self.assertEqual(txt, '<pre>multiple<br />*lines* of<br />code</pre>')
def test_bullet_list(self): txt = slackdown.render(u'\u2022 item 1\n\u2022 item 2') self.assertEqual( txt, '<ul class="list-container-dot"><li>item 1</li><li>item 2</li></ul>' )
def parse_and_send_message(config, message, matrix_room, txnId, is_later): content = {} is_thread = False is_reply = False if message["type"] == "message": if "subtype" in message: if (message["subtype"] == "bot_message" or message["subtype"] == "bot_remove" or message["subtype"] == "slackbot_response" or message["subtype"] == "channel_name" or message["subtype"] == "channel_join" or message["subtype"] == "channel_purpose" or message["subtype"] == "group_name" or message["subtype"] == "group_join" or message["subtype"] == "group_purpose"): return txnId if message["subtype"] == "file_comment": # TODO migrate file_comments return txnId # ignore hidden messages if "hidden" in message: if message["hidden"] == True: return txnId # ignore hidden files message if "is_hidden_by_limit" in message: if message["is_hidden_by_limit"] == True: return txnId if "user" in message: #TODO what messages have no user? if not message["user"] in userLUT: # ignore messages from bots return txnId else: print("Message without user") print(message) # list of subtypes ''' bot_message A message was posted by an app or integration me_message A /me message was sent message_changed A message was changed message_deleted A message was deleted channel_join A member joined a channel channel_leave A member left a channel channel_topic A channel topic was updated channel_purpose A channel purpose was updated channel_name A channel was renamed channel_archive A channel was archived channel_unarchive A channel was unarchived group_join A member joined a group group_leave A member left a group group_topic A group topic was updated group_purpose A group purpose was updated group_name A group was renamed group_archive A group was archived group_unarchive A group was unarchived file_share A file was shared into a channel file_reply A reply was added to a file file_mention A file was mentioned in a channel pinned_item An item was pinned in a channel unpinned_item An item was unpinned from a channel ''' body = message["text"] # TODO do not migrate empty messages? #if body == "": # # return txnId # replace mentions body = body.replace("<!channel>", "@room") body = body.replace("<!here>", "@room") body = body.replace("<!everyone>", "@room") body = re.sub('<@[A-Z0-9]+>', replace_mention, body) if "files" in message: if "subtype" in message: print(message["subtype"]) if message["subtype"] == "file_comment" or message[ "subtype"] == "thread_broadcast": #TODO treat as reply print("") else: txnId = process_files(message["files"], matrix_room, userLUT[message["user"]], body, txnId, config) else: txnId = process_files(message["files"], matrix_room, userLUT[message["user"]], body, txnId, config) if "attachments" in message: if message["user"] in userLUT: # ignore attachments from bots txnId = process_attachments(message["attachments"], matrix_room, userLUT[message["user"]], body, txnId, config) for attachment in message["attachments"]: if "is_share" in attachment and attachment["is_share"]: if body: body += "\n" attachment_footer = "no footer" if "footer" in attachment: attachment_footer = attachment["footer"] attachment_text = "no text" if "text" in attachment: attachment_text = attachment["text"] body += "".join([ "> _Shared (", attachment_footer, "):_ ", attachment_text, "\n" ]) if "replies" in message: # this is the parent of a thread is_thread = True previous_message = None for reply in message["replies"]: if "user" in message and "ts" in message: first_message = message["user"] + message["ts"] current_message = reply["user"] + reply["ts"] if not previous_message: previous_message = first_message replyLUT[current_message] = previous_message if config_yaml["threads-reply-to-previous"]: previous_message = current_message # replys / threading if "thread_ts" in message and "parent_user_id" in message and not "replies" in message: # this message is a reply to another message is_reply = True if not message["user"] + message["ts"] in replyLUT: # seems like we don't know the thread yet, save event for later if not is_later: later.append(message) return txnId slack_event_id = replyLUT[message["user"] + message["ts"]] matrix_event_id = eventLUT[slack_event_id] # TODO pinned / stared items? # replace emojis body = emojize(body, use_aliases=True) # TODO some URLs with special characters (e.g. _ ) are parsed wrong formatted_body = slackdown.render(body) if not is_reply: content = { "body": body, "msgtype": "m.text", "format": "org.matrix.custom.html", "formatted_body": formatted_body, } else: replyEvent = threadLUT[message["parent_user_id"] + message["thread_ts"]] fallbackHtml = getFallbackHtml(matrix_room, replyEvent) fallbackText = getFallbackText(replyEvent) body = fallbackText + "\n\n" + body formatted_body = fallbackHtml + formatted_body content = { "m.relates_to": { "m.in_reply_to": { "event_id": matrix_event_id, }, }, "msgtype": "m.text", "body": body, "format": "org.matrix.custom.html", "formatted_body": formatted_body, } # send message ts = message["ts"].replace(".", "")[:-3] res = send_event(config, content, matrix_room, userLUT[message["user"]], "m.room.message", txnId, ts) # save event id if res == False: print("ERROR while sending event '" + message["user"] + " " + message["ts"] + "'") else: _content = json.loads(res.content) # use "user" combined with "ts" as id like Slack does as "client_msg_id" is not always set if "user" in message and "ts" in message: eventLUT[message["user"] + message["ts"]] = _content["event_id"] txnId = txnId + 1 if is_thread: threadLUT[message["user"] + message["ts"]] = { "body": body, "formatted_body": formatted_body, "sender": userLUT[message["user"]], "event_id": _content["event_id"] } # handle reactions if "reactions" in message: roomId = matrix_room eventId = eventLUT[message["user"] + message["ts"]] for reaction in message["reactions"]: for user in reaction["users"]: #print("Send reaction in room " + roomId) try: send_reaction( config, roomId, eventId, emojize(":" + reaction["name"] + ":", use_aliases=True), userLUT[user], txnId) txnId = txnId + 1 except KeyError: print("KeyError in reaction at " + message["ts"]) else: print("Ignoring message type " + message["type"]) return txnId
def test_all_bold(self): txt = slackdown.render('*All bold text*') self.assertEqual(txt, '<p><b>All bold text</b></p>')
def convert_slack_to_html(body): try: return slackdown.render(body) except: return body
def test_line_breaks(self): txt = slackdown.render('multiple\n\ntext\nlines') self.assertEqual(txt, '<p>multiple</p><p></p><p>text</p><p>lines</p>')
def test_italics(self): txt = slackdown.render('Some _italics_ text.') self.assertEqual(txt, '<p>Some <i>italics</i> text.</p>')
def test_hyperlinks(self): txt = slackdown.render('This is a tweet <https://example.com>.') self.assertEqual( txt, '\ <p>This is a tweet <a href="https://example.com" target="blank">https://example.com</a>.</p>\ ')
def test_escaping(self): txt = slackdown.render('The \*unbolded\* text should not be *bold*.') self.assertEqual( txt, '<p>The \*unbolded\* text should not be <b>bold</b>.</p>')
def test_bad_bold_wrapping(self): txt = slackdown.render('*Multiple lines\nof bold text.*') self.assertEqual(txt, '<p>*Multiple lines</p><p>of bold text.*</p>')
def test_bold_in_list(self): txt = slackdown.render(u'- *item 1*\n- item 2') self.assertEqual( txt, '<ul class="list-container-dash"><li><b>item 1</b></li><li>item 2</li></ul>' )
def test_multi_line_blockquote(self): txt = slackdown.render('>>> Someone else\nsaid this.') self.assertEqual( txt, '<blockquote>Someone else<br />said this.</blockquote>')
def test_spaces(self): txt = slackdown.render('large spaces between text') self.assertEqual( txt, '<p>large     spaces    between     text</p>' )
def convert_slack_to_html(body): try: return slackdown.render(body) except: return body
def test_single_line_code(self): txt = slackdown.render('Some `*code*` text.') self.assertEqual(txt, '<p>Some <code>*code*</code> text.</p>')
def test_strikethrough(self): txt = slackdown.render('Some ~strikethrough~ text.') self.assertEqual(txt, '<p>Some <s>strikethrough</s> text.</p>')
def test_bold(self): txt = slackdown.render('Some *bold* text.') self.assertEqual(txt, '<p>Some <b>bold</b> text.</p>')