No Description

app.py 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. """
  2. Copyright 2018 Alex Taber ("astronautlevel")
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. """
  13. from matrix_client.client import MatrixClient
  14. import discord
  15. import requests
  16. import re
  17. from config import *
  18. matrix_client = MatrixClient(matrix_homeserver)
  19. token = matrix_client.login(matrix_username, matrix_password)
  20. discord_client = discord.Client()
  21. matrix_room = matrix_client.join_room(matrix_room_id)
  22. matrix_file_types = ('m.file', 'm.image', 'm.video', 'm.audio')
  23. message_id_cache = {}
  24. unmatched_messages_cache = {}
  25. message_delete_queue = []
  26. def prepare_matrix_content(message):
  27. reg = re.match(r"^<a?:\w+:(\d+)>$", message.content)
  28. if reg:
  29. return "https://cdn.discordapp.com/emojis/{}.png?size=32".format(reg.group(1))
  30. attachments = "\n".join([x.url for x in message.attachments])
  31. content = message.clean_content + ("\n" + attachments if attachments != "" else "")
  32. content = re.sub(r"<a?(:\w+:)\d*>", r"\g<1>", content)
  33. return content
  34. guild = None
  35. channel = None
  36. emojis = {}
  37. @discord_client.event
  38. async def on_ready():
  39. global guild
  40. global emojis
  41. global webhook
  42. global channel
  43. channel = discord_client.get_channel(discord_channel)
  44. guild = channel.guild
  45. for emoji in guild.emojis:
  46. if not emoji.animated:
  47. emojis[":{}:".format(emoji.name)] = "<:{}:{}>".format(emoji.name, emoji.id)
  48. else:
  49. emojis[":{}:".format(emoji.name)] = "<a:{}:{}>".format(emoji.name, emoji.id)
  50. @discord_client.event
  51. async def on_message(message):
  52. for message_id in message_delete_queue:
  53. message_delete_queue.remove(message_id)
  54. message = await channel.get_message(message_id)
  55. await message.delete()
  56. if message.author.name in unmatched_messages_cache.keys():
  57. message_id_cache[unmatched_messages_cache[message.author.name]] = message.id
  58. del unmatched_messages_cache[message.author.name]
  59. if message.author.discriminator == "0000" or message.channel.id != discord_channel: return
  60. username = message.author.name[:1] + "\u200B" + message.author.name[1:] + "#" + message.author.discriminator
  61. content = prepare_matrix_content(message)
  62. matrix_message_id = matrix_room.send_text("<{}> {}".format(username, content))['event_id']
  63. message_id_cache[message.id] = matrix_message_id
  64. @discord_client.event
  65. async def on_message_edit(before, after):
  66. if after.author.discriminator == "0000" or after.channel.id != discord_channel: return
  67. if after.content == before.content: return
  68. after.attachments = []
  69. username = after.author.name[:1] + "\u200B" + after.author.name[1:] + "#" + after.author.discriminator
  70. content = prepare_matrix_content(after)
  71. matrix_room.redact_message(message_id_cache[before.id], reason="Message Edited")
  72. message_id_cache[after.id] = matrix_room.send_text("<{}> {} (edited)".format(username, content))['event_id']
  73. @discord_client.event
  74. async def on_raw_message_delete(paylod):
  75. if payload.message_id in message_id_cache.keys():
  76. matrix_room.redact_message(message_id_cache[paylod.message_id], reason="Message Deleted")
  77. def send_webhook(username, avatar_url, content, matrix_id):
  78. unmatched_messages_cache[username] = matrix_id;
  79. payload = {}
  80. payload['content'] = content
  81. payload['avatar_url'] = avatar_url
  82. payload['username'] = username
  83. for tries in range(5):
  84. r = requests.post(webhook_url, data = payload)
  85. if r.ok:
  86. return
  87. else:
  88. print(r.status_code)
  89. def prepare_discord_content(content):
  90. content = content.replace("@everyone", "@\u200Beveryone")
  91. content = content.replace("@here", "@\u200Bhere")
  92. content = re.sub("</?del>", "~~", content)
  93. mentions = re.findall("(^|\s)(@(\w*))", content)
  94. for mention in mentions:
  95. member = guild.get_member_named(mention[2])
  96. if not member: continue
  97. content = content.replace(mention[1], member.mention)
  98. for emoji_name, emoji_id in emojis.items():
  99. if emoji_name in content:
  100. content = content.replace(emoji_name, emoji_id)
  101. return content
  102. def on_matrix_message(room, event):
  103. user = matrix_client.get_user(event['sender'])
  104. if event['type'] == "m.room.message" and not user.user_id == matrix_user_id:
  105. if event['content']['msgtype'] == "m.text":
  106. username = "{}{}".format(discord_prefix, user.get_display_name())
  107. avatar = user.get_avatar_url()
  108. content = prepare_discord_content(event['content']['body'])
  109. send_webhook(username, avatar, content, event['event_id'])
  110. if event['content']['msgtype'] in matrix_file_types:
  111. username = "{}{}".format(discord_prefix, user.get_display_name())
  112. avatar = user.get_avatar_url()
  113. content = matrix_homeserver + "/_matrix/media/v1/download/" + event['content']['url'][6:]
  114. send_webhook(username, avatar, content, event['event_id'])
  115. if event['type'] == "m.room.redaction" and not user.user_id == matrix_user_id:
  116. try:
  117. message_delete_queue.append(message_id_cache[event['redacts']])
  118. except KeyError:
  119. pass
  120. matrix_room.add_listener(on_matrix_message)
  121. matrix_client.start_listener_thread()
  122. discord_client.run(discord_token)