예제 #1
0
파일: Roles.py 프로젝트: Fluxticks/MultiBot
 async def on_reaction(self, payload):
     """When someone reacts to a message in the guild
     
     Args:
         payload (discord.RawReactionActionEvent): The raw reaction data
     """
     if not payload.member.bot:
         bt.INFO(
             f'Received reaction {payload.emoji.name} from {payload.member.name}'
         )
         guild = bt.get_guild_by_id(self._bot, payload.guild_id)
         data_channel_id = list(
             self._channels.get(str(payload.guild_id)).keys())[0]
         data = self._channels.get(str(payload.guild_id))
         data = data.get(str(data_channel_id))
         if str(payload.channel_id) == str(data_channel_id):
             message = await bt.get_message_by_id(
                 bt.get_channel_by_id(guild, payload.channel_id),
                 payload.message_id)
             await message.remove_reaction(payload.emoji, payload.member)
             if payload.emoji.name in data:
                 role = bt.get_role_from_guild(
                     guild,
                     data.get(str(payload.emoji.name))[0])
                 await payload.member.add_roles(role)
                 bt.INFO(
                     f'Gave {payload.member.name} {role} role in {guild.name}'
                 )
             else:
                 bt.INFO('Ignoring Emoji as not in reaction data')
예제 #2
0
    async def find_or_make_category(self, ctx):
        """Summary
        
        Args:
            ctx: The context of the call
        
        Returns:
            discord.CategoryChannel: Either the category found or the one created by the bot
        """
        bt.INFO(f'Finding category for {ctx.guild.id}')
        categories = ctx.guild.categories
        found = []
        for category in categories:
            if category.name == category_name or 'bot' in category.name:
                found.append(category)

        category = None

        if len(found) < 1:
            bt.INFO(f'Found no categories in {ctx.guild.name}, making one called {category_name}')
            category = await ctx.guild.create_category_channel(category_name)
        elif len(found) == 1:
            category = found[0]
        else:
            for category in found:
                if category.name == category_name:
                    return category
            category = found[0]

        return category
예제 #3
0
파일: Music.py 프로젝트: Fluxticks/MultiBot
 async def play_next(self, player, timer):
     """Summary
     
     Args:
         player (discord.Client.voice_client): The voice client to get the queue of
         timer (str): The time in seconds to wait for
     """
     try:
         time = int(timer)
         await asyncio.sleep(time + 3)
         bt.INFO(f'Sleeping for {timer} seconds for player {player}')
         if len(self.players[player]) == 1:
             bt.INFO(f'No more songs to play for {player}')
             self.players[player] = []
             await self.edit_song_message(player)
             asyncio.create_task(self.empty(player,
                                            datetime.datetime.now()))
         elif len(self.players[player]) > 1:
             self.players[player].pop(0)
             next_song = self.players[player][0]
             bt.INFO(
                 f'Playing next song in queue for {player} : {next_song["title"]}'
             )
             await self.play_song(player, next_song)
     except BaseException as e:
         ex_type, ex_value, ex_traceback = sys.exc_info()
         bt.ERROR(
             f'Unable to play the next song due to an error: {ex_value}')
예제 #4
0
def keyboardInterruptHandler(signal, frame):
    """Handles when the program is shutdown with a keyboard interrupt
    
    Args:
        signal: The signal interrupt that is recieved
        frame: The current execution frame
    """
    bt.INFO('Doing cleanup')
    bot.gather_data()
    bt.INFO('Cleanup done!')
    exit(0)
예제 #5
0
 async def find_channel(self, ctx, find):
     bt.INFO(f'Finding {find} channel in {ctx.guild.id}')
     channel = bt.get_channel_by_name(ctx.guild, find)
     if channel is None:
         bt.INFO(f'Unable to find {find} channel in {ctx.guild.id}, making one')
         channel = await ctx.guild.create_text_channel(find, category=bt.get_channel_by_id(ctx.guild,
                                                                                           self._categories.get(
                                                                                               f'{ctx.guild.id}')),
                                                       overwrites=self.gen_overwrites(ctx))
     else:
         await self.clear(channel)
예제 #6
0
파일: Music.py 프로젝트: Fluxticks/MultiBot
def teardown(bot):
    """Unloads the Music extension
    
    Args:
        bot commands.Bot: The bot unloading the Music extension
    """
    bt.INFO('Unloading Music.py')
예제 #7
0
파일: Roles.py 프로젝트: Fluxticks/MultiBot
def teardown(bot):
    """Unloads the Roles extension from the bot
    
    Args:
        bot (commands.Bot): The bot to be unloaded from
    """
    bt.INFO('Unloading Roles.py')
예제 #8
0
def teardown(bot):
    """Summary
    
    Args:
        bot (commands.Bot): The bot that is unloading this extension
    """
    bt.INFO('Unloading Misc.py')
예제 #9
0
def setup(bot):
    """Loads the Misc extensions into the bot
    
    Args:
        bot (commands.Bot): The bot to be added as a cog to
    """
    bt.INFO('Loading Misc.py')
    bot.add_cog(Misc(bot))
예제 #10
0
파일: Roles.py 프로젝트: Fluxticks/MultiBot
def setup(bot):
    """Loads the Roles extension into the bot given
    
    Args:
        bot (commands.Bot): The bot to be loaded into
    """
    bt.INFO('Loading Roles.py')
    bot.add_cog(Roles(bot))
예제 #11
0
파일: Music.py 프로젝트: Fluxticks/MultiBot
def setup(bot):
    """Loads the Music extension into bot
    
    Args:
        bot commands.Bot: The bot to be loaded into
    """
    bt.INFO('Loading Music.py')
    bot.add_cog(Music(bot))
예제 #12
0
파일: Music.py 프로젝트: Fluxticks/MultiBot
 def __init__(self, bot):
     """Initialises the Music extension
     
     Args:
         bot (commands.Bot): The bot initialising the Music extension
     """
     self._bot = bot
     bt.INFO('Initialised Music Cog')
예제 #13
0
파일: Roles.py 프로젝트: Fluxticks/MultiBot
 def __init__(self, bot):
     """Initialises the Roles extension
     
     Args:
         bot (commands.Bot): The bot initialising the extension
     """
     self._bot = bot
     bt.INFO('Initialised Roles Bot')
예제 #14
0
파일: Music.py 프로젝트: Fluxticks/MultiBot
 def find_url(self, string):
     """Determines if the string parsed through is a url
     
     Args:
         string (str): The string to be checked
     
     Returns:
         bool: True if the string is a url, False if not
     """
     url = re.findall(
         'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+] |[!*\(\), ]|(?:%[0-9a-fA-F][0-9a-fA-F]))+',
         string)
     if len(url) != 0:
         bt.INFO('Song was a url')
         return True
     else:
         bt.INFO('Song was not a url')
         return False
예제 #15
0
 async def roles(self, ctx):
     """Performs the setup for just the roles channel, Usage: !setup roles
     
     Args:
         ctx: The context of the call
     """
     bt.INFO(f'Setting up roles for {ctx.guild.id}')
     await self.setup(ctx)
     await self.find_or_make_roles(ctx)
예제 #16
0
 async def music(self, ctx):
     """Performs the setup for just the music channel, Usage: !setup music
     
     Args:
         ctx: The context of the call
     """
     bt.INFO(f'Setting up music for {ctx.guild.id}')
     await self.setup(ctx)
     await self.find_or_make_music(ctx)
예제 #17
0
 async def do_setup(self, ctx):
     """Adds the required channels for the bot to function in, Usage: !setup [optional] <roles|music>
     
     Args:
         ctx: The context of the call
     """
     bt.INFO(f'Performing complete Setup for {ctx.guild.id}')
     await self.setup(ctx)
     await self.roles(ctx)
     await self.music(ctx)
예제 #18
0
파일: Music.py 프로젝트: Fluxticks/MultiBot
    async def play_command(self, ctx, *args):
        """Adds the song to the queue, if the queue is empty it will play it. Usage: !play <url|song name>
        
        Args:
            ctx: The context of the call
            *args: The name of the song to search for or the url of the song
        """

        await ctx.message.delete()

        if self._channels.get(str(ctx.guild.id)) is not None:
            if ctx.channel.id == self._channels.get(str(ctx.guild.id)):

                channel = self.get_channel(ctx)
                client = self.get_voice_client(channel)

                if client is None:
                    client = await self.do_join(ctx)

                song = ""

                for arg in args:
                    song += " " + arg

                song = song.strip()

                if client is not None:
                    if not self.find_url(song):
                        data = await self.find_song(song)
                        song = 'https://youtube.com' + data.get('link')
                    if len(self.players[client]) == 0:
                        file_data = self.get_song(song)
                        if file_data is not None:
                            self.players[client].append(file_data)
                            bt.INFO(f'Playing song: {file_data["title"]}')
                            await self.play_song(client, file_data)
                    else:
                        file_data = self.get_song(song)
                        if file_data is not None:
                            self.players[client].append(file_data)
                            await self.edit_song_message(client)
            else:
                music_channel = bt.get_channel_by_id(
                    ctx.guild, self._channels.get(str(ctx.guild.id)))
                await ctx.send(embed=bt.embed_message(
                    "Error!",
                    description=f"That command is only available "
                    f"in the {music_channel} channel",
                    colour='red'))
        else:
            await ctx.send(embed=bt.embed_message(
                f'Setup is not complete!',
                description="Run !setup for full setup or "
                "'!setup music' for just music",
                colour='red'))
예제 #19
0
 async def setup(self, ctx):
     """Summary
     
     Args:
         ctx: The context of the call
     """
     if self._categories.get(str(ctx.guild.id)) is None:
         category = await self.find_or_make_category(ctx)
         self._categories[str(ctx.guild.id)] = category.id
     else:
         bt.INFO(f'Category already identified for guild {ctx.guild.id}')
예제 #20
0
파일: Roles.py 프로젝트: Fluxticks/MultiBot
 async def do_role(self, ctx, role, emoji, name):
     """Performs the role command
     
     Args:
         ctx: The context of the call
         role (str): The role being added
         emoji (str): The emoji being associated with the role
         name (str): The description of the role
     """
     bt.INFO(f'Adding role {role} with emoji {emoji}')
     await self.add(ctx, role, emoji, name)
예제 #21
0
 async def clear_command(self, ctx):
     """Clears the current channel of the last 100 messages, Usage: !clear
     
     Args:
         ctx: The context of the call
     """
     bt.INFO(f'Clearing channel {ctx.channel} in {ctx.guild.name} (id: {ctx.guild.id})')
     channel = ctx.message.channel
     counter = await self.clear(channel)
     result = await ctx.send(
         embed=bt.embed_message("Cleared channel", description=f"Deleted {counter} messages from this channel"))
     await result.delete(delay=5)
예제 #22
0
파일: Music.py 프로젝트: Fluxticks/MultiBot
 def get_song(self, url, retries=0):
     """Prunes the song's data that was retrieved
     
     Args:
         url (str): The url of the song to be downloaded
         retries (int, optional): The number of retries performed if the fetch has failed
     
     Returns:
         dict: The file data of the song
     """
     try:
         info = self.download_song(url)
         file_data = {
             'file': 'songs/' + info['title'] + '-' + info['id'] + '.mp3',
             'title': info['title'],
             'artist': info['artist'],
             'duration': info['duration'],
             'track': info['track'],
             'id': info['id'],
             'link': url
         }
         bt.INFO(f'Title: {file_data["title"]}')
         bt.INFO(f'Artist: {file_data["artist"]}')
         bt.INFO(f'Track: {file_data["track"]}')
         bt.INFO(f'Duration: {file_data["duration"]}')
         bt.INFO(f'File: {file_data["file"]}')
         bt.INFO(f'ID: {file_data["id"]}')
         return file_data
     except Exception as e:
         bt.ERROR(f'Unable to find the requested song: {url}')
         if retries < 3:
             return self.get_song(url, retries=retries + 1)
         else:
             return None
예제 #23
0
async def reload(ctx):
    """Reloads the bots commands, Usage !reload
    
    Args:
        ctx: The context of the call
    """
    bt.WARN('Reloading Extensions!')
    reload_extensions()
    bot.load_data()
    message = await ctx.send(
        embed=bt.embed_message('Done Reloading!', colour='green'))
    await message.delete(delay=3.0)
    bt.INFO('Done Reloading Extensions!')
예제 #24
0
파일: Music.py 프로젝트: Fluxticks/MultiBot
 async def play_song(self, client, file_data):
     """Plays the song in file_data for the voice client client
     
     Args:
         client (discord.Client.voice_client): The voice client instance to play music to
         file_data (dict): A dictionary of the file data about the song 
     """
     client.play(discord.FFmpegPCMAudio(file_data['file']))
     client.volume = 100
     bt.INFO(f'{client} Playing status: {client.is_playing()}')
     await self.edit_preview(client)
     await self.edit_song_message(client)
     asyncio.create_task(self.play_next(client, file_data['duration']))
예제 #25
0
파일: Music.py 프로젝트: Fluxticks/MultiBot
    async def pause(self, ctx):
        """Pauses the current song
        
        Args:
            ctx: The context of the call
        """
        await ctx.message.delete()
        channel = self.get_channel(ctx)
        client = self.get_voice_client(channel)
        bt.INFO(f'Paused playback for {client}')

        if client is not None:
            client.pause()
            await self.edit_preview(client, default=True)
예제 #26
0
파일: Music.py 프로젝트: Fluxticks/MultiBot
    async def skip(self, ctx):
        """Skips the current song and plays the next one
        
        Args:
            ctx: The context of the call
        """
        await ctx.message.delete()
        channel = self.get_channel(ctx)
        client = self.get_voice_client(channel)

        if client is not None:
            bt.INFO(f'Skipping song for client {client}')
            client.pause()
            asyncio.create_task(self.play_next(client, -3))
예제 #27
0
파일: Music.py 프로젝트: Fluxticks/MultiBot
    async def stop(self, ctx):
        """Stops playback and clears the queue
        
        Args:
            ctx: The context of the call
        """
        await ctx.message.delete()
        channel = self.get_channel(ctx)
        client = self.get_voice_client(channel)
        bt.INFO(f'Stopped playback for {client}')

        if client is not None:
            client.stop()
            self.players[client] = []
예제 #28
0
파일: Music.py 프로젝트: Fluxticks/MultiBot
    async def resume(self, ctx):
        """Resumes the current playback
        
        Args:
            ctx: The context of the call
        """
        await ctx.message.delete()
        channel = self.get_channel(ctx)
        client = self.get_voice_client(channel)
        bt.INFO(f'Resumed playback for {client}')

        if client is not None:
            if client.is_paused():
                client.resume()
                await self.edit_preview(client)
예제 #29
0
파일: Roles.py 프로젝트: Fluxticks/MultiBot
 async def remove(self, ctx, emoji):
     """Performs the role remove command
     
     Args:
         ctx: The context of the call
         emoji (str): The emoji association to be removed
     """
     await ctx.message.delete()
     result, channel = self.check_and_get_channel_id(ctx)
     if result:
         guild_data = self._channels.get(f'{ctx.guild.id}').get(channel)
         if emoji not in guild_data:
             message = await ctx.send(embed=bt.embed_message(
                 'Error!',
                 description=f'Unable to remove {emoji} as '
                 f'it does not exist!'))
             await message.delete(delay=4.0)
         else:
             bt.INFO(
                 f'Removing {emoji} from {ctx.guild.name}\'s reaction roles'
             )
             keys = list(guild_data.keys())
             index = keys.index(str(emoji))
             bt.INFO('Editing roles message')
             message = await self.get_reaction_message(ctx)
             content = message.content
             split_content = content.split('\n')
             split_content.pop(index + 1)
             content = ''
             for line in split_content:
                 content += line + '\n'
             await message.edit(content=content)
             await message.clear_reaction(emoji)
             bt.INFO('Edit complete!')
             del guild_data[str(emoji)]
             bt.INFO('Removed data entry')
예제 #30
0
def load():
    """Loads the token from the file

    Returns:
        str: The string of the token
    """
    cipher = AESCipher(calculate_hash())
    with open('token.key', 'rb') as f:
        data = f.read()

    decrypted = cipher.decrypt(data)
    decrypted = decrypted.replace('\t', '\n')
    dictionary = json.loads(decrypted)
    token = dictionary.get('token')
    bt.INFO(f'Got bot token: {token}')
    return token