178 lines
5.4 KiB
Python
178 lines
5.4 KiB
Python
import os, re, hashlib, sys, traceback
|
|
import asyncio
|
|
import nextcord
|
|
|
|
class GatewayDiscord(nextcord.Client):
|
|
def __init__(self, plexus, settings, gateway_name, gateway_data):
|
|
nextcord.Client.__init__(self, loop = asyncio.get_event_loop(), intents = nextcord.Intents.all())
|
|
|
|
global PLEXUS
|
|
PLEXUS = plexus
|
|
|
|
self.settings = settings
|
|
|
|
self.gateway_name = gateway_name
|
|
|
|
self.discord_ready = False
|
|
|
|
self.room_name_to_pair = {}
|
|
self.pair_to_room_name = {}
|
|
|
|
self.discord_id_to_xdm_id = {}
|
|
self.xdm_id_to_discord_id = {}
|
|
|
|
self.my_puppets = {}
|
|
|
|
self.webhooks = {}
|
|
|
|
self.active_users = {}
|
|
|
|
self.new_user_queue = []
|
|
|
|
def new_user(identification, nick_name):
|
|
if identification[0] == "discord" and identification[1] == self.gateway_name:
|
|
return
|
|
|
|
self.new_user_queue.append(identification)
|
|
|
|
if self.discord_ready:
|
|
self.handle_new_user_queue()
|
|
PLEXUS.sub("new_user", new_user)
|
|
|
|
def message(msg_unique_id, room_name, nick_name, gateway_type, gateway_name, unique_id, body, attachments, was_edit):
|
|
if gateway_type == "discord" and gateway_name == self.gateway_name:
|
|
# Ignore ours
|
|
return
|
|
|
|
if len(attachments):
|
|
body = str(body) + "\n\n" + "\n".join([str(a) for a in attachments])
|
|
|
|
guild, channel = self.room_name_to_pair[room_name]
|
|
wh = self.webhooks[channel]
|
|
|
|
if was_edit:
|
|
if msg_unique_id not in self.xdm_id_to_discord_id:
|
|
# Too late
|
|
return
|
|
|
|
asyncio.ensure_future(wh.edit_message(self.xdm_id_to_discord_id[msg_unique_id], content = str(body)))
|
|
else:
|
|
def on_done(fut):
|
|
wh_msg = fut.result()
|
|
self.xdm_id_to_discord_id[msg_unique_id] = wh_msg.id
|
|
self.discord_id_to_xdm_id[wh_msg.id] = msg_unique_id
|
|
|
|
asyncio.ensure_future(wh.send(content = str(body), username = nick_name, wait = True, allowed_mentions = nextcord.AllowedMentions(everyone = False))).add_done_callback(on_done)
|
|
PLEXUS.sub("message", message)
|
|
|
|
PLEXUS.sub("ready", lambda: asyncio.ensure_future(self.start(gateway_data["token"])))
|
|
|
|
def handle_new_user_queue(self):
|
|
for identification in self.new_user_queue:
|
|
self.my_puppets[identification] = {}
|
|
self.new_user_queue.clear()
|
|
|
|
def ensure_user_is_active(self, member):
|
|
if member.id not in self.active_users:
|
|
self.active_users[member.id] = {}
|
|
PLEXUS.pub("new_user", ("discord", self.gateway_name, member.id), member.display_name)
|
|
|
|
async def on_message(self, message):
|
|
if message.author.bot:
|
|
# Ignore ours
|
|
return
|
|
|
|
if not isinstance(message.channel, nextcord.TextChannel):
|
|
return
|
|
|
|
guild_id = message.channel.guild.id
|
|
channel_id = message.channel.id
|
|
|
|
if (guild_id, channel_id) not in self.pair_to_room_name:
|
|
return
|
|
|
|
room_name = self.pair_to_room_name[(guild_id, channel_id)]
|
|
|
|
self.ensure_user_is_active(message.author)
|
|
|
|
msg_unique_id = os.urandom(16)
|
|
self.xdm_id_to_discord_id[msg_unique_id] = message.id
|
|
self.discord_id_to_xdm_id[message.id] = msg_unique_id
|
|
|
|
PLEXUS.pub("message", msg_unique_id, room_name, message.author.display_name, "discord", self.gateway_name, message.author.id, message.clean_content, [a.url for a in message.attachments], False)
|
|
|
|
async def on_message_edit(self, before, after):
|
|
if before.author.bot:
|
|
# Ignore ours
|
|
return
|
|
|
|
if not isinstance(before.channel, nextcord.TextChannel):
|
|
return
|
|
|
|
guild_id = after.channel.guild.id
|
|
channel_id = after.channel.id
|
|
|
|
if (guild_id, channel_id) not in self.pair_to_room_name:
|
|
return
|
|
|
|
if before.clean_content == after.clean_content:
|
|
return
|
|
|
|
# Message content was edited
|
|
|
|
if before.id not in self.discord_id_to_xdm_id:
|
|
return
|
|
|
|
msg_unique_id = self.discord_id_to_xdm_id[after.id]
|
|
room_name = self.pair_to_room_name[(guild_id, channel_id)]
|
|
PLEXUS.pub("message", msg_unique_id, room_name, after.author.display_name, "discord", self.gateway_name, after.author.id, after.clean_content, [a.url for a in after.attachments], True)
|
|
|
|
async def on_message_delete(self, message):
|
|
if message.author.bot:
|
|
# Ignore ours
|
|
return
|
|
|
|
if not isinstance(message.channel, nextcord.TextChannel):
|
|
return
|
|
|
|
guild_id = message.channel.guild.id
|
|
channel_id = message.channel.id
|
|
|
|
if (guild_id, channel_id) not in self.pair_to_room_name:
|
|
return
|
|
|
|
room_name = self.pair_to_room_name[(guild_id, channel_id)]
|
|
|
|
if message.author.id not in self.active_users:
|
|
return
|
|
|
|
if message.id not in self.discord_id_to_xdm_id:
|
|
return
|
|
|
|
msg_unique_id = self.discord_id_to_xdm_id[message.id]
|
|
PLEXUS.pub("message_delete", msg_unique_id, room_name, "discord", self.gateway_name, message.author.id)
|
|
|
|
async def on_ready(self):
|
|
for room_name, room_gateways in self.settings.ROOMS.items():
|
|
for gateway in room_gateways:
|
|
if "discord" in gateway and gateway["discord"] == self.gateway_name:
|
|
discord_channel = self.get_channel(gateway["channel"])
|
|
|
|
wh = None
|
|
for webhook in await discord_channel.webhooks():
|
|
if webhook.name == "xdm":
|
|
if not webhook.is_authenticated():
|
|
await webhook.delete(reason = "Must recreate")
|
|
else:
|
|
wh = webhook
|
|
if not wh:
|
|
wh = await discord_channel.create_webhook(name = "xdm", reason = "XDM bridge")
|
|
|
|
self.webhooks[gateway["channel"]] = wh
|
|
|
|
self.room_name_to_pair[room_name] = (gateway["guild"], gateway["channel"])
|
|
self.pair_to_room_name[(gateway["guild"], gateway["channel"])] = room_name
|
|
|
|
self.discord_ready = True
|
|
self.handle_new_user_queue()
|