async def on_command_error(ctx, error): if isinstance(error, commands.CommandOnCooldown): msg = f'{datetime.now().strftime("%I:%M:%S %p")}\tUser:[{ctx.author}]\tChannel:[{ctx.channel.name}]\tTriggered cooldown [{ctx.command}]' print(msg) elif isinstance(error, commands.CommandNotFound): await ctx.send(embed=tools.single_embed_tooltip( f'I\'m sorry. That command doesn\'t exist.')) msg = f'{datetime.now().strftime("%I:%M:%S %p")}\tUser:[{ctx.author}]\tChannel:[{ctx.channel.name}]\tTriggered CommandNotFound [{ctx.command}]' print(msg) elif isinstance(error, commands.CheckFailure): await ctx.send(embed=tools.single_embed( f'You do not have permission to run this command.'), delete_after=10) msg = f'{datetime.now().strftime("%I:%M:%S %p")}\tUser:[{ctx.author}]\tChannel:[{ctx.channel.name}]\tTriggered permissions error [{ctx.command}]' print(msg) elif isinstance(error, discord.errors.NotFound): msg = f'{datetime.now().strftime("%I:%M:%S %p")}\tUser:[{ctx.author}]\tChannel:[{ctx.channel.name}]\tTriggered permissions error [{ctx.command}]' print(msg) elif isinstance(error, commands.CommandInvokeError): await ctx.send(embed=tools.single_embed( f'An error occurred when running {ctx.command}.')) msg = f'{datetime.now().strftime("%I:%M:%S %p")}\tUser:[{ctx.author}]\tChannel:[{ctx.channel.name}]\tTriggered CommandInvokeError [{ctx.command}] {error}' print(msg) else: msg = f'{datetime.now().strftime("%I:%M:%S %p")}\tUser:[{ctx.author}]\tChannel:[{ctx.channel.name}]\tTriggered an error [{ctx.command}:{error}]' print(msg)
async def report(self, ctx, member: discord.Member, *, report: str = None): if len(ctx.message.attachments) < 1: msg = f'Your negative review is incomplete. Please attach a screenshot or picture verifying your claim.' try: await ctx.author.send(embed=tools.single_embed(msg)) except discord.Forbidden: await ctx.send(embed=tools.single_embed(msg), delete_after=5) await ctx.message.delete() return channel = db.get_administrative(ctx.guild) embed = discord.Embed(title='Report', description=report, color=discord.Color.red()) reporter = f'Name: {ctx.author.mention} ({ctx.author})\n' \ f'Joined: {tools.format_date(ctx.author.joined_at)}\n' \ f'Created: {tools.format_date(ctx.author.joined_at)}\n' \ f'Context: {ctx.channel.mention}\n' \ f'[Jump to Message]({ctx.message.jump_url})' embed.add_field(name='Reporter', value=reporter) reported = f'Name: {member.mention} ({member})\n' \ f'Joined: {tools.format_date(member.joined_at)}\n' \ f'Created: {tools.format_date(member.joined_at)}\n' \ f'ID: {member.id}' embed.add_field(name='Reported', value=reported) try: url = ctx.message.attachments[0].url embed.set_image(url=url) except IndexError: print('index error') embed.set_author(name=ctx.author.display_name, icon_url=ctx.author.avatar_url) await channel.send(embed=embed) await ctx.message.delete() await ctx.send(embed=tools.single_embed(f'Your report has been delivered. Thank you.'), delete_after=5)
async def kick(self, ctx, member: discord.Member, *, reason: str = None): if not await self.admin_cog_on(ctx): return msg = f'Are you sure you want to kick {member.display_name}?' if reason is not None: msg += f'\nReason: {reason}' else: msg += 'A reason was not given.' prompt = await ctx.send(embed=tools.single_embed(msg)) answer = await self.yes_no_buttons(prompt, ctx.author) if answer == 'yes': if reason is None: reason = 'A reason was not given.' try: msg = f'You have been kicked from {ctx.guild.name}.\nReason: {reason}' await member.send(embed=tools.single_embed_neg(msg)) except discord.Forbidden: msg = f'{member.display_name} have been kicked from {ctx.guild.name}.\nReason: {reason}' await ctx.send(embed=tools.single_embed_neg(msg)) await member.kick() await ctx.send(embed=tools.single_embed(f'{member.mention}: **See ya, my guy.** :hiking_boot:')) if answer == 'no': await ctx.send(embed=tools.single_embed(f'Kick cancelled.'))
async def ban(self, ctx, member: discord.Member, *, reason: str = None): if not await self.admin_cog_on(ctx): return msg = f'Are you sure you want to ban {member.display_name}?' if reason is not None: msg += f'\nReason: {reason}' prompt = await ctx.send(embed=tools.single_embed(msg)) answer = await self.yes_no_buttons(prompt, ctx.author) if answer == 'yes': await ctx.send(embed=tools.single_embed(f'{member.mention}: **See ya, my guy.** :hammer:')) try: await member.ban(reason=reason, delete_message_days=7) except Exception as e: print(e) await member.ban() if reason is None: reason = 'A reason was not given.' try: await member.send(f'You have been banned from {ctx.guild.name}.\n' f'Reason: {reason}') except discord.Forbidden: pass if answer == 'no': await ctx.send(embed=tools.single_embed(f'Ban cancelled.'), delete_after=30)
async def sub(self, ctx, method, member: discord.Member, points: int, *, message: str = None): if not await self.rep_cog_on(ctx): return if message is None: message = 'No additional information given.' if not database.in_members_table(ctx.author): database.add_member(ctx.author) bot_spam = database.get_spam(ctx.guild) message = f'**{ctx.author.display_name}** removed {points} {method} point(s) from **{member.display_name}**.\n'\ f'> {message}' if method == 'pos': database.sub_pos(member, points) await bot_spam.send(embed=tools.single_embed(message)) await self.assign_new_role(member) if method == 'neg': database.sub_neg(member, points) await bot_spam.send(embed=tools.single_embed_neg(message)) await ctx.send( embed=tools.single_embed(f'Your changes have been updated.'))
async def afk(self, ctx, *autoresponse): if len(autoresponse) == 0: await ctx.send(embed=tools.single_embed('You are no longer **AFK**.')) db.set_afk(ctx.author, 0, None) return else: db.set_afk(ctx.author, 1, ' '.join(autoresponse).replace("'", "\'")) await ctx.send(embed=tools.single_embed(f'AFK message set to \n {" ".join(autoresponse)}'))
async def member_info_error(self, ctx, error): if isinstance(error, commands.BadArgument): await ctx.send(embed=tools.single_embed('I could not find that member'), delete_after=15) if isinstance(error, commands.CommandOnCooldown): await ctx.send(embed=tools.single_embed(f'{error}'), delete_after=30) if isinstance(error, discord.HTTPException): await ctx.send(embed=tools.single_embed(f'An error occurred when searching for this user.'), delete_after=30) print(error)
async def on_raw_reaction_add(self, payload): if payload.channel_id != 711981322658119722: return try: guild = self.client.get_guild(payload.guild_id) user = discord.utils.get(guild.members, id=payload.user_id) if user.bot or user is None: return except AttributeError: return emoji = payload.emoji.name message_id = payload.message_id if emoji == '👍': (number, _type, member, issue, resolved, message) = await self.get_ticket_by_message_id(message_id) member = discord.utils.get(guild.members, id=member) try: msg = f'Your ticket number **{number}** has been assigned to a helper.\n' \ f'> {issue}' await member.send(embed=tools.single_embed(msg)) except discord.Forbidden: pass await self.resolve_ticket(number) message = await self.client.get_channel(711981322658119722).fetch_message(id=message_id) new_embed = message.embeds[0].to_dict() new_embed['title'] = f'Ticket assigned.' new_embed['footer']['text'] = 'Click the check mark to resolve the ticket.' name = f'Ticket assigned to:' date = tools.format_date(datetime.utcnow()) value = f'{user}/{user.mention}\nDate: {date} UTC.' new_embed['fields'].append({'name': name, 'value': value, 'inline': False}) embed = discord.Embed.from_dict(new_embed) await message.edit(embed=embed) await message.clear_reactions() await message.add_reaction('✔️') elif emoji == '✔️': (number, _type, member, issue, resolved, message) = await self.get_ticket_by_message_id(message_id) member = discord.utils.get(guild.members, id=member) try: msg = f'Your ticket number **{number}** has been resolved.\n' \ f'> {issue}' await member.send(embed=tools.single_embed(msg)) except discord.Forbidden: pass await self.resolve_ticket(number) message = await self.client.get_channel(711981322658119722).fetch_message(id=message_id) new_embed = message.embeds[0].to_dict() new_embed['title'] = 'Ticket resolved.' new_embed['footer']['text'] = 'no actions required' name = f'Ticket resolved by:' date = tools.format_date(datetime.utcnow()) value = f'{user}/{user.mention}\nDate: {date} UTC.' new_embed['fields'].append({'name': name, 'value': value, 'inline': False}) embed = discord.Embed.from_dict(new_embed) await message.edit(embed=embed) await message.clear_reactions()
async def rep(self, ctx, state): if state.lower() not in ['on', 'off']: msg = 'Supported states are `on` and `off`.' await ctx.send(embed=tools.single_embed(msg)) else: m = {'on': 1, 'off': 0} database.rep_set(ctx.guild, m.get(state.lower())) msg = f'**Rep** cog turned **{state}**' await ctx.send(embed=tools.single_embed(msg))
async def nick(self, ctx, *nickname): if len(nickname) < 1: msg = 'You name cannot be empty.' await ctx.send(embed=tools.single_embed(msg), delete_after=5) return spam = db.get_spam(ctx.guild) msg = f'{ctx.author.display_name} changed their nickname to {" ".join(nickname)}.' await ctx.author.edit(nick=' '.join([w.replace("'", "\'") for w in nickname])) await ctx.send(embed=tools.single_embed(msg)) await spam.send(embed=tools.single_embed(msg))
async def autorole(self, ctx, role: discord.Role = None): if not await self.admin_cog_on(ctx): return admin_channel = database.get_administrative(ctx.guild) if role is None: database.update_autorole(ctx.guild, role) await admin_channel.send(embed=tools.single_embed(f'Autorole set to `none`')) else: database.update_autorole(ctx.guild, role) await admin_channel.send(embed=tools.single_embed(f'Autorole set to `{role}`'))
async def assign_new_role(member: discord.Member): # send new role notifications to general chan = None channels = [c for c in member.guild.channels if 'general'] for c in channels: if 'general' in c.name: chan = c if chan is None: chan = database.get_spam(member.guild) if not database.in_members_table(member): database.add_member(member) pos, neg = database.get_rep(member) with open('files/ranks.json') as f: ranks = json.load(f)["host ranks"] for rank, reviews in ranks.items(): if pos >= reviews: if rank not in [role.name for role in member.guild.roles]: await member.guild.create_role(name=rank, hoist=True) role = discord.utils.get(member.guild.roles, name=rank) if role.name not in [r.name for r in member.roles]: await member.add_roles(role) await chan.send(embed=tools.single_embed( f':tada: {member.mention} has earned the **{role}** role!' ))
async def sw_set(self, ctx, code: str): with open('files/sw.json', 'r') as f: data = json.load(f) data[str(ctx.author.id)] = code.upper() with open('files/sw.json', 'w') as f: json.dump(data, f, indent=4) await ctx.send(embed=tools.single_embed(f'{ctx.author.display_name}\'s friend code has been set to **{code.upper()}**'))
async def on_guild_join(self, guild): spam = await guild.system_channel msg = f'{self.client.user.display_name} has joined {guild.name}' await spam.send(embed=tools.single_embed(msg)) database.add_guild(guild) for member in guild.members: database.add_member(member)
async def get_blacklist(self, ctx): if not await self.admin_cog_on(ctx): return blacklist = '\n'.join(database.get_blacklist(ctx.guild)) msg = f'**Blacklist**\n' \ f'```\n{blacklist}```' await ctx.send(embed=tools.single_embed(msg))
async def get_filter(self, ctx): if not await self.admin_cog_on(ctx): return fltr = '\n'.join(database.get_filter(ctx.guild)) msg = f'**Current Filters**\n' \ f'```\n{fltr}```' await ctx.send(embed=tools.single_embed(msg))
async def reset(self, ctx): with open('files/incident.json') as f: i = json.load(f) i = tools.display_time(int(time.time() - i)) with open('files/incident.json', 'w') as f: json.dump(time.time(), f, indent=4) await ctx.send(embed=tools.single_embed(f'Incident date recorded. Last incident was `{i}` ago.'))
async def automod_restart(self, ctx): print('Unloading automoderator') self.client.unload_extension('cogs.automoderator') print('Cancelling loops') self.spam_reset.cancel() print('Loading automoderator') self.client.load_extension('cogs.automoderator') await ctx.send(embed=tools.single_embed('Automoderator reloaded'))
async def clean_messages(self, ctx, member: discord.Member, num: int): def is_member(m): return m.author == member if not await self.admin_cog_on(ctx): return await ctx.message.delete() deleted = await ctx.channel.purge(limit=num, check=is_member) await ctx.send(embed=tools.single_embed(f'{len(deleted)} messages removed.'), delete_after=5)
async def server(self, ctx, *, issue: str): ticket_channel = await self.ticket_channel() embed = await self.ticket_embed(ctx, 'server', ctx.author, issue) message = await ticket_channel.send(embed=embed) await message.add_reaction('👍') await ctx.send(embed=tools.single_embed(f'Your ticket has been submitted.')) await self.add_ticket('server', ctx, issue, message) await ctx.message.delete()
async def reload_reminders(self, ctx): print('* Cancelling tasks') self.check_reminders.cancel() print('* Unloading reminders') self.client.unload_extension('cogs.reminders') print('* Loading reminders') self.client.load_extension('cogs.reminders') await ctx.send(embed=tools.single_embed('reminders reloaded'))
async def find(self, ctx, member): if ctx.invoked_subcommand is None: members = [m for m in ctx.guild.members if member in m.display_name.lower() or member in m.name.lower() or member in str(m.id)] description = '\n'.join([f'{m.name} / {m.display_name} ({m.id})' for m in members]) if len(description) > 2000: await ctx.send(embed=tools.single_embed(f'Your search is too broad. Try to be more specific.')) return embed = discord.Embed(title='Found Members', description=description, color=discord.Color.green()) await ctx.send(embed=embed)
async def my_warnings(self, ctx): if not database.in_warnings_table(ctx.author, ctx.guild): msg = f'You have `0` warnings.' embed = discord.Embed(color=discord.Color.green(), description=msg) embed.set_thumbnail(url=ctx.author.avatar_url) await ctx.author.send(embed=embed) await ctx.send(embed=tools.single_embed('A private DM has been sent.'), delete_after=10) else: warnings, messages = database.get_warnings(ctx.author) fmt = [] for m in messages: fmt.append(f'`{m[0]}.` {m[4]} - {m[3]} ') if len(fmt) > 0: msg = f'__Past Warnings__\n' + '\n'.join(fmt) embed = discord.Embed(color=discord.Color.red(), description=msg) embed.set_author(name=f'{ctx.author.display_name} ({ctx.author})', icon_url=ctx.author.avatar_url) await ctx.author.send(embed=embed) await ctx.send(embed=tools.single_embed('A private DM has been sent.'), delete_after=10)
async def mass_pos(self, ctx, *, review: str = None): if await self.can_bypass_cooldown(ctx): self.mass_pos.reset_cooldown(ctx) if not await self.rep_cog_on(ctx): return members = [ m for m in ctx.guild.members if m.mentioned_in(ctx.message) if m is not ctx.author ] if len(members) < 1: await ctx.send(embed=tools.single_embed( f'No one was mentioned in your review.')) return for member in members: database.add_pos(member) database.add_review(member, ctx.author, review) await self.assign_new_role(member) message = f'**{", ".join(m.display_name for m in members)}** each gained 1 positive review from **{ctx.author.display_name}**!\n\n' if review is None: review = f'Sadly, {ctx.author.display_name} did not leave a message. :pig: *Snort!*' message += f'**{ctx.author.display_name}** said: \n"{review}"' for _ in range(len(members)): database.add_reviews_given(ctx.author) # create embed and post it in the review channel embed = discord.Embed(color=discord.Color.green(), description=message) embed.set_thumbnail(url=self.client.user.avatar_url) time = tools.format_date_long(datetime.now()) embed.set_footer(text=f'{time}') review_chan = database.get_review_channel(ctx.guild) await review_chan.send(embed=embed) # notify the user if the current channel is not the review channel if ctx.channel.id != review_chan.id: await ctx.send(embed=tools.single_embed( f'Thank you, **{ctx.author.display_name}**!\n' f'Your review has been received and posted in ' f'{review_chan.mention}.')) await ctx.message.delete()
async def pos(self, ctx, member: discord.Member, *, review: str = None): if await self.can_bypass_cooldown(ctx): self.pos.reset_cooldown(ctx) if not await self.rep_cog_on(ctx): return if ctx.author == member: msg = f'You cannot give yourself a review, {ctx.author.display_name}. *Snort!*' await ctx.send(embed=tools.single_embed(msg), delete_after=15) return if not database.in_members_table(ctx.author): database.add_member(ctx.author) database.add_pos(member) pos, neg = database.get_rep(member) message = f'**{member.display_name}** gained 1 positive review from **{ctx.author.display_name}**!\n\n' if review is None: review = f'Sadly, {ctx.author.display_name} did not leave a message. :pig: *Snort!*' message += f'**{ctx.author.display_name}** said: \n"{review}"' database.add_review(member, ctx.author, review) database.add_reviews_given(ctx.author) # create embed and post it in the review channel embed = discord.Embed(color=discord.Color.green(), description=message) embed.set_thumbnail(url=member.avatar_url) time = tools.format_date_long(datetime.now()) embed.set_footer( text=f'{member.display_name} now has {pos} positive reviews! {time}' ) review_chan = database.get_review_channel(ctx.guild) await review_chan.send(embed=embed) await self.assign_new_role(member) # notify the user if the current channel is not the review channel if ctx.channel.id != review_chan.id: await ctx.send(embed=tools.single_embed( f'Thank you, **{ctx.author.display_name}**!\n' f'Your review has been received and posted in ' f'{review_chan.mention}.')) await ctx.message.delete()
async def on_member_join(self, member): # add member to the database database.add_member(member) # if admin cog is not set, do not give autorole if not database.admin_cog(member.guild): return autorole = database.get_autorole(member.guild) if autorole is not None: try: await member.add_roles(autorole) spam = database.get_spam(member.guild) msg = f'{member.display_name} was given the role {autorole.name}' await spam.send(embed=tools.single_embed(msg)) print( f'* Giving {member.display_name} the autorole {autorole.name}' ) except Exception as e: spam = database.get_spam(member.guild) msg = f'Unable to give {member.display_name} the role {autorole.name}' await spam.send(embed=tools.single_embed(msg)) print( f'* Unable to give {member.display_name} the role {autorole.name}: {e}' ) # store nickname nicknames = [n[0] for n in database.get_member_nick_history(member)] if member.name not in nicknames: database.add_member_nick_history(member, member.name) # update the server statistics try: member_stats = self.client.get_channel(706099708434841621) members = [m for m in member.guild.members if not m.bot] await member_stats.edit(name=f'Members: {len(members)}') except Exception as e: print(f'Could not update server stats: {e}') # alert general on every 1000th member if len([m for m in member.guild.members if not m.bot]) % 1000 == 0: chan = self.client.get_channel(694013862667616310) msg = f'Welcome {member.mention} as our {len(member.guild.members)}th member!' await chan.send(embed=tools.single_embed(msg))
async def on_message(self, message): # search messages for discord links if message is None or message.author.bot: return # check for custom commands if message.content.startswith('!'): for k, v in self.custom_commands.items(): if k == message.content.split(' ')[0][1:]: await message.channel.send(embed=tools.single_embed(v))
async def load(ctx, extension_name: str): if not await client.is_owner(ctx.author): return try: client.load_extension('cogs.' + extension_name) except (AttributeError, ImportError) as e: print(f'* Error loading cog {extension_name}: {e}') await ctx.send( embed=tools.single_embed(f'{extension_name.capitalize()} loaded')) print(f'* Loaded {extension_name}')
async def update_counter(self, ctx): try: member_stats = self.client.get_channel(706099708434841621) members = [m for m in ctx.guild.members if not m.bot] await member_stats.edit(name=f'Members: {len(members)}') await ctx.send(embed=tools.single_embed('Member count updated!')) except Exception as e: print(e) await ctx.send(embed=tools.single_embed_neg( f'An error occurred when updating the member count.\n{e}'))
async def karma_too_soon(message): conn, curs = load_database() curs.execute("SELECT last_karma FROM members WHERE member_id = (:member_id)", {'member_id': message.author.id}) last_karma = curs.fetchone()[0] if last_karma is not None: remaining_time = int(time.time() - last_karma) if remaining_time < 180: msg = f'{message.author.display_name}, you must wait {180 - remaining_time} seconds to give karma again.' await message.channel.send(embed=tools.single_embed(msg)) return True return False