Ejemplo n.º 1
0
    async def on_member_join(self, member: discord.Member):
        """ Called when a member joins a guild (server) the bot is in."""
        log.info("{0.display_name} (ID: {0.id}) joined {0.guild.name}".format(
            member))
        # Updating member list
        if member.id in self.members:
            self.members[member.id].append(member.guild.id)
        else:
            self.members[member.id] = [member.guild.id]

        # No welcome message for lite servers and servers not tracking worlds
        if member.guild.id in config.lite_servers or tracked_worlds.get(
                member.guild.id) is None:
            return

        server_welcome = get_server_property("welcome", member.guild.id, "")
        pm = (config.welcome_pm + "\n" + server_welcome).format(
            user=member,
            server=member.guild,
            bot=self.user,
            owner=member.guild.owner)

        embed = discord.Embed(description="{0.mention} joined.".format(member))
        icon_url = get_user_avatar(member)
        embed.colour = discord.Colour.green()
        embed.set_author(name="{0.name}#{0.discriminator}".format(member),
                         icon_url=icon_url)
        embed.timestamp = dt.datetime.utcnow()

        # Check if user already has characters registered and announce them on log_channel
        # This could be because he rejoined the server or is in another server tracking the same worlds
        world = tracked_worlds.get(member.guild.id)
        if world is not None:
            c = userDatabase.cursor()
            try:
                c.execute(
                    "SELECT name, vocation, ABS(level) as level, guild "
                    "FROM chars WHERE user_id = ? and world = ?", (
                        member.id,
                        world,
                    ))
                results = c.fetchall()
                if len(results) > 0:
                    pm += "\nYou already have these characters in {0} registered to you: {1}"\
                        .format(world, join_list([r["name"] for r in results], ", ", " and "))
                    characters = [
                        "\u2023 {name} - Level {level} {voc} - **{guild}**".
                        format(**c, voc=get_voc_abb_and_emoji(c["vocation"]))
                        for c in results
                    ]
                    embed.add_field(name="Registered characters",
                                    value="\n".join(characters))
            finally:
                c.close()

        await self.send_log_message(member.guild, embed=embed)
        await member.send(pm)
Ejemplo n.º 2
0
    def check(self, ctx):
        """Check which users are currently not registered."""
        if not ctx.message.channel.is_private:
            return True

        author = ctx.message.author
        if author.id in mod_ids + owner_ids:
            author_servers = get_user_servers(self.bot, author.id)
        else:
            author_servers = get_user_admin_servers(self.bot, author.id)

        embed = discord.Embed(description="Members with unregistered users.")

        yield from self.bot.send_typing(ctx.message.channel)
        c = userDatabase.cursor()
        try:
            for server in author_servers:
                world = tracked_worlds.get(server.id, None)
                if world is None:
                    continue
                c.execute(
                    "SELECT user_id FROM chars WHERE world LIKE ? GROUP BY user_id",
                    (world, ))
                result = c.fetchall()
                if len(result) <= 0:
                    embed.add_field(
                        name=server.name,
                        value="There are no registered characters.",
                        inline=False)
                    continue
                users = [str(i["user_id"]) for i in result]
                empty_members = list()
                for member in server.members:
                    if member.id == self.bot.user.id:
                        continue
                    if member.id not in users:
                        empty_members.append("**@" + member.display_name +
                                             "**")
                if len(empty_members) == 0:
                    embed.add_field(name=server.name,
                                    value="There are no unregistered users.",
                                    inline=False)
                    continue
                field_value = "\n{0}".format("\n".join(empty_members))
                split_value = split_message(field_value, FIELD_VALUE_LIMIT)
                for empty_member in split_value:
                    if empty_member == split_value[0]:
                        name = server.name
                    else:
                        name = "\u200F"
                    embed.add_field(name=name,
                                    value=empty_member,
                                    inline=False)
            yield from self.bot.say(embed=embed)
        finally:
            c.close()
Ejemplo n.º 3
0
    def remove_char(self, ctx, *, name):
        """Removes a registered character.

        The syntax is:
        /stalk removechar name"""
        if not ctx.message.channel.is_private:
            return True
        # This could be used to remove deleted chars so we don't need to check anything
        # Except if the char exists in the database...
        yield from self.bot.send_typing(ctx.message.channel)
        c = userDatabase.cursor()
        try:
            c.execute(
                "SELECT name, user_id, world, ABS(last_level) as level, vocation "
                "FROM chars WHERE name LIKE ?", (name, ))
            result = c.fetchone()
            if result is None:
                yield from self.bot.say(
                    "There's no character with that name registered.")
                return
            user = get_member(self.bot, result["user_id"])
            username = "******" if user is None else user.display_name
            c.execute("DELETE FROM chars WHERE name LIKE ?", (name, ))
            yield from self.bot.say(
                "**{0}** was removed successfully from **@{1}**.".format(
                    result["name"], username))
            if user is not None:
                for server in get_user_servers(self.bot, user.id):
                    world = tracked_worlds.get(server.id, None)
                    if world != result["world"]:
                        continue
                    log_msg = "{0.mention} removed **{1}** ({2} {3}) from {4.mention}.".\
                        format(ctx.message.author, result["name"], result["level"], result["vocation"], user)
                    yield from send_log_message(self.bot, server, log_msg)

            return
        finally:
            c.close()
            userDatabase.commit()
Ejemplo n.º 4
0
Archivo: mod.py Proyecto: Sinsae/NabBot
    async def unregistered(self, ctx):
        """Check which users are currently not registered."""

        world = tracked_worlds.get(ctx.guild.id, None)
        entries = []
        if world is None:
            await ctx.send("This server is not tracking any worlds.")
            return

        with closing(userDatabase.cursor()) as c:
            c.execute(
                "SELECT user_id FROM chars WHERE world LIKE ? GROUP BY user_id",
                (world, ))
            result = c.fetchall()
            if len(result) <= 0:
                await ctx.send("There are no registered characters.")
                return
            users = [i["user_id"] for i in result]
        for member in ctx.guild.members:  # type: discord.Member
            if member.id == ctx.me.id:
                continue
            if member.id not in users:
                entries.append(
                    f"@**{member.display_name}** \u2014 Joined on: **{member.joined_at.date()}**"
                )
        if len(entries) == 0:
            await ctx.send("There are no unregistered users.")
            return

        pages = Paginator(self.bot,
                          message=ctx.message,
                          entries=entries,
                          title="Unregistered members",
                          per_page=10)
        try:
            await pages.paginate()
        except CannotPaginate as e:
            await ctx.send(e)
Ejemplo n.º 5
0
    def add_account(self, ctx, *, params):
        """Register a character and all other visible characters to a discord user.

        If a character is hidden, only that character will be added. Characters in other worlds are skipped.

        The syntax is the following:
        /stalk addacc user,char"""
        if not ctx.message.channel.is_private:
            return True
        params = params.split(",")
        if len(params) != 2:
            yield from self.bot.say(
                "The correct syntax is: ``/stalk addacc username,character``")
            return

        author = ctx.message.author
        if author.id in mod_ids + owner_ids:
            author_servers = get_user_servers(self.bot, author.id)
        else:
            author_servers = get_user_admin_servers(self.bot, author.id)
        author_worlds = get_user_worlds(self.bot, author.id)

        user = get_member_by_name(self.bot,
                                  params[0],
                                  server_list=author_servers)
        user_servers = get_user_servers(self.bot, user.id)
        user_worlds = get_user_worlds(self.bot, user.id)

        common_worlds = list(set(author_worlds) & set(user_worlds))
        yield from self.bot.send_typing(ctx.message.channel)
        character = yield from get_character(params[1])
        if user is None:
            yield from self.bot.say(
                "I don't see any user named **{0}** in the servers you manage."
                .format(params[0]))
            return
        if type(character) is not dict:
            if character == ERROR_NETWORK:
                yield from self.bot.say(
                    "I couldn't fetch the character, please try again.")
            elif character == ERROR_DOESNTEXIST:
                yield from self.bot.say("That character doesn't exists.")
            return
        c = userDatabase.cursor()
        try:
            chars = character['chars']
            # If the char is hidden,we still add the searched character
            if len(chars) == 0:
                yield from self.bot.say("Character is hidden.")
                chars = [character]
            skipped = list()
            added = list()
            added_tuples = list()
            reassigned_tuples = list()
            existent = list()
            error = list()
            for char in chars:
                # Character not in followed server(s), skip.
                if char['world'] not in common_worlds:
                    skipped.append([char["name"], char["world"]])
                    continue
                name = char["name"]
                # If char is the same we already looked up, no need to look him up again
                if character["name"] == char["name"]:
                    char = character
                else:
                    char = yield from get_character(char["name"])
                if type(char) is not dict:
                    error.append(name)
                    continue
                # Skip characters scheduled for deletion
                if char.get("deleted", False):
                    skipped.append([char["name"], char["world"]])
                    continue
                c.execute(
                    "SELECT id, name,user_id FROM chars WHERE name LIKE ?",
                    (char['name'], ))
                result = c.fetchone()
                # Char is already in database
                if result is not None:
                    # Registered to different user
                    if str(result["user_id"]) != user.id:
                        current_user = get_member(self.bot, result["user_id"])
                        # Char is registered to user no longer in server
                        if current_user is None:
                            added.append(char)
                            reassigned_tuples.append((
                                user.id,
                                result["id"],
                            ))
                            continue
                        else:
                            yield from self.bot.say(
                                "{0} is already assigned to {1}. We can't add any other of these "
                                "characters.".format(
                                    char["name"], current_user.display_name))
                            return
                    # Registered to current user
                    existent.append(char)
                    continue
                added.append(char)
                added_tuples.append((
                    char["name"],
                    char["level"] * -1,
                    char["vocation"],
                    user.id,
                    char["world"],
                ))
            c.execute("SELECT id from users WHERE id = ?", (user.id, ))
            result = c.fetchone()
            if result is None:
                c.execute("INSERT INTO users(id,name) VALUES (?,?)", (
                    user.id,
                    user.display_name,
                ))

            c.executemany(
                "INSERT INTO chars(name,last_level,vocation,user_id, world) VALUES (?,?,?,?,?)",
                added_tuples)
            c.executemany("UPDATE chars SET user_id = ? WHERE id = ?",
                          reassigned_tuples)
            reply = ""
            log_reply = dict().fromkeys([server.id for server in user_servers],
                                        "")
            if added:
                reply += "\nThe following characters were registered or reassigned successfully:"
                for char in added:
                    char["guild"] = char.get("guild", "No guild")
                    reply += "\n\t**{name}** ({level} {vocation}) - **{guild}**".format(
                        **char)
                    # Announce on server log of each server
                    for server in user_servers:
                        # Only announce on worlds where the character's world is tracked
                        if tracked_worlds.get(server.id,
                                              None) == char["world"]:
                            log_reply[
                                server.
                                id] += "\n\t{name} - {level} {vocation} - **{guild}**".format(
                                    **char)
            if existent:
                reply += "\nThe following characters were already registered to this user:"******"guild"] = char.get("guild", "No guild")
                    reply += "\n\t**{name}** ({level} {vocation}) - **{guild}**".format(
                        **char)
            if skipped:
                reply += "\nThe following characters were skipped (not in tracked worlds or scheduled deletion):"
                for char, world in skipped:
                    reply += "\n\t{0} ({1})".format(char, world)
            if error:
                reply += "\nThe following characters couldn't be fetched: "
                reply += ", ".join(error)
            yield from self.bot.say(reply)
            for server_id, message in log_reply.items():
                if message:
                    message = "{0.mention} registered the following characters to {1.mention}: {2}".format(
                        author, user, message)
                    yield from send_log_message(self.bot,
                                                self.bot.get_server(server_id),
                                                message)
            return
        finally:
            c.close()
            userDatabase.commit()
Ejemplo n.º 6
0
    def add_char(self, ctx, *, params):
        """Registers a tibia character to a discord user.

        The syntax is:
        /stalk addchar user,character"""
        if not ctx.message.channel.is_private:
            return True
        params = params.split(",")
        if len(params) != 2:
            yield from self.bot.say(
                "The correct syntax is: ``/stalk addchar username,character``")
            return

        author = ctx.message.author
        if author.id in mod_ids + owner_ids:
            author_servers = get_user_servers(self.bot, author.id)
        else:
            author_servers = get_user_admin_servers(self.bot, author.id)
        author_worlds = get_user_worlds(self.bot, author.id)

        # Only search in the servers the command author is
        user = get_member_by_name(self.bot,
                                  params[0],
                                  server_list=author_servers)
        user_servers = get_user_servers(self.bot, user.id)
        user_worlds = get_user_worlds(self.bot, author.id)

        common_worlds = list(set(author_worlds) & set(user_worlds))

        yield from self.bot.send_typing(ctx.message.channel)
        char = yield from get_character(params[1])

        if user is None:
            yield from self.bot.say(
                "I don't see any user named **{0}** in the servers you manage."
                .format(params[0]))
            return
        if type(char) is not dict:
            if char == ERROR_NETWORK:
                yield from self.bot.say(
                    "I couldn't fetch the character, please try again.")
            elif char == ERROR_DOESNTEXIST:
                yield from self.bot.say("That character doesn't exists.")
            return
        if char["world"] not in common_worlds:
            yield from self.bot.say(
                "**{name}** ({world}) is not in a world you can manage.".
                format(**char))
            return
        if char.get("deleted", False):
            yield from self.bot.say(
                "**{name}** ({world}) is scheduled for deletion and can't be added."
                .format(**char))
            return
        c = userDatabase.cursor()
        try:
            c.execute("SELECT id, name, user_id FROM chars WHERE name LIKE ?",
                      (char['name'], ))
            result = c.fetchone()
            # Char is already in database
            if result is not None:
                # Update name if it was changed
                if char['name'] != params[1]:
                    c.execute("UPDATE chars SET name = ? WHERE id = ?", (
                        char['name'],
                        result["id"],
                    ))
                    yield from self.bot.say(
                        "This character's name was changed from **{0}** to **{1}**"
                        .format(params[1], char['name']))
                # Registered to a different user
                if result["user_id"] != user.id:
                    current_user = get_member(self.bot, result["user_id"])
                    # User no longer in server
                    if current_user is None:
                        c.execute("UPDATE chars SET user_id = ? WHERE id = ?",
                                  (
                                      user.id,
                                      result["id"],
                                  ))
                        yield from self.bot.say(
                            "This character was registered to a user no longer in server. "
                            "It was assigned to this user successfully.")
                        # Log on relevant servers
                        for server in user_servers:
                            world = tracked_worlds.get(server.id, None)
                            if world == char["world"]:
                                log_msg = "{0.mention} registered **{1}** ({2} {3}) to {4.mention}."
                                yield from send_log_message(
                                    self.bot, server,
                                    log_msg.format(author, char["name"],
                                                   char["level"],
                                                   char["vocation"], user))
                    else:
                        yield from self.bot.say(
                            "This character is already registered to **@{0}**".
                            format(current_user.display_name))
                    return
                # Registered to current user
                yield from self.bot.say(
                    "This character is already registered to this user.")
                return
            c.execute(
                "INSERT INTO chars (name,last_level,vocation,user_id, world) VALUES (?,?,?,?,?)",
                (char["name"], char["level"] * -1, char["vocation"], user.id,
                 char["world"]))
            # Check if user is already registered
            c.execute("SELECT id from users WHERE id = ?", (user.id, ))
            result = c.fetchone()
            if result is None:
                c.execute("INSERT INTO users(id,name) VALUES (?,?)", (
                    user.id,
                    user.display_name,
                ))
            yield from self.bot.say(
                "**{0}** was registered successfully to this user.".format(
                    char['name']))
            # Log on relevant servers
            for server in user_servers:
                world = tracked_worlds.get(server.id, None)
                if world == char["world"]:
                    char["guild"] = char.get("guild", "No guild")
                    log_msg = "{0.mention} registered **{1}** ({2} {3}, {4}) to {5.mention}."
                    yield from send_log_message(
                        self.bot, server,
                        log_msg.format(author, char["name"], char["level"],
                                       char["vocation"], char["guild"], user))
            return
        finally:
            c.close()
            userDatabase.commit()