This commit is contained in:
git-bruh 2020-12-01 13:57:36 +05:30
parent 6cf4855aa4
commit 5af126cee3
No known key found for this signature in database
GPG key ID: E1475C50075ADCE6

257
main.py
View file

@ -36,38 +36,32 @@ matrix_logger = logging.getLogger("matrix_logger")
message_store = {} message_store = {}
class MatrixClient(object): class MatrixClient(nio.AsyncClient):
async def create(self): async def create(self):
homeserver = config["homeserver"]
username = config["username"]
password = config["password"] password = config["password"]
timeout = 30000 timeout = 30000
global matrix_client matrix_logger.info(await self.login(password))
matrix_client = nio.AsyncClient(homeserver, username)
matrix_logger.info(await matrix_client.login(password))
matrix_logger.info("Doing initial sync.") matrix_logger.info("Doing initial sync.")
await matrix_client.sync(timeout) await self.sync(timeout)
# Set up event callbacks # Set up event callbacks
callbacks = Callbacks() callbacks = Callbacks(self, self.process_message)
matrix_client.add_event_callback( self.add_event_callback(
callbacks.message_callback, callbacks.message_callback,
(nio.RoomMessageText, nio.RoomMessageMedia)) (nio.RoomMessageText, nio.RoomMessageMedia))
matrix_client.add_event_callback( self.add_event_callback(
callbacks.redaction_callback, nio.RedactionEvent) callbacks.redaction_callback, nio.RedactionEvent)
matrix_client.add_ephemeral_callback( self.add_ephemeral_callback(
callbacks.typing_callback, nio.EphemeralEvent) callbacks.typing_callback, nio.EphemeralEvent)
matrix_logger.info("Syncing forever.") matrix_logger.info("Syncing forever.")
await matrix_client.sync_forever(timeout=timeout) await self.sync_forever(timeout=timeout)
await matrix_client.close() await self.close()
async def message_send(self, message, reply_id=None, edit_id=None): async def message_send(self, message, reply_id=None, edit_id=None):
content = { content = {
@ -76,7 +70,7 @@ class MatrixClient(object):
} }
if reply_id: if reply_id:
reply_event = await matrix_client.room_get_event( reply_event = await self.room_get_event(
config["room_id"], reply_id config["room_id"], reply_id
) )
@ -107,7 +101,7 @@ class MatrixClient(object):
"rel_type": "m.replace", "rel_type": "m.replace",
} }
message = await matrix_client.room_send( message = await self.room_send(
room_id=config["room_id"], room_id=config["room_id"],
message_type="m.room.message", message_type="m.room.message",
content=content content=content
@ -116,7 +110,7 @@ class MatrixClient(object):
return message.event_id return message.event_id
async def message_redact(self, message): async def message_redact(self, message):
await matrix_client.room_redact( await self.room_redact(
room_id=config["room_id"], room_id=config["room_id"],
event_id=message event_id=message
) )
@ -137,12 +131,36 @@ class MatrixClient(object):
except discord.errors.HTTPException as e: except discord.errors.HTTPException as e:
matrix_logger.warning(f"Failed to send message {event_id}: {e}") matrix_logger.warning(f"Failed to send message {event_id}: {e}")
async def process_message(self, message):
mentions = re.findall(r"(^|\s)(@(\w*))", message)
emotes = re.findall(r":(.*?):", message)
guild = channel.guild
for emote in emotes:
emote_ = discord.utils.get(guild.emojis, name=emote)
if emote_:
message = message.replace(f":{emote}:", str(emote_))
for mention in mentions:
member = await guild.query_members(query=mention[2])
if member:
message = message.replace(mention[1], member[0].mention)
message = message.replace("@everyone", "@\u200Beveryone")
message = message.replace("@here", "@\u200Bhere")
return message
class DiscordClient(discord.Client): class DiscordClient(discord.Client):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.bg_task = self.loop.create_task(MatrixClient().create()) self.matrix_client = MatrixClient(
config["homeserver"], config["username"])
self.bg_task = self.loop.create_task(self.matrix_client.create())
async def on_ready(self): async def on_ready(self):
print(f"Logged in as {self.user}") print(f"Logged in as {self.user}")
@ -156,9 +174,9 @@ class DiscordClient(discord.Client):
config["channel_id"]: config["channel_id"]:
return return
content = await Process().discord(message) content = await self.process_message(message)
matrix_message = await MatrixClient().message_send( matrix_message = await self.matrix_client.message_send(
content[0], content[1]) content[0], content[1])
message_store[message.id] = matrix_message message_store[message.id] = matrix_message
@ -168,114 +186,23 @@ class DiscordClient(discord.Client):
config["channel_id"]: config["channel_id"]:
return return
content = await Process().discord(after) content = await self.process_message(after)
await MatrixClient().message_send( await self.matrix_client().message_send(
content[0], edit_id=message_store[before.id]) content[0], edit_id=message_store[before.id])
async def on_message_delete(self, message): async def on_message_delete(self, message):
if message.id in message_store: if message.id in message_store:
await MatrixClient().message_redact(message_store[message.id]) await self.matrix_client.message_redact(message_store[message.id])
async def on_typing(self, channel, user, when): async def on_typing(self, channel, user, when):
if user.bot or str(channel.id) != config["channel_id"]: if user.bot or str(channel.id) != config["channel_id"]:
return return
# Send typing event # Send typing event
await matrix_client.room_typing(config["room_id"], timeout=0) await self.matrix_client.room_typing(config["room_id"], timeout=0)
async def process_message(self, message):
class Callbacks(object):
async def message_callback(self, room, event):
# Don't act on activities in other rooms
if room.room_id != config["room_id"]:
return
# https://github.com/Rapptz/discord.py/issues/6058
# content_dict = event.source.get("content")
# try:
# if content_dict["m.relates_to"]["rel_type"] == "m.replace":
# edited_event = content_dict["m.relates_to"]["event_id"]
# edited_content = content_dict["m.new_content"]["body"]
# webhook_message = message_cache[edited_event]
# await something_edit_webhook(webhook_message, edited_content)
# return
# except KeyError:
# pass
message = event.body
if not message:
return
# Don't act on ourselves
if event.sender == matrix_client.user:
return
author = event.sender[1:]
avatar = None
homeserver = author.split(":")[-1]
url = "https://matrix.org/_matrix/media/r0/download"
message = await Process().matrix(message)
# Get attachments
try:
attachment = event.url.split("/")[-1]
# Highlight attachment name
message = f"`{message}`"
message += f"\n{url}/{homeserver}/{attachment}"
except AttributeError:
pass
# Get avatar
for user in room.users.values():
if user.user_id == event.sender:
if user.avatar_url:
avatar = user.avatar_url.split("/")[-1]
avatar = f"{url}/{homeserver}/{avatar}"
break
await MatrixClient().webhook_send(
author, avatar, message, event.event_id)
async def redaction_callback(self, room, event):
# Don't act on activities in other rooms
if room.room_id != config["room_id"]:
return
# Don't act on ourselves
if event.sender == matrix_client.user:
return
# Redact webhook message
try:
message = message_store[event.redacts]
await message.delete()
except KeyError:
pass
async def typing_callback(self, room, event):
# Don't act on activities in other rooms
if room.room_id != config["room_id"]:
return
if room.typing_users:
# Don't act on ourselves
if len(room.typing_users) == 1 \
and room.typing_users[0] == matrix_client.user:
return
# Send typing event
async with channel.typing():
pass
class Process(object):
async def discord(self, message):
content = message.clean_content content = message.clean_content
replied_event = None replied_event = None
@ -298,26 +225,92 @@ class Process(object):
return content, replied_event return content, replied_event
async def matrix(self, message):
mentions = re.findall(r"(^|\s)(@(\w*))", message)
emotes = re.findall(r":(.*?):", message)
guild = channel.guild class Callbacks(object):
def __init__(self, client, process_message):
self.client = client
self.process_message = process_message
for emote in emotes: async def message_callback(self, room, event):
emote_ = discord.utils.get(guild.emojis, name=emote) # Ignore messages from ourselves or other rooms
if emote_: if room.room_id != config["room_id"] or \
message = message.replace(f":{emote}:", str(emote_)) event.sender == self.client.user:
return
for mention in mentions: # https://github.com/Rapptz/discord.py/issues/6058
member = await guild.query_members(query=mention[2]) # content_dict = event.source.get("content")
if member: # try:
message = message.replace(mention[1], member[0].mention) # if content_dict["m.relates_to"]["rel_type"] == "m.replace":
# edited_event = content_dict["m.relates_to"]["event_id"]
# edited_content = content_dict["m.new_content"]["body"]
# webhook_message = message_cache[edited_event]
# await something_edit_webhook(webhook_message, edited_content)
# return
# except KeyError:
# pass
message = message.replace("@everyone", "@\u200Beveryone") message = event.body
message = message.replace("@here", "@\u200Bhere")
return message if not message:
return
author = event.sender[1:]
avatar = None
homeserver = author.split(":")[-1]
url = "https://matrix.org/_matrix/media/r0/download"
message = await self.process_message(message)
# Get attachments
try:
attachment = event.url.split("/")[-1]
# Highlight attachment name
message = f"`{message}`"
message += f"\n{url}/{homeserver}/{attachment}"
except AttributeError:
pass
# Get avatar
for user in room.users.values():
if user.user_id == event.sender:
if user.avatar_url:
avatar = user.avatar_url.split("/")[-1]
avatar = f"{url}/{homeserver}/{avatar}"
break
await self.client.webhook_send(
author, avatar, message, event.event_id)
async def redaction_callback(self, room, event):
# Ignore messages from ourselves or other rooms
if room.room_id != config["room_id"] or \
event.sender == self.client.user:
return
# Redact webhook message
try:
message = message_store[event.redacts]
await message.delete()
except KeyError:
pass
async def typing_callback(self, room, event):
# Ignore events from other rooms
if room.room_id != config["room_id"]:
return
if room.typing_users:
# Ignore events from ourselves
if len(room.typing_users) == 1 \
and room.typing_users[0] == self.client.user:
return
# Send typing event
async with channel.typing():
pass
def main(): def main():