From fe143678fe080b9703799c275b8ccf681149aabd Mon Sep 17 00:00:00 2001 From: davfsa Date: Thu, 21 Jun 2018 20:04:07 +0200 Subject: [PATCH] Updated some files --- sebimachine/cogs/basic_commands.py | 98 ++++----- sebimachine/cogs/bot_management.py | 227 +++++++++------------ src/cogs/basic_commands.py | 68 ------- src/cogs/bot_management.py | 189 ------------------ src/cogs/moderation.py | 62 ------ src/cogs/music.py | 306 ----------------------------- 6 files changed, 130 insertions(+), 820 deletions(-) delete mode 100644 src/cogs/basic_commands.py delete mode 100644 src/cogs/bot_management.py delete mode 100644 src/cogs/moderation.py delete mode 100644 src/cogs/music.py diff --git a/sebimachine/cogs/basic_commands.py b/sebimachine/cogs/basic_commands.py index 74eec70..80fc5d5 100644 --- a/sebimachine/cogs/basic_commands.py +++ b/sebimachine/cogs/basic_commands.py @@ -1,10 +1,9 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -import asyncio from discord.ext import commands import discord - +import asyncio class BasicCommands: def __init__(self, bot): @@ -12,83 +11,58 @@ class BasicCommands: @commands.command() async def tutorial(self, ctx): - await ctx.send( - f"Hello, {ctx.author.display_name}. Welcome to Sebi's Bot Tutorials. \nFirst off, would you like a quick walkthrough on the server channels?" - ) + await ctx.send(f"Hello, {ctx.author.display_name}. Welcome to Sebi's Bot Tutorials. \nFirst off, would you like a quick walkthrough on the server channels?") + + channel_list = {'channel-1' : self.bot.get_channel(333149949883842561).mention, + 'd.py-rewrite-start' : self.bot.get_channel(386419285439938560).mention, + 'js-klasa-start' : self.bot.get_channel(341816240186064897).mention, + 'async2rewrite-start' : self.bot.get_channel(392223495389577217).mention, + 'd.js' : self.bot.get_channel(436771798303113217).mention} - channel_list = { - "channel-1": self.bot.get_channel(333149949883842561).mention, - "d.py-rewrite-start": self.bot.get_channel(386419285439938560).mention, - "js-klasa-start": self.bot.get_channel(341816240186064897).mention, - "d.js": self.bot.get_channel(436771798303113217).mention, - } + bots_channels = (self.bot.get_channel(339112602867204097).mention, + self.bot.get_channel(411586546551095296).mention) - bots_channels = ( - self.bot.get_channel(339112602867204097).mention, - self.bot.get_channel(411586546551095296).mention, - ) - - help_channels = ( - self.bot.get_channel(425315253153300488).mention, - self.bot.get_channel(392215236612194305).mention, - self.bot.get_channel(351034776985141250).mention, - ) + help_channels = (self.bot.get_channel(425315253153300488).mention, + self.bot.get_channel(392215236612194305).mention, + self.bot.get_channel(351034776985141250).mention) def check(m): - return ( - True - if m.author.id == ctx.author.id and m.channel.id == ctx.channel.id - else False - ) + return True if m.author.id == ctx.author.id and m.channel.id == ctx.channel.id else False + + msg = await self.bot.wait_for('message', check = check, timeout = 15) - msg = await self.bot.wait_for("message", check=check, timeout=15) - - agree = ("yes", "yep", "yesn't", "ya", "ye") + agree = ("yes", "yep", "non't", "ya", "ye", "yup", "ok", "why not") if msg is None: - await ctx.send( - "Sorry, {ctx.author.mention}, you didn't reply on time. You can run the command again when you're free :)" - ) + await ctx.send("Sorry, {ctx.author.mention}, you didn't reply on time. You can run the command again when you're free :)") else: if msg.content.lower() in agree: async with ctx.typing(): await ctx.send("Alrighty-Roo... Check your DMs!") await ctx.author.send("Alrighty-Roo...") - await ctx.author.send( - f"To start making your bot from scratch, you first need to head over to {channel_list['channel-1']}" - " (Regardless of the language you're gonna use)." - ) - + await ctx.author.send(f"To start making your bot from scratch, you first need to head over to {channel_list['channel-1']}" + " (Regardless of the language you're gonna use).") + await asyncio.sleep(0.5) - await ctx.author.send( - f"After you have a bot account, you can either continue with {channel_list['d.py-rewrite-start']}" - f"if you want to make a bot in discord.py rewrite __or__ go to {channel_list['js-klasa-start']} or " - f"{channel_list['d.js']} for making a bot in JavaScript." - ) - - await ctx.author.send( - "...Read all the tutorials and still need help? You have two ways to get help." - ) + await ctx.author.send(f"After you have a bot account, you can either continue with {channel_list['d.py-rewrite-start']} " + f"if you want to make a bot in discord.py rewrite __or__ go to {channel_list['js-klasa-start']} or " + f"{channel_list['d.js']} for making a bot in JavaScript." + f"If you already have old Discord.py async code and you want to use it with the new Rewrite versions, head to {channel_list['async2rewrite-start']}") + + await ctx.author.send("...Read all the tutorials and still need help? You have two ways to get help.") await asyncio.sleep(1.5) - await ctx.author.send( - "**Method-1**\nThis is the best method of getting help. You help yourself.\n" - f"To do so, head over to a bots dedicated channel (either {bots_channels[0]} or {bots_channels[1]})" - " and type `?rtfm rewrite thing_you_want_help_with`.\nThis will trigger the bot R.Danny Bot and will" - "give you links on your query on the official discord.py rewrite docs. *PS: Let the page completely load*" - ) - + await ctx.author.send("**Method-1**\nThis is the best method of getting help. You help yourself.\n" + f"To do so, head over to a bots dedicated channel (either {bots_channels[0]} or {bots_channels[1]})" + " and type `?rtfm rewrite thing_you_want_help_with`.\nThis will trigger the bot R.Danny Bot and will " + "give you links on your query on the official discord.py rewrite docs. *PS: Let the page completely load*") + await asyncio.sleep(5) - await ctx.author.send( - "**Method-2**\nIf you haven't found anything useful with Method-1, feel free to ask your question " - f"in any of the related help channels. ({', '.join(help_channels)})\nMay the force be with you!!" - ) - + await ctx.author.send("**Method-2**\nIf you haven't found anything useful with Method-1, feel free to ask your question " + f"in any of the related help channels. ({', '.join(help_channels)})\nMay the force be with you!!") + else: - return await ctx.send( - "Session terminated. You can run this command again whenever you want." - ) - + return await ctx.send("Session terminated. You can run this command again whenever you want.") def setup(bot): bot.add_cog(BasicCommands(bot)) diff --git a/sebimachine/cogs/bot_management.py b/sebimachine/cogs/bot_management.py index a28526f..2e8d523 100644 --- a/sebimachine/cogs/bot_management.py +++ b/sebimachine/cogs/bot_management.py @@ -1,7 +1,6 @@ import discord from discord.ext import commands - - + class BotManager: def __init__(self, bot): self.bot = bot @@ -12,88 +11,76 @@ class BotManager: return else: # The member is a bot - await member.add_roles(discord.utils.get(member.guild.roles, name="Bots")) + bot_owner = member.guild.get_member((await self.bot.db_con.fetchval('select owner from bots where id = $1', member.id)) + await bot_owner.add_roles(discord.utils.get(member.guild.roles, name='Bot Developers')) + + await member.add_roles(discord.utils.get(member.guild.roles, name='Bots')) try: - await member.edit( - nick="[" - + await self.bot.db_con.fetch( - "select prefix from bots where id = $1", member.id - ) - + "] " - + member.name - ) + await member.edit(nick='[' + await self.bot.db_con.fetchval('select prefix from bots where id = $1', member.id) + + '] ' + member.name) except: pass - + async def on_member_remove(self, member): # If the member is not a bot if member.bot is False: return else: # The member is a bot - await self.bot.db_con.execute("DELETE FROM bots WHERE id = $1", member.id) + await self.bot.db_con.execute('DELETE FROM bots WHERE id = $1', member.id) + + async def on_member_ban(self, guild, user): + if member.bot is True: + return + else: + # I need to finish this + pass @commands.command() async def invite(self, ctx, bot=None, prefix=None): bot = await ctx.bot.get_user_info(bot) if not bot: - raise Warning( - "You must include the id of the bot you are trying to invite... Be exact." - ) + raise Warning('You must include the id of the bot you are trying to invite... Be exact.') if not bot.bot: - raise Warning("You can only invite bots.") + raise Warning('You can only invite bots.') if not prefix: - raise Warning("Please provide a prefix") + raise Warning('Please provide a prefix') # Make sure that the bot has not been invited already and it is not being tested - if ( - await self.bot.db_con.fetch( - "select count(*) from bots where id = $1", bot.id - ) - == 1 - ): - raise Warning("The bot has already been invited or is being tested") + if await self.bot.db_con.fetch('select count(*) from bots where id = $1', bot.id) == 1: + raise Warning('The bot has already been invited or is being tested') - await self.bot.db_con.execute( - "insert into bots (id, owner, prefix) values ($1, $2, $3)", - bot.id, - ctx.author.id, - prefix, - ) + await self.bot.db_con.execute('insert into bots (id, owner, prefix) values ($1, $2, $3)', + bot.id, ctx.author.id, prefix) em = discord.Embed(colour=self.bot.embed_color) em.title = "Hello {},".format(ctx.author.name) - em.description = "Thanks for inviting your bot! It will be tested and invited shortly. " "Please open your DMs if they are not already so the bot can contact " "you to inform you about the progress of the bot!" + em.description = "Thanks for inviting your bot! It will be tested and invited shortly. " \ + "Please open your DMs if they are not already so the bot can contact " \ + "you to inform you about the progress of the bot!" await ctx.send(embed=em) - + em = discord.Embed(title="Bot invite", colour=discord.Color(0x363941)) + em.description = discord.utils.oauth_url(client_id, permissions=None, guild=ctx.guild)) em.set_thumbnail(url=bot.avatar_url) em.add_field(name="Bot name", value=bot.name) em.add_field(name="Bot id", value="`" + str(bot.id) + "`") em.add_field(name="Bot owner", value=ctx.author.mention) em.add_field(name="Bot prefix", value="`" + prefix + "`") - await ctx.bot.get_channel(448803675574370304).send(embed=em) + await ctx.bot.get_channel(459280759945953300).send(embed=em) - @commands.command(name="claim", aliases=["makemine", "gimme"]) + @commands.command(name='claim', aliases=['makemine', 'gimme']) @commands.cooldown(1, 5, commands.BucketType.user) - async def _claim_bot( - self, - ctx, - bot: discord.Member = None, - prefix: str = None, - owner: discord.Member = None, - ): + async def _claim_bot(self, ctx, bot: discord.Member = None, prefix: str = None, owner: discord.Member = None): if not bot: - raise Warning( - "You must include the name of the bot you are trying to claim... Be exact." - ) + raise Warning('You must include the name of the bot you are trying to claim... Be exact.') if not bot.bot: - raise Warning("You can only claim bots.") + raise Warning('You can only claim bots.') if not prefix: - if bot.display_name.startswith("["): - prefix = bot.display_name.split("]")[0].strip("[") + if bot.display_name.startswith('['): + prefix = bot.display_name.split(']')[0].strip('[') else: - raise Warning("Prefix not provided and can't be found in bot nick.") + raise Warning('Prefix not provided and can\'t be found in bot nick.') if owner is not None and ctx.author.guild_permissions.manage_roles: author_id = owner.id @@ -102,126 +89,100 @@ class BotManager: em = discord.Embed() - if ( - await self.bot.db_con.fetchval( - "select count(*) from bots where owner = $1", author_id - ) - >= 10 - ): + if await self.bot.db_con.fetchval('select count(*) from bots where owner = $1', author_id) >= 10: em.colour = self.bot.error_color - em.title = "Too Many Bots Claimed" - em.description = "Each person is limited to claiming 10 bots as that is how " "many bots are allowed by the Discord API per user." + em.title = 'Too Many Bots Claimed' + em.description = 'Each person is limited to claiming 10 bots as that is how ' \ + 'many bots are allowed by the Discord API per user.' return await ctx.send(embed=em) - existing = await self.bot.db_con.fetchrow( - "select * from bots where id = $1", bot.id - ) + existing = await self.bot.db_con.fetchrow('select * from bots where id = $1', bot.id) if not existing: - await self.bot.db_con.execute( - "insert into bots (id, owner, prefix) values ($1, $2, $3)", - bot.id, - author_id, - prefix, - ) + await self.bot.db_con.execute('insert into bots (id, owner, prefix) values ($1, $2, $3)', + bot.id, author_id, prefix) em.colour = self.bot.embed_color - em.title = "Bot Claimed" - em.description = f"You have claimed {bot.display_name} with a prefix of {prefix}\n" f"If there is an error please run command again to correct the prefix,\n" f"or {ctx.prefix}unclaim {bot.mention} to unclaim the bot." - elif existing["owner"] and existing["owner"] != author_id: + em.title = 'Bot Claimed' + em.description = f'You have claimed {bot.display_name} with a prefix of {prefix}\n' \ + f'If there is an error please run command again to correct the prefix,\n' \ + f'or {ctx.prefix}unclaim {bot.mention} to unclaim the bot.' + elif existing['owner'] and existing['owner'] != author_id: em.colour = self.bot.error_color - em.title = "Bot Already Claimed" - em.description = "This bot has already been claimed by someone else.\n" "If this is actually your bot please let the guild Administrators know." - elif existing["owner"] and existing["owner"] == author_id: + em.title = 'Bot Already Claimed' + em.description = 'This bot has already been claimed by someone else.\n' \ + 'If this is actually your bot please let the guild Administrators know.' + elif existing['owner'] and existing['owner'] == author_id: em.colour = self.bot.embed_color - em.title = "Bot Already Claimed" - em.description = "You have already claimed this bot.\n" "If the prefix you provided is different from what is already in the database" " it will be updated for you." - if existing["prefix"] != prefix: - await self.bot.db_con.execute( - "update bots set prefix = $1 where id = $2", prefix, bot.id - ) - elif not existing["owner"]: - await self.bot.db_con.execute( - "update bots set owner = $1, prefix = $2 where id = $3", - author_id, - prefix, - bot.id, - ) + em.title = 'Bot Already Claimed' + em.description = 'You have already claimed this bot.\n' \ + 'If the prefix you provided is different from what is already in the database' \ + ' it will be updated for you.' + if existing['prefix'] != prefix: + await self.bot.db_con.execute("update bots set prefix = $1 where id = $2", prefix, bot.id) + elif not existing['owner']: + await self.bot.db_con.execute('update bots set owner = $1, prefix = $2 where id = $3', + author_id, prefix, bot.id) em.colour = self.bot.embed_color - em.title = "Bot Claimed" - em.description = f"You have claimed {bot.display_name} with a prefix of {prefix}\n" f"If there is an error please run command again to correct the prefix,\n" f"or {ctx.prefix}unclaim {bot.mention} to unclaim the bot." + em.title = 'Bot Claimed' + em.description = f'You have claimed {bot.display_name} with a prefix of {prefix}\n' \ + f'If there is an error please run command again to correct the prefix,\n' \ + f'or {ctx.prefix}unclaim {bot.mention} to unclaim the bot.' else: em.colour = self.bot.error_color - em.title = "Something Went Wrong..." + em.title = 'Something Went Wrong...' await ctx.send(embed=em) - @commands.command(name="unclaim") + @commands.command(name='unclaim') @commands.cooldown(1, 5, commands.BucketType.user) async def _unclaim_bot(self, ctx, bot: discord.Member = None): if not bot: - raise Warning( - "You must include the name of the bot you are trying to claim... Be exact." - ) + raise Warning('You must include the name of the bot you are trying to claim... Be exact.') if not bot.bot: - raise Warning("You can only unclaim bots.") + raise Warning('You can only unclaim bots.') em = discord.Embed() - existing = await self.bot.db_con.fetchrow( - "select * from bots where id = $1", bot.id - ) - if not existing or not existing["owner"]: + existing = await self.bot.db_con.fetchrow('select * from bots where id = $1', bot.id) + if not existing or not existing['owner']: em.colour = self.bot.error_color - em.title = "Bot Not Found" - em.description = "That bot is not claimed" - elif ( - existing["owner"] != ctx.author.id - and not ctx.author.guild_permissions.manage_roles - ): + em.title = 'Bot Not Found' + em.description = 'That bot is not claimed' + elif existing['owner'] != ctx.author.id and not ctx.author.guild_permissions.manage_roles: em.colour = self.bot.error_color - em.title = "Not Claimed By You" - em.description = "That bot is claimed by someone else.\n" "You can't unclaim someone else's bot" + em.title = 'Not Claimed By You' + em.description = 'That bot is claimed by someone else.\n' \ + 'You can\'t unclaim someone else\'s bot' else: - await self.bot.db_con.execute( - "update bots set owner = null where id = $1", bot.id - ) + await self.bot.db_con.execute('update bots set owner = null where id = $1', bot.id) em.colour = self.bot.embed_color - em.title = "Bot Unclaimed" - em.description = f"You have unclaimed {bot.display_name}\n" f"If this is an error please reclaim using\n" f'{ctx.prefix}claim {bot.mention} {existing["prefix"]}' + em.title = 'Bot Unclaimed' + em.description = f'You have unclaimed {bot.display_name}\n' \ + f'If this is an error please reclaim using\n' \ + f'{ctx.prefix}claim {bot.mention} {existing["prefix"]}' await ctx.send(embed=em) - @commands.command(name="listclaims", aliases=["claimed", "mybots"]) + @commands.command(name='listclaims', aliases=['claimed', 'mybots']) @commands.cooldown(1, 5, commands.BucketType.user) async def _claimed_bots(self, ctx, usr: discord.Member = None): if usr is None: usr = ctx.author - bots = await self.bot.db_con.fetch( - "select * from bots where owner = $1", usr.id - ) + bots = await self.bot.db_con.fetch('select * from bots where owner = $1', usr.id) if bots: - em = discord.Embed( - title=f"{usr.display_name} has claimed the following bots:", - colour=self.bot.embed_color, - ) + em = discord.Embed(title=f'{usr.display_name} has claimed the following bots:', + colour=self.bot.embed_color) for bot in bots: - member = ctx.guild.get_member(int(bot["id"])) - em.add_field( - name=member.display_name, - value=f'Stored Prefix: {bot["prefix"]}', - inline=False, - ) + member = ctx.guild.get_member(int(bot['id'])) + em.add_field(name=member.display_name, value=f'Stored Prefix: {bot["prefix"]}', inline=False) else: - em = discord.Embed( - title="You have not claimed any bots.", colour=self.bot.embed_color - ) + em = discord.Embed(title='You have not claimed any bots.', + colour=self.bot.embed_color) await ctx.send(embed=em) - @commands.command(name="whowns") + @commands.command(name='whowns') async def _whowns(self, ctx, bot: discord.Member): if not bot.bot: - await ctx.send("this commands only for bots") + await ctx.send('this commands only for bots') else: - owner = await self.bot.db_con.fetchrow( - "select * from bots where id = $1", bot.id - ) - await ctx.send(ctx.guild.get_member(owner["owner"]).display_name) + owner = await self.bot.db_con.fetchrow('select * from bots where id = $1', bot.id) + await ctx.send(ctx.guild.get_member(owner['owner']).display_name) def setup(bot): diff --git a/src/cogs/basic_commands.py b/src/cogs/basic_commands.py deleted file mode 100644 index 80fc5d5..0000000 --- a/src/cogs/basic_commands.py +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -from discord.ext import commands -import discord -import asyncio - -class BasicCommands: - def __init__(self, bot): - self.bot = bot - - @commands.command() - async def tutorial(self, ctx): - await ctx.send(f"Hello, {ctx.author.display_name}. Welcome to Sebi's Bot Tutorials. \nFirst off, would you like a quick walkthrough on the server channels?") - - channel_list = {'channel-1' : self.bot.get_channel(333149949883842561).mention, - 'd.py-rewrite-start' : self.bot.get_channel(386419285439938560).mention, - 'js-klasa-start' : self.bot.get_channel(341816240186064897).mention, - 'async2rewrite-start' : self.bot.get_channel(392223495389577217).mention, - 'd.js' : self.bot.get_channel(436771798303113217).mention} - - bots_channels = (self.bot.get_channel(339112602867204097).mention, - self.bot.get_channel(411586546551095296).mention) - - help_channels = (self.bot.get_channel(425315253153300488).mention, - self.bot.get_channel(392215236612194305).mention, - self.bot.get_channel(351034776985141250).mention) - - def check(m): - return True if m.author.id == ctx.author.id and m.channel.id == ctx.channel.id else False - - msg = await self.bot.wait_for('message', check = check, timeout = 15) - - agree = ("yes", "yep", "non't", "ya", "ye", "yup", "ok", "why not") - - if msg is None: - await ctx.send("Sorry, {ctx.author.mention}, you didn't reply on time. You can run the command again when you're free :)") - else: - if msg.content.lower() in agree: - async with ctx.typing(): - await ctx.send("Alrighty-Roo... Check your DMs!") - await ctx.author.send("Alrighty-Roo...") - - await ctx.author.send(f"To start making your bot from scratch, you first need to head over to {channel_list['channel-1']}" - " (Regardless of the language you're gonna use).") - - await asyncio.sleep(0.5) - await ctx.author.send(f"After you have a bot account, you can either continue with {channel_list['d.py-rewrite-start']} " - f"if you want to make a bot in discord.py rewrite __or__ go to {channel_list['js-klasa-start']} or " - f"{channel_list['d.js']} for making a bot in JavaScript." - f"If you already have old Discord.py async code and you want to use it with the new Rewrite versions, head to {channel_list['async2rewrite-start']}") - - await ctx.author.send("...Read all the tutorials and still need help? You have two ways to get help.") - await asyncio.sleep(1.5) - await ctx.author.send("**Method-1**\nThis is the best method of getting help. You help yourself.\n" - f"To do so, head over to a bots dedicated channel (either {bots_channels[0]} or {bots_channels[1]})" - " and type `?rtfm rewrite thing_you_want_help_with`.\nThis will trigger the bot R.Danny Bot and will " - "give you links on your query on the official discord.py rewrite docs. *PS: Let the page completely load*") - - await asyncio.sleep(5) - await ctx.author.send("**Method-2**\nIf you haven't found anything useful with Method-1, feel free to ask your question " - f"in any of the related help channels. ({', '.join(help_channels)})\nMay the force be with you!!") - - else: - return await ctx.send("Session terminated. You can run this command again whenever you want.") - -def setup(bot): - bot.add_cog(BasicCommands(bot)) diff --git a/src/cogs/bot_management.py b/src/cogs/bot_management.py deleted file mode 100644 index 2e8d523..0000000 --- a/src/cogs/bot_management.py +++ /dev/null @@ -1,189 +0,0 @@ -import discord -from discord.ext import commands - -class BotManager: - def __init__(self, bot): - self.bot = bot - - async def on_member_join(self, member): - # If the member is not a bot - if member.bot is False: - return - else: - # The member is a bot - bot_owner = member.guild.get_member((await self.bot.db_con.fetchval('select owner from bots where id = $1', member.id)) - await bot_owner.add_roles(discord.utils.get(member.guild.roles, name='Bot Developers')) - - await member.add_roles(discord.utils.get(member.guild.roles, name='Bots')) - try: - await member.edit(nick='[' + await self.bot.db_con.fetchval('select prefix from bots where id = $1', member.id) - + '] ' + member.name) - except: - pass - - async def on_member_remove(self, member): - # If the member is not a bot - if member.bot is False: - return - else: - # The member is a bot - await self.bot.db_con.execute('DELETE FROM bots WHERE id = $1', member.id) - - async def on_member_ban(self, guild, user): - if member.bot is True: - return - else: - # I need to finish this - pass - - @commands.command() - async def invite(self, ctx, bot=None, prefix=None): - bot = await ctx.bot.get_user_info(bot) - if not bot: - raise Warning('You must include the id of the bot you are trying to invite... Be exact.') - if not bot.bot: - raise Warning('You can only invite bots.') - if not prefix: - raise Warning('Please provide a prefix') - - # Make sure that the bot has not been invited already and it is not being tested - if await self.bot.db_con.fetch('select count(*) from bots where id = $1', bot.id) == 1: - raise Warning('The bot has already been invited or is being tested') - - await self.bot.db_con.execute('insert into bots (id, owner, prefix) values ($1, $2, $3)', - bot.id, ctx.author.id, prefix) - - em = discord.Embed(colour=self.bot.embed_color) - em.title = "Hello {},".format(ctx.author.name) - em.description = "Thanks for inviting your bot! It will be tested and invited shortly. " \ - "Please open your DMs if they are not already so the bot can contact " \ - "you to inform you about the progress of the bot!" - await ctx.send(embed=em) - - em = discord.Embed(title="Bot invite", colour=discord.Color(0x363941)) - em.description = discord.utils.oauth_url(client_id, permissions=None, guild=ctx.guild)) - em.set_thumbnail(url=bot.avatar_url) - em.add_field(name="Bot name", value=bot.name) - em.add_field(name="Bot id", value="`" + str(bot.id) + "`") - em.add_field(name="Bot owner", value=ctx.author.mention) - em.add_field(name="Bot prefix", value="`" + prefix + "`") - await ctx.bot.get_channel(459280759945953300).send(embed=em) - - @commands.command(name='claim', aliases=['makemine', 'gimme']) - @commands.cooldown(1, 5, commands.BucketType.user) - async def _claim_bot(self, ctx, bot: discord.Member = None, prefix: str = None, owner: discord.Member = None): - if not bot: - raise Warning('You must include the name of the bot you are trying to claim... Be exact.') - if not bot.bot: - raise Warning('You can only claim bots.') - if not prefix: - if bot.display_name.startswith('['): - prefix = bot.display_name.split(']')[0].strip('[') - else: - raise Warning('Prefix not provided and can\'t be found in bot nick.') - - if owner is not None and ctx.author.guild_permissions.manage_roles: - author_id = owner.id - else: - author_id = ctx.author.id - - em = discord.Embed() - - if await self.bot.db_con.fetchval('select count(*) from bots where owner = $1', author_id) >= 10: - em.colour = self.bot.error_color - em.title = 'Too Many Bots Claimed' - em.description = 'Each person is limited to claiming 10 bots as that is how ' \ - 'many bots are allowed by the Discord API per user.' - return await ctx.send(embed=em) - existing = await self.bot.db_con.fetchrow('select * from bots where id = $1', bot.id) - if not existing: - await self.bot.db_con.execute('insert into bots (id, owner, prefix) values ($1, $2, $3)', - bot.id, author_id, prefix) - em.colour = self.bot.embed_color - em.title = 'Bot Claimed' - em.description = f'You have claimed {bot.display_name} with a prefix of {prefix}\n' \ - f'If there is an error please run command again to correct the prefix,\n' \ - f'or {ctx.prefix}unclaim {bot.mention} to unclaim the bot.' - elif existing['owner'] and existing['owner'] != author_id: - em.colour = self.bot.error_color - em.title = 'Bot Already Claimed' - em.description = 'This bot has already been claimed by someone else.\n' \ - 'If this is actually your bot please let the guild Administrators know.' - elif existing['owner'] and existing['owner'] == author_id: - em.colour = self.bot.embed_color - em.title = 'Bot Already Claimed' - em.description = 'You have already claimed this bot.\n' \ - 'If the prefix you provided is different from what is already in the database' \ - ' it will be updated for you.' - if existing['prefix'] != prefix: - await self.bot.db_con.execute("update bots set prefix = $1 where id = $2", prefix, bot.id) - elif not existing['owner']: - await self.bot.db_con.execute('update bots set owner = $1, prefix = $2 where id = $3', - author_id, prefix, bot.id) - em.colour = self.bot.embed_color - em.title = 'Bot Claimed' - em.description = f'You have claimed {bot.display_name} with a prefix of {prefix}\n' \ - f'If there is an error please run command again to correct the prefix,\n' \ - f'or {ctx.prefix}unclaim {bot.mention} to unclaim the bot.' - else: - em.colour = self.bot.error_color - em.title = 'Something Went Wrong...' - await ctx.send(embed=em) - - @commands.command(name='unclaim') - @commands.cooldown(1, 5, commands.BucketType.user) - async def _unclaim_bot(self, ctx, bot: discord.Member = None): - if not bot: - raise Warning('You must include the name of the bot you are trying to claim... Be exact.') - if not bot.bot: - raise Warning('You can only unclaim bots.') - - em = discord.Embed() - - existing = await self.bot.db_con.fetchrow('select * from bots where id = $1', bot.id) - if not existing or not existing['owner']: - em.colour = self.bot.error_color - em.title = 'Bot Not Found' - em.description = 'That bot is not claimed' - elif existing['owner'] != ctx.author.id and not ctx.author.guild_permissions.manage_roles: - em.colour = self.bot.error_color - em.title = 'Not Claimed By You' - em.description = 'That bot is claimed by someone else.\n' \ - 'You can\'t unclaim someone else\'s bot' - else: - await self.bot.db_con.execute('update bots set owner = null where id = $1', bot.id) - em.colour = self.bot.embed_color - em.title = 'Bot Unclaimed' - em.description = f'You have unclaimed {bot.display_name}\n' \ - f'If this is an error please reclaim using\n' \ - f'{ctx.prefix}claim {bot.mention} {existing["prefix"]}' - await ctx.send(embed=em) - - @commands.command(name='listclaims', aliases=['claimed', 'mybots']) - @commands.cooldown(1, 5, commands.BucketType.user) - async def _claimed_bots(self, ctx, usr: discord.Member = None): - if usr is None: - usr = ctx.author - bots = await self.bot.db_con.fetch('select * from bots where owner = $1', usr.id) - if bots: - em = discord.Embed(title=f'{usr.display_name} has claimed the following bots:', - colour=self.bot.embed_color) - for bot in bots: - member = ctx.guild.get_member(int(bot['id'])) - em.add_field(name=member.display_name, value=f'Stored Prefix: {bot["prefix"]}', inline=False) - else: - em = discord.Embed(title='You have not claimed any bots.', - colour=self.bot.embed_color) - await ctx.send(embed=em) - - @commands.command(name='whowns') - async def _whowns(self, ctx, bot: discord.Member): - if not bot.bot: - await ctx.send('this commands only for bots') - else: - owner = await self.bot.db_con.fetchrow('select * from bots where id = $1', bot.id) - await ctx.send(ctx.guild.get_member(owner['owner']).display_name) - - -def setup(bot): - bot.add_cog(BotManager(bot)) diff --git a/src/cogs/moderation.py b/src/cogs/moderation.py deleted file mode 100644 index ee7e773..0000000 --- a/src/cogs/moderation.py +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -from discord.ext import commands -import discord - -class Moderation: - """ - Moderation Commands - """ - def __init__(self, bot): - self.bot = bot - - @commands.command() - async def kick(self, ctx, member: discord.Member = None): - """ - Kick a discord member from your server. - Only contributors can use this command. - - Usage: - - kick - - """ - await ctx.trigger_typing() - if ctx.author.id not in self.bot.ownerlist: - return await ctx.send('Only my contributors can use me like this :blush:', delete_after=10) - - if member is None: - await ctx.send('Are you sure you are capable of this command?') - try: - await member.kick() - await ctx.send(f'You kicked **`{member.name}`** from **`{ctx.guild.name}`**') - - except Exception as e: - await ctx.send('You may not use this command, as you do not have permission to do so:\n\n**`{ctx.guild.name}`**' - f'\n\n```py\n{e}\n```') - @commands.command() - async def ban(self, ctx, member: discord.Member = None): - """ - Ban a discord member from your server. - Only contributors can use this command. - - Usage: - - ban - - """ - await ctx.trigger_typing() - if ctx.author.id not in self.bot.ownerlist: - return await ctx.send('Only my contributors can use me like this :blush:', delete_after=10) - - if member is None: - await ctx.send('Are you sure you are capable of this command?') - try: - await member.ban() - await ctx.send(f'You banned **`{member.name}`** from **`{ctx.guild.name}`**') - - except Exception as e: - await ctx.send('You may not use this command, as you do not have permission to do so:\n\n**`{ctx.guild.name}`**' - f'\n\n```py\n{e}\n```') - -def setup(bot): - bot.add_cog(Moderation(bot)) diff --git a/src/cogs/music.py b/src/cogs/music.py deleted file mode 100644 index 54eb3a9..0000000 --- a/src/cogs/music.py +++ /dev/null @@ -1,306 +0,0 @@ -import asyncio -import inspect -import traceback -import weakref -from typing import Dict - -import async_timeout -import dataclasses -import discord -from discord.ext import commands -import youtube_dl - -# noinspection PyUnresolvedReferences,PyUnresolvedReferences,PyPackageRequirements -from . utils import noblock - - -YT_DL_OPTS = { - "format": 'mp3[abr>0]/bestaudio/best', - "ignoreerrors": True, - "default_search": "auto", - "source_address": "0.0.0.0", - 'quiet': True -} - - -# Let it be waiting on an empty queue for about 30 minutes -# before closing the connection from being idle. -IDLE_FOR = 60 * 30 - - -@dataclasses.dataclass(repr=True) -class Request: - """Track request.""" - who: discord.Member - what: str # Referral - title: str # Video title - actual_url: str # Actual URL to play - - def __str__(self): - return self.title - - def __hash__(self): - return hash(str(self.who.id) + self.what) - - -# noinspection PyBroadException -class Session: - """ - Each player being run is a session; (E.g. if you open a player in one server and I did in another). - Sessions will have a queue, an event that can fire to stop the current track and move on, and a voice - channel to bind to. This is defined as the voice channel the owner of the session was in when they made the channel. - To create a session, call ``Session.new_session``. Do not call the constructor directly. - Attributes: - ctx: discord.ext.commands.Context - The context of the original command invocation we are creating a session for. - loop: asyncio.AbstractEventLoop - The event loop to run this in. - voice_client: discord.VoiceClient - Voice client we are streaming audio through. - queue: asyncio.Queue - Track queue. - """ - @classmethod - async def new_session(cls, ctx: commands.Context): - """ - Helper to make a new session. Invoke constructor using this, as it handles any errors. It also ensures - we connect immediately. - """ - try: - s = cls(ctx) - await s.connect() - except Exception as ex: - traceback.print_exc() - await ctx.send(f"I couldn't connect! Reason: {str(ex) or type(ex).__qualname__}") - return None - else: - return s - - def __init__(self, ctx: commands.Context) -> None: - """Create a new session.""" - if ctx.author.voice is None: - raise RuntimeError('Please enter a voice channel I have access to first.') - - # Holds the tasks currently running associated with this. - self.voice_channel = ctx.author.voice.channel - self.ctx: commands.Context = ctx - self.voice_client: discord.VoiceClient = None - self.loop: asyncio.AbstractEventLoop = weakref.proxy(self.ctx.bot.loop) - self.queue = asyncio.Queue() - - # Lock-based event to allow firing a handler to advance to the next track. - self._start_next_track_event = asyncio.Event() - self._on_stop_event = asyncio.Event() - self._player: asyncio.Task = None - self._track: asyncio.Task = None - - @property - def is_connected(self) -> bool: - return self.voice_client and self.voice_client.is_connected() - - async def connect(self) -> None: - """Connects to the VC.""" - if not self.is_connected and not self._player: - # noinspection PyUnresolvedReferences - self.voice_client = await self.voice_channel.connect() - self._start_next_track_event.clear() - self._player = self.__spawn_player() - else: - raise RuntimeError('I already have a voice client/player running.') - - async def disconnect(self) -> None: - """Disconnects from the VC.""" - await self.voice_client.disconnect() - self.voice_client = None - - def __spawn_player(self) -> asyncio.Task: - """Starts a new player.""" - async def player(): - try: - while True: - # Wait on an empty queue for a finite period of time. - with async_timeout.timeout(IDLE_FOR): - request = await self.queue.get() - - await self.ctx.send(f'Playing `{request}` requested by {request.who}') - - # Clear the skip event if it is set. - self._start_next_track_event.clear() - - # Start the player if it was a valid request, else continue to the next track. - if not self.__play(request.actual_url): - await self.ctx.send(f'{request.referral} was a bad request and was skipped.') - continue - - await self._start_next_track_event.wait() - - if self.voice_client.is_playing(): - self.voice_client.stop() - - except asyncio.CancelledError: - # Hit when someone kills the player using stop(). - print('Requested to stop player', repr(self)) - except asyncio.TimeoutError: - await self.ctx.send('Was idle for too long...') - print('Player queue was empty for too long and was stopped', repr(self)) - except Exception: - traceback.print_exc() - finally: - if self.voice_client.is_playing(): - await self.voice_client.stop() - if self.is_connected: - await self.disconnect() - return self.loop.create_task(player()) - - def __play(self, url): - """Tries to play the given URL. If it fails, we return False, else we return True.""" - try: - ffmpeg_player = discord.FFmpegPCMAudio(url) - - # Play the stream. After we finish, either from being cancelled or otherwise, fire the - # skip track event to start the next track. - self.voice_client.play(ffmpeg_player, after=lambda error: self._start_next_track_event.set()) - except Exception: - traceback.print_exc() - return False - else: - return True - - def skip(self): - """Request to skip track.""" - self._start_next_track_event.set() - - def stop(self): - """Request to stop playing.""" - if self._player: - self._player.cancel() - self._on_stop_event.set() - self._on_stop_event.clear() - - def on_exit(self, func): - """Decorates a function to invoke it on exit.""" - async def callback(): - await self._on_stop_event.wait() - inspect.iscoroutinefunction(func) and await func() or func() - self.loop.create_task(callback()) - return func - - -# noinspection PyBroadException -class PlayerCog: - def __init__(self): - self.sessions: Dict[discord.Guild, Session] = {} - - # noinspection PyMethodMayBeStatic - async def __local_check(self, ctx): - return ctx.guild - - @commands.command() - async def join(self, ctx): - if ctx.guild not in self.sessions: - p = await Session.new_session(ctx) - if p: - self.sessions[ctx.guild] = p - - @p.on_exit - def when_terminated(): - try: - self.sessions.pop(ctx.guild) - finally: - return - - await ctx.send("*hacker voice*\n**I'm in.**", delete_after=15) - else: - await ctx.send(f'I am already playing in {self.sessions[ctx.guild].voice_channel.mention}') - - # noinspection PyNestedDecorators - @staticmethod - @noblock.no_block - def _get_video_meta(referral): - downloader = youtube_dl.YoutubeDL(YT_DL_OPTS) - info = downloader.extract_info(referral, download=False) - return info - - @commands.command() - async def queue(self, ctx): - if ctx.guild not in self.sessions: - return await ctx.send('Please join me into a voice channel first.') - - sesh = self.sessions[ctx.guild] - if sesh.queue.empty(): - return await ctx.send( - 'There is nothing in the queue at the moment!\n\n' - 'Add something by running `<>play https://url` or `<>play search term`!') - - # We cannot faff around with the actual queue so make a shallow copy of the internal - # non-async dequeue. - # noinspection PyProtectedMember - agenda = sesh.queue._queue.copy() - - message = ['**Queue**'] - - for i, item in enumerate(list(agenda)[:15]): - message.append(f'`{i+1: >2}: {item.title} ({item.who})`') - - if len(agenda) >= 15: - message.append('') - message.append(f'There are {len(agenda)} items in the queue currently.') - - await ctx.send('\n'.join(message)[:2000]) - - @commands.command() - async def play(self, ctx, *, referral): - if ctx.guild not in self.sessions: - return await ctx.send('Please join me into a voice channel first.') - - try: - try: - info = await self._get_video_meta(referral) - - # If it was interpreted as a search, it appears this happens? - # The documentation is so nice. - if info.get('_type') == 'playlist': - info = info['entries'][0] - - # ...wait... did I say nice? I meant "non existent." - - url = info['url'] - title = info.get('title') or referral - except IndexError: - return await ctx.send('No results...', delete_after=15) - except Exception as ex: - return await ctx.send(f"Couldn't add this to the queue... reason: {ex!s}") - - await self.sessions[ctx.guild].queue.put(Request(ctx.author, referral, title, url)) - await ctx.send(f'Okay. Queued `{title or referral}`.') - except KeyError: - await ctx.send('I am not playing in this server.') - - @commands.command() - async def stop(self, ctx): - try: - await self.sessions[ctx.guild].stop() - except KeyError: - await ctx.send('I am not playing in this server.') - except TypeError: - await ctx.send("I wasn't playing anything, but okay.", delete_after=15) - - @commands.command() - async def skip(self, ctx): - try: - self.sessions[ctx.guild].skip() - try: - await ctx.message.add_reaction('\N{OK HAND SIGN}') - except discord.Forbidden: - await ctx.send('\N{OK HAND SIGN}') - except KeyError: - await ctx.send('I am not playing in this server.') - - @commands.command() - async def disconnect(self, ctx): - await self.sessions[ctx.guild].stop() - await self.disconnect() - - -def setup(bot): - bot.add_cog(PlayerCog())