async def _enable(self, ctx, cog): """Enable/Disable bot features within your guild.""" if ctx.invoked_with == 'disable': value = False else: value = True try: if cog in {*ctx.bot.cogs}: await ctx.setting(cog + 'Enabled', value) action = 'enabled' if value else 'disabled' embed = make_embed(msg_type='success', title=f'{cog} {action}.') await ctx.send(embed=embed) return else: embed = make_embed(msg_type='error', title=f'{cog} not found.') await ctx.send(embed=embed) return except errors.PostgresError as e: msg = "{}: {}".format(type(e).__name__, e) embed = make_embed(msg_type='error', title=f'Error enabling {cog}', content=msg) await ctx.send(embed=embed) raise
async def _prefix(self, ctx, *, new_prefix: str = None): """Get prefix and set server prefix. Use the argument 'reset' to reset the guild prefix to default. """ bot = ctx.bot default_prefix = bot.default_prefix if not ctx.guild: if new_prefix: embed = make_embed( msg_type='error', title=f"Prefix can only be changed in guilds.") await ctx.send(embed=embed) else: embed = make_embed(msg_type='info', title=f"Prefix is {default_prefix}") await ctx.send(embed=embed) else: if await ctx.is_co_owner(): if new_prefix: await ctx.guild_dm.prefix(new_prefix) if new_prefix.lower() == 'reset': new_prefix = bot.default_prefix embed = make_embed(msg_type='success', title=f"Prefix set to {new_prefix}") return await ctx.send(embed=embed) guild_prefix = await ctx.guild_dm.prefix() prefix = guild_prefix if guild_prefix else default_prefix embed = make_embed(msg_type='info', title=f"Prefix is {prefix}") await ctx.send(embed=embed)
async def guild_perms(self, ctx, guild_id=None): """Gets bot's permissions for the guild.""" if not ctx.guild and not guild_id: await ctx.send(embed=make_embed( msg_type='error', title="This is a DM. Please provide ID.")) return if guild_id: guild = ctx.bot.get_guild(int(guild_id)) if not guild: await ctx.send( embed=make_embed(msg_type='error', title="Guild not found") ) return else: guild = ctx.guild guild_perms = guild.me.guild_permissions req_perms = ctx.bot.req_perms perms_compare = guild_perms >= req_perms core_dir = ctx.bot.core_dir data_dir = os.path.join(core_dir, '..', 'data') data_file = 'permissions.json' msg = f"{guild}\nID {guild.id}\n" msg += f"```py\n{guild_perms.value}\n" msg += f"{perms_compare}```" with open(os.path.join(data_dir, data_file), "r") as perm_json: perm_dict = json.load(perm_json) for perm, bitshift in perm_dict.items(): if bool((req_perms.value >> bitshift) & 1): if bool((guild_perms.value >> bitshift) & 1): msg += ":white_small_square: {}\n".format(perm) else: msg += ":black_small_square: {}\n".format(perm) try: if not isinstance(ctx.channel, discord.DMChannel): if not ctx.channel.permissions_for(ctx.guild.me).embed_links: await ctx.send(msg) return embed = make_embed(msg_type='info', title='Guild Permissions', content=msg) await ctx.send(embed=embed) except discord.errors.Forbidden: embed = make_embed(msg_type='info', title='Guild Permissions', content=msg) await ctx.author.send(embed=embed)
async def channel_perms(self, ctx, channel_id=None): """Gets bot's permissions for the channel.""" if channel_id: channel = ctx.bot.get_channel(int(channel_id)) if not channel: await ctx.send(embed=make_embed(msg_type='error', title="Channel not found")) return else: channel = ctx.channel dm_channel = isinstance(channel, discord.DMChannel) me = ctx.bot.user if dm_channel else channel.guild.me chan_perms = channel.permissions_for(me) req_perms = ctx.bot.req_perms perms_compare = chan_perms >= req_perms core_dir = ctx.bot.core_dir data_dir = os.path.join(core_dir, '..', 'data') data_file = 'permissions.json' msg = "" if not dm_channel: msg += f"{channel.guild}\nID {channel.guild.id}\n" msg += f"{channel}\nID {channel.id}\n" msg += f"```py\n{chan_perms.value}\n" msg += f"{perms_compare}```" with open(os.path.join(data_dir, data_file), "r") as perm_json: perm_dict = json.load(perm_json) for perm, bitshift in perm_dict.items(): if bool((req_perms.value >> bitshift) & 1): if bool((chan_perms.value >> bitshift) & 1): msg += f":white_small_square: {perm}\n" else: msg += f":black_small_square: {perm}\n" try: if not isinstance(ctx.channel, discord.DMChannel): if not ctx.channel.permissions_for(ctx.guild.me).embed_links: await ctx.send(msg) return embed = make_embed(msg_type='info', title='Channel Permissions', content=msg) await ctx.send(embed=embed) except discord.errors.Forbidden: embed = make_embed(msg_type='info', title='Channel Permissions', content=msg) await ctx.author.send(embed=embed)
async def reload_cm(self, ctx): """Reload Cog Manager.""" bot = ctx.bot try: bot.unload_extension('wobbuffet.core.cog_manager') bot.load_extension('wobbuffet.core.cog_manager') embed = make_embed(msg_type='success', title='Cog Manager reloaded.') await ctx.send(embed=embed) except Exception as e: msg = "{}: {}".format(type(e).__name__, e) embed = make_embed(msg_type='error', title='Error loading Cog Manager', content=msg) await ctx.send(embed=embed)
async def _username(self, ctx, *, username: str): """Sets bot's username""" try: await ctx.bot.user.edit(username=username) except discord.HTTPException: embed = make_embed( msg_type='error', title="Failed to change name", content=("Remember that you can only do it up to 2 times an " "hour. Use nicknames if you need frequent changes. " "**{}set nickname**").format(ctx.prefix)) await ctx.send(embed=embed) else: embed = make_embed(msg_type='success', title="Username set.") await ctx.send(embed=embed)
async def _nickname(self, ctx, *, nickname: str): """Sets bot's nickname""" try: await ctx.guild.me.edit(nick=nickname) except discord.Forbidden: embed = make_embed( msg_type='error', title="Failed to set nickname", content=("I'm missing permissions to change my nickname. " "Use **{}get guildperms** to check permissions." "").format(ctx.prefix)) await ctx.send(embed=embed) else: embed = make_embed(msg_type='success', title="Nickname set.") await ctx.send(embed=embed)
async def _game(self, ctx, *, game: str): """Sets the bot's activity""" status = ctx.me.status game = discord.Game(name=game) await ctx.bot.change_presence(status=status, activity=game) embed = make_embed(msg_type='success', title='Game set.') await ctx.send(embed=embed)
async def status(self, ctx, *, status: str): """Sets the bot's online status Available statuses: online idle dnd """ statuses = { "online": discord.Status.online, "idle": discord.Status.idle, "dnd": discord.Status.dnd, "invisible": discord.Status.invisible } game = ctx.me.activity try: status = statuses[status.lower()] except KeyError: await ctx.bot.send_cmd_help(ctx) else: await ctx.bot.change_presence(status=status, activity=game) embed = make_embed(msg_type='success', title="Status changed to {}.".format(status)) await ctx.send(embed=embed)
async def _break(self, ctx): """Simulates a sudden disconnection.""" embed = make_embed(msg_type='warning', title='Faking a crash...') try: await ctx.send(embed=embed) except discord.HTTPException: pass await ctx.bot.logout()
async def purge(self, ctx, msg_number: int = 10): """Delete a number of messages from the channel. Default is 10. Max 100.""" if msg_number > 100: embed = make_embed( msg_type='info', title="ERROR", content="No more than 100 messages can be purged at a time.", guild=ctx.guild) await ctx.send(embed=embed) return deleted = await ctx.channel.purge(limit=msg_number) embed = make_embed(msg_type='success', title='Deleted {} message{}'.format( len(deleted), "s" if len(deleted) > 1 else "")) result_msg = await ctx.send(embed=embed) await asyncio.sleep(3) await result_msg.delete()
async def _shutdown(self, ctx): """Shuts down the bot""" embed = make_embed(title='Shutting down.', msg_colour='red', icon="https://i.imgur.com/uBYS8DR.png") try: await ctx.send(embed=embed) except discord.HTTPException: pass await ctx.bot.shutdown()
async def _stats(self, ctx): """Shows stats about bot""" bot = ctx.bot owner = await bot.get_user_info(ctx.bot.owner) uptime_str = bot.uptime_str cpu_p = await ctx.bot.loop.run_in_executor(None, self.get_cpu) mem = psutil.virtual_memory() mem_p = round((mem.available / mem.total) * 100, 2) bot_process = psutil.Process() ppid = bot_process.ppid() p_mem = bot_process.memory_info().rss swapped = psutil.swap_memory().used data_sizes = {'B': 1, 'KB': 1024, 'MB': 1048576, 'GB': 1073741824} for size, value in data_sizes.items(): if (p_mem / value) > 1 < 1024: p_mem_str = "{} {}".format(round(p_mem / value, 2), size) if (swapped / value) > 1 < 1024: swap_str = "{} {}".format(round(swapped / value, 2), size) member_count = 0 server_count = 0 for guild in bot.guilds: server_count += 1 member_count += guild.member_count msg_table = bot.dbi.table('discord_messages') msg_table.query(msg_table['*'].count) message_count = await msg_table.query.get_value() cmd_table = bot.dbi.table('command_log') cmd_table.query(cmd_table['*'].count) command_count = await cmd_table.query.get_value() embed = make_embed(msg_type='info', title="Bot Statistics") instance_msg = (f"**Owner:** {owner}\n**Uptime:** {uptime_str}\n" f"**Version:** {bot.version}\n" f"**D.Py Ver:** {bot.dpy_version}\n" f"**Python:** {bot.py_version}") session_msg = ( f"**Servers:** {server_count}\n**Members:** {member_count}\n" f"**Messages:** {message_count}\n" f"**Commands:** {command_count}\n" f"**Reconnections:** {bot.resumed_count}") process_msg = (f"**PID:** {ppid}\n**Process RAM:** {p_mem_str}\n" f"**Swap File:** {swap_str}\n**System RAM:** {mem_p}\n" f"**System CPU:** {cpu_p}\n") embed.add_field(name="ACTIVITY", value=session_msg) embed.add_field(name="PROCESS", value=process_msg) embed.add_field(name="INSTANCE", value=instance_msg) try: await ctx.send(embed=embed) except discord.HTTPException: await ctx.send("I need the `Embed links` permission to send this")
async def on_ready(self): intro = "Wobbuffet - Discord bot for Pokemon Go Communities, dedicated for PvP" intro_deco = "{0}\n{1}\n{0}".format('='*len(intro), intro) if not self.launch_time: self.launch_time = datetime.utcnow() if not self.launcher: print(intro_deco) if self.from_restart: print("We're back!\n") else: print("We're on!\n") print(f"Bot Version: {self.version}\n") if self.debug: print(f"Python Version: {self.py_version}") print(f"Discord.py Version: {self.dpy_version}") print(f"Platform: {self.platform}\n") guilds = len(self.guilds) users = len(list(self.get_all_members())) if guilds: print(f"Servers: {guilds}") print(f"Members: {users}") else: print("I'm not in any server yet, so be sure to invite me!") if self.invite_url: print(f"\nInvite URL: {self.invite_url}\n") if self.from_restart: table = self.dbi.table('restart_savedata') table.query.order_by(table['restart_snowflake'], asc=False) table.query.limit(1) last_restart = (await table.query.get())[0] embed = make_embed(title='Restart Complete.', msg_type='success') guild = self.get_guild(last_restart['restart_guild']) if guild: channel = guild.get_channel(last_restart['restart_channel']) if channel: original_message = await channel.get_message( last_restart['restart_message']) return await original_message.edit(embed=embed) else: channel = self.get_user(last_restart['restart_by']) if not channel: channel = self.get_user(self.owner) if not channel: return self.logger.error('Bot owner not found.') return await channel.send(embed=embed)
async def _bot_invite(self, ctx, plain_url: bool = False): """Shows bot's invite url""" invite_url = ctx.bot.invite_url if plain_url: await ctx.send("Invite URL: <{}>".format(invite_url)) return else: embed = make_embed(title='Click to invite me to your server!', title_url=invite_url, msg_colour='blue', icon="https://i.imgur.com/DtPWJPG.png") try: await ctx.send(embed=embed) except discord.errors.Forbidden: await ctx.send("Invite URL: <{}>".format(invite_url))
async def _list(self, ctx): """List all loaded cogs.""" cog_list = [] for cog in ctx.bot.cogs: value = await ctx.setting(f'{cog}Enabled') if value is not None: value = convert_to_bool(value) if value is None: status = ":black_small_square:" elif value is True: status = ":white_small_square:" elif value is False: status = ":small_orange_diamond:" cog_list.append(f"{status} {cog}") cog_msg = '\n'.join(cog_list) embed = make_embed(msg_type='info', title='Available Cogs', content=cog_msg) await ctx.send(embed=embed)
async def embed(self, title, description=None, plain_msg='', *, msg_type=None, title_url=None, colour=None, icon=None, thumbnail='', image='', fields: dict = None, footer=None, footer_icon=None, send=True, inline=False): """Send or build an embed using context details.""" embed = make_embed(title=title, content=description, msg_type=msg_type, title_url=title_url, msg_colour=colour, icon=icon, thumbnail=thumbnail, image=image, guild=self.guild) if fields: for key, value in fields.items(): ilf = inline if not isinstance(value, str): ilf = value[0] value = value[1] embed.add_field(name=key, value=value, inline=ilf) if footer: footer = {'text': footer} if footer_icon: footer['icon_url'] = footer_icon embed.set_footer(**footer) if not send: return embed return await self.send(plain_msg, embed=embed)
async def _restart(self, ctx): """Restarts the bot""" embed = make_embed(title='Restarting...', msg_colour='red', icon="https://i.imgur.com/uBYS8DR.png") try: restart_msg = await ctx.send(embed=embed) except discord.HTTPException: restart_msg = None data = { 'restart_snowflake': next(snowflake.create()), 'restart_by': ctx.author.id, 'restart_channel': ctx.channel.id, 'restart_guild': ctx.guild.id } if restart_msg: data['restart_message'] = restart_msg.id table = ctx.bot.dbi.table('restart_savedata') table.insert(**data) await table.insert.commit() await ctx.bot.shutdown(restart=True)
async def _about(self, ctx): """Shows info about the bot""" bot = ctx.bot author_repo = "https://github.com/makonde-on-git" bot_repo = author_repo + "/Wobbuffet" uptime_str = bot.uptime_str owner = await ctx.get.user(ctx.bot.owner) invite_str = "[Invite Me!]({})".format(bot.invite_url) prefix = None if ctx.guild: prefix = await ctx.bot.dbi.prefix_stmt.fetchval(ctx.guild.id) if not prefix: prefix = ctx.bot.default_prefix server_count = len(bot.guilds) member_count = sum([g.member_count for g in bot.guilds]) about = [ "A Bot for Pokemon Go Communities, PvP oriented!", f"**[Docs & Source!]({bot_repo})** | **{invite_str}**\n\n", f"Guild Prefix: `{prefix}`\n", f"Help: `{prefix}help`\n\n", f"**Owner:** {owner}", f"**Uptime:** {uptime_str}", f"**Servers:** {server_count}", f"**Members:** {member_count}" ] embed_colour = await url_color(bot.avatar_small) embed = make_embed(icon=bot.avatar_small, title=f"{bot.user}", content='\n'.join(about), msg_colour=embed_colour) embed.set_thumbnail(url=bot.avatar) try: await ctx.send(embed=embed) except discord.HTTPException: await ctx.send("I need the `Embed links` permission to send this")
async def _resumed(self, ctx): """Gets the number of websocket reconnections.""" r_c = ctx.bot.resumed_count embed = make_embed(msg_type='info', title=f"Connections Resumed: {r_c}") await ctx.send(embed=embed)