class CustomCommands(commands.Cog, name='CustomCommands'): def __init__(self, bot): self.bot = bot self.db = bot.mdb['custom_commands'] async def cog_check(self, ctx): return ctx.guild is not None async def run_custom_commands(self, ctx): if ctx.guild is None: return cc = await self.db.find_one({'guild_id': ctx.guild_id, 'name': ctx.invoked_with}) if cc is None: return cc = CustomCommand.from_dict(cc) return await ctx.send(cc.content) @commands.group(name='cc', invoke_without_command=True) async def cc_base(self, ctx): """ Base command for CustomCommand commands. Will list any custom commands for this server. Any of these commands require the "DM" or "Dragonspeaker" role. """ aliases = await self.db.find({'guild_id': ctx.guild.id}).to_list(None) source = CommandMenu(data=[CustomCommand.from_dict(a) for a in aliases], ctx=ctx) cc_list = menus.MenuPages(source=source, clear_reactions_after=True) await cc_list.start(ctx) @cc_base.command(name='create') @commands.check_any(commands.has_any_role(BOT_MODS), is_owner()) async def cc_create(self, ctx, name: str, *, content: str): """ Create a new Custom Command. """ try: new_cc = await CustomCommand.new(self.bot, owner_id=ctx.author.id, guild_id=ctx.guild_id, name=name, content=content) except InvalidArgument as e: return await ctx.send(f'Encountered an error while creating the command:\n{str(e)}') return await ctx.send(f'Created new command with name `{new_cc.name}`') @cc_base.command(name='delete') @commands.check_any(commands.has_any_role(BOT_MODS), is_owner()) async def cc_delete(self, ctx, name: str): """ Deletes a Custom Counter. The name must be an existing CC. """ cc_dict = await self.db.find_one({'guild_id': ctx.guild_id, 'name': name}) if cc_dict is None: return await ctx.send(f'No CC with name `{name}` found.') await self.db.delete_one({'guild_id': ctx.guild_id, 'name': name}) return await ctx.send(f'Deleted CC with name `{name}` from the server.')
async def help(self, ctx): if commands.has_any_role(FONDATEUR): await ctx.send(self.generateur_help(ctx, COG_FONDATEUR)) if commands.has_any_role(ADMIN): await ctx.send(self.generateur_help(ctx, COG_ADMIN)) if commands.has_any_role(PROFESSEUR): await ctx.send(self.generateur_help(ctx, COG_PROFESSEUR)) await ctx.send(self.generateur_help(ctx, COG_GENERALE)) await ctx.send(self.generateur_help(ctx, COG_FICHE)) await ctx.send(HELP)
def add_slash_command(self, cmd: typing.Callable, roles: typing.Optional[typing.Sequence] = None, channels: typing.Optional[typing.Sequence] = None, options: typing.Optional[typing.Sequence] = None, **kwargs) -> None: async def wrapper(ctx: SlashContext, cmd=cmd, **kwargs): return await cmd(ctx, **kwargs) def check_channels(channels: typing.Sequence): def predicate(ctx: SlashContext): print(f"channels: {channels}") if channels is None: return True for channel in channels: name = self.config['channels'].get(channel, channel) if ctx.channel.name == name: return True return False return commands.check(predicate) cmd = check_channels(channels)(wrapper) if roles is not None: cmd = commands.has_any_role(*roles)(cmd) # have to set a dummy list to prevent # discord_slash from probing our cmd's args if options is None: options = [] return self.slash.add_slash_command(cmd, guild_ids=self.guild_ids, options=options, **kwargs)
class BotControl(commands.Cog): def __init__(self, bot): self.bot = bot # @commands.Cog.listener() # async def on_ready(self): # pass # from TLE bot. @commands.command(brief="Check if bot is still alive.") async def ping(self, ctx): """Replies to a ping.""" start = time.perf_counter() message = await ctx.send('<:pingreee:665243570655199246>') end = time.perf_counter() duration = (end - start) * 1000 await message.edit( content= f'<:pingreee:665243570655199246>\nREST API latency: {int(duration)}ms\n' f'Gateway API latency: {int(self.bot.latency * 1000)}ms') @commands.command(brief="Kill bot. ") @commands.check_any(commands.is_owner(), commands.has_any_role('Admin', 'Mod VNOI')) async def kill(self, ctx): """Kill bot""" await ctx.send("Dying") exit(0) @commands.command(brief='Restart bot') @commands.check_any(commands.is_owner(), commands.has_any_role('Admin', 'Mod VNOI')) async def restart(self, ctx): await ctx.send('Restarting...') os.execv(sys.executable, [sys.executable] + sys.argv) @commands.command(brief='Get database') @commands.check_any(commands.is_owner(), commands.has_any_role('Admin', 'Mod VNOI')) async def db(self, ctx): await ctx.send( file=discord.File('database/potd.db', filename='potd.db'))
class Handle(commands.Cog): def __init__(self, bot): self.bot = bot @commands.command(brief="Set nick codeforces cho người khác", usage="@user codeforces_handle") @commands.check_any(commands.is_owner(), commands.has_any_role('Admin', 'Mod VNOI')) async def set(self, ctx, member: discord.Member, handle): """ Dùng command này để set nick codeforces cho người khác """ discord_id = member.id TaggingDb.TaggingDb.add_handle(discord_id, handle) if os.path.exists('database/save/' + str(discord_id) + '.json'): os.remove('database/save/' + str(discord_id) + '.json') if os.path.exists('database/save/info_' + str(discord_id) + '.json'): os.remove('database/save/info_' + str(discord_id) + '.json') await ctx.send(SET_HANDLE_SUCCESS.format(discord_id, handle)) @commands.command(brief="Tự set nick codeforces", usage="codeforces_handle") async def identify(self, ctx, handle): """ Dùng command này để set nick codeforces: Ví dụ account codeforces của mình là leduykhongngu thì mình dùng: ;identify leduykhongngu """ if ctx.guild is None: await ctx.send( "Lệnh này chỉ được dùng ở server discord của VNOI, không được dùng trong tin nhắn" ) return discord_id = ctx.author.id TaggingDb.TaggingDb.add_handle(discord_id, handle) await ctx.send(SET_HANDLE_SUCCESS.format(discord_id, handle))
mjs_only = commands.check_any( commands.check(lambda ctx: ctx.message.webhook_id), commands.has_role(config.Role.get_raw("mj")) # nom du rôle ) #: Décorateur pour commandes d'IA (:func:`discord.ext.commands.check`) : #: commande exécutable par un :attr:`MJ <.config.Role.mj>`, un #: :attr:`Rédacteur <.config.Role.redacteur>` ou un webhook (tâche planifiée) mjs_et_redacteurs = commands.check_any( mjs_only, commands.has_role(config.Role.get_raw("redacteur"))) #: Décorateur pour commande (:func:`discord.ext.commands.check`) : #: commande exécutable uniquement par un joueur, #: :attr:`vivant <.config.Role.joueur_en_vie>` ou #: :attr:`mort <.config.Role.joueur_mort>`. joueurs_only = commands.has_any_role(config.Role.get_raw("joueur_en_vie"), config.Role.get_raw("joueur_mort")) #: Décorateur pour commande (:func:`discord.ext.commands.check`) : #: commande exécutable uniquement par un #: :attr:`joueur vivant <.config.Role.joueur_en_vie>` vivants_only = commands.has_role(config.Role.get_raw("joueur_en_vie")) def private(callback): """Décorateur : commande utilisable dans son chan privé uniquement. Lors d'une invocation de la commande décorée hors d'un channel privé (commençant par :attr:`config.private_chan_prefix`), supprime le message d'invocation et exécute la commande dans le channel privé de l'invoqueur.
class Misc(commands.Cog): def __init__(self, bot): self.bot = bot @commands.Cog.listener() async def on_message(self, message): if message.content.lower() == '!role furaime': await message.add_reaction('👀') if self.bot.user in message.mentions: emoji = discord.utils.get(self.bot.emojis, name='SahasrahBot') if emoji: await asyncio.sleep(random.random()*5) await message.add_reaction(emoji) if discord.utils.get(message.role_mentions, id=524738280630124574): async with message.channel.typing(): await asyncio.sleep((random.random()*30)+30) if random.choice([True, False]): await message.channel.send(f'@{message.author.mention}') @commands.command(aliases=['joineddate']) @commands.check_any( commands.has_any_role(523276397679083520, 307883683526868992), commands.has_permissions(administrator=True), commands.has_permissions(manage_guild=True), checks.has_any_channel_id(608008164356653066) ) async def memberinfo(self, ctx, member: discord.Member = None): if member is None: member = ctx.author embed = discord.Embed( title=f"Member info for {member.name}#{member.discriminator}", color=member.color ) embed.add_field(name='Created at', value=member.created_at, inline=False) embed.add_field(name='Joined at', value=member.joined_at, inline=False) embed.add_field(name="Discord ID", value=member.id, inline=False) embed.set_thumbnail(url=member.avatar_url) await ctx.send(embed=embed) @commands.command() async def prng(self, ctx): await ctx.send("PRNG is RNG! It is random! Humans tend to identify patterns where they do not exist.\n\nIf you're a Linux nerd check this out: https://www.2uo.de/myths-about-urandom/") @commands.command(hidden=True) async def pedestalgoal(self, ctx): await ctx.send("> If it takes 2 hours its because GT is required, which really isn't a thing anymore in pedestal goal games\n-Synack") @commands.command( aliases=['crc32'], brief="Posts instructions on how to verify your ROM is correct.", help="Posts instructions on how to verify your ROM is correct, or how to get the permalink to your randomized game." ) async def rom(self, ctx): await ctx.send( "If you need help verifying your legally-dumped Japanese version 1.0 A Link to the Past Game file needed to run ALttPR, use this tool: <http://alttp.mymm1.com/game/checkcrc/>\n" "It can also help get the permalink page URL which has access to the Spoiler Log depending on the settings that were chosen. Not all games that are generated have access to the Spoiler Log.\n\n" "For legal reasons, we cannot provide help with finding this ROM online. Please do not ask here for assistance with this.\n" "See <#543572578787393556> for details." ) @commands.command(hidden=True) async def trpegs(self, ctx): await ctx.send(discord.utils.get(ctx.bot.emojis, name='RIPLink')) @commands.command(hidden=True, aliases=['8ball']) async def eightball(self, ctx): msg = random.choice([ "It is certain.", "It is decidedly so.", "Without a doubt.", "Yes – definitely.", "You may rely on it.", "As I see it, yes.", "Most likely.", "Outlook good.", "Yes.", "Signs point to yes.", "Reply hazy, try again.", "Ask again later.", "Better not tell you now.", "Cannot predict now.", "Concentrate and ask again.", "Don't count on it.", "My reply is no.", "My sources say no.", "Outlook not so good.", "Very doubtful.", ]) await ctx.send(msg) @commands.command( brief="Retrieves a holy image.", help="Retrieves a holy image from http://alttp.mymm1.com/holyimage/", aliases=['holy'] ) async def holyimage(self, ctx, slug=None, game='z3r'): holyimage = await holy(slug=slug, game=game) embed = discord.Embed( title=holyimage.image.get('title'), description=html2markdown.convert( holyimage.image['desc']) if 'desc' in holyimage.image else None, color=discord.Colour.from_rgb(0xFF, 0xAF, 0x00) ) if 'url' in holyimage.image: url = urljoin('http://alttp.mymm1.com/holyimage/', holyimage.image['url']) if holyimage.image.get('mode', '') == 'redirect': embed.add_field(name='Link', value=url, inline=False) else: embed.set_thumbnail(url=url) embed.add_field(name="Source", value=holyimage.link) if 'credit' in holyimage.image: embed.set_footer(text=f"Created by {holyimage.image['credit']}") await ctx.send(embed=embed) @commands.command( brief="Retrieves the next ALTTPR SG daily race.", help="Retrieves the next ALTTPR SG daily race.", ) @commands.cooldown(rate=1, per=900, type=commands.BucketType.channel) async def sgdaily(self, ctx, get_next=1): sg_schedule = await speedgaming.get_upcoming_episodes_by_event('alttprdaily', hours_past=0, hours_future=192) if len(sg_schedule) == 0: await ctx.send("There are no currently SpeedGaming ALTTPR Daily Races scheduled within the next 8 days.") return if get_next == 1: embed = discord.Embed( title=sg_schedule[0]['event']['name'], description=f"**Mode:** {'*TBD*' if sg_schedule[0]['match1']['title'] == '' else sg_schedule[0]['match1']['title']}\n[Full Schedule](http://speedgaming.org/alttprdaily)" ) else: embed = discord.Embed( title="ALTTP Randomizer SG Daily Schedule", description="[Full Schedule](http://speedgaming.org/alttprdaily)" ) for episode in sg_schedule[0:get_next]: when = dateutil.parser.parse(episode['when']) when_central = when.astimezone(pytz.timezone( 'US/Eastern')).strftime('%m-%d %I:%M %p') when_europe = when.astimezone(pytz.timezone( 'Europe/Berlin')).strftime('%m-%d %I:%M %p') difference = when - datetime.datetime.now(when.tzinfo) if get_next == 1: embed.add_field( name='Time', value=f"**US:** {when_central} Eastern\n**EU:** {when_europe} CET/CEST\n\n{round(difference / datetime.timedelta(hours=1), 1)} hours from now", inline=False) broadcast_channels = [a['name'] for a in episode['channels'] if not a['name'] == 'No Stream'] if broadcast_channels: embed.add_field(name="Twitch Channels", value=', '.join( [f"[{a}](https://twitch.tv/{a})" for a in broadcast_channels]), inline=False) else: embed.add_field( name='TBD' if episode['match1']['title'] == '' else episode['match1']['title'], value=( f"**US:** {when_central} Eastern\n" f"**EU:** {when_europe} CET/CEST\n\n" ), inline=False ) embed.set_footer() embed.set_thumbnail( url='https://pbs.twimg.com/profile_images/1185422684190105600/3jiXIf5Y_400x400.jpg') await ctx.send(embed=embed)
class Misc(Cog): """A cog containing miscellaneous commands.""" def __init__(self, bot: utils.Bot): self.bot = bot with open("./assets/json/colors_lower.json", "r", encoding="utf-8") as f: self.colors = json.load(f) @commands.command() async def nether(self, ctx: Context, *, query: str): """Gets an image from https://ceapa.cool/nether.""" async with ctx.typing(): quoted = parse.quote(query) async with self.bot.session.get( f"https://ceapa.cool/nether/?obj={quoted}") as resp: image = await resp.read() ext = imghdr.what(None, h=image) if not ext: embed = discord.Embed(color=EGG_COLOR, timestamp=ctx.message.created_at) embed.set_author(name="No images found.", icon_url=ctx.me.avatar_url) return await ctx.send(embed=embed) ext = ext.lower().replace("jpeg", "jpg") await ctx.send(file=discord.File( BytesIO(image), filename=f"nether_{query.replace(' ', '_')}.{ext}")) @commands.command() async def melon(self, ctx: Context, *, query: str): """Gets an image from https://ceapa.cool/melon.""" async with ctx.typing(): quoted = parse.quote(query) async with self.bot.session.get( f"https://ceapa.cool/melon/?txt={quoted}") as resp: image = await resp.read() ext = imghdr.what(None, h=image).lower().replace("jpeg", "jpg") await ctx.send(file=discord.File( BytesIO(image), filename=f"melon_{query.replace(' ', '_')}.{ext}")) @commands.command() async def cumrat(self, ctx: Context, *, text: str): """Makes a "Cum rat says:" image.""" if len(text) > 100: embed = discord.Embed(color=EGG_COLOR, timestamp=ctx.message.created_at) embed.set_author(name="Text must be 100 characters or less.", icon_url=ctx.me.avatar_url) return await ctx.send(embed=embed) async with ctx.typing(): image = await self.bot.loop.run_in_executor( None, self.create_cumrat, text) await ctx.send(file=discord.File(image, filename=f"cumrat.png")) @staticmethod def create_cumrat(text: str): """Takes the provided text and applies it onto the cum rat template.""" text = textwrap.fill(re.sub(r"[^\w\s]+", "", text), 25, break_long_words=True) font = ImageFont.truetype("./assets/fonts/angeltears.ttf", size=150) image = Image.open("./assets/images/cumrat.png") draw = ImageDraw.Draw(image) buffer = BytesIO() draw.multiline_text((50, 175), text, fill="#000F55", font=font, spacing=0) image.save(buffer, "png") buffer.seek(0) return buffer @commands.command() async def roblox(self, ctx: Context): """Shows how many members are playing Roblox.""" players = [] desc = [] for member in ctx.guild.members: if member.activity and member.activity.name: if member.activity.name.lower().startswith("roblox"): players.append(str(member)) amount = len(players) for _ in range(10): try: player = players.pop(0) desc.append(player) except IndexError: break if players: desc.append(f"...and {len(players)} more \N{FLUSHED FACE}") embed = discord.Embed(description="\n".join(desc), color=EGG_COLOR, timestamp=ctx.message.created_at) embed.set_author( name=f"{amount} {utils.plural('member', amount)} " f"{'are' if amount != 1 else 'is'} currently playing Roblox.", icon_url=ctx.me.avatar_url) await ctx.send(embed=embed) @commands.command(aliases=["ud", "urbandictionary", "urb"]) async def urban(self, ctx, term: str, *, index: str = None): """Gets a definition from Urban Dicrionary.""" if index is None: index = 0 else: maybe_index = index.split()[-1] if maybe_index.isdigit(): if int(maybe_index) < 1: embed = discord.Embed(color=EGG_COLOR, timestamp=ctx.message.created_at) embed.set_author(name="Invalid index.", icon_url=ctx.me.avatar_url) await ctx.send(embed=embed) else: term += f" {' '.join(index.split()[:-1])}" index = int(maybe_index) - 1 else: term += f" {index}" index = 0 async with aiohttp.ClientSession() as session: url = f"http://api.urbandictionary.com/v0/define?term={html.escape(term)}" async with session.get(url.replace(" ", "%20")) as response: resp = await response.json() try: item = resp["list"][index] except IndexError: embed = discord.Embed(color=EGG_COLOR, timestamp=ctx.message.created_at) embed.set_author(name="No definitions found.", icon_url=ctx.me.avatar_url) return await ctx.send(embed=embed) def convert_to_url(match): term = match.group(0).strip('[]') url = f"https://www.urbandictionary.com/define.php?term={term}".replace( " ", "%20") return f"[{match.group(0).strip('[]')}]({url})" definition = re.sub(r"\[[^\]]*\]", convert_to_url, item["definition"]) example = re.sub(r"\[[^\]]*\]", convert_to_url, item["example"]) written_on = datetime.strptime(item["written_on"][:10], "%Y-%m-%d").strftime("%B %d, %Y") embed = discord.Embed(title=f"**__{item['word']}__**", description=f"{definition}\n\n_{example}_", color=EGG_COLOR, url=item["permalink"]) embed.set_author(name="Urban Dictionary", icon_url=ctx.me.avatar_url, url="https://www.urbandictionary.com/") embed.set_footer( text=f"\N{SPEAKING HEAD IN SILHOUETTE}: {item['author']} | " f"\N{THUMBS UP SIGN}/\N{THUMBS DOWN SIGN}: " f"{item['thumbs_up']}/{item['thumbs_down']} | {written_on}") try: await ctx.send(embed=embed) except discord.HTTPException: embed = discord.Embed(color=EGG_COLOR, timestamp=ctx.message.created_at) embed.set_author(name="Definition over 2048 characters.", icon_url=ctx.me.avatar_url) embed.add_field(name="Link to definition", value=item["permalink"]) await ctx.send(embed=embed) @commands.group(invoke_without_command=True) @commands.check_any( commands.check(lambda ctx: ctx.channel.id == 527938405951078407), commands.has_any_role("@moderator", "@admin", "@owner")) async def main2(self, ctx: Context): """Gives a role with permissions to send messages in Main 2. The role is automatically removed after 10 minutes of inactivity in the channel. """ if await self.bot.db.fetchone( "SELECT * FROM main2_blacklist WHERE id = ?", ctx.author.id): embed = discord.Embed(color=EGG_COLOR, timestamp=ctx.message.created_at) embed.set_author(name="You're blacklisted from this command.", icon_url=ctx.me.avatar_url) return await ctx.send(embed=embed) role = ctx.guild.get_role(723223787130191953) if role in ctx.author.roles: return embed = discord.Embed( description="You can now send messages in <#704713087772524565>.", color=EGG_COLOR, timestamp=ctx.message.created_at) embed.set_author(name="Role added.", icon_url=ctx.me.avatar_url) await ctx.author.add_roles(role) await ctx.send(embed=embed) def message_check(message: discord.Message): return message.author == ctx.author and message.channel.id == 704713087772524565 def role_check(before: discord.Member, after: discord.Member): return role in before.roles and role not in after.roles while True: futures = [ self.bot.wait_for("message", check=message_check), self.bot.wait_for("member_update", check=role_check) ] done, pending = await asyncio.wait( futures, timeout=600.0, return_when=asyncio.FIRST_COMPLETED) for future in pending: future.cancel() if not done: break result = done.pop().result() if isinstance(result, discord.Message): continue break await ctx.author.remove_roles(role) @main2.command() @commands.has_any_role("@moderator", "@admin", "@owner") async def block(self, ctx: Context, *, member: discord.Member): if role := discord.utils.get(member.roles, name="Main 2"): await member.remove_roles(role) _id = member.id await self.bot.db.execute( "INSERT OR IGNORE INTO main2_blacklist (id) VALUES (?)", _id) await ctx.message.add_reaction("\N{FLUSHED FACE}")
class Handle(commands.Cog): def __init__(self, bot): self.bot = bot @commands.command(brief="Set nick codeforces để dùng bot.", usage="nick codeforces của bạn.") async def identify(self, ctx, handle): """ Dùng command này để set nick codeforces. Bot sẽ yêu cầu bạn nộp một code bị dịch lỗi tới bài nào đó trong vòng 60s. Nếu nick codeforces mình là `leduykhongngu` thì mình dùng: ;voj identify leduykhongngu """ discord_id = ctx.author.id tmp = RankingDb.RankingDb.get_handle(discord_id) if tmp is not None: await ctx.send('Ông identify lần 2 làm cái gì. Có nick {0} chưa đủ à'.format(tmp)) return subs = await codeforces_api.get_user_status(handle) problem = random.choice(codeforces_api.problems) await ctx.send(f'<@{str(ctx.author.id)}>, Hãy nộp một submission bị DỊCH LỖI tới bài <https://codeforces.com/problemset/problem/{problem[0]}/{problem[1]}> trong 60 giây') for i in range(6): await asyncio.sleep(10) subs = await codeforces_api.get_user_status(handle) if any(sub == problem[2] for sub in subs): x = RankingDb.RankingDb.set_handle(discord_id, handle) if x != 0: await ctx.send('Lỗi, nick {0} đã được set cho user <@{1}>. Gọi @Cá nóc cắn cáp nếu cần giúp đỡ'.format(handle, x)) else: await ctx.send(SET_HANDLE_SUCCESS.format(discord_id, handle)) return await ctx.send(f'<@{str(ctx.author.id)}>, thử lại pls. Dùng `;voj help identify` nếu cần giúp đỡ.') @commands.command(brief='Set Codeforces handle of a user') @commands.check_any(commands.is_owner(), commands.has_any_role('Admin', 'Mod VNOI')) async def set(self, ctx, member: discord.Member, handle): # message = ( # "Vẫn đang được dev, xin quay lại sau ...\n" # "~~Vì lý do đặc biệt nên xem xét dùng các command sau:\n" # "- Nếu user chưa identify bao giờ -> ;voj set_new @member handle\n" # "- Nếu user muốn đổi acc codeforces -> ;voj change @member new_handle\n" # "- Nếu user dùng acc discord mới -> ;voj ~~" # ) # await ctx.send(message) # return # await ctx.send("Cẩn thận khi dùng cái này, nên hú Thức cho chắc.") if RankingDb.RankingDb.set_handle(member.id, handle) == 0: await ctx.send(SET_HANDLE_SUCCESS.format(member.id, handle)) else: await ctx.send("Failed ?? :D ??") @commands.command(brief='Lấy nick của user tương ứng') async def get(self, ctx, member: discord.Member): """ Lấy codeforces nick của user discord tương ứng. Nếu mình muốn lấy nick codeforces của Cá Nóc Cắn Cáp, thì dùng: ;voj get @cá nóc cắn cáp (tag vào) """ handle = RankingDb.RankingDb.get_handle(member.id) if handle is None: await ctx.send(f'Không tìm thấy nick của {member.mention} trong dữ liệu. Xin hãy dùng command ;voj identify nick_cf') return await ctx.send(SET_HANDLE_SUCCESS.format(member.id, handle))
def predicate(ctx): return commands.has_any_role(Roles.IF1A, Roles.IF1B, Roles.IB1A, Roles.IB1B, Roles.IB1C, Roles.IB1D)
- ctx: discord.Context object Returns: - isDM: str""" # If message guild is None, we are in DMs if ctx.guild is None: return True return False # region mod commands # This decorator adds the command to the command list @bot.command() @commands.check_any(commands.has_any_role(*config.elevated_roles), commands.is_owner()) # The function name is the name of the command, unless specified. async def ban(ctx, musr: typing.Union[discord.Member, str] = None, *, reason: str = f"No reason supplied; {config.botname}"): # Check if the musr object was properly parsed as a User object if isinstance(musr, discord.Member): # ignore if self if ctx.author == musr: return # Fail if user is invincible if len([r for r in musr.roles if r.id in config.invincibleroles]) > 0: return await ctx.send("_🚫 You can't ban invincible users_")
@disq.command( name="time", aliases=["t"], description= "Check how long until you or a user is re-eligible for giveaways.") async def disq_time(self, ctx, user: discord.Member = None): # This should return a timedelta? iunno lol if user is None: ctx.bot.disq(ctx.author) ctx.bot.disq(user) # Giveaway @commands.group(name="giveaway", aliases=["give", "g"]) @commands.check_any(commands.has_guild_permissions(manage_messages=True), commands.has_any_role()) async def give(self, ctx): """All giveaway-related commands.""" if not ctx.invoked_subcommand: await ctx.send_help(self.give) @give.command(name="start", aliases=["s"]) async def give_start(self, ctx, channel: typing.Optional[discord.TextChannel], *, giveaway_data): """ Starts a giveaway on a given channel. giveaway_data should have the following data: - Ending time - Platform data w/ giveaway row (Optional),
class POTD(commands.Cog): def __init__(self, bot): self.bot = bot @commands.Cog.listener() async def on_ready(self): self.POTD_dis = self.bot.get_channel(int(_POTD_DISCUSSION_CHANNEL)) self.POTD_post = self.bot.get_channel(int(_POTD_POST)) self.POTD_sug = self.bot.get_channel(int(_POTD_SUGGESTION)) @commands.Cog.listener() async def on_message(self, message): if str(message.channel.id) != str(_POTD_SUGGESTION): return if message.author.bot: return note = message.content pattern = r"https?:\/\/\S+" links = re.findall(pattern, note) if len(links) == 0: return if len(links) > 1: await message.channel.send("Ít bài thôi, không prof đau ruột thừa mất.") return link = links[0] author = message.author.id if potd_database.PotdDB.add_potd(link, note, author): for x in message.guild.emojis: if x.name == 'dab': await message.add_reaction(x) else: await message.channel.send('Ông đừng tưởng tôi không biết ông đạo bài nhé. Gửi bài khác đê.') @commands.command(brief="Lấy role SOTD sau khi hoàn thành bài") async def gimme(self, ctx): if potd_database.PotdDB.today_potd() is None: await ctx.send("Hôm nay làm gì có Problem of the day, ông định lừa ai?") return sotd = None for role in ctx.guild.roles: if role.name == _SOLVER_OF_THE_DAY: sotd = role if sotd is None: await ctx.send(f'Sever đã có role `{_SOLVER_OF_THE_DAY}` đâu mà cho') return for role in ctx.author.roles: if role.name == _SOLVER_OF_THE_DAY: await ctx.send('Xin 1 lần thôi xin gì xin lắm!!!!') return await ctx.author.add_roles(sotd) for x in ctx.guild.emojis: if x.name == 'dab': await ctx.message.add_reaction(x) async def clear_role(self, ctx): sotd = None for role in ctx.guild.roles: if role.name == _SOLVER_OF_THE_DAY: sotd = role if sotd is None: return cnt_AC = 0 for member in sotd.members: await member.remove_roles(sotd) cnt_AC += 1 print("Cleared role SOTD") return cnt_AC async def post_new_problem(self, ctx): potd = potd_database.PotdDB.get_potd() if potd is None: await ctx.send(f"Trong queue hết bài rồi, các bạn vào suggest đi <:sadness:662197924918329365>") return link = potd[0] note = potd[1] author = potd[2] author = ctx.guild.get_member(int(author)) if author is None: author = ctx.author color = discord_common._SUCCESS_BLUE_ today = datetime.today().strftime('%d-%m-%Y') embed = discord.Embed(title=f"Problem of the day {today}", description= note, url=link, color=color) embed.set_author(name=author.display_name, icon_url=author.avatar_url) embed.set_thumbnail(url="https://cdn.discordapp.com/avatars/669671624793915402/8c8e467d1ce25a0474279d076a33529a.jpg?size=1024") await self.POTD_post.send(embed=embed) return potd @commands.command(brief="Renew potd") @commands.check_any(commands.is_owner(), commands.has_any_role('Admin', 'Mod VNOI')) async def renew(self, ctx): #clear role SOTD current_potd = potd_database.PotdDB.today_potd() if current_potd is not None: cnt_AC = await self.clear_role(ctx) await ctx.send(f"Có {cnt_AC} người đã AC potd") link, note, author = current_potd potd_database.PotdDB.move_problem('potd_using', 'potd_used', link, note, author) #get new problem new_potd = await self.post_new_problem(ctx) if new_potd is not None: link, note, author = new_potd potd_database.PotdDB.move_problem('potd_queue', 'potd_using', link, note, author)
def predicate(ctx): return commands.has_any_role(ServerRoles.ALL_GROUPS)
await payload.member.send("Your reaction is recorded") await message.remove_reaction(reaction.emoji, payload.member) await c.execute( "INSERT INTO reactions (user_id,message_id) VALUES (?,?)", (member, payload.message_id)) await c.execute("SELECT * FROM reactions") z = await c.fetchall() print(z) await conn.commit() elif users != None: await payload.member.send("You can't vote again") await message.remove_reaction(reaction.emoji, payload.member) @commands.command() @commands.check_any(commands.has_any_role("Mod", "BookKeeper"), is_suv()) async def save(self, ctx): for attachment in ctx.message.attachments: print("hello") if any(attachment.filename.lower().endswith(image) for image in image_types): for attachment in ctx.message.attachments: await attachment.save(attachment.filename) await ctx.send(f"Saved {attachment.filename}") @save.error async def save_error(self, ctx, error): if isinstance(error, commands.MissingAnyRole): await ctx.send("You don't have the role to run the command")
class reaction(commands.Cog): def __init__(self, bot): self.bot = bot @commands.command(name='create poll', aliases=['cp']) @commands.check_any(commands.has_any_role("Mod", "BookKeeper"), is_suv()) async def create_poll(self, ctx, question, *options): conn = await aiosqlite.connect('test.db') c = await conn.cursor() member = ctx.message.author member_name = member.name member_avatar = member.avatar_url print(member_name) embed = discord.Embed(colour=discord.Colour.green(), title=question) embed.set_author(name=member_name, icon_url=member_avatar) fields = [("Options", "\n".join([ f"{alphabets[idx]} {option}" for idx, option in enumerate(options) ]), False), ("Instructions", "React slowly and on one option.", False)] for name, value, inline in fields: embed.add_field(name=name, value=value, inline=inline) sent_message = await ctx.send(embed=embed) for emote in alphabets[:len(options)]: await sent_message.add_reaction(emote) message_id = sent_message.id await c.execute("INSERT INTO reactions (message_id) VALUES ( ?)", (message_id)) await conn.commit() await c.execute("SELECT * FROM reactions") b = await c.fetchone() print("Command", b) @create_poll.error async def create_poll_error(self, ctx, error): if isinstance(error, commands.MissingAnyRole): await ctx.send("You don't have the role to run the command") @commands.Cog.listener() async def on_raw_reaction_add(self, payload): conn = await aiosqlite.connect('test.db') c = await conn.cursor() member = payload.user_id await c.execute( "SELECT user_id FROM reactions WHERE user_id = ? AND message_id = ?", (member, payload.message_id)) users = await c.fetchone() print("User", users) await c.execute("SELECT message_id FROM reactions") message = await self.bot.get_channel(payload.channel_id ).fetch_message(payload.message_id ) for reaction in message.reactions: if (not payload.member.bot and users == None and payload.member in await reaction.users().flatten()): await payload.member.send("Your reaction is recorded") await message.remove_reaction(reaction.emoji, payload.member) await c.execute( "INSERT INTO reactions (user_id,message_id) VALUES (?,?)", (member, payload.message_id)) await c.execute("SELECT * FROM reactions") z = await c.fetchall() print(z) await conn.commit() elif users != None: await payload.member.send("You can't vote again") await message.remove_reaction(reaction.emoji, payload.member)
class Music(commands.Cog): def __init__(self, bot): self.bot = bot self.music_queue = defaultdict(list) @commands.command() @commands.check_any(commands.is_owner(), commands.has_any_role(*voice_channel_moderator_roles)) async def summon(self, ctx): """Joins a voice channel""" logger.info(f"Summoned! author:'{ctx.author}'") @commands.command() @commands.check_any(commands.is_owner(), commands.has_any_role(*voice_channel_moderator_roles)) async def play(self, ctx, *, song): """Play a song or playlist""" logger.info( f"play command - song:'{song}' author:'{ctx.author}' guild:'{ctx.guild}'" ) music_queue = self.music_queue[ctx.guild.id] await self.queue_song(ctx, song) if len(music_queue) > 0 and not ctx.voice_client.is_playing(): await self.play_music(ctx) @commands.command() @commands.check_any(commands.is_owner(), commands.has_any_role(*voice_channel_moderator_roles)) async def skip(self, ctx): """Skip to next song""" logger.info(f"skip command - author:{ctx.author}") if ctx.voice_client: ctx.voice_client.stop() #await self.play_music(ctx) @commands.command() @commands.check_any(commands.is_owner(), commands.has_any_role(*voice_channel_moderator_roles)) async def queue(self, ctx): """List songs in the queue""" logger.info(f"queue command - author:'{ctx.author}'") music_queue = self.music_queue[ctx.guild.id] if len(music_queue) > 0: embed = discord.Embed(title=f"Song queue") text = "" for (n, (player, _)) in enumerate(music_queue): text += f"{n+1}. **{player.title}**\n" embed.description = text await ctx.send(embed=embed) else: await ctx.send(f":shrug: Queue is empty") @commands.command() @commands.check_any(commands.is_owner(), commands.has_any_role(*voice_channel_moderator_roles)) async def volume(self, ctx, volume: int): """Changes the player's volume""" logger.info( f"volume command - volume:'{volume}' author:'{ctx.author}'") if ctx.voice_client is None: return await ctx.send("Not connected to a voice channel.") volume = max(0, min(volume, 100)) ctx.voice_client.source.volume = volume / 100 await ctx.send(f"Changed volume to {volume}%") @commands.command() @commands.check_any(commands.is_owner(), commands.has_any_role(*voice_channel_moderator_roles)) async def pause(self, ctx): """Pause or resume music""" logger.info(f"stop command - author:'{ctx.author}'") if ctx.voice_client is not None: if ctx.voice_client.is_paused(): ctx.voice_client.resume() await ctx.send(f":arrow_forward: Resuming the music") elif ctx.voice_client.is_playing(): ctx.voice_client.pause() await ctx.send(f":pause_button: Pausing the music") @commands.command() @commands.check_any(commands.is_owner(), commands.has_any_role(*voice_channel_moderator_roles)) async def stop(self, ctx): """Stops and disconnects the bot from voice""" logger.info(f"stop command - author:'{ctx.author}'") music_queue = self.music_queue[ctx.guild.id] if ctx.voice_client is not None: await ctx.voice_client.disconnect() music_queue.clear() @commands.command() @commands.check_any(commands.is_owner(), commands.has_any_role(*voice_channel_moderator_roles)) async def solo(self, ctx): """Soloooooooo""" logger.info(f"solo command - author:'{ctx.author}'") music_queue = self.music_queue[ctx.guild.id] await self.queue_song(ctx, solo) if len(music_queue) > 0 and not ctx.voice_client.is_playing(): await self.play_music(ctx) @commands.Cog.listener() async def on_voice_state_update(self, member: discord.Member, before: discord.VoiceState, after: discord.VoiceState): if member.id == self.bot.user.id: return voice = member.guild.voice_client if voice is None: return logger.info( f"voice update voice:{voice} member:{member} before:{before.channel} after:{after.channel}" ) channel = voice.channel if len(channel.members ) == 1 and channel.members[0].id == self.bot.user.id: logger.info(f"channel empty, wait 20s - channel:{channel}") await asyncio.sleep(20) if len(channel.members ) == 1 and channel.members[0].id == self.bot.user.id: logger.info(f"disconnecting from {channel}") music_queue = self.music_queue[channel.guild.id] await voice.disconnect() music_queue.clear() async def queue_song(self, ctx, song): async with ctx.typing(): songs = await YTDLSource.from_url(song, loop=self.bot.loop) if len(songs) == 0: await ctx.send( f":shrug: Couldn't find **{song}** -- requested by {ctx.author.mention}" ) else: text = "" music_queue = self.music_queue[ctx.guild.id] for song in songs: logger.info(f"adding song {song.title}") text += f":musical_note: Added **{song.title}** to the queue\n" music_queue.append((song, ctx.author.mention)) if len(music_queue) >= 1: await ctx.send(embed=discord.Embed(description=text)) async def play_music(self, ctx): music_queue = self.music_queue[ctx.guild.id] if len(music_queue) > 0: (song, author) = music_queue.pop(0) await ctx.send(embed=discord.Embed( description= f":arrow_forward: Playing **{song.title}** -- requested by {author}" )) loop = self.bot.loop ctx.voice_client.play( song, after=lambda e: wrap_await( play_next(ctx, ctx.voice_client, music_queue, loop), loop)) @play.before_invoke @solo.before_invoke @skip.before_invoke @summon.before_invoke async def ensure_voice(self, ctx): logger.info("ensuring voice connection") if ctx.author.voice: logger.info(f"connecting to {ctx.author.voice.channel.name}") if ctx.voice_client is None: await ctx.author.voice.channel.connect() else: await ctx.voice_client.move_to(ctx.author.voice.channel) else: await ctx.send("You are not connected to a voice channel.") raise commands.CommandError( "Author not connected to a voice channel.")
class RankingCommand(commands.Cog): def __init__(self, bot): self.bot = bot username = os.getenv('CODEFORCES_USERNAME') password = os.getenv('CODEFORCES_PASSWORD') group_id = os.getenv('CODEFORCES_GROUP_ID') self.crawler = SubmissionCrawler.Crawler(username, password, group_id) self.rank_cache = [] self.looper.start() self.index = 0 @tasks.loop(minutes=10.0) async def looper(self): self.index += 1 print("looping " + str(self.index)) try: await self.crawl(None, 1, 162) await self.calculate_rank(None) except Exception as e: print(e) @commands.command(brief="Lấy thông tin các huy hiệu") async def badge(self, ctx): """ Hiện phần trăm điểm yêu cầu để đạt được huy hiệu tương ứng. """ style = table.Style('{:<} {:<} {:<}') t = table.Table(style) t += table.Header('Tên huy hiệu', '% yêu cầu', '% giới hạn') t += table.Line() for rank in badge.RATED_RANKS: title = rank.title low = max(0, rank.low) hi = min(100, rank.high) low = "{:.2f}%".format(low) hi = "{:.2f}%".format(hi) t += table.Data(title, low, hi) table_str = f'```\n{t}\n```' embed = discord_common.cf_color_embed( title="% điểm yêu cầu." "Tổng điểm hiện tại SUM_SCORE={:.2f}".format(badge.MAX_SCORE), description=table_str) await ctx.send(embed=embed) @commands.command(brief="Update badge info.") @commands.check_any(commands.is_owner(), commands.has_any_role('Admin', 'Mod VNOI')) async def update_badge(self, ctx, name, low, hi): try: for i in range(len(badge.RATED_RANKS)): if badge.RATED_RANKS[i].title == name: rank = badge.RATED_RANKS[i] #Rank = namedtuple('Rank', 'low high title title_abbr color_graph color_embed') badge.RATED_RANKS[i] = badge.Rank(float(low), float(hi), name, rank.title_abbr, rank.color_graph, rank.color_embed) await ctx.send('Ok') return else: await ctx.send('Badge {0} not found'.format(name)) except Exception as e: print(e) await ctx.send(str(e)) # from TLE bot: https://github.com/cheran-senthil/TLE/blob/97c9bff9800b3bbaefb72ec00faa57a4911d3a4b/tle/cogs/duel.py#L410 @commands.command(brief="Hiện bảng xếp hạng") async def rank(self, ctx): """ Hiện bảng xếp hạng. """ if len(self.rank_cache) == 0: await self.calculate_rank(ctx) _PER_PAGE = 10 def make_page(chunk, page_num): style = table.Style('{:>} {:<} {:<}') t = table.Table(style) t += table.Header('#', 'Handle', 'Point') t += table.Line() for index, (point, handle) in enumerate(chunk): point_str = '{:.3f}'.format(point) t += table.Data(_PER_PAGE * page_num + index, handle, point_str) table_str = f'```yml\n{t}\n```' embed = discord.Embed(description=table_str) return 'Bảng xếp hạng VOJ', embed pages = [ make_page(chunk, k) for k, chunk in enumerate( paginator.chunkify(self.rank_cache, _PER_PAGE)) ] paginator.paginate(self.bot, ctx.channel, pages) @commands.command(brief="Calculate ranking and cache it.") @commands.check_any(commands.is_owner(), commands.has_any_role('Admin', 'Mod VNOI')) async def calculate_rank(self, ctx): start = time.perf_counter() message = "" if ctx != None: message = await ctx.send( '<:pingreee:665243570655199246> Calculating ...') # calculating problem_points = common.get_problem_points(force=True) badge.MAX_SCORE = 0 # for p, point in problem_points.items(): # #remove scale # badge.MAX_SCORE += point # # badge.MAX_SCORE += 2 user_data = RankingDb.RankingDb.get_data('user_data', limit=None) user_handles = {} for cf_id, handle, discord_id in user_data: if cf_id is None: continue user_handles[int(cf_id)] = handle user_points = {} solved_info = RankingDb.RankingDb.get_data('solved_info', limit=None) for user_id, problem_id, result, date in solved_info: handle = user_handles[int(user_id)] if handle not in user_points: user_points[handle] = 0 if result == 'AC': result = 100 result = float(result) #remove scale user_points[handle] += result * problem_points[int( problem_id)] / 100 # user_points[handle] += result * 2 / 100 self.rank_cache = [] badge.MAX_SCORE = 0 for handle, point in user_points.items(): self.rank_cache.append((point, handle)) badge.MAX_SCORE = max(badge.MAX_SCORE, point) self.rank_cache.sort(reverse=True) end = time.perf_counter() duration = (end - start) * 1000 if ctx != None: await message.edit( content=f'Done. Calculation time: {int(duration)}ms.') @commands.command(brief="Test crawler") @commands.check_any(commands.is_owner(), commands.has_any_role('Admin', 'Mod VNOI')) async def exclude(self, ctx, contest_id): open('database/contest_id_whitelist.txt', 'a').write(str(contest_id) + '\n') await ctx.send('ok') @commands.command(brief="Test crawler") @commands.check_any(commands.is_owner(), commands.has_any_role('Admin', 'Mod VNOI')) async def crawl(self, ctx, l, r): if self.crawler.login() == False: if ctx is not None: await ctx.send( 'Failed when log in to codeforces, please try later.') else: print('Failed when log in to codeforces, please try later.') return l = int(l) r = int(r) problems = self.crawler.get_new_submissions(l, r) if ctx is not None: await ctx.send('Found {0} submissions.'.format(len(problems))) else: print('Found {0} submissions.'.format(len(problems))) cnt = 0 for p_info in problems: cnt += 1 if cnt % 10 == 0: print(cnt) id, problem_name, short_link, handle, user_id, verdict, date = p_info RankingDb.RankingDb.handle_new_submission(problem_name, short_link, verdict, user_id, handle, date) RankingDb.RankingDb.conn.commit()
class BotControl(commands.Cog): def __init__(self, bot): self.bot = bot self.start_time = time.time() # @commands.Cog.listener() # async def on_ready(self): # pass # from TLE bot. @commands.command(brief="Check if bot is still alive.") @commands.check_any(commands.is_owner(), commands.has_any_role('Admin', 'Mod VNOI')) async def ping(self, ctx): """Replies to a ping.""" start = time.perf_counter() message = await ctx.send('<:pingreee:665243570655199246>') end = time.perf_counter() duration = (end - start) * 1000 await message.edit( content= f'<:pingreee:665243570655199246>\nREST API latency: {int(duration)}ms\n' f'Gateway API latency: {int(self.bot.latency * 1000)}ms') @commands.command(brief="Kill bot. ") @commands.check_any(commands.is_owner(), commands.has_any_role('Admin', 'Mod VNOI')) async def kill(self, ctx): """Kill bot""" await ctx.send("Dying") exit(0) @commands.command(brief='Restart bot') @commands.check_any(commands.is_owner(), commands.has_any_role('Admin', 'Mod VNOI')) async def restart(self, ctx): await ctx.send('Restarting...') os.execv(sys.executable, [sys.executable] + sys.argv) @commands.command(brief="Get database. ") @commands.check_any(commands.is_owner(), commands.has_any_role('Admin', 'Mod VNOI')) async def database(self, ctx): last_submission = open('database/last_submission.txt').read().strip() await ctx.send('Last submissions: {0}'.format(last_submission), file=discord.File('database/ranking.db', filename='ranking.db')) @commands.command(brief="Update bot & restart") @commands.check_any(commands.is_owner(), commands.has_any_role('Admin', 'Mod VNOI')) async def update_restart(self, ctx): await self.update(ctx) await self.restart(ctx) @commands.command(brief='Get git information') @commands.check_any(commands.is_owner(), commands.has_any_role('Admin', 'Mod VNOI')) async def git(self, ctx): """Replies with git information.""" await ctx.send('```yaml\n' + git_history() + '```') @commands.command(brief='Incorporates changes from the remote repository') @commands.check_any(commands.is_owner(), commands.has_any_role('Admin', 'Mod VNOI')) async def update(self, ctx): mess = await ctx.send('Getting changes from the remote repository...') result = subprocess.run( ['git', 'pull', 'origin', 'dev'], stdout=subprocess.PIPE).stdout.decode('utf-8').strip() await mess.edit(content='```\n' + result + '\n```')
class SheetApproval(commands.Cog): def __init__(self, bot): self.bot = bot async def sheet_from_emoji(self, payload) -> ToBeApproved: # Check the Guild guild_id = payload.guild_id if guild_id != self.bot.personal_server['server_id']: return None # Check the Roles member = payload.member if member is None: member = self.bot.get_guild(guild_id).get_member(payload.user_id) if member is None: return None if len([ role for role in member.roles if role.name.lower() in APPROVAL_ROLES ]) == 0: return None # Check to see if it's an existing sheet result = await self.bot.mdb['to_approve'].find_one( {'message_id': payload.message_id}) if result is None: return None # Get rid of object id result.pop('_id') sheet: ToBeApproved = ToBeApproved.from_dict(result) return sheet @commands.Cog.listener('on_raw_reaction_add') async def check_for_approval(self, payload): sheet: ToBeApproved = await self.sheet_from_emoji(payload) if sheet is None: return if len(sheet.approvals) >= 2: return guild = self.bot.get_guild(payload.guild_id) await sheet.add_approval(guild, payload.member, self.bot) await sheet.commit(self.bot.mdb['to_approve']) @commands.Cog.listener('on_raw_reaction_remove') async def check_for_deny(self, payload): sheet: ToBeApproved = await self.sheet_from_emoji(payload) if sheet is None: return guild = self.bot.get_guild(payload.guild_id) await sheet.remove_approval(guild, payload.user_id, self.bot) await sheet.commit(self.bot.mdb['to_approve']) @commands.command(name='sheet', aliases=['submit']) @is_personal_server() async def new_sheet(self, ctx, *, content: str): """ Adds a sheet to be approved """ embed = create_default_embed(ctx) embed.title = f'Sheet Approval - {ctx.author.display_name}' embed.description = content if '(url)' in content: return await ctx.author.send( 'You must include your *actual* sheet URL in the command, not `(url)`' ) # If not character-submission or FrogBot dev if (ctx.channel.id != self.bot.personal_server['sheet_channel'] ) and not (ctx.guild.id == 755202524859859004): return await ctx.send( 'This channel is not valid for submitting sheets.') msg = await ctx.send(embed=embed) new_sheet = ToBeApproved(message_id=msg.id, approvals=[], channel_id=ctx.channel.id, owner_id=ctx.author.id) await self.bot.mdb['to_approve'].insert_one(new_sheet.to_dict()) @commands.command('cleanup_sheets') @is_personal_server() @commands.check_any(is_owner(), commands.has_any_role(*BOT_MODS)) async def remove_sheets(self, ctx): """ Removes deleted sheets from database. Run every once and a while. """ db = self.bot.mdb['to_approve'] embed = create_default_embed(ctx) embed.title = f'Pruning Old Sheets from Database.' all_sheets = await db.find().to_list(None) count = 0 for sheet in all_sheets: sheet.pop('_id') sheet = ToBeApproved.from_dict(sheet) channel = ctx.guild.get_channel(sheet.channel_id) if channel is None: continue try: await channel.fetch_message(sheet.message_id) except discord.NotFound: count += 1 await db.delete_one({'message_id': sheet.message_id}) embed.description = f'Pruned {count} Sheet{"s" if count != 1 else ""} from the DB.' await ctx.send(embed=embed)
class Loot(commands.Cog): def __init__(self, bot): self.bot = bot self.timeFormats = [ "%d/%m/%Y", "%d/%m/%y", "%m/%d", "%d-%m-%Y", "%d-%m-%y", "%m-%d" ] @commands.command(help="Adds a user to the loot tracking Database.") @commands.check_any(commands.has_any_role(*keys.LOOT_MODS), is_me()) async def addUser(self, ctx, username: str): with self.createConnection() as conn: with conn.cursor() as cur: cur.execute( "SELECT * FROM {0} WHERE username ILIKE %s".format( keys.USERS_TABLE), (username, )) if (cur.fetchone() == None): cur.execute( "INSERT INTO {0} (username) VALUES(%s)".format( keys.USERS_TABLE), (username, )) await ctx.message.add_reaction('✅') else: await ctx.send( "User `{0}` already added to database.".format( username)) @commands.command( help= "Adds a drop.\n Timestamp should be of the format DD/MM or DD/MM/YY. If no year is specified, the current year will be assumed." ) @commands.check_any(commands.has_any_role(*keys.LOOT_MODS), is_me()) async def addLoot(self, ctx, username: str, timestamp: str, *, loot): with self.createConnection() as conn: with conn.cursor() as cur: ##table = "drops2" if ctx.channel.id == 718219865483116545 else "drops" table = keys.SECONDARY_MAPPINGS[ ctx.channel. id] if ctx.channel.id in keys.SECONDARY_MAPPINGS else keys.MAIN_DB ##Validate username and exit if invalid ret = await self.__validateUsername(ctx, cur, username) if (ret): return () ##Validate timestamp, store in self.dTime, and exit if invalid ret = await self.__validateTimestamp(ctx, timestamp) if (ret): return () ##Validate loot and exit if invalid ret = await self.__validateLoot(ctx, cur, loot) if (ret): return () try: cur.execute( "INSERT INTO {0} (date, username, loot) VALUES(%s, %s, %s)" .format(table), (self.dTime, username, loot)) await ctx.message.add_reaction('✅') except psycopg2.errors.UniqueViolation as e: await ctx.send("Duplicate, unable to insert.") except Exception as e: print("Error inserting: {0}".format(e)) await ctx.send( "Unable to insert, contact Will if you think this is in error." ) @commands.command( help= "Deletes user and ALL associated drops from database. Use carefully.") @commands.check_any(commands.has_any_role(*keys.LOOT_MODS), is_me()) async def deleteUser(self, ctx, username: str): with self.createConnection() as conn: with conn.cursor() as cur: ##Validate username and exit if invalid ret = await self.__validateUsername(ctx, cur, username) if (ret): return () r1 = cur.execute("DELETE FROM drops WHERE username ILIKE %s", (username, )) r2 = cur.execute( "DELETE FROM {0} WHERE username ILIKE %s".format( keys.USERS_TABLE), (username, )) r3 = cur.execute("DELETE FROM drops2 WHERE username ILIKE %s", (username, )) print(r1, r2) await ctx.message.add_reaction('✅') @commands.command( help="Deletes a specific drop from the database. Use carefully.") @commands.check_any(commands.has_any_role(*keys.LOOT_MODS), is_me()) async def deleteLoot(self, ctx, username: str, timestamp: str, *, loot): with self.createConnection() as conn: with conn.cursor() as cur: table = keys.SECONDARY_MAPPINGS[ ctx.channel. id] if ctx.channel.id in keys.SECONDARY_MAPPINGS else keys.MAIN_DB ##Validate username and exit if invalid ret = await self.__validateUsername(ctx, cur, username) if (ret): return () ##Validate timestamp, store in self.dTime, and exit if invalid ret = await self.__validateTimestamp(ctx, timestamp) if (ret): return () ##Validate loot and exit if invalid ret = await self.__validateLoot(ctx, cur, loot) if (ret): return () cur.execute( "DELETE FROM {0} WHERE date = %s AND username ILIKE %s AND loot ILIKE %s" .format(table), (self.dTime, username, loot)) await ctx.message.add_reaction('✅') async def __validateLoot(self, ctx, cur, loot): cur.execute( "SELECT * FROM {0} WHERE loot ILIKE %s".format( keys.DROPS_TABLE_DB), (loot, )) if (cur.fetchone() == None): cur.execute( "SELECT *, similarity(loot, %s) FROM {0} ORDER BY 5 desc LIMIT 5;" .format(keys.DROPS_TABLE_DB), (loot, )) simList = "\n".join(["`{0[1]}`".format(x) for x in cur.fetchall()]) await ctx.send( "Loot `{0}` not in database.\nDid you mean:\n{1}".format( loot, simList)) return (1) return (0) async def __validateUsername(self, ctx, cur, username): cur.execute( "SELECT * FROM {0} WHERE username ILIKE %s".format( keys.USERS_TABLE), (username, )) if (cur.fetchone() == None): cur.execute( "SELECT *, similarity(username, %s) FROM {0} ORDER BY 3 desc LIMIT 5;" .format(keys.USERS_TABLE), (username, )) simList = "\n".join(["`{0[1]}`".format(x) for x in cur.fetchall()]) await ctx.send( "User `{0}` not in database.\nYou can add them with ```?addUser {0}```\nOr, did you mean:\n{1}" .format(username, simList)) return (1) return (0) async def __validateTimestamp(self, ctx, timestamp): self.dTime = None for tFormat in self.timeFormats: try: self.dTime = time.strptime(timestamp, tFormat) break except: pass if (self.dTime == None): await ctx.send("Invalid time format specified. Try MM/DD") return (1) self.dTime = datetime.datetime(*self.dTime[:6]) if (self.dTime.year == 1900): self.dTime = self.dTime.replace(year=datetime.datetime.now().year) if (self.dTime > datetime.datetime.now() + datetime.timedelta(days=1)): await ctx.send("Timestamp is in the future.") return (1) return (0) async def __validateRaid(self, ctx, cur, raid): cur.execute( "SELECT * FROM {0} WHERE raid ILIKE %s".format( keys.DROPS_TABLE_DB), (raid, )) if (cur.fetchone() == None): cur.execute( "SELECT DISTINCT (raid), similarity(raid, %s) FROM {0} ORDER BY similarity DESC LIMIT 5" .format(keys.DROPS_TABLE_DB), (raid, )) simList = "\n".join(["`{0[0]}`".format(x) for x in cur.fetchall()]) await ctx.send( "Raid `{0}` not in database.\nDid you mean:\n{1}".format( raid, simList)) return (1) return (0) async def __validateBoss(self, ctx, cur, boss): cur.execute( "SELECT * FROM {0} WHERE boss ILIKE %s".format( keys.DROPS_TABLE_DB), (boss, )) if (cur.fetchone() == None): cur.execute( "SELECT DISTINCT (boss), similarity(boss, %s) FROM {0} ORDER BY similarity DESC LIMIT 5" .format(keys.DROPS_TABLE_DB), (boss, )) simList = "\n".join(["`{0[0]}`".format(x) for x in cur.fetchall()]) await ctx.send( "Boss `{0}` not in database.\nDid you mean:\n{1}".format( boss, simList)) return (1) return (0) @commands.command(help="Exports entire database as a csv.") @commands.check_any(commands.has_any_role(*keys.LOOT_MODS), is_me()) async def exportCSV(self, ctx): with self.createConnection() as conn: with conn.cursor() as cur: table = keys.SECONDARY_MAPPINGS[ ctx.channel. id] if ctx.channel.id in keys.SECONDARY_MAPPINGS else keys.MAIN_DB cur.execute("SELECT * FROM {0}".format(table)) drops = cur.fetchall() dropList = "username,date,loot\n" + "\n".join( ["{0[2]},{0[1]},{0[3]}".format(x) for x in drops]) f = discord.File(io.StringIO(dropList), filename="loot.csv") await ctx.send("Exported csv:", file=f) @commands.command(help="Displays the loot recieved by the given user.") @commands.check_any(commands.has_any_role(*USERS), is_me()) async def loot(self, ctx, *, username): with self.createConnection() as conn: with conn.cursor() as cur: table = keys.SECONDARY_MAPPINGS[ ctx.channel. id] if ctx.channel.id in keys.SECONDARY_MAPPINGS else keys.MAIN_DB ##Validate username and exit if invalid ret = await self.__validateUsername(ctx, cur, username) if (ret): return () cur.execute( "SELECT * FROM {0} WHERE username ILIKE %s".format(table), (username, )) drops = cur.fetchall() dropList = "\n\t".join( ["`{0[3]}` - {0[1]}".format(x) for x in drops]) outStr = "`{0}` has received drops:\n\t{1}".format( username, dropList) ##if we can't attach the full log, send as an attachment. if (len(outStr) > 2000): f = discord.File(io.StringIO("\n".join( ["{0[3]} - {0[1]}".format(x) for x in drops])), filename="{0}_drops.txt".format(username)) await ctx.send( "Drop Log for `{0}` exceeds the message length limit. Attaching as file." .format(username), file=f) else: await ctx.send(outStr) @commands.command(help="Displays who has looted the given item.") @commands.check_any(commands.has_any_role(*USERS), is_me()) async def looted(self, ctx, *, drop): with self.createConnection() as conn: with conn.cursor() as cur: table = keys.SECONDARY_MAPPINGS[ ctx.channel. id] if ctx.channel.id in keys.SECONDARY_MAPPINGS else keys.MAIN_DB ##Validate loot and exit if invalid ret = await self.__validateLoot(ctx, cur, drop) if (ret): return () cur.execute( "SELECT * FROM {0} WHERE loot ILIKE %s".format(table), (drop, )) drops = cur.fetchall() dropList = "\n\t".join( ["`{0[2]}` - {0[1]}".format(x) for x in drops]) outStr = "All recipients of `{0}`:\n\t{1}".format( drop, dropList) ##if we can't attach the full log, send as an attachment. if (len(outStr) > 2000): f = discord.File( io.StringIO("\n".join( ["{0[2]} - {0[1]}".format(x) for x in drops])), filename="{0}_drops.txt".format(drop).replace( " ", "_")) await ctx.send( "Drop Log for `{0}` exceeds the message length limit. Attaching as file." .format(drop), file=f) else: await ctx.send(outStr) @commands.command(help="Displays the sources for the given item.") @commands.check_any(commands.has_any_role(*USERS), is_me()) async def sources(self, ctx, *, loot): with self.createConnection() as conn: with conn.cursor() as cur: ##Validate loot and exit if invalid ret = await self.__validateLoot(ctx, cur, loot) if (ret): return () cur.execute( "SELECT * FROM {0} WHERE loot ILIKE %s".format( keys.DROPS_TABLE_DB), (loot, )) sources = cur.fetchall() sourceList = "\n\t".join( ["{0[2]} in {0[3]}".format(x) for x in sources]) await ctx.send("`{0}` is available from:\n\t{1}".format( loot, sourceList)) @commands.command(help="Displays the bosses in the given raid.") @commands.check_any(commands.has_any_role(*USERS), is_me()) async def raid(self, ctx, *, raid): with self.createConnection() as conn: with conn.cursor() as cur: ##Validate raod and exit if invalid ret = await self.__validateRaid(ctx, cur, raid) if (ret): return () cur.execute( "SELECT DISTINCT (boss) FROM {0} WHERE raid ILIKE %s". format(keys.DROPS_TABLE_DB), (raid, )) bosses = cur.fetchall() bossList = "\n\t".join(["`{0[0]}`".format(x) for x in bosses]) await ctx.send( "Bosses in raid `{0}` are:\n\t{1}\nYou can use `?boss <boss>` to view a boss' drops." .format(raid, bossList)) @commands.command(help="Displays the possible drops from the given boss.") @commands.check_any(commands.has_any_role(*USERS), is_me()) async def boss(self, ctx, *, boss): with self.createConnection() as conn: with conn.cursor() as cur: ##Validate boss and exit if invalid ret = await self.__validateBoss(ctx, cur, boss) if (ret): return () cur.execute( "SELECT loot FROM {0} WHERE boss ILIKE %s".format( keys.DROPS_TABLE_DB), (boss, )) loot = cur.fetchall() lootList = "\n\t".join(["`{0[0]}`".format(x) for x in loot]) await ctx.send("`{0}` can drop:\n\t{1}".format(boss, lootList)) @commands.command(help="Displays all the loot on a given date.") @commands.check_any(commands.has_any_role(*USERS), is_me()) async def lootDate(self, ctx, timestamp: str): with self.createConnection() as conn: with conn.cursor() as cur: table = keys.SECONDARY_MAPPINGS[ ctx.channel. id] if ctx.channel.id in keys.SECONDARY_MAPPINGS else keys.MAIN_DB ##Validate timestamp, store in self.dTime, and exit if invalid ret = await self.__validateTimestamp(ctx, timestamp) if (ret): return () dateStr = self.dTime.strftime("%D") cur.execute( "SELECT * FROM {0} WHERE date::date = %s".format(table), (dateStr, )) drops = cur.fetchall() dropList = "\n\t".join( ["`{0[3]}` - `{0[2]}`".format(x) for x in drops]) outStr = "All items looted on `{0}`:\n\t{1}".format( dateStr, dropList) ##if we can't attach the full log, send as an attachment. if (len(outStr) > 2000): f = discord.File( io.StringIO("\n".join( ["{0[3]} - {0[2]}".format(x) for x in drops])), filename="{0}_drops.txt".format(dateStr).replace( "/", "-")) await ctx.send( "Drop Log for `{0}` exceeds the message length limit. Attaching as file." .format(dateStr), file=f) else: await ctx.send(outStr) def createConnection(self): return (psycopg2.connect(dbname="loot", user=keys.PSQL_USERNAME, password=keys.PSQL_PASSWORD, host="192.168.1.20", port=5432))
try: response = requests.get( "https://www.googleapis.com/customsearch/v1" f"?key={GOOGLE_API_KEY}&cx={pseid}&q={query}").json( )["items"][0]["link"] except KeyError: response = "No matches found." return response @OMEGA.command( name="iq", help= "Takes a username, analyzes their post history to generate an estimate of their IQ", ) @commands.check_any(commands.has_any_role("Regular", "Admin"), commands.check(is_in_playground)) async def estimate_iq(ctx, *args): """Returns Omega's most accurate possible estimate of given username's IQ""" if len(args) >= 1: queried_username = args[0] queried_iq_estimate = random.randint(25, 100) requester_iq_estimate = queried_iq_estimate - random.randint(5, 30) requester_username = ctx.message.author response = ( f"Based on post history, {queried_username} has an IQ of approximately " f"{queried_iq_estimate} (which is {queried_iq_estimate - requester_iq_estimate} points " f"higher than the estimated value of {requester_iq_estimate} for {requester_username})." ) else: requester_iq_estimate = random.randint(5, 65)
def predicate(ctx): return commands.has_any_role(Roles.INFORMATIK, Roles.WIRTSCHAFTSINFORMATIK, Roles.DATA_SCIENCE)
@list.error async def list_error(ctx, error): message = 'Wot?' if isinstance(error, commands.MissingRequiredArgument): message = 'List confluences or essences.' elif isinstance(error, commands.CommandInvokeError): err = error.original if isinstance(err, KeyError): message = "Not found." await ctx.send(f'**ERROR**: `{message}`') print(error) # TODO: add "new" command line "list" @bot.command() @commands.check_any(commands.has_any_role(*ADMIN_ROLES), commands.is_owner()) async def new(ctx, what, *args): what = what.lower() if what == 'essence': await new_essence(ctx, *args) elif what == 'combination': await new_combination(ctx, *args) else: raise commands.MissingRequiredArgument async def new_essence(ctx, name, rarity='Unknown'): name, rarity = map(logic.form, [name, rarity]) logic.add_essence(name, rarity) await ctx.send(f'Added new essence `{name} [{rarity}]`.')
class Modmail(commands.Cog, name="Modmail System"): def __init__(self, client): self.client = client self.IST = pytz.timezone('Asia/Kolkata') print("Caching Modmail Data...") self.active_channels_dict = { i['_id']: i["channel_id"] for i in self.client.sent_users.find() } self.ban_dict = { i['_id']: { 'reason': i['reason'], 'mod': i['mod'] } for i in self.client.blacklisted_users.find() } with open("data.json") as f: data = json.load(f) f.close() self.category_id = data['category_id'] self.server_id = data['guild_id'] self.mod_role_id = data['mod_role_id'] self.log_channel_id = data['log_channel_id'] self.guild = self.client.get_guild(self.server_id) self.log_channel = discord.utils.get(self.guild.channels, id=data['log_channel_id']) self.msg = None print("Done") @commands.Cog.listener() async def on_ready(self): print(f"{self.__class__.__name__} loaded successfully.") @commands.Cog.listener() async def on_message(self, message): modmail_category = discord.utils.get(self.guild.categories, id=int(self.category_id)) mod_role = discord.utils.get(self.guild.roles, id=int(self.mod_role_id)) if message.author == self.client.user: return if not message.guild: if message.author not in self.guild.members: message_dm = await message.author.send( "You are not in **Gallant Asia**. Join the server to use modmail and connect with the staffs.\n" "Click on ✅ to get invite link.") await message_dm.add_reaction('✅') def check(reaction, user): return user == message.author and str( reaction.emoji) == '✅' try: _, user_ = await self.client.wait_for('reaction_add', check=check, timeout=10.0) except asyncio.TimeoutError: pass else: await user_.send("https://discord.gg/NPFqwc9") return if message.author.id in self.ban_dict: await message.author.send( f"You are banned from using Modmail.\n`Reason: {self.ban_dict[message.author.id]['reason']}`" ) return if message.author.id not in self.active_channels_dict: overwrites = { self.guild.default_role: discord.PermissionOverwrite(read_messages=False), self.guild.me: discord.PermissionOverwrite(read_messages=True), mod_role: discord.PermissionOverwrite(read_messages=True) } channel = await self.guild.create_text_channel( f"{message.author.name}", overwrites=overwrites, category=modmail_category) post = {'_id': message.author.id, "channel_id": channel.id} self.client.sent_users.insert_one(post) self.active_channels_dict[message.author.id] = channel.id self.msg = await self.log_channel.send( content=channel.mention, embed=discord.Embed( title='New Thread', description= f"New thread created by {message.author.name}({message.author.name})\n" f"Channel Created => {channel.mention}", timestamp=datetime.now(self.IST), color=discord.Color.gold())) files = [ await attachment.to_file() for attachment in message.attachments ] if message.attachments != [] else None await message.author.send( "Thank you for your message! You've opened up a new thread with our team of supportive moderators and admins." "As long as the bot is online, messages you send here will be forwarded to the team.\n" "If you've realised that you no longer need our help, reply with 'close' and we'll close your thread." ) await channel.send(files=files, embed=discord.Embed( title='Reply with *reply', description=message.content, timestamp=datetime.now(self.IST), color=discord.Color.green())) else: channel = discord.utils.get(self.guild.channels, id=self.active_channels_dict.get( message.author.id)) await self.log_channel.send( content=channel.mention, embed=discord.Embed( title='New message', description= f" Message from {message.author.name}({message.author.name})\n", timestamp=datetime.now(self.IST), color=discord.Color.random())) await message.add_reaction("✅") await channel.send( embed=discord.Embed(title='Reply with *reply or *r', description=message.content, timestamp=datetime.now(self.IST), color=discord.Color.green())) @commands.Cog.listener() async def on_member_remove(self, member): if member.id in self.active_channels_dict.keys(): channel = discord.utils.get( self.guild.channels, id=self.active_channels_dict[member.id]) try: self.client.sent_users.delete_one({'_id': member.id}) del self.active_channels_dict[member.id] except KeyError: pass await member.send( 'You left our server. Your thread has been closed.\n' 'Hope to see you back soon.\n- Gallant Asia Management Team.') await channel.send( f"{member.name} has left the server. Thread has been closed.Channel will be deleted in 5 minutes." ) await self.log_channel.send( content=channel.mention, embed=discord.Embed( title='Thread closed!', description= f'Thread {channel.mention} has been closed due to {member.name} left the server.', color=discord.Color.orange())) await asyncio.sleep(300.0) check = discord.utils.get(self.guild.channels, id=channel.id) if check is not None: await channel.delete() await self.log_channel.send(embed=discord.Embed( title='Ticket deleted.', description=f"{member.name}'s ticket has been deleted.", color=discord.Color.red())) @commands.command(aliases=['r']) @commands.check_any(commands.has_permissions(administrator=True), commands.has_any_role("Moderator", "Head Mod")) async def reply(self, ctx, *, message): if isinstance(ctx.channel, discord.DMChannel): return user = discord.utils.get(self.guild.members, id=self.get_key(ctx.channel.id)) if user is not None: var = 'Community Lead' if ctx.author.top_role.name == '.' else ctx.author.top_role.name files = [ await attachment.to_file() for attachment in ctx.message.attachments ] if ctx.message.attachments != [] else None await user.send( content= f"**({var}){ctx.author.name}#{ctx.author.discriminator}:** {message}", files=files) await ctx.message.add_reaction('✅') await self.log_channel.send( content=ctx.channel.mention, embed=discord.Embed( description= f'{ctx.author.name} replied to {ctx.channel.mention}', timestamp=datetime.now(self.IST), color=discord.Color.random())) else: await ctx.send( 'Some error occurred. Maybe you are not using the command in a thread channel.' ) @commands.command() @commands.check_any(commands.has_permissions(administrator=True), commands.has_any_role("Moderator", "Head Mod")) async def close(self, ctx): if isinstance(ctx.channel, discord.DMChannel): return if ctx.channel.id in self.active_channels_dict.values(): self.client.sent_users.delete_one( {'_id': self.get_key(ctx.channel.id)}) user = discord.utils.get(self.guild.members, id=self.get_key(ctx.channel.id)) try: del self.active_channels_dict[user.id] except KeyError: pass await user.send('Your thread has been closed.') await ctx.channel.send( 'Thread marked as closed. Channel will be deleted in 5 minutes.' ) await self.log_channel.send( content=ctx.channel.mention, embed=discord.Embed( title='Thread closed!', description= f'Thread {ctx.channel.mention} has been marked as closed by {ctx.author.mention}', color=discord.Color.orange())) await asyncio.sleep(300.0) check = discord.utils.get(self.guild.channels, id=ctx.channel.id) if check is not None: await ctx.channel.delete() await self.log_channel.send(embed=discord.Embed( title='Ticket deleted.', description= f"{user.name}({user.mention})'s ticket has been deleted.", color=discord.Color.red())) @commands.command() @commands.is_owner() async def delete(self, ctx, user_id): try: del self.active_channels_dict[user_id] self.client.sent_users.delete_one({"_id": user_id}) await ctx.send("Deleted.") except KeyError: await ctx.send(f"{user_id} not found in local database.") @commands.command() @commands.has_permissions(administrator=True) async def list(self, ctx): text = '' for key, val in self.active_channels_dict.items(): text += f"<@{key}> => <#{val}>\n" await ctx.send(text) def get_key(self, value): for key, val in self.active_channels_dict.items(): if val == value: return key return None @commands.command(aliases=['bl', 'mban']) @commands.check_any(commands.has_permissions(administrator=True), commands.has_role('Moderator')) async def blacklist(self, ctx, user: discord.Member, reason): self.ban_dict[user.id] = dict( reason=reason, mod=f'{ctx.author.name}#{ctx.author.discriminator}') post = { '_id': user.id, 'reason': reason, 'mod': f'{ctx.author.name}#{ctx.author.discriminator}' } self.client.blacklisted_users.insert_one(post) await ctx.send( discord.Embed(title=f'Banned {user.name}#{user.discriminator}', description=f"**Reason**: {reason}", color=discord.Color.red(), timestamp=datetime.now(self.IST)).set_footer( text=f"Mod - {ctx.author.name}")) @commands.command() @commands.check_any(commands.has_permissions(administrator=True), commands.has_role('Moderator')) async def banlist(self, ctx): embed = discord.Embed(title="Banned users list!", description='', colour=ctx.author.color) for x, y in self.ban_dict.items(): embed.description += f"<@{x}>\n**Reason**: {y['reason']}\nMod: {y['mod']}\n-----------------------------------------" await ctx.send(embed=embed)
class Misc(commands.Cog): def __init__(self, bot): self.bot = bot @commands.Cog.listener() async def on_message(self, message): if message.content.lower() == '!role furaime': await message.add_reaction('👀') if discord.utils.get(message.role_mentions, id=524738280630124574): if random.choice([True, False]): await asyncio.sleep((random.random() * 30) + 30) await message.channel.send(f'@{message.author.mention}') @commands.command(aliases=['joineddate']) @commands.check_any( commands.has_any_role(523276397679083520, 307883683526868992), commands.has_permissions(administrator=True), commands.has_permissions(manage_guild=True)) async def memberinfo(self, ctx, member: discord.Member = None): if member is None: member = ctx.author embed = discord.Embed( title=f"Member info for {member.name}#{member.discriminator}", color=member.color) embed.add_field(name='Created at', value=member.created_at, inline=False) embed.add_field(name='Joined at', value=member.joined_at, inline=False) embed.add_field(name="Discord ID", value=member.id, inline=False) embed.set_thumbnail(url=member.avatar_url) await ctx.send(embed=embed) @commands.command() @commands.is_owner() async def throwerror(self, ctx): raise Exception('omg') @commands.command() async def prng(self, ctx): await ctx.send( "PRNG is RNG! It is random! Humans tend to identify patterns where they do not exist.\n\nIf you're a Linux nerd check this out: https://www.2uo.de/myths-about-urandom/" ) @commands.command(hidden=True) async def pedestalgoal(self, ctx): await ctx.send( "> If it takes 2 hours its because GT is required, which really isn't a thing anymore in pedestal goal games\n-Synack" ) @commands.command( aliases=['crc32'], brief="Posts instructions on how to verify your ROM is correct.", help= "Posts instructions on how to verify your ROM is correct, or how to get the permalink to your randomized game." ) async def rom(self, ctx): await ctx.send( "If you need help verifying your legally-dumped Japanese version 1.0 A Link to the Past Game file needed to run ALttPR, use this tool: <http://alttp.mymm1.com/game/checkcrc/>\n" "It can also help get the permalink page URL which has access to the Spoiler Log depending on the settings that were chosen. Not all games that are generated have access to the Spoiler Log.\n\n" "For legal reasons, we cannot provide help with finding this ROM online. Please do not ask here for assistance with this.\n" "See <#543572578787393556> for details.") @commands.command(hidden=True) async def trpegs(self, ctx): await ctx.send(discord.utils.get(ctx.bot.emojis, name='RIPLink')) @commands.command( brief="Retrieves a holy image.", help="Retrieves a holy image from http://alttp.mymm1.com/holyimage/", aliases=['holy']) async def holyimage(self, ctx, slug=None, game='z3r'): holyimage = await holy(slug=slug, game=game) embed = discord.Embed( title=holyimage.image.get('title'), description=html2markdown.convert(holyimage.image['desc']) if 'desc' in holyimage.image else None, color=discord.Colour.from_rgb(0xFF, 0xAF, 0x00)) if 'url' in holyimage.image: url = urljoin('http://alttp.mymm1.com/holyimage/', holyimage.image['url']) if holyimage.image.get('mode', '') == 'redirect': embed.add_field(name='Link', value=url, inline=False) else: embed.set_thumbnail(url=url) embed.add_field(name="Source", value=holyimage.link) if 'credit' in holyimage.image: embed.set_footer(text=f"Created by {holyimage.image['credit']}") await ctx.send(embed=embed)
async def cog_check(self, ctx): '''Allow only moderators to invoke these commands''' return commands.has_any_role(*check_author())
def is_community_manager(): return commands.has_any_role(*constants.COMMUNITY_MANAGER_ROLES)
class Topics(commands.Cog): """Get topics for discussion.""" def __init__(self, bot: Bot): self.bot = bot self.messages = None async def gen_topic(self): topic = await self.bot.db.get_random_topic() embed = Embed( description=topic["topic"], colour=0x87CEEB, timestamp=topic["created_at"], ) user = self.bot.get_user(topic["author_id"]) embed.set_footer( text=f"From: {user if user else 'unknown'} • ID: {topic['id']} • Created:" ) return embed @commands.command(name="topic") @commands.cooldown(rate=1, per=60, type=commands.BucketType.channel) @in_channel(264417177094848512, 737760236013748295, 779479420481175554) async def get_topic(self, ctx: Context): """Get a topic to talk about.""" embed = await self.gen_topic() msg = await ctx.reply(embed=embed) await msg.add_reaction("🔁") self.message = TopicMessage(msg) @commands.command(name="newtopic") @commands.cooldown(rate=1, per=600, type=commands.BucketType.member) @commands.check_any(commands.is_owner(), commands.has_any_role(339445127917338635, 337442104026595329)) @in_channel(264417177094848512, 737760236013748295) async def new_topic(self, ctx: Context, *, topic: str): """Create a new topic.""" if len(topic) > 200: return await ctx.reply("Topics must be 200 characters or less.") topic = await self.bot.db.create_topic(ctx.author.id, topic) await ctx.reply(f"Topic created! ID: {topic['id']}") @commands.command(name="importtopics") @commands.check_any(commands.is_owner(), commands.has_role(337442104026595329)) async def import_topics(self, ctx: Context): """Import topics from a text file.""" if not ctx.message.attachments: return await ctx.reply("You must attach a file for this.") async with ctx.typing(): file = await self.bot.sess.get(ctx.message.attachments[0].url) file = await file.text() ids = [] for line in file.split("\n"): if line: topic = await self.bot.db.create_topic(ctx.author.id, line) ids.append(topic['id']) await ctx.reply(f"Successfully inserted {len(ids)} topics") @commands.command(name="deltopic") @commands.check_any(commands.is_owner(), commands.has_role(337442104026595329)) async def del_topic(self, ctx: Context, id: int): """Delete a topic.""" await self.bot.db.delete_topic(id) await ctx.message.add_reaction("👌") @commands.command(name="topicinfo") @commands.check_any(commands.is_owner(), commands.has_role(337442104026595329)) async def topic_info(self, ctx: Context, id: int): """Get information about a topic.""" topic = await self.bot.db.get_topic_by_id(id) if not topic: return await ctx.reply("Not a valid topic.") await ctx.reply(f"ID: {topic['id']}\nCreated by: {ctx.guild.get_member(topic['author_id'])} ({topic['author_id']})\nData:```\n{topic['topic']}```") @commands.command(name="lstopics") @commands.check_any(commands.is_owner(), commands.has_role(337442104026595329)) async def list_topics(self, ctx: Context): """List all topics.""" topics = await self.bot.db.get_topics() data = "\n".join([f"{str(topic['id']).zfill(4)}: {topic['topic']}" for topic in topics]) await ctx.reply(f"There are a total of {len(topics)} topics:", file=File(StringIO(data), filename="topics.txt")) @commands.Cog.listener() async def on_reaction_add(self, reaction: Reaction, member: Member): """Allows for refreshing the topic.""" if not isinstance(member, Member): return if member == self.bot.user: return if not self.message: return if self.message.msg.id != reaction.message.id: return if self.message.time + 30 < time(): return self.message.users.add(member.id) if len(self.message.users) >= 4: await self.message.msg.edit(embed=await self.gen_topic()) self.message = None
def is_moderator(): return commands.has_any_role(*constants.MODERATOR_ROLES)