def __init__(self, client):
        self.client = client
        self.client_tools = ClientTools(client)
        self.database_tools = DatabaseTools(client)

        insert_channel = "INSERT INTO channels (channel_id, channel_name) VALUES (%s, %s)"
        update_channel = "UPDATE `gssp_logging`.`channels` SET `channel_name`=%s WHERE `channel_id`=%s;"
        if not bool(config['discord'].get("skip_scrape")):
            for guild in client.guilds:
                logger.info("{}: Updating channels".format(str(guild)))
                for channel in guild.text_channels:
                    try:
                        cursor.execute(
                            insert_channel,
                            (channel.id, emoji.demojize(channel.name)))
                        logger.debug("Inserted {} to DB".format(
                            emoji.demojize(channel.name)))
                    except mysql.connector.errors.IntegrityError:
                        cursor.execute(
                            update_channel,
                            (emoji.demojize(channel.name), channel.id))
                        logger.debug("Updated {}".format(
                            emoji.demojize(channel.name)))
                logger.info("{}: Updating users".format(str(guild)))
                for member in tqdm(guild.members,
                                   total=len(guild.members),
                                   desc="Adding users for {}".format(
                                       str(guild))):
                    self.database_tools.add_user(member)

                logger.info("{}: Finished {} users".format(
                    str(guild), len(guild.members)))
                logger.info("{}: Updating roles".format(str(guild)))
                for role in guild.roles:
                    if role.name != "@everyone":
                        try:
                            cursor.execute(insert_role,
                                           (role.id, emoji.demojize(role.name),
                                            guild.id, int(role.mentionable)))
                        except mysql.connector.errors.IntegrityError:
                            cursor.execute(update_role, (emoji.demojize(
                                role.name), int(role.mentionable), role.id))

                        # this is designed to assist with migration, by moving old discord role members over to the new
                        # system seamlessly
                        member_ids = []
                        for member in role.members:
                            member_ids.append(member.id)
                        role_db = DbRole(role.id,
                                         role.name,
                                         0,
                                         members=member_ids)
                        role_db.save_members()
                logger.info("{}: Finished {} roles".format(
                    guild, len(guild.roles)))
                cnx.commit()
        else:
            logger.warn(
                "Skipping scraping data from existing servers - data may be out of date"
            )
    async def experiments(self, ctx):
        """
        Opt into data analysis and experiments.
        """
        message = ctx.message
        channel = message.channel

        author = message.author
        create_user = "******"
        try:
            cursor.execute(create_user, (author.id, author.name))
            cnx.commit()

            em = discord.Embed(
                title=strings['data_collection']['opt_in_title'], description=opt_in_message)

            em.set_footer(text=strings['data_collection']['opt_in_footer'])
            return await channel.send(embed=em)
        except mysql.connector.errors.IntegrityError:
            get_user = "******"
            cursor.execute(get_user, (author.id,))

            opt_in_user = "******"

            cursor.execute(opt_in_user, (author.id,))
        await channel.send(strings['data_collection']['data_track_start'] + " for " + str(ctx.message.author))

        await self.client_tools.build_data_profile([author])
        await channel.send(strings['data_collection']['complete'].format(author.name))
示例#3
0
 async def pingable(self, ctx, *, role_name):
     """Change a role from not pingable to pingable or vice versa"""
     if role_name[0] == '"' and role_name[-1] == '"':
         role_name = role_name[1:-1]
     role = get_role(ctx.guild.id, role_name)
     if role is None:
         return await ctx.channel.send(
             embed=discord.Embed(title='Error',
                                 description='Could not find that role',
                                 color=red))
     if role['is_pingable'] == 1:
         update_query = "UPDATE `gssp`.`roles` SET `is_pingable`='0' WHERE `role_id`=%s AND `guild_id` = %s;"
         text = "not pingable"
     else:
         update_query = "UPDATE `gssp`.`roles` SET `is_pingable`='1' WHERE `role_id`=%s AND `guild_id` = %s;"
         text = "pingable"
     cursor.execute(update_query, (
         role['role_id'],
         ctx.guild.id,
     ))
     cnx.commit()
     await ctx.channel.send(
         embed=discord.Embed(title="SUCCESS",
                             description="Set {} ({}) to {}".format(
                                 role['role_name'], role['role_id'], text),
                             color=green))
    async def rename(self, ctx, role_name=None, new_name=None):
        """
        Changes the name of a role

        Params:
            role_name : name of the role to be changed
            new_name : name the role should be
        """

        # Removes excess spaces at the beginning of a role name
        if role_name[0] == '"' and role_name[-1] == '"':
            role_name = role_name[1:-1]

        role_check = get_role(ctx.guild.id, role_name)
        em = discord.Embed(title='Success',
                           description="Renamed {} to {}".format(
                               role_name, new_name),
                           color=green)
        if role_check is None:
            em = discord.Embed(
                title="Error",
                description="{} is not in the DB".format(role_name),
                color=red)
        else:
            query = "UPDATE `gssp`.`roles` SET `role_name` = %s WHERE (`role_name` = %s AND `guild_id` = %s);"
            cursor.execute(query, (new_name, role_name, ctx.guild.id))
            cnx.commit()
        return await ctx.channel.send(embed=em)
示例#5
0
    async def joinable(self, ctx, *, role_name):
        """
        Toggles whether a role is joinable
        """
        if role_name[0] == '"' and role_name[-1] == '"':
            role_name = role_name[1:-1]
        role = get_role(ctx.guild.id, role_name)
        if role is None:
            em = discord.Embed(
                title="Error",
                description="Could not find role {}".format(role_name),
                color=red)
            return await ctx.channel.send(embed=em)
        if role['is_joinable'] == 1:
            update_query = "UPDATE `gssp`.`roles` SET `is_joinable`='0' WHERE `role_id`=%s;"
            text = "not joinable"
        else:
            update_query = "UPDATE `gssp`.`roles` SET `is_joinable`='1' WHERE `role_id`=%s;"
            text = "joinable"
        cursor.execute(update_query, (role['role_id'], ))
        em = discord.Embed(title="Success",
                           description="Set {} ({} to {}".format(
                               role['role_name'], role['role_id'], text),
                           color=green)
        cnx.commit()

        await ctx.channel.send(embed=em)
 def add_message_to_db(self, message):
     from ags_experiments.client_tools import ClientTools
     self.client_tools = ClientTools(self.client)
     try:
         is_allowed = self.client_tools.channel_allowed(
             message.channel.id, message.channel, message.channel.is_nsfw())
     except AttributeError:
         is_allowed = False  # in PMs, and other channels, NSFW isn't an option
     if is_allowed:
         try:
             while True:
                 result = cursor.fetchone()
                 if result is not None:
                     logger.debug(result + " - < Unread result")
                 else:
                     break
             cursor.execute(add_message_custom, (
                 int(message.id), message.author.id, str(
                     message.channel.id),
                 message.created_at.strftime('%Y-%m-%d %H:%M:%S'),
                 message.content,))
         except mysql.connector.errors.IntegrityError:
             pass
         except mysql.connector.errors.DataError:
             logger.warn(
                 "Couldn't insert {} - likely a time issue".format(message.id))
         cnx.commit()
示例#7
0
def get_roles(guild_id, limit_to_joinable=True):
    cnx.commit()
    if limit_to_joinable:
        query = "SELECT * FROM `gssp`.`roles` WHERE `guild_id` = %s AND `is_joinable` = 1"
    else:
        query = "SELECT * FROM `gssp`.`roles` WHERE `guild_id` = %s"
    query = "{query} ORDER BY role_name".format(query=query)
    cursor.execute(query, (guild_id, ))
    return cursor.fetchall()
 async def optout_user(self, user):
     """
     Opt a user out of experiments, and delete their data
     Returns number of messages deleted
     """
     logger.info("Deleting data for user ID {}".format(user.id))
     cursor.execute("DELETE FROM users WHERE user_id = %s", (user.id, ))
     result = cursor.execute(
         "DELETE FROM messages_detailed WHERE user_id = %s", (user.id, ))
     cnx.commit()
     logger.info("Data deleted.")
 def add_user(self, member):
     try:
         cursor.execute(insert_users, (member.id,))
         cnx.commit()
     except mysql.connector.errors.IntegrityError:
         pass  # we pass because we just want to make sure we add any new users, so we expect some already here
     try:
         cursor.execute(insert_settings, (member.id,))
         cnx.commit()
     except mysql.connector.errors.IntegrityError:
         pass  # see above
示例#10
0
def get_role(guild_id, role_name):
    cnx.commit()
    query = "SELECT * FROM `gssp`.`roles` WHERE `role_name` = %s AND `guild_id` = %s"
    cursor.execute(query, (role_name, guild_id))
    members = []
    try:
        a = cursor.fetchall()[0]
        members += json.loads(a['role_assignees'])
    except IndexError:
        return None
    a['members'] = members
    return a
示例#11
0
    async def output_toggle_public_ping(self, ctx):
        user_settings = get_user(ctx.author.id)

        if user_settings['ping_public'] == 1:
            query = "UPDATE `gssp`.`ping_settings` SET `ping_public`='0' WHERE `user_id`='%s';"
            return_msg = "You will now be pinged over DM"
        else:
            query = "UPDATE `gssp`.`ping_settings` SET `ping_public`='1' WHERE `user_id`='%s';"
            return_msg = "You will now be pinged publicly"

        cursor.execute(query, (ctx.author.id, ))
        cnx.commit()
        await ctx.channel.send(embed=discord.Embed(
            title="Success", description=return_msg, color=green))
示例#12
0
 async def delete(self, ctx, *, role_name):
     """Deletes a role - cannot be undone!"""
     if role_name[0]=='"' and role_name[-1] == '"':
         role_name=role_name[1:-1]
     role_check = get_role(ctx.guild.id, role_name)
     em = discord.Embed(
         title="Success", description="Deleted role {}".format(role_name), color=green)
     if role_check is None:
         em = discord.Embed(
             title="Error", description="{} is not in the DB".format(role_name), color=red)
     else:
         query = "DELETE FROM `gssp`.`roles` WHERE `role_name` = %s AND `guild_id` = %s"
         cursor.execute(query, (role_name, ctx.guild.id))
         cnx.commit()
     return await ctx.channel.send(embed=em)
示例#13
0
 async def add(self, ctx, *, role_name):
     """Add a role. Note: by default, it isn't joinable"""
     if role_name[0]=='"' and role_name[-1] == '"':
         role_name=role_name[1:-1]
     role_check = get_role(ctx.guild.id, role_name)
     em = discord.Embed(
         title="Success", description="Created role {}".format(role_name), color=green)
     if role_check is not None:
         em = discord.Embed(
             title="Error", description="Role is already in the DB", color=red)
     else:
         query = "INSERT INTO `gssp`.`roles` (`role_name`, `guild_id`) VALUES (%s, %s);"
         cursor.execute(query, (role_name, ctx.guild.id))
         cnx.commit()
     return await ctx.channel.send(embed=em)
 def is_automated(self, user):
     """
     Returns true if user is opted in to automation, false if not
     """
     cnx.commit()
     get_user = "******"
     cursor.execute(get_user, (user.id,))
     results = cursor.fetchall()
     cnx.commit()
     try:
         if results[0][0] != 1:
             return False
     except IndexError:
         return False
     return True
    async def save_markov(self, model, user_id):
        """
        Save a model to markov table

        user_id : user's ID we want to save for
        model: Markov model object
        """
        save = "INSERT INTO `markovs` (`user`, `markov_json`) VALUES (%s, %s);"
        save_update = "UPDATE `markovs` SET `markov_json`=%s WHERE `user`=%s;"

        try:
            cursor.execute(save, (user_id, model.to_json()))
        except mysql.connector.errors.IntegrityError:
            cursor.execute(save_update, (model.to_json(), user_id))
        cnx.commit()
        return
示例#16
0
async def main():
    global opted_in_users
    global position
    error_count = 0
    while True:
        try:
            for x in range(position, len(opted_in_users)):
                server, channel = await get_channel()
                position = x
                user = opted_in_users[x]
                messages, channels = await database_tools.get_messages(user.id, config['limit'])
                cnx.commit()
                text_full = ""

                for x in range(0, len(messages)):
                    channel_temp = client.get_channel(int(channels[x]))
                    if channel_temp is not None:
                        if not channel_temp.is_nsfw():
                            text_full = text_full + messages[x] + "\n"
                try:
                    text_model = markovify.NewlineText(
                        text_full, state_size=config['state_size'])
                    em = discord.Embed(
                        title=user.display_name, description=text_model.make_short_sentence(140))
                    em.set_thumbnail(url=user.avatar_url)
                    name = await client_tools.get_delete_emoji()
                    name = name[0]
                    em.set_footer(
                        text=strings['markov']['output']['footer'].format(name))
                    output = await channel.send(embed=em)
                    time.sleep(1)
                    async for message in channel.history(limit=1, reverse=True):
                        message = message
                        break
                    await delete_option(client, message, channel, client.get_emoji(int(strings['emojis']['delete'])) or "❌")
                except KeyError:
                    pass
            opted_in_users = await get_members(server)
            error_count = 0
            position = 0 # this means that, we don't continue from the *end*
        except Exception as e:
            error_count += 1
            print(e)
            if error_count > 3:
                sys.exit(1)
    async def automated(self, ctx):
        """
        Opt in to automated messages. Run this again to opt out.
        """
        if not self.database_tools.opted_in(user_id=ctx.author.id):
            return await ctx.channel.send(embed=discord.Embed(title="Error", description=strings['tagger']['errors']['not_opted_in'], color=colours.red))

        if self.database_tools.is_automated(ctx.author):
            output = await ctx.channel.send("Opting you out of automation.")
            query = "UPDATE `users` SET `automate_opted_in`=b'0' WHERE `user_id`=%s;"
            cursor.execute(query, (ctx.author.id,))
            cnx.commit()
            await output.delete()
            return await ctx.channel.send(embed=discord.Embed(title="Success", description='You will be removed from the pool on the next refresh (IE: when the bot goes back around in a loop again)'))
        else:
            output = await ctx.channel.send("Opting you into automation")
            query = "UPDATE`users` SET `automate_opted_in`=b'1' WHERE `user_id`=%s;"
            cursor.execute(query, (ctx.author.id,))
            cnx.commit()
            await output.delete()
            return await ctx.channel.send(embed=discord.Embed(title="Success", description='Opted in!', color=colours.green))
    async def process_message(self, message):
        await self.check_flags(message)
        user_exp = self.database_tools.opted_in(user_id=message.author.id)

        if user_exp is not False:
            self.database_tools.add_message_to_db(message)
        logger.debug("Message from {}".format(user_exp))
        # this records analytical data - don't adjust this without reading
        # Discord TOS first
        try:
            cursor.execute(add_message,
                           (int(message.id), str(message.channel.id),
                            message.created_at.strftime('%Y-%m-%d %H:%M:%S')))
            cnx.commit()
        except mysql.connector.errors.IntegrityError:
            pass
        try:
            # if its double(or more) prefixed then it cant be a command (?word is a command, ????? is not)
            if message.content[len(config['discord']
                                   ['prefix'])] == config['discord']['prefix']:
                return
        except IndexError:
            return
示例#19
0
def get_user(user_id):
    cnx.commit()  # we run this just to make sure we have nothing pending
    query = "SELECT * FROM gssp.ping_settings WHERE user_id = %s"
    cursor.execute(query, (user_id, ))
    return cursor.fetchone()
示例#20
0
 def save_members(self):
     members_j = json.dumps(self.members)
     cursor_dict.execute(update_query, (members_j, self.role_id))
     cnx.commit()