diff options
author | romangraef <romangraef@loves.dicksinhisan.us> | 2018-08-21 16:12:39 +0200 |
---|---|---|
committer | romangraef <romangraef@loves.dicksinhisan.us> | 2018-08-21 16:12:39 +0200 |
commit | a4c058b5c0ec4e441c63ae2ef15235a4869d2bac (patch) | |
tree | 64a039e55976adace41fb56d4fc77e88333db802 /modules | |
download | notaselfbotv2finalforsure-a4c058b5c0ec4e441c63ae2ef15235a4869d2bac.tar.gz notaselfbotv2finalforsure-a4c058b5c0ec4e441c63ae2ef15235a4869d2bac.tar.bz2 notaselfbotv2finalforsure-a4c058b5c0ec4e441c63ae2ef15235a4869d2bac.zip |
Initial commit
Diffstat (limited to 'modules')
-rw-r--r-- | modules/admin.py | 126 | ||||
-rw-r--r-- | modules/binary.py | 27 | ||||
-rw-r--r-- | modules/converters.py | 42 | ||||
-rw-r--r-- | modules/copypasta.py | 27 | ||||
-rw-r--r-- | modules/dump.py | 78 | ||||
-rw-r--r-- | modules/github.py | 68 | ||||
-rw-r--r-- | modules/pypi.py | 48 | ||||
-rw-r--r-- | modules/ragequit.py | 17 |
8 files changed, 433 insertions, 0 deletions
diff --git a/modules/admin.py b/modules/admin.py new file mode 100644 index 0000000..fb50a2e --- /dev/null +++ b/modules/admin.py @@ -0,0 +1,126 @@ +import asyncio +import os +import re +from typing import List, Dict, Pattern + +import discord +from discord import Embed, Color, Message +from discord.ext import commands +from discord.ext.commands import Context as CommandContext, Bot + +from config import config +from utils import load_all_modules + +REPLACEMENTS: Dict[Pattern, str] = { + re.compile(r'<@!?(?P<id>[0-9]+)>'): '(guild.get_member({id}) if guild is not None else client.get_user({id}))', + re.compile(r'<#(?P<id>[0-9]+)>'): '(discord.utils.get(all_channels, id={id}))', + re.compile(r'<@&(?P<id>[0-9]+)>'): '(discord.utils.get(all_roles, id={id}))', + # Maybe later emoji support +} + + +async def handle_eval(message: discord.Message, client: discord.Client, to_eval: str): + channel: discord.TextChannel = message.channel + author: discord.Member = message.author + + all_channels: List[discord.Guild] = [] + all_roles: List[discord.Role] = [] + for guild in client.guilds: + guild: discord.Guild = guild # for type hints + all_channels += guild.channels + all_roles += guild.roles + + variables = { + 'message': message, + 'author': author, + 'channel': channel, + 'all_channels': all_channels, + 'all_roles': all_roles, + 'client': client, + 'discord': discord, + 'os': os, + 'github': config.github.github, + 'print': (lambda *text: client.loop.create_task(channel.send(' '.join(text)))), + 'guild': channel.guild if hasattr(channel, 'guild') else None, + } + lines: List[str] = to_eval.strip().split('\n') + lines[-1] = 'return ' + lines[-1] + block: str = '\n'.join(' ' + line for line in lines) + code = f"async def code({', '.join(variables.keys())}):\n" \ + f"{block}" + + for regex, replacement in REPLACEMENTS.items(): + code = re.sub(regex, lambda match: replacement.format(**match.groupdict()), code) + + _globals, _locals = {}, {} + try: + exec(code, _globals, _locals) + except Exception as e: + await message.channel.send( + embed=discord.Embed(color=discord.Color.red(), description="Compiler Error: `%s`" % (str(e)))) + return + result = {**_globals, **_locals} + try: + result = await result["code"](**variables) + except Exception as e: + await message.channel.send( + embed=discord.Embed(color=discord.Color.red(), description="Runtime Error: `%s`" % (str(e)))) + return + + return await channel.send( + embed=Embed( + color=Color.red(), + description="📥 Evaluation success: ```py\n%r\n```" % result)) + + +class AdminCog(object): + def __init__(self, bot: commands.Bot): + self.bot: commands.Bot = bot + + # noinspection PyMethodMayBeStatic + async def on_ready(self): + print('Logged in.') + + @commands.command() + async def eval(self, ctx: CommandContext, *, to_eval: str = None): + if to_eval is None: + return await ctx.send( + embed=Embed( + description="<Insert generic insult about your stupidity here>", + color=Color.red())) + await handle_eval(ctx.message, self.bot, to_eval) + + @commands.command() + async def reload(self, ctx: CommandContext, *extensions): + for extension in (extensions or self.bot.extensions.copy().keys()): + self.bot.unload_extension(extension) + messages: List[Message] = [ + await ctx.send( + embed=Embed( + color=Color.red(), + description='Unloaded extensions')), + ctx.message] + if len(extensions) == 0: + load_all_modules(self.bot) + else: + for extension in extensions: + try: + self.bot.load_extension(extension) + except: + messages.append( + await ctx.send( + embed=Embed( + title=f"Failed to load module `{extension}`", + color=Color.red()))) + messages.append( + await ctx.send( + embed=Embed( + title=f"Reloaded {len(extensions) or len(self.bot.extensions)} extension(s)", + color=Color.green()))) + await asyncio.sleep(10) + for mes in messages: + await mes.delete() + + +def setup(bot: Bot): + bot.add_cog(AdminCog(bot)) diff --git a/modules/binary.py b/modules/binary.py new file mode 100644 index 0000000..70ed010 --- /dev/null +++ b/modules/binary.py @@ -0,0 +1,27 @@ +from discord import Message +from discord.ext.commands import Bot, command, Context + + +class BinaryCog(object): + def __init__(self, bot: Bot): + self.bot: Bot = bot + + @command() + async def binary(self, ctx: Context, *, text: str): + binary = ' '.join(bin(ord(ch))[2:].zfill(8) for ch in text) + mes: Message = ctx.message + await mes.edit(content=binary) + + @command() + async def un_binary(self, ctx: Context, message: Message): + text: str = message.content + print(text) + text.replace(' ', '').replace('\n', '') + chunks, chunk_size = len(text), len(text) // 4 + await ctx.message.edit( + content=f"Decoded message {message.jump_url}: " + f"{''.join([chr(int(text[i:i + chunk_size], 2)) for i in range(0, chunks, chunk_size)])}") + + +def setup(bot: Bot): + bot.add_cog(BinaryCog(bot)) diff --git a/modules/converters.py b/modules/converters.py new file mode 100644 index 0000000..f86ff59 --- /dev/null +++ b/modules/converters.py @@ -0,0 +1,42 @@ +from string import digits + +from discord import TextChannel +from discord.ext.commands import Converter, Context, Bot, BadArgument, converter + + +def is_int(text): + return all(map(digits.__contains__, text)) + + +class GuildConverter(Converter): + async def convert(self, ctx: Context, argument): + bot: Bot = ctx.bot + try: + return bot.get_guild(int(argument)) + except: + try: + return [guild for guild in bot.guilds if guild.name.casefold() == argument.casefold()][0] + except: + raise BadArgument(f"Could not find guild with id or name {argument}") + + +class MessageConverter(Converter): + async def convert(self, ctx: Context, argument: str): + bot: Bot = ctx.bot + if is_int(argument): + message = int(argument) + channel: TextChannel = ctx.channel + else: + _, channel, message = list(map(int, filter(is_int, argument.split('/')))) + channel: TextChannel = bot.get_channel(channel) + + if bot.user.bot: + return await channel.get_message(message) + else: + return (await channel.history(around=message, limit=2).flatten())[1] + + +# noinspection PyUnusedLocal +def setup(bot: Bot): + converter.MessageConverter = MessageConverter + converter.GuildConverter = GuildConverter diff --git a/modules/copypasta.py b/modules/copypasta.py new file mode 100644 index 0000000..4cb747f --- /dev/null +++ b/modules/copypasta.py @@ -0,0 +1,27 @@ +from _contextvars import Context +from string import digits, ascii_uppercase, ascii_lowercase + +from discord.ext.commands import Bot, command, Converter + + +class CopyPastaTextConverter(Converter): + + async def convert(self, ctx: Context, argument: str): + allowed_characters = ascii_uppercase + ascii_lowercase + digits + '_- ' + if any(ch not in allowed_characters for ch in argument): + return + with open(f'copypasta/{argument}.txt') as fp: + return fp.read().strip() + + +class CopyPasta(object): + def __init__(self, bot: Bot): + self.bot: Bot = bot + + @command(aliases=['cp', 'copy-pasta', 'copypasta']) + async def copy_pasta(self, ctx: Context, copy_pasta: CopyPastaTextConverter): + await ctx.message.edit(content=str(copy_pasta)) + + +def setup(bot: Bot): + bot.add_cog(CopyPasta(bot)) diff --git a/modules/dump.py b/modules/dump.py new file mode 100644 index 0000000..5281d7d --- /dev/null +++ b/modules/dump.py @@ -0,0 +1,78 @@ +from typing import List + +from discord import User, Embed, Profile, Guild, Member, Permissions, Message +from discord.ext.commands import Bot, command, Context as CommandContext, Context + + +async def _context_react(self: Context, emoji): + await self.message.add_reaction(emoji) + + +Context.react = _context_react + + +def dump_perms(permissions: Permissions): + def perm_names(): + for perm, value in permissions: + if value: + yield perm + + return ', '.join(perm_names()) + + +class DumpCog(object): + def __init__(self, bot: Bot): + self.bot = bot + + @command() + async def raw(self, ctx: CommandContext, message: Message): + content: str = message.content + escaped = content.replace('```', '``\u200B`') + await ctx.send(content=f'```\n{escaped}\n```') + await ctx.react('✅') + + @command() + async def user(self, ctx: CommandContext, user: User, guild: Guild = None): + if guild is None and ctx.guild is not None: + guild: Guild = ctx.guild + profile: Profile = await user.profile() + description = "" + if profile.nitro: + description += f"i can haz animated emojis since {profile.premium_since}\n" + if profile.hypesquad: + description += f"they got some hype\n" + if profile.partner: + description += "insrt BLU INFINITY SYMBOL her\n" + if profile.staff: + description += "staff. if this is b1nzy, then FUCK him for banning selfbots\n" + mutual: List[Guild] = profile.mutual_guilds + + mutual_text = '\n'.join(guild.name for guild in mutual) + if len(mutual_text) > 512: + mutual_text = f"Together in {len(mutual)} guilds. [Truncated]" + + em = Embed( + title=str(user), + description=description, + ) + if guild: + member: Member = guild.get_member(user.id) + if member: + if guild.owner_id == member.id: + em.add_field(name="Owner", value="Yeah", inline=True) + em.colour = member.color + em.add_field(name="Joined Guild", value=member.joined_at, inline=True) + em.add_field(name="Permissions", value=dump_perms(member.guild_permissions), inline=True) + em.set_author(name=user.display_name, icon_url=user.avatar_url) + em.add_field(name="Mutual guilds", value=mutual_text, inline=True) + em.add_field(name="Joined Discord", value=user.created_at, inline=True) + for connection in profile.connected_accounts: + em.add_field(name=connection['type'], value=('☑' if connection['verified'] else '') + connection['name'], + inline=True) + em.set_thumbnail(url=user.avatar_url) + await ctx.send(embed=em) + await ctx.react('✅') + + +def setup(bot: Bot): + bot.add_cog(DumpCog(bot)) diff --git a/modules/github.py b/modules/github.py new file mode 100644 index 0000000..cb639dc --- /dev/null +++ b/modules/github.py @@ -0,0 +1,68 @@ +from typing import List + +from discord import Embed, Color +from discord.ext.commands import Bot, Group +from discord.ext.commands import Context as CommandContext, group +from github.NamedUser import NamedUser +from github.Repository import Repository + +from config import config + +github = config.github.github + + +def find_repo(search): + repos: List[Repository] = list(github.get_repos()) + checks = [ + lambda r: r.id.lower() == search.lower(), + lambda r: search.lower() in r.name.lower(), + lambda r: search.lower() in repo.description.lower(), + ] + for check in checks: + for repo in repos: + if check(repo): + return repo + + +class GithubCog(object): + def __init__(self, bot: Bot): + self.bot: Bot = bot + + @group(invoke_without_subcommand=True) + async def github(self, ctx: CommandContext): + pass + + github: Group = github + + @github.command() + async def me(self, ctx: CommandContext): + user: NamedUser = github.get_user() + embed = Embed( + color=Color.blurple(), + title=user.login, + description=user.bio, + url=user.url, + ) + embed.add_field(name='Followers', value=user.followers) + embed.add_field(name='Following', value=user.following) + embed.add_field(name='Repositories', + value=f'[{user.public_repos + user.total_private_repos}](https://github.com/{user.login})') + embed.set_thumbnail(url=user.avatar_url) + await ctx.send(embed=embed) + + @github.command() + async def repo(self, ctx: CommandContext, *, search): + repo = find_repo(search) + print(repo) + print(search) + if repo: + embed = Embed( + title=repo.id, + description=repo.description, + url=repo.html_url + ) + await ctx.send(embed=embed) + + +def setup(bot: Bot): + bot.add_cog(GithubCog(bot)) diff --git a/modules/pypi.py b/modules/pypi.py new file mode 100644 index 0000000..eebd3be --- /dev/null +++ b/modules/pypi.py @@ -0,0 +1,48 @@ +import re +from subprocess import Popen, PIPE +from typing import List +from typing import Pattern + +from discord import Message, Embed, Color +from discord.ext.commands import Bot, Context as CommandContext, command + +matcher: Pattern = re.compile(r'(?P<name>\w+)[^(]+\((?P<version>[^)]+)\)[^\-]+(?P<description>.*)') + + +class PyPiCog(object): + def __init__(self, bot: Bot): + self.bot: Bot = bot + + @command() + async def pypi(self, ctx: CommandContext, search, *, text=''): + message: Message = ctx.message + proc = Popen(['pip', 'search', search], stdout=PIPE, stderr=PIPE) + if proc.wait() != 0: + await message.edit( + embed=Embed( + color=Color.red(), + description='Failed to search for `{search}` on pypi.')) + stdout, _ = proc.communicate() + stdout = stdout.decode(encoding='utf-8') + lines: List[str] = stdout.split('\n') + content = lines[0] + ' '.join(line.strip() for line in lines[1:] if line.startswith(' ')) + match = matcher.match(content) + if not match: + await message.edit( + embed=Embed( + color=Color.dark_orange(), + description=f"Weird response format:```\n{stdout[:512]}```")) + name = match.group("name") + version = match.group("version") + description = match.group("description") + await message.edit( + content=text, + embed=Embed( + title=name, + url=f"https://pypi.org/project/{name}/", + description=description + ).set_footer(text=version)) + + +def setup(bot: Bot): + bot.add_cog(PyPiCog(bot)) diff --git a/modules/ragequit.py b/modules/ragequit.py new file mode 100644 index 0000000..aaf43f8 --- /dev/null +++ b/modules/ragequit.py @@ -0,0 +1,17 @@ +from discord import Guild +from discord.ext.commands import Bot, command, Context as CommandContext, guild_only + + +class RageQuitCog(object): + def __init__(self, bot: Bot): + self.bot: Bot = bot + + @command() + @guild_only() + async def ragequit(self, ctx: CommandContext): + guild: Guild = ctx.guild + await guild.leave() + + +def setup(bot: Bot): + bot.add_cog(RageQuitCog(bot)) |