Esempio n. 1
0
 def sql_guilds_refresh(self):
     for guild in self.bot.client.state.guilds.copy().keys():
         try:
             guild_object = self.bot.client.state.guilds.get(guild, None)
             if guild_object is not None:
                 sql_guild = handle_sql(
                     db_session.query(guilds).filter_by(
                         guild_id=guild, ).first, )
                 if sql_guild is None:
                     sql_guild = guilds(
                         guild_id=guild,
                         last_seen=datetime.now().isoformat(),
                         name=guild_object.name,
                     )
                     handle_sql(db_session.add, sql_guild)
                 else:
                     try:
                         handle_sql(
                             db_session.query(guilds).filter_by(
                                 guild_id=guild, ).update,
                             {
                                 "last_seen": datetime.now().isoformat(),
                                 "name": guild_object.name
                             },
                         )
                     except SQLexception as e:
                         log.warning(
                             "Failed to post server to SQL server in status: {}"
                             .format(e.previous_exception))
                     else:
                         handle_sql(db_session.flush)
         except CommandError as e:
             log.warning("Failed to call SQL server: {}".format(e.msg))
             log.warning(str(e.original_exception))
             break
Esempio n. 2
0
 def on_guild_update(self, event):
     try:
         guild = handle_sql(
             db_session.query(guilds).filter_by(
                 guild_id=event.guild.id, ).first)
         if guild is None:
             guild = guilds(
                 guild_id=event.guild.id,
                 last_seen=datetime.now().isoformat(),
                 name=event.guild.name,
             )
             handle_sql(db_session.add, guild)
             handle_sql(db_session.flush)
         else:
             if guild.name != event.guild.name:
                 handle_sql(
                     db_session.query(guilds).filter_by(
                         guild_id=event.guild.id, ).update,
                     {
                         "name": event.guild.name,
                         "last_seen": datetime.now().isoformat(),
                     },
                 )
                 handle_sql(db_session.flush)
     except CommandError as e:
         log.warning("Failed to update guild {} SQL entry: {}".format(
             event.guild.id, e.msg))
         log.exception(e.original_exception)
Esempio n. 3
0
    def get_user_info(self, target: str, guild: int = None):
        """
        Used to get a Discord user's information from the SQL server.

        Args:
            target: int/str
                The target user's Discord id or their name/alias.

        Return dict format:
            "user_id": int
                The user's Discord id.
            "username": 2 <= string <= 15
                The user's Last.FM username.
            "period": string [
                                'overall',
                                '7day',
                                '1month',
                                '3month',
                                '6month',
                                '12month'
                            ]
                The period which 'Top' commands should use.
            "guild": int
                The guild id used for alias lookup.
        """
        try:
            target = AT_to_id(target)
        except CommandError as e:
            if guild is not None and not isinstance(guild, int):
                data = handle_sql(
                    db_session.query(aliases).filter(
                        aliases.guild_id == guild,
                        aliases.alias.like(target)).first)
                if data:
                    target = data.user_id
                else:
                    raise CommandError("User alias not found.")
            elif isinstance(guild, bool):
                raise CommandError("User aliases aren't enabled in DMs.")
            else:
                raise e
        data = handle_sql(
            db_session.query(users).filter_by(user_id=target, ).first)
        if data is None:
            user = users(user_id=target)
            handle_sql(db_session.add, user)
            handle_sql(db_session.flush)
            data = {"user_id": target, "username": None, "period": periods[0]}
        else:
            data = {
                "user_id": data.user_id,
                "username": data.last_username,
                "period": periods[data.period],
            }
        if data["username"] is None:
            raise CommandError(
                "User should set a last.fm account using ``fm.username``")
        return data
Esempio n. 4
0
 def on_alias_list_command(self, event, target=None):
     """
     Last.fm Used to get a list of a user's aliases in a guild.
     When no arguments are given, this will return the author's aliases.
     Otherwise, this accepts one argument (a target user's @, ID or alias) and will return a list of the target's alises.
     """
     if event.channel.is_dm:
         api_loop(
             event.channel.send_message,
             "Alias commands are guild specific.",
         )
     else:
         if target is None:
             target = event.author.id
         else:
             try:
                 target = AT_to_id(target)
             except CommandError as e:
                 data = handle_sql(
                     db_session.query(aliases).filter(
                         aliases.guild_id == event.guild.id,
                         aliases.alias.like(target),
                     ).first)
                 if data is None:
                     raise CommandError(
                         "User alias not found in this guild.")
                 else:
                     target = data.user_id
         data = handle_sql(
             db_session.query(aliases).filter_by(
                 user_id=target,
                 guild_id=event.guild.id,
             ).all)
         user = self.client.api.guilds_members_get(event.guild.id, target)
         if data:
             inline = {
                 str(index + 1): alias.alias
                 for index, alias in enumerate(data)
             }
             embed = bot.generic_embed_values(
                 title="{}'s aliases in {}".format(
                     user.name,
                     event.guild.name,
                 ),
                 non_inlines=inline,
             )
             api_loop(
                 event.channel.send_message,
                 embed=embed,
             )
         else:
             api_loop(
                 event.channel.send_message,
                 "User doesn't have any aliases set in this guild.",
             )
Esempio n. 5
0
 def on_username_command(self, event, username: str = None):
     """
     Last.fm Set user default last.fm account.
     This command accepts a username that fits Last.FM's username format as of 2019/04/11 and will assign that as the author's Last.FM account.
     If no arguments are passed, it will return the author's assigned Last.FM username.
     """
     if username is not None:
         username = self.get_last_account(username)["user"]["name"]
         handle_sql(
             db_session.query(users).filter_by(
                 user_id=event.author.id, ).update,
             {"last_username": username},
         )
         handle_sql(db_session.flush)
         api_loop(
             event.channel.send_message,
             "Username for ``{}`` changed to ``{}``.".format(
                 event.author, username),
         )
     else:
         try:
             current_username = self.get_user_info(
                 event.author.id)["username"]
         except CommandError:
             api_loop(
                 event.channel.send_message,
                 "Username not set for ``{}``".format(event.author),
             )
         else:
             api_loop(
                 event.channel.send_message,
                 "Username for ``{}`` currently set to ``{}``.".format(
                     event.author,
                     current_username,
                 ))
Esempio n. 6
0
 def load(self, ctx):
     super(CorePlugin, self).load(ctx)
     bot.custom_prefix_init(self)
     self.status_thread = status_thread_handler(
         self,
         db_token=bot.local.api.dbl_token,
         gg_token=bot.local.api.discord_bots_gg,
         user_agent=bot.local.api.user_agent,
     )
     bot.local.get(
         self,
         "owners",
         "exception_dms",
         "exception_channels",
     )
     self.command_prefix = (bot.local.prefix
                            or bot.local.disco.bot.commands_prefix or "fm.")
     bot.init_help_embeds(self)
     self.cool_down = {"prefix": {}}
     self.cache = {"prefix": {}}
     self.prefixes = {}
     try:
         for guild in handle_sql(db_session.query(guilds).all):
             self.prefixes[guild.guild_id] = guild.prefix
     except CommandError as e:
         log.critical(
             "Failed to load data from guild data from SQL servers, they're probably down."
         )
         log.exception(e.original_exception)
Esempio n. 7
0
 def on_guild_leave(self, event):
     if type(event.unavailable) is Unset:
         try:
             handle_sql(
                 db_session.query(guilds).filter_by(
                     guild_id=event.id, ).delete)
             handle_sql(db_session.flush)
         except CommandError as e:
             log.warning(
                 "Failed to remove guild {} from SQL database: {}".format(
                     event.id, e.msg))
             log.exception(e.original_exception)
Esempio n. 8
0
 def on_guild_join(self, event):
     if type(event.unavailable) is Unset:
         if handle_sql(
                 db_session.query(guilds).filter_by(
                     guild_id=event.guild.id).first, ) is None:
             guild = guilds(
                 guild_id=event.guild.id,
                 last_seen=datetime.now().isoformat(),
                 name=event.guild.name,
             )
             db_session.add(guild)
             handle_sql(db_session.flush)
             self.prefixes[event.guild.id] = self.command_prefix
Esempio n. 9
0
 def on_help_command(self, event, command=None):
     """
     Miscellaneous Get a list of the commands in a module.
     If arg is passed, will try to return the info for the relevant command.
     Otherwise, it will just return a list of all the enabled commands.
     """
     if not event.channel.is_dm:
         channel = api_loop(event.author.open_dm)
     else:
         channel = event.channel
     if command is None:
         for help_embed in bot.help_embeds.values():
             dm_default_send(event, channel, embed=help_embed)
     else:
         command_obj = bot.commands_dict.get(command, None)
         if command_obj:
             if command_obj.raw_args is not None:
                 args = " " + command_obj.raw_args + ";"
             else:
                 args = str()
             docstring = command_obj.get_docstring().replace("    ",
                                                             "").strip("\n")
             embed = bot.generic_embed_values(
                 title="{}{}{} a command in the {} module.".format(
                     self.command_prefix,
                     str(command_obj.triggers).replace("[", "(").replace(
                         "'", "**").replace(",", " |").replace("]", ")") +
                     ":", args,
                     docstring.split(" ", 1)[0]),
                 url=bot.local.embed_values.url,
                 description=docstring.split(" ", 1)[1],
             )
             dm_default_send(event, channel, embed=embed)
         else:
             dm_default_send(
                 event,
                 channel,
                 content="``{}`` command not found.".format(command),
             )
     user_info = handle_sql(
         db_session.query(users).filter_by(user_id=event.author.id).first, )
     if user_info is None or user_info.last_username is None:
         dm_default_send(
             event,
             channel,
             content=
             "To get started with this bot, you can set your default last.fm username using the command ``{}username <username>``."
             .format(self.command_prefix),
         )
Esempio n. 10
0
 def on_friends_add_command(self, event, friend):
     """
     Last.fm Add another user to your friends list.
     This command will either add the user if they're not in your friend's list or remove them otherwise
     and won't target users that haven't setup a last.fm username.
     This command accepts either a Discord user ID or @user
     """
     # friend = AT_to_id(friend)
     # username = self.get_user_info(friend, event.guild.id)["username"]
     friend = self.get_user_info(friend, event.guild.id)["user_id"]
     user = self.state.users.get(int(friend))
     if user is not None:
         user = str(user)
     else:
         user = friend
     friendship = handle_sql(
         db_session.query(friends).filter_by(
             master_id=event.author.id,
             slave_id=friend,
         ).first)
     if friendship is None:
         friendship = friends(master_id=event.author.id, slave_id=friend)
         handle_sql(db_session.add, friendship)
         api_loop(
             event.channel.send_message,
             "Added user ``{}`` to friends list.".format(friend),
         )
     else:
         handle_sql(
             db_session.query(friends).filter_by(master_id=event.author.id,
                                                 slave_id=friend).delete)
         api_loop(
             event.channel.send_message,
             "Removed user ``{}`` from friends list.".format(friend),
         )
     handle_sql(db_session.flush)
Esempio n. 11
0
 def on_top_period_command(self, event, period=None):
     """
     Last.fm Used to set the default period for the 'top' group of commands.
     Accepts a string argument with the supported arguments being displayed allow.
         Overall
         7 days
         1 months
         3 months
         6 months
         12 months
     The argument isn't case sensative (capital letters don't matter) and spaces are ignored.
     If no arguments are passed, the command will respond with the author's current default period.
     """
     if period is not None:
         period = period.replace(" ", "").strip("s").lower()
         if period in periods.values():
             data = self.get_user_info(event.author.id)
             handle_sql(
                 db_session.query(users).filter_by(
                     user_id=event.author.id, ).update,
                 {
                     "period": {y: x
                                for x, y in periods.items()}[period],
                 },
             )
             handle_sql(db_session.flush)
             api_loop(
                 event.channel.send_message,
                 "Default period for 'top' commands updated to ``{}``.".
                 format(period),
             )
         else:
             api_loop(
                 event.channel.send_message,
                 "Invalid argument, see ``fm.help top period`` for more details.",
             )
     else:
         data = self.get_user_info(event.author.id)
         api_loop(
             event.channel.send_message,
             "Your default 'top' period is currently set to ``{}``".format(
                 data["period"]),
         )
Esempio n. 12
0
 def on_friends_command(self, event):
     """
     Last.fm Get a list of what your friends have recently listened to.
     Accepts no arguments.
     """
     data = handle_sql(
         db_session.query(friends).filter_by(
             master_id=event.author.id, ).all)
     if not data:
         api_loop(
             event.channel.send_message,
             "You don't have any friends, use ``fm.friends add @`` to get some.",
         )
     else:
         data = [x.slave_id for x in data]
         content, embed = self.friends_search(
             data,
             0,
             author=event.author.id,
             title="{} friends.".format(event.author),
             thumbnail=event.author.avatar_url,
         )
         reply = api_loop(event.channel.send_message, embed=embed)
         if len(data) > 5 and not event.channel.is_dm:
             bot.reactor.init_event(
                 message=reply,
                 timing=30,
                 author=event.author.id,
                 data=data,
                 index=0,
                 amount=5,
                 edit_message=self.friends_search,
             )
             bot.reactor.add_reactors(
                 self,
                 reply,
                 generic_react,
                 event.author.id,
                 "\N{leftwards black arrow}",
                 "\N{Cross Mark}",
                 "\N{black rightwards arrow}",
             )
Esempio n. 13
0
 def on_alias_set_command(self, event, alias):
     """
     Last.fm Used to add or remove a user alias in a guild.
     Users are limited to 5 alises in a guild.
     Alises are limited to 20 characters and cannot contain Discord's reserved special characters (e.g. '@', '#').
     """
     if event.channel.is_dm:
         api_loop(event.channel.send_message,
                  "Alias commands are guild specific.")
     else:
         if len(alias) > 20 or sanitize(alias) != alias:
             api_loop(
                 event.channel.send_message,
                 "Aliasas are limited to 20 characters and cannot contain Discord's reserved special characters.",
             )
         else:
             data = handle_sql(
                 db_session.query(aliases).filter(
                     aliases.user_id == event.author.id,
                     aliases.guild_id == event.guild.id,
                     aliases.alias.like(alias),
                 ).first)
             if data is None:
                 if (handle_sql(
                         db_session.query(aliases).filter_by(
                             user_id=event.author.id,
                             guild_id=event.guild.id,
                         ).count) < 5):
                     payload = aliases(
                         user_id=event.author.id,
                         guild_id=event.guild.id,
                         alias=alias,
                     )
                     handle_sql(db_session.add, payload)
                     handle_sql(db_session.flush)
                     api_loop(
                         event.channel.send_message,
                         "Added alias ``{}``.".format(alias),
                     )
                 else:
                     api_loop(
                         event.channel.send_message,
                         "You've reached the 5 alias limit for this guild.".
                         format(data.alias, ),
                     )
             else:
                 if data.user_id == event.author.id:
                     handle_sql(
                         db_session.query(aliases).filter_by(
                             user_id=event.author.id,
                             guild_id=event.guild.id,
                             alias=data.alias,
                         ).delete)
                     handle_sql(db_session.flush)
                     api_loop(
                         event.channel.send_message,
                         "Removed alias ``{}``.".format(data.alias),
                     )
                 else:
                     api_loop(
                         event.channel.send_message,
                         "Alias ``{}`` is already taken in this guild.".
                         format(data.alias),
                     )
Esempio n. 14
0
 def friends_search(self, data, index, author, limit=5, **kwargs):
     embed = bot.generic_embed_values(**kwargs)
     if len(data) - index < limit:
         limit = len(data) - index
     for x in range(limit):
         current_index = index + x
         while True:
             user = self.state.users.get(int(data[current_index]))
             if user is not None:
                 user = str(user)
             else:
                 user = data[current_index]
             try:
                 friend = self.get_user_info(data[current_index])
             except CommandError:
                 handle_sql(
                     db_session.query(friends).filter_by(
                         master_id=author,
                         slave_id=data[current_index]).delete, )
                 handle_sql(db_session.flush)
                 data.pop(current_index)
                 if current_index >= len(data) - 1:
                     finished = True
                     break
             else:
                 finished = False
                 break
         if finished:
             break
         limit = 2
         url = "https://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user={}&api_key={}&format=json&limit={}".format(
             friend["username"],
             self.last_key,
             limit,
         )
         try:
             self.get_fm_secondary(
                 embed=embed,
                 url=url,
                 name="[{}] {} ({})".format(
                     current_index + 1,
                     user,
                     friend["username"],
                 ),
                 primary_index="recenttracks",
                 secondary_index="track",
                 artists=True,
                 artist_name="#text",
                 entry_format="ago",
                 seperator="\n",
                 limit=limit,
             )
         except CommandError:
             embed.add_field(
                 name="[{}] {}".format(current_index + 1, user),
                 value=("Last.fm account `{}` was not found.".format(
                     friend["username"], )),
                 inline=True,
             )
         if current_index >= len(data) - 1:
             break
     return None, embed
Esempio n. 15
0
    def custom_prefix(self, event):
        if not event.author.bot:
            if ((not hasattr(event, "channel") or event.channel is None)
                    and not isinstance(event.guild_id, Unset)):
                guild = getattr(event, "guild", None)
                if guild is None:
                    event.guild = self.client.state.guilds.get(
                        event.guild_id,
                        None,
                    )
                    if event.guild is None:
                        event.guild = self.client.state.guilds[
                            event.guild_id] = api_loop(
                                self.client.api.guilds_get,
                                event.guild_id,
                            )
                event.channel = event.guild.channels.get(
                    event.channel_id, None)
                if event.channel is None:
                    event.channel = api_loop(
                        self.client.api.channels_get,
                        event.channel_id,
                    )
            elif ((not hasattr(event, "channel") or event.channel is None)
                  and isinstance(event.guild_id, Unset)):
                event.channel = api_loop(
                    self.client.api.channels_get,
                    event.message.channel_id,
                )

            if event.channel.is_dm:
                prefix = self.command_prefix
            else:
                prefix = self.prefixes.get(event.guild_id, None)
                if prefix is None:
                    guild = handle_sql(
                        db_session.query(guilds).filter_by(
                            guild_id=event.guild_id, ).first, )
                    if guild is None:
                        prefix = self.command_prefix
                        self.prefixes[event.guild_id] = prefix
                        guild = guilds(
                            guild_id=event.guild_id,
                            last_seen=datetime.now().isoformat(),
                            prefix=prefix,
                        )
                        handle_sql(db_session.add, guild)
                        handle_sql(db_session.flush)
                    else:
                        preifx = guild.prefix
                        self.prefixes[event.guild_id] = guild.prefix

            if event.message.content and event.message.content.startswith(
                    prefix):
                prefix_len = len(prefix)
                if (len(event.message.content) > prefix_len
                        and event.message.content[prefix_len] == " "):
                    prefix_len += 1
                message_dict = event.message.content[prefix_len:].split(" ")
                commands = [message_dict[0]]
                if len(message_dict) > 1:
                    for word in message_dict[1:]:
                        commands.append(commands[-1] + " " + word)
                commands = bot.triggers_set.intersection(commands)
                if commands:
                    command = sorted(commands)[-1]
                    event.args = event.message.content[prefix_len +
                                                       len(command):].split()
                    event.name = command
                    event.msg = event.message
                    try:
                        bot.commands_dict[command].execute(event)
                    except CommandError as e:
                        api_loop(event.channel.send_message, str(e))
                    except Exception as e:
                        self.exception_response(event, e)
Esempio n. 16
0
 def on_prefix_command(self, event, prefix=None):
     """
     Miscellaneous Set a custom guild bot prefix (Manage Guild).
     This command will default to displaying the current prefix
     and ignore perms if no args are given.
     """
     if not event.channel.is_dm:
         if prefix is None:
             guild = handle_sql(
                 db_session.query(guilds).filter_by(
                     guild_id=event.guild.id, ).first, )
             if guild is None:
                 prefix = self.command_prefix
                 guild = guilds(
                     guild_id=event.guild.id,
                     last_seen=datetime.now().isoformat(),
                     name=event.guild.name,
                 )
                 handle_sql(db_session.add, guild)
                 handle_sql(db_session.flush)
             else:
                 prefix = guild.prefix
             return api_loop(
                 event.channel.send_message,
                 "Current prefix is ``{}``".format(prefix),
             )
         user_perms = event.guild.get_member(
             event.author, ).permissions.to_dict()
         if user_perms["manage_guild"] or user_perms["administrator"]:
             if (event.guild.id not in self.cool_down["prefix"]
                     or self.cool_down["prefix"][event.guild.id] <= time()):
                 if handle_sql(
                         db_session.query(guilds).filter_by(
                             guild_id=event.guild.id).first, ) is None:
                     guild = guilds(
                         guild_id=event.guild.id,
                         last_seen=datetime.now().isoformat(),
                         name=event.guild.name,
                         prefix=prefix,
                     )
                     handle_sql(db_session.add, guild)
                 else:
                     handle_sql(
                         db_session.query(guilds).filter_by(
                             guild_id=event.guild.id).update,
                         {
                             "name": event.guild.name,
                             "prefix": prefix
                         },
                     )
                 handle_sql(db_session.flush)
                 self.prefixes[event.guild.id] = prefix
                 api_loop(
                     event.channel.send_message,
                     "Prefix changed to ``{}``".format(prefix),
                 )
                 self.cool_down["prefix"][event.guild.id] = time() + 60
             else:
                 cooldown = self.cool_down["prefix"][event.guild.id]
                 return api_loop(
                     event.channel.send_message,
                     "Cool down: {} seconds left.".format(
                         round(Decimal(cooldown - time())), ),
                 )
         else:
             api_loop(
                 event.channel.send_message,
                 "You need to have the Guild Manage permission to use this command.",
             )
     else:
         api_loop(
             event.channel.send_message,
             "This command can only be used in guilds.",
         )