From b5033ca34efab102ae61adf87bc95109b43ac6f2 Mon Sep 17 00:00:00 2001 From: tema5002 Date: Sun, 17 May 2026 16:09:25 +0300 Subject: [PATCH] initial commit --- .gitignore | 4 + IMG_20260303_181133_732.jpg | Bin 0 -> 58290 bytes LICENSE | 13 + main.py | 659 ++++++++++++++++++++++++++++++++++++ 4 files changed, 676 insertions(+) create mode 100644 .gitignore create mode 100755 IMG_20260303_181133_732.jpg create mode 100644 LICENSE create mode 100755 main.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..38b050c --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.venv +config.json +db.dat +emojis.dat diff --git a/IMG_20260303_181133_732.jpg b/IMG_20260303_181133_732.jpg new file mode 100755 index 0000000000000000000000000000000000000000..563e9e79bc8b618f47fa3e77daf97b753dc99b4d GIT binary patch literal 58290 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 ?X#QtrVJE(stQypJfRuXYC7v2qM)K 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 literal 0 HcmV?d00001 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ff9e935 --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + +Copyright (C) 2004 Sam Hocevar + +Everyone is permitted to copy and distribute verbatim or modified +copies of this license document, and changing it is allowed as long +as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. diff --git a/main.py b/main.py new file mode 100755 index 0000000..2c0f2a7 --- /dev/null +++ b/main.py @@ -0,0 +1,659 @@ +import pickle +import json +from typing import Callable, Awaitable +from dataclasses import dataclass, field +import discord +from discord.ext import commands +import traceback + +bot = commands.Bot(command_prefix="\0", intents=discord.Intents.all()) + + +@dataclass +class ReactionRole: + emoji: str + role_id: int + description: str + + def __str__(self): + return f"{self.emoji} - {self.description}" + + +@dataclass +class TrackedMessage: + guild_id: int + channel_id: int + message_id: int + header: str + own_message: bool + reactions: list[ReactionRole] = field(default_factory=list) + + def __str__(self): + return f"message at https://discord.com/channels/{self.guild_id}/{self.channel_id}/{self.message_id} with {len(self.reactions)} reaction roles" + + def __repr__(self): + return (self.header or " ") + '\n' + ("\n".join( + str(rr) for rr in self.reactions) or f"-# waiting for reactions, message id is {self.message_id}") + + +class Database: + def __init__(self, d: str): + self.__tracked_messages: dict[int, TrackedMessage] = {} + self.__file: str = d + self.__load() + + def __load(self) -> None: + try: + self.__tracked_messages = pickle.load(open(self.__file, "rb")) + except FileNotFoundError: + self.__tracked_messages = {} + + def __save(self) -> None: + pickle.dump(self.__tracked_messages, open(self.__file, "wb")) + + def track_message(self, guild_id: int, channel_id: int, message_id: int, header: str, own_message: bool) -> bool: + if message_id in self.__tracked_messages: + return True + self.__tracked_messages[message_id] = TrackedMessage(guild_id, channel_id, message_id, header, own_message, []) + self.__save() + return False + + def edit_header(self, message_id: int, header: str) -> None: + self.__tracked_messages[message_id].header = header + + def untrack_message(self, message_id: int): + del self.__tracked_messages[message_id] + self.__save() + + def add_reaction_role(self, message_id: int, emoji: str, role_id: int, description: str) -> bool: + if message_id not in self.__tracked_messages: + return True + + if any(rr.emoji == emoji or rr.role_id == role_id for rr in self.__tracked_messages[message_id].reactions): + return True + + self.__tracked_messages[message_id].reactions.append(ReactionRole(emoji, role_id, description)) + self.__save() + return False + + def edit_reaction_role_description(self, message_id: int, emoji: str, description: str) -> str | None: + if message_id not in self.__tracked_messages: + return None + + for rr in self.__tracked_messages[message_id].reactions: + if rr.emoji == emoji: + old_desc = rr.description + rr.description = description + self.__save() + return old_desc + + return None + + def remove_reaction_role(self, message_id: int, emoji: str) -> None: + self.__tracked_messages[message_id].reactions = [x for x in self.__tracked_messages[message_id].reactions if + x.emoji != emoji] + self.__save() + + def embed_message(self, message_id: int) -> discord.Embed: + m = self.__tracked_messages[message_id] + return discord.Embed( + title=f"message with {len(m.reactions)} reactions", + description="\n".join(f"{x.emoji}" + (f" ({x.emoji.removesuffix('>').split(':')[2]})" if ':' in x.emoji else "") + f" - <@&{x.role_id}>" for x in m.reactions) + ) + + def format_message(self, message_id: int) -> str: + return repr(self.__tracked_messages[message_id]) + + def is_tracked_already(self, message_id: int): + return message_id in self.__tracked_messages + + def is_my_message(self, message_id: int): + return self.__tracked_messages[message_id].own_message + + async def get_message(self, message_id: int) -> discord.Message | None: + if message_id not in self.__tracked_messages: + return None + tm = self.__tracked_messages[message_id] + channel = bot.get_channel(tm.channel_id) + if channel is None: + return channel + message = await channel.fetch_message(tm.message_id) + return message + + def get_reaction_role(self, message_id: int, emoji: str) -> ReactionRole | None: + if message_id not in self.__tracked_messages: + return None + for rr in self.__tracked_messages[message_id].reactions: + if rr.emoji == emoji: + return rr + return None + + +class Config: + def __init__(self, d: str): + self.__file = d + self.__load() + + def __load(self): + try: + c: dict[str, str | list[int]] = json.load(open(self.__file)) + self.__prefix: str = c["prefix"] + self.__trusted: list[int] = c["trusted"] + self.__token: str = c["token"] + except FileNotFoundError: + json.dumps({ + "prefix": "hey rc ", + "trusted": [], + "token": "https://youtu.be/dQw4w9WgXcQ" + }, open(self.__file, "w"), indent=4) + raise FileNotFoundError("Config not found") + + @property + def prefix(self): + return self.__prefix + + @property + def trusted(self): + return self.__trusted + + def run_bot(self): + bot.run(self.__token) + + +class EmojiStorage: + def __init__(self, d: str): + self.__emoji_storage: dict[int, dict[str, int | list[str]]] = {} + self.db_file: str = d + self.__load() + + + def __load(self) -> None: + try: + self.__emoji_storage = pickle.load(open(self.db_file, "rb")) + except (FileNotFoundError, EOFError): + self.__emoji_storage = {} + + def __save(self) -> None: + pickle.dump(self.__emoji_storage, open(self.db_file, "wb")) + + def add_emoji_storage(self, server_id: int) -> bool: + if server_id in self.__emoji_storage: + return True + + self.__emoji_storage[server_id] = {"emoji_message_channel": 0, "emoji_message": 0, "emojis": []} + self.__save() + return False + + def set_emoji_message(self, server_id: int, channel_id: int, message_id: int): + self.__emoji_storage[server_id]["emoji_message_channel"] = channel_id + self.__emoji_storage[server_id]["emoji_message"] = message_id + self.__save() + + def remove_emoji_storage(self, server_id: int) -> bool: + if server_id not in self.__emoji_storage: + return True + + del self.__emoji_storage[server_id] + self.__save() + return False + + async def __add_emoji(self, server_id: int, emoji: str): + self.__emoji_storage[server_id]["emojis"].append(emoji) + self.__save() + channel = bot.get_channel(self.__emoji_storage[server_id]["emoji_message_channel"]) + message = await channel.fetch_message(self.__emoji_storage[server_id]["emoji_message"]) + await message.edit(content=''.join(self.__emoji_storage[server_id]["emojis"] or "-# dust")) + + async def try_add_emoji(self, name: str, image: bytes) -> discord.Emoji | None: + for x in self.__emoji_storage: + g = bot.get_guild(x) + if len(g.emojis) == g.emoji_limit: + continue + emoji = await g.create_custom_emoji(name=name, image=image) + await self.__add_emoji(x, str(emoji)) + return emoji + return None + +DATABASE: Database = Database("db.dat") +EMOJI_STORAGE: EmojiStorage = EmojiStorage("emojis.dat") +CONFIG: Config = Config("config.json") + + +@bot.event +async def on_ready(): + print(f"{bot.user} is ready") + await bot.change_presence(activity=discord.CustomActivity("gaming")) + await bot.tree.sync() + + +rc_func = Callable[[list[str], discord.Message], Awaitable[tuple[str | discord.Embed, bool]]] +registry: list[tuple[str, rc_func, int]] = [] + +def register(name: str, args_amount: int): + def decorator(func: rc_func): + registry.append((name, func, args_amount)) + return func + return decorator + + +@register("show", 1) +async def show(args: list[str], message: discord.Message) -> tuple[str | discord.Embed, bool]: + if len(args) != 1: + return "i dont understand your command", True + + if not args[0].isdigit(): + return "not a valid message id", True + + if not DATABASE.is_tracked_already(int(args[0])): + return "not tracked", True + + return DATABASE.embed_message(int(args[0])), False + +@register("send", 2) +async def send(args: list[str], message: discord.Message) -> tuple[str, bool]: + if not message.author.guild_permissions.manage_guild: + return "no permission", True + + if not 1 <= len(args) <= 2: + return "i dont understand your command", True + + if not args[0].isdigit(): + return "not a valid channel id", True + + channel = bot.get_channel(int(args[0])) + if channel is None: + return "channel not found", True + + try: + sent_message = await channel.send("hold on") + except discord.Forbidden: + return "no permission", True + + DATABASE.track_message(sent_message.guild.id, sent_message.channel.id, sent_message.id, + args[1] if len(args) == 2 else "", True) + await sent_message.edit(content=DATABASE.format_message(sent_message.id)) + return "<:thumbsup:1486044381784834168>", True + + +@register("track", 2) +async def track(args: list[str], message: discord.Message) -> tuple[str, bool]: + if not message.author.guild_permissions.manage_guild: + return "no permission", True + + if len(args) != 2: + return "i dont understand your command", True + + if not args[0].isdigit(): + return "not a valid channel id", True + + if not args[1].isdigit(): + return "not a valid message id", True + + if DATABASE.is_tracked_already(int(args[1])): + return "already tracked", True + + channel = bot.get_channel(int(args[0])) + if channel is None: + return "channel not found", True + + try: + tracked_msg = await channel.fetch_message(int(args[1])) + DATABASE.track_message(tracked_msg.guild.id, tracked_msg.channel.id, tracked_msg.id, "", False) + return f"successfully tracked message {args[1]}", True + except discord.NotFound: + return "message not found", True + except discord.Forbidden: + return "no permission to access that message", True + + +@register("add", 4) +async def add(args: list[str], message: discord.Message) -> tuple[str, bool]: + if not message.author.guild_permissions.manage_guild: + return "no permission", True + + if not 3 <= len(args) <= 4: + return "i dont understand your command", True + + if not args[0].isdigit(): + return "not a valid message id", True + + if not DATABASE.is_tracked_already(int(args[0])): + return "that message is not tracked. use `track` or `send` command first", True + + tracked_msg = await DATABASE.get_message(int(args[0])) + if tracked_msg is None: + return "could not fetch the message", True + + my = DATABASE.is_my_message(int(args[0])) + + if my and len(args) != 4: + return "that's MY message and i want a description for it", True + + role = discord.utils.get(tracked_msg.guild.roles, name=args[2]) + if role is None: + if args[2].isdigit(): + role = tracked_msg.guild.get_role(int(args[2])) + else: + return "not a role", True + + if args[1].isdigit(): + args[1] = bot.get_emoji(int(args[1])) + if args[1] is None: + return "emoji not found", True + args[1] = str(args[1]) + + if DATABASE.add_reaction_role(int(args[0]), args[1], role.id, args[3] if len(args) == 4 else ""): + return "that emoji already has a reaction role on this message", True + + try: + await tracked_msg.add_reaction(args[1]) + except discord.NotFound: + return "invalid emoji", True + except discord.Forbidden: + return "missing permissions to add reactions", True + except discord.HTTPException as e: + return f"failed to add reaction: {e}", True + + if my: + await tracked_msg.edit(content=DATABASE.format_message(int(args[0]))) + + return f"successfully added reaction role: {args[1]} -> {role.name}" + (f" ({args[3]})" if len(args) == 4 else ""), True + + +@register("remove", 2) +async def remove(args: list[str], message: discord.Message) -> tuple[str, bool]: + if not message.author.guild_permissions.manage_guild: + return "no permission", True + + if len(args) != 2: + return "i dont understand your command", True + + if not args[0].isdigit(): + return "not a valid message id", True + + if not DATABASE.is_tracked_already(int(args[0])): + return "that message is not tracked", True + + if args[1].isdigit(): + args[1] = bot.get_emoji(int(args[1])) + if args[1] is None: + return "emoji not found", True + args[1] = str(args[1]) + + reaction_role = DATABASE.get_reaction_role(int(args[0]), args[1]) + if reaction_role is None: + return "no reaction role found with that emoji on this message", True + + tracked_msg = await DATABASE.get_message(int(args[0])) + if tracked_msg is None: + return "could not fetch the message", True + + try: + await tracked_msg.clear_reaction(args[1]) + except discord.Forbidden: + return "missing permissions to remove reactions", True + except discord.NotFound: + pass + except discord.HTTPException as e: + return f"failed to remove reaction: {e}", True + + DATABASE.remove_reaction_role(int(args[0]), args[1]) + + if DATABASE.is_my_message(int(args[0])): + await tracked_msg.edit(content=DATABASE.format_message(int(args[0]))) + + return f"successfully removed reaction role: {args[1]}", True + + +@register("delete", 1) +async def delete(args: list[str], message: discord.Message) -> tuple[str, bool]: + if not message.author.guild_permissions.manage_guild: + return "no permission", True + + if len(args) != 1: + return "i dont understand your command", True + + if not args[0].isdigit(): + return "not a valid message id", True + + if not DATABASE.is_tracked_already(int(args[0])): + return "that message is not tracked", True + + if not DATABASE.is_my_message(int(args[0])): + return "i can only delete messages that i own (messages created with the `send` command)", True + + tracked_msg = await DATABASE.get_message(int(args[0])) + + if tracked_msg: + try: + await tracked_msg.delete() + except discord.Forbidden: + return "missing permissions to delete this message", True + except discord.NotFound: + pass + except discord.HTTPException as e: + return f"failed to delete message: {e}", True + + DATABASE.untrack_message(int(args[0])) + + return f"successfully deleted tracked message {int(args[0])}", True + + +@register("kill yourself", 0) +async def kill_yourself(args: list[str], message: discord.Message): + raise Exception("ok") + + +@register("add this server to emoji storage", 0) +async def add_this_server_to_emoji_storage(args: list[str], message: discord.Message) -> tuple[str, bool]: + if message.author.id not in CONFIG.trusted: + return "no", True + + if EMOJI_STORAGE.add_emoji_storage(message.guild.id): + return "already added", True + + sent_message = await message.channel.send("ok") + EMOJI_STORAGE.set_emoji_message(sent_message.guild.id, sent_message.channel.id, sent_message.id) + return "should've worked", True + + +@register("addemoji", 1) +async def addemoji(args: list[str], message: discord.Message) -> tuple[str, bool]: + if message.guild.id != 1480697029780045875: + return "this command cannot be ran in this server", True + + if not message.author.guild_permissions.manage_guild: + return "no permission", True + + if len(args) != 1: + return "i dont understand this command", True + + if len(message.attachments) != 1: + return "nothing to add", True + + attachment = message.attachments[0] + b: bytes = await attachment.read() + emoji = await EMOJI_STORAGE.try_add_emoji(args[0], b) + if emoji is None: + return "failed to add emoji", True + + if args[0] == "arch": + await message.channel.send("should've alpined") + return f"added {emoji} with id {emoji.id}", False + + +@register("editdesc", 3) +async def editdesc(args: list[str], message: discord.Message) -> tuple[str, bool]: + if not message.author.guild_permissions.manage_guild: + return "no permission", True + + if len(args) != 3: + return "i dont understand your command", True + + if not args[0].isdigit(): + return "not a valid message id", True + + if not DATABASE.is_tracked_already(int(args[0])): + return "that message is not tracked. use `track` or `send` command first", True + + tracked_msg = await DATABASE.get_message(int(args[0])) + if tracked_msg is None: + return "could not fetch the message", True + + my = DATABASE.is_my_message(int(args[0])) + if not my: + return "can't help it it's not my message", True + + if args[1].isdigit(): + args[1] = bot.get_emoji(int(args[1])) + if args[1] is None: + return "emoji not found", True + args[1] = str(args[1]) + + result = DATABASE.edit_reaction_role_description(int(args[0]), args[1], args[2]) + if result is None: + return "reaction role not found", True + await tracked_msg.edit(content=DATABASE.format_message(int(args[0]))) + return f"changed reaction role description from {result} to {args[2]}", True + + + +@register("edithdr", 2) +async def edithdr(args: list[str], message: discord.Message) -> tuple[str, bool]: + if not message.author.guild_permissions.manage_guild: + return "no permission", True + + if len(args) != 2: + return "i dont understand your command", True + + if not args[0].isdigit(): + return "not a valid message id", True + + if not DATABASE.is_tracked_already(int(args[0])): + return "that message is not tracked. use `track` or `send` command first", True + + tracked_msg = await DATABASE.get_message(int(args[0])) + if tracked_msg is None: + return "could not fetch the message", True + + my = DATABASE.is_my_message(int(args[0])) + if not my: + return "can't help it it's not my message", True + + DATABASE.edit_header(int(args[0]), args[1]) + await tracked_msg.edit(content=DATABASE.format_message(int(args[0]))) + return "i have done the thing", True + + +async def handle_command(msg: str, message: discord.Message) -> tuple[str | discord.Embed, bool]: + for reg in registry: + if msg.lower().startswith(reg[0] + ' '): + return await (reg[1])( + msg.removeprefix(reg[0] + ' ').split(' ', max(0, reg[2] - 1)) if msg != reg[0] else [], + message + ) + + return "i dont know this command", True + + +@bot.event +async def on_message(message: discord.Message): + try: + msg = message.content + if not msg.lower().startswith(CONFIG.prefix): + return + + result, d = await handle_command(msg.removeprefix(CONFIG.prefix), message) + + if isinstance(result, str): + if d: + await message.reply(result, delete_after=60) + else: + await message.reply(result) + elif isinstance(result, discord.Embed): + await message.reply(embed=result) + except Exception as e: + await message.reply("```py\n" + '\n'.join(traceback.format_exception(e)) + "\n```") + + +@bot.event +async def on_raw_reaction_add(payload: discord.RawReactionActionEvent): + if payload.user_id == bot.user.id: + return + + reaction_role = DATABASE.get_reaction_role(payload.message_id, str(payload.emoji)) + if reaction_role is None: + return + + guild = bot.get_guild(payload.guild_id) + if guild is None: + return + + member = guild.get_member(payload.user_id) + if member is None: + return + + role = guild.get_role(reaction_role.role_id) + if role is None: + return + + try: + await member.add_roles(role, reason="reaction role") + except discord.Forbidden: + print(f"missing permissions to add role {role.name} to {member.name}") + except discord.HTTPException as e: + print(f"failed to add role: {e}") + + +@bot.event +async def on_raw_reaction_remove(payload: discord.RawReactionActionEvent): + if payload.user_id == bot.user.id: + return + + reaction_role = DATABASE.get_reaction_role(payload.message_id, str(payload.emoji)) + if reaction_role is None: + return + + guild = bot.get_guild(payload.guild_id) + if guild is None: + return + + member = guild.get_member(payload.user_id) + if member is None: + return + + role = guild.get_role(reaction_role.role_id) + if role is None: + return + + try: + await member.remove_roles(role, reason="reaction role") + except discord.Forbidden: + print(f"missing permissions to remove role {role.name} from {member.name}") + except discord.HTTPException as e: + print(f"failed to remove role: {e}") + + +@bot.tree.command(name="help", description="this description is here to help you use your help hope it helps") +async def help_slash_command(interaction: discord.Interaction): + await interaction.response.send_message(embed=discord.Embed( + title="reaction bot", + description=rf""" made by tema5002 +hosted by `[insert your name here at line {__import__('inspect').currentframe().f_lineno} at {__import__('os').path.abspath(__import__('os').path.abspath(__file__))}]` + +"rc" stands for reaction clanker + +Usage: +- {CONFIG.prefix}show message-id: Shows info about the message +- {CONFIG.prefix}send channel-id header (optional): Sends a message with `header` as it's top contents to be used for reaction roles +- {CONFIG.prefix}track channel-id message-id: Track an existing message for reaction roles +- {CONFIG.prefix}add message-id emoji/emoji-id role-id/role-name description: Adds a reaction role to message with `message-id` displayed as `emoji` `description` that gives you `role` +- {CONFIG.prefix}remove message-id;emoji: Removes a reaction role from a tracked message +- {CONFIG.prefix}delete message-id: Deletes a tracked message that the bot owns +- {CONFIG.prefix}addemoji emoji-name + attachment: Adds emoji to the emoji storage. Only available for the "fuck alpinedevs,systemd,... server" +- {CONFIG.prefix}editdesc message-id emoji header: Edit description for a reaction roles emoji +- {CONFIG.prefix}edithdr message-id header: Edit header for a reaction roles message""", + color=discord.Color(0xa2d2df) + )) + +CONFIG.run_bot()