feat(voicefix): Add channel linker.
This commit is contained in:
@@ -19,6 +19,7 @@ active = [
|
|||||||
'.video_channels',
|
'.video_channels',
|
||||||
'.meta',
|
'.meta',
|
||||||
'.blanket',
|
'.blanket',
|
||||||
|
'.voicefix',
|
||||||
'.test',
|
'.test',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
7
src/modules/voicefix/__init__.py
Normal file
7
src/modules/voicefix/__init__.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
async def setup(bot):
|
||||||
|
from .cog import VoiceFixCog
|
||||||
|
await bot.add_cog(VoiceFixCog(bot))
|
||||||
165
src/modules/voicefix/cog.py
Normal file
165
src/modules/voicefix/cog.py
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
from typing import Optional
|
||||||
|
import asyncio
|
||||||
|
from cachetools import FIFOCache
|
||||||
|
|
||||||
|
import discord
|
||||||
|
from discord.ext import commands as cmds
|
||||||
|
from discord import app_commands as appcmds
|
||||||
|
|
||||||
|
from meta import LionBot, LionCog, LionContext
|
||||||
|
from . import logger
|
||||||
|
|
||||||
|
|
||||||
|
async def prepare_attachments(attachments: list[discord.Attachment]):
|
||||||
|
results = []
|
||||||
|
for attach in attachments:
|
||||||
|
try:
|
||||||
|
as_file = await attach.to_file(spoiler=attach.is_spoiler())
|
||||||
|
results.append(as_file)
|
||||||
|
except discord.HTTPException:
|
||||||
|
pass
|
||||||
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
async def prepare_embeds(message: discord.Message):
|
||||||
|
embeds = [embed for embed in message.embeds if embed.type == 'rich']
|
||||||
|
if message.reference:
|
||||||
|
embed = discord.Embed(
|
||||||
|
colour=discord.Colour.dark_gray(),
|
||||||
|
description=f"Reply to {message.reference.jump_url}"
|
||||||
|
)
|
||||||
|
embeds.append(embed)
|
||||||
|
return embeds
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class VoiceFixCog(LionCog):
|
||||||
|
def __init__(self, bot: LionBot):
|
||||||
|
self.bot = bot
|
||||||
|
|
||||||
|
# Map of linkids to list of channelids
|
||||||
|
self.link_channels = {}
|
||||||
|
|
||||||
|
# Map of channelids to linkids
|
||||||
|
self.channel_links = {}
|
||||||
|
|
||||||
|
# Map of channelids to initialised discord.Webhook
|
||||||
|
self.hooks = {}
|
||||||
|
|
||||||
|
# Map of messageid to list of (channelid, webhookmsg) pairs, for updates
|
||||||
|
self.message_cache = FIFOCache(maxsize=200)
|
||||||
|
# webhook msgid -> orig msgid
|
||||||
|
self.wmessages = FIFOCache(maxsize=600)
|
||||||
|
|
||||||
|
self.lock = asyncio.Lock()
|
||||||
|
|
||||||
|
|
||||||
|
async def cog_load(self):
|
||||||
|
# TODO: Just manually filling here, but move to data eventually
|
||||||
|
self.link_channels = {
|
||||||
|
1: (
|
||||||
|
1122589406809821184, 1101422204471750728
|
||||||
|
)
|
||||||
|
}
|
||||||
|
self.channel_links = {
|
||||||
|
1122589406809821184: (1,),
|
||||||
|
1101422204471750728: (1,)
|
||||||
|
}
|
||||||
|
self.hooks[1101422204471750728] = discord.Webhook.from_url(
|
||||||
|
"https://discord.com/api/webhooks/1154751966153560105/DPIIo0IyE5-jfIb6vjeHYBXqME9wwYEMSXLJyotu2T9kn84ZczkZgypzb4misErOiE9l",
|
||||||
|
client=self.bot
|
||||||
|
)
|
||||||
|
self.hooks[1122589406809821184] = discord.Webhook.from_url(
|
||||||
|
"https://discord.com/api/webhooks/1154752336628039680/mVVYsY5D3NRP-n3RAk-4Nvv7jrQ6F2y1AFVXZ5X9IFAHlk4jd23onfgsYaknBB7HZQKw",
|
||||||
|
client=self.bot
|
||||||
|
)
|
||||||
|
|
||||||
|
@LionCog.listener('on_message')
|
||||||
|
async def on_message(self, message: discord.Message):
|
||||||
|
# Don't need this because everything except explicit messages are webhooks now
|
||||||
|
# if self.bot.user and (message.author.id == self.bot.user.id):
|
||||||
|
# return
|
||||||
|
if message.webhook_id:
|
||||||
|
return
|
||||||
|
|
||||||
|
async with self.lock:
|
||||||
|
sent = []
|
||||||
|
linkids = self.channel_links.get(message.channel.id, ())
|
||||||
|
if linkids:
|
||||||
|
if message.attachments:
|
||||||
|
files = await prepare_attachments(message.attachments)
|
||||||
|
else:
|
||||||
|
files = []
|
||||||
|
|
||||||
|
for linkid in linkids:
|
||||||
|
for channelid in self.link_channels[linkid]:
|
||||||
|
if channelid != message.channel.id:
|
||||||
|
hook = self.hooks[channelid]
|
||||||
|
avatar = message.author.avatar or message.author.default_avatar
|
||||||
|
msg = await hook.send(
|
||||||
|
content=message.content,
|
||||||
|
wait=True,
|
||||||
|
username=message.author.display_name,
|
||||||
|
avatar_url=avatar.url,
|
||||||
|
embeds=await prepare_embeds(message),
|
||||||
|
files=files,
|
||||||
|
allowed_mentions=discord.AllowedMentions.none()
|
||||||
|
)
|
||||||
|
sent.append((channelid, msg))
|
||||||
|
self.wmessages[msg.id] = message.id
|
||||||
|
if sent:
|
||||||
|
# For easier lookup
|
||||||
|
self.wmessages[message.id] = message.id
|
||||||
|
sent.append((message.channel.id, message))
|
||||||
|
|
||||||
|
self.message_cache[message.id] = sent
|
||||||
|
logger.info(f"Forwarded message {message.id}")
|
||||||
|
|
||||||
|
|
||||||
|
@LionCog.listener('on_message_edit')
|
||||||
|
async def on_message_edit(self, before, after):
|
||||||
|
async with self.lock:
|
||||||
|
cached_sent = self.message_cache.pop(before.id, ())
|
||||||
|
new_sent = []
|
||||||
|
for cid, msg in cached_sent:
|
||||||
|
try:
|
||||||
|
if msg.id != before.id:
|
||||||
|
msg = await msg.edit(
|
||||||
|
content=after.content,
|
||||||
|
embeds=await prepare_embeds(after),
|
||||||
|
)
|
||||||
|
new_sent.append((cid, msg))
|
||||||
|
except discord.NotFound:
|
||||||
|
pass
|
||||||
|
if new_sent:
|
||||||
|
self.message_cache[after.id] = new_sent
|
||||||
|
|
||||||
|
@LionCog.listener('on_message_delete')
|
||||||
|
async def on_message_delete(self, message):
|
||||||
|
async with self.lock:
|
||||||
|
origid = self.wmessages.get(message.id, None)
|
||||||
|
if origid:
|
||||||
|
cached_sent = self.message_cache.pop(origid, ())
|
||||||
|
for _, msg in cached_sent:
|
||||||
|
try:
|
||||||
|
if msg.id != message.id:
|
||||||
|
await msg.delete()
|
||||||
|
except discord.NotFound:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@LionCog.listener('on_reaction_add')
|
||||||
|
async def on_reaction_add(self, reaction: discord.Reaction, user: discord.User):
|
||||||
|
async with self.lock:
|
||||||
|
message = reaction.message
|
||||||
|
emoji = reaction.emoji
|
||||||
|
origid = self.wmessages.get(message.id, None)
|
||||||
|
if origid and reaction.count == 1:
|
||||||
|
cached_sent = self.message_cache.get(origid, ())
|
||||||
|
for _, msg in cached_sent:
|
||||||
|
# TODO: Would be better to have a Message and check the reactions
|
||||||
|
try:
|
||||||
|
if msg.id != message.id:
|
||||||
|
await msg.add_reaction(emoji)
|
||||||
|
except discord.HTTPException:
|
||||||
|
pass
|
||||||
|
|
||||||
Reference in New Issue
Block a user