commit 8a7ba55014dee5d123f5a6179c5574740bca9dae Author: pfero Date: Sat Mar 30 18:11:33 2019 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ec09648 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +token +token.personal +env/ +emoji/*.png diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..5a8e332 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,14 @@ + 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/bot.py b/bot.py new file mode 100644 index 0000000..f5eae7d --- /dev/null +++ b/bot.py @@ -0,0 +1,129 @@ +import discord +import logging +import aiohttp +from os import listdir +from os.path import splitext, basename +from urllib.parse import urlparse +from asyncio import Lock + +def url(str): + try: + parse = urlparse(str) + if not parse.scheme or not parse.netloc or not parse.path: + return None + return parse + except: + return None + +def checkext(str): + return splitext(basename(str))[1] in [".png", ".jpg", ".jpeg"] + +class Client(discord.Client): + async def on_ready(self): + print("Logged on as", self.user) + self.emoji_lock = Lock() + + async def on_message(self, message): + if message.author == self.user: + return + + if message.channel.name != "suggestions": + return + + lowermsg = message.content.lower() + if "why" in lowermsg and ("happening" in lowermsg or "habbening" in lowermsg): + await message.channel.send("https://axyllia.root.sx/seedot.png") + + name = None + image_name = None + image = None + + remove = [] + + if message.attachments: + for attach in message.attachments: + if not checkext(attach.url): + continue + image_name = splitext(attach.filename.replace(" ", "_"))[0] + image = attach.url + break + + for part in message.content.split(): + if not name and part[0] == ":" and part[-1] == ":": + name = part[1:-1] + elif part.startswith("<:") and part.endswith(">") and len(part) >= 20 and part[-20] == ":": + if not name: + name = part[2:-20] + try: + remove.append(int(part[-19:-1])) + except: + pass + elif not image: + parsed = url(part) + if not parsed or not checkext(parsed.path): + continue + image_name = splitext(basename(parsed.path))[0] + image = part + + async with self.emoji_lock: + for emoji in message.guild.emojis: + if len(message.guild.emojis) <= 35: + break + if emoji.id in remove: + try: + print("", emoji.name + ":", emoji.id) + await emoji.delete() + print("[DEL EMOJI]", emoji.name + ":", emoji.id) + except: + pass + + if not image: + return + + if not name: + name = image_name + + if len(name) > 32 or len(name) < 2: + await message.add_reaction("⁉") + return + + try: + async with aiohttp.ClientSession() as session: + async with session.get(image) as resp: + if resp.content_type not in ["image/png", "image/jpeg"]: + return + image_data = bytes() + while True: + new_data = await resp.content.read(1024) + if not new_data: + break + image_data += new_data + if len(image_data) >= 256 * 1024: + await message.add_reaction("⁉") + return + + async with self.emoji_lock: + if len(message.guild.emojis) >= 50: + emoji = sorted(message.guild.emojis, key=lambda x: x.created_at)[0] + try: + print("", emoji.name + ":", emoji.id) + await emoji.delete() + print("[DEL EMOJI]", emoji.name + ":", emoji.id) + except: + pass + + print("", name + ":", image) + ret = await message.guild.create_custom_emoji(name=name, image=image_data) + if not isinstance(ret, int): + print("[NEW EMOJI]", name + ":", image) + else: + time = "%d minutes and %d seconds" % (ret / 1000 / 60, ret / 1000 % 60) + print("[RATE LIMIT] Wait", time) + await message.channel.send("We're being rate limited for %s 😔" % time) + except: + await message.add_reaction("⁉") + raise + +logging.basicConfig(level=logging.WARNING) +client = Client() +client.run(open("token").read().strip()) diff --git a/discord.py-emojilimit.patch b/discord.py-emojilimit.patch new file mode 100644 index 0000000..047f3f3 --- /dev/null +++ b/discord.py-emojilimit.patch @@ -0,0 +1,30 @@ +# The bot depends on this patch to handle rate limits with the uploading of emoji +# There isn't a cleaner way to do this as of right now... + +diff --git a/discord/guild.py b/discord/guild.py +index 6982356..d6cd907 100644 +--- a/discord/guild.py ++++ b/discord/guild.py +@@ -1209,6 +1209,8 @@ class Guild(Hashable): + if roles: + roles = [role.id for role in roles] + data = await self._state.http.create_custom_emoji(self.id, name, img, roles=roles, reason=reason) ++ if isinstance(data, int): ++ return data + return self._state.store_emoji(self, data) + + async def create_role(self, *, reason=None, **fields): +diff --git a/discord/http.py b/discord/http.py +index b103a7e..0c21f4c 100644 +--- a/discord/http.py ++++ b/discord/http.py +@@ -183,6 +183,9 @@ class HTTPClient: + if r.status == 429: + fmt = 'We are being rate limited. Retrying in %.2f seconds. Handled under the bucket "%s"' + ++ if bucket.endswith(":/guilds/{guild_id}/emojis"): ++ return data["retry_after"] ++ + # sleep a bit + retry_after = data['retry_after'] / 1000.0 + log.warning(fmt, retry_after, bucket) diff --git a/dumpemoji.py b/dumpemoji.py new file mode 100644 index 0000000..7e2fc9b --- /dev/null +++ b/dumpemoji.py @@ -0,0 +1,23 @@ +import discord +import aiohttp + +async def wget(url): + async with aiohttp.ClientSession() as session: + async with session.get(url) as response: + return await response.read() + +class Client(discord.Client): + async def on_ready(self): + print("Logged on as", self.user) + + guild = self.get_guild(256674225211834369) + for emoji in guild.emojis: + print(emoji) + + image = await wget(emoji.url) + open("emoji/%s.png" % emoji.name, "wb").write(image) + + await self.logout() + +client = Client() +client.run(open("token.personal").read().strip(), bot=False) diff --git a/emoji/.gitkeep b/emoji/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/perms.txt b/perms.txt new file mode 100644 index 0000000..6369bb8 --- /dev/null +++ b/perms.txt @@ -0,0 +1,6 @@ +- Manage Emojis +- Read Messages + +1073742848 + +https://discordapp.com/api/oauth2/authorize?client_id=558004490545004554&scope=bot&permissions=1073742848 diff --git a/restoreemoji.py b/restoreemoji.py new file mode 100644 index 0000000..91bd8d0 --- /dev/null +++ b/restoreemoji.py @@ -0,0 +1,21 @@ +import discord + +from os import listdir + +class Client(discord.Client): + async def on_ready(self): + print("Logged on as", self.user) + + guild = self.get_guild(256674225211834369) + for emoji in guild.emojis: + print(emoji) + await emoji.delete() + + for image in listdir("emoji"): + print(image.split(".")[0]) + await guild.create_custom_emoji(name=image.split(".")[0], image=open("emoji/" + image, "rb").read()) + + await self.logout() + +client = Client() +client.run(open("token.personal").read().strip(), bot=False)