Exemple #1
0
def get_db():
    db = Session()

    try:
        yield db
    finally:
        db.close()
Exemple #2
0
    async def steam_news_clear(self, ctx):
        """
        Clear channels subscriptions.

        :param ctx: Context
        :return:
        """
        async with session_lock:
            with Session() as session:
                apps = []
                subs = crud_subscription.get_multi_by_channel_id(session, ctx.message.channel.id)
                for s in subs:
                    old_s = crud_subscription.remove(session, uuid=s.uuid)
                    apps.append(old_s.app_id)

                embed = discord.Embed()
                embed.set_author(name=self.__bot.user.name,
                                 url=settings.URL,
                                 icon_url=self.__bot.user.avatar_url)
                embed.title = f"Cleared subscriptions on **{ctx.message.channel}**."
                embed.description = "Removed subscriptions for Steam Apps with IDs:"

                for a in apps:
                    embed.description += f"\n{a}"

                embed.timestamp = datetime.datetime.utcnow()
                await ctx.send(embed=embed)
Exemple #3
0
    async def update(self, ctx, discord_id: int, description: str):
        """
        Update role description

        :param ctx: Context
        :param discord_id: Role Discord ID
        :param description: New description of Role
        :return:
        """
        embed = Embed()
        embed.set_author(name=self.__bot.user.name,
                         url=settings.URL,
                         icon_url=self.__bot.user.avatar_url)
        async with session_lock:
            with Session() as session:
                db_role = role_crud.get_by_discord(session, discord_id)
                if db_role is None:
                    embed.title = "Role not found"
                    embed.colour = Colors.error
                else:
                    role_update = UpdateRole(**{
                        "description": description
                    })

                    db_role = role_crud.update(
                        session, db_obj=db_role, obj_in=role_update
                    )

                    embed.title = f"Role *{db_role.name}* updated."
                    embed.colour = Colors.success

        embed.timestamp = datetime.utcnow()
        await ctx.send(embed=embed)
Exemple #4
0
    async def delete(self, ctx, discord_id: int):
        """
        Delete assignable role

        :param ctx: Context
        :param discord_id: Role Discord ID
        :return:
        """
        embed = Embed()
        embed.set_author(name=self.__bot.user.name,
                         url=settings.URL,
                         icon_url=self.__bot.user.avatar_url)
        async with session_lock:
            with Session() as session:
                db_role = role_crud.get_by_discord(session, discord_id)

                if db_role is None:
                    embed.title = "Role not found"
                    embed.colour = Colors.error
                else:
                    db_emoji = emoji_crud.get_by_role(session, db_role.uuid)

                    if db_emoji is not None:
                        emoji_crud.remove(session, uuid=db_emoji.uuid)

                    db_role = role_crud.remove(session, uuid=db_role.uuid)
                    embed.title = f"Role *{db_role.name}* removed."
                    embed.colour = Colors.success

        embed.timestamp = datetime.utcnow()
        await ctx.send(embed=embed)
Exemple #5
0
 async def on_member_join(self, member):
     async with session_lock:
         with Session() as session:
             db_player = get_create(session,
                                    crud_player,
                                    obj_in=CreatePlayer(
                                        **{
                                            "discord_id": member.id,
                                            "name": member.name,
                                            "hidden": True
                                        }))
             db_server = get_create(session,
                                    crud_server,
                                    obj_in=CreateServer(
                                        **{
                                            "discord_id": member.guild.id,
                                            "name": member.guild.name,
                                            "server_exp": 0,
                                            "channel": None
                                        }))
             get_create(session,
                        crud_member,
                        obj_in=CreateMember(
                            **{
                                "exp": 0,
                                "player_uuid": db_player.uuid,
                                "server_uuid": db_server.uuid,
                                "level_uuid": None
                            }))
Exemple #6
0
    async def list(self, ctx):
        """
        Get all roles for current server

        :param ctx: Context
        :return:
        """
        embed = Embed()
        embed.set_author(name=self.__bot.user.name,
                         url=settings.URL,
                         icon_url=self.__bot.user.avatar_url)
        async with session_lock:
            with Session() as session:

                # Get server data
                server = get_create_ctx(ctx, session, server_crud)

                # Get roles for server
                roles = role_crud.get_multi_by_server_uuid(
                    session, server.uuid
                )

                embed.title = f"Roles for *{ctx.guild.name}*"
                embed.colour = Colors.success

                # List all roles for current server
                for role in roles:
                    embed.add_field(
                        name=role.name, value=role.description, inline=False
                    )

        embed.timestamp = datetime.utcnow()
        await ctx.send(embed=embed)
Exemple #7
0
 async def on_server_join(self, server):
     async with session_lock:
         with Session() as session:
             get_create(session,
                        crud_server,
                        obj_in=CreateServer(
                            **{
                                "discord_id": server.id,
                                "name": server.name,
                                "server_exp": 0,
                                "channel": None
                            }))
Exemple #8
0
    async def generate_levels(self, ctx, up_to=None):
        embed = discord.Embed()
        embed.set_author(name=self.__bot.user.name,
                         url=settings.URL,
                         icon_url=self.__bot.user.avatar_url)

        async with session_lock:
            with Session() as session:
                levels = crud_level.generate_many(session, up_to)

        embed.title = "Levels generated."
        embed.description = f"Levels generated up to {len(levels)}!"
        embed.colour = Colors.other

        embed.timestamp = datetime.datetime.utcnow()
        await ctx.send(embed=embed)
Exemple #9
0
    async def add(self, ctx, name: str):
        """
        Assign role for author
        :param ctx: Context
        :param name: Role name
        :return:
        """
        embed = Embed()
        embed.set_author(name=self.__bot.user.name,
                         url=settings.URL,
                         icon_url=self.__bot.user.avatar_url)
        async with session_lock:
            with Session() as session:
                db_member = get_create_ctx(ctx, session, member_crud)

                found, d_id = add_to_role(
                    session, db_member.uuid, role_name=name
                )

                # If role is not found
                if not found:
                    embed.title = "This role is not assignable!"
                    embed.colour = Colors.error
                    embed.description = "This role doesn't exists or " \
                                        "it is not assignable."
                else:
                    try:
                        role = ctx.guild.get_role(int(d_id))
                        await ctx.author.add_roles(
                            role,
                            reason="Added through role add command."
                        )

                        embed.title = f"*{ctx.author.name}* has been " \
                                      f"added to *{name}*!"
                        embed.colour = Colors.success
                    except Forbidden:
                        embed.title = "I don't have a permission to do that :("
                        embed.colour = Colors.unauthorized
                        embed.description = "Give me a permission to manage" \
                                            " roles or give me a higher role."
                    except HTTPException:
                        embed.title = "Something happened, didn't succeed :/"
                        embed.colour = Colors.error

        embed.timestamp = datetime.utcnow()
        await ctx.send(embed=embed)
Exemple #10
0
    async def weekly_top5(self):
        await self.__bot.wait_until_ready()
        now = datetime.datetime.now()
        next_sat = next_weekday(now, 5).replace(hour=12, minute=0, second=0)

        delta = next_sat - now
        await asyncio.sleep(delta.total_seconds())
        async with session_lock:
            with Session() as session:
                for server in self.__bot.guilds:
                    server_obj = get_create(session,
                                            crud_server,
                                            obj_in=CreateServer(
                                                **{
                                                    "discord_id": server.id,
                                                    "name": server.name,
                                                    "server_exp": 0,
                                                    "channel": None
                                                }))

                    if server_obj.channel is None:
                        continue

                    top_5 = crud_member.get_top(session, server_obj.uuid, 5)

                    embed = discord.Embed()
                    embed.title = f"Weekly TOP 5 on **{server_obj.name}**"
                    embed.description = f"More data can be found " \
                                        f"[here]({settings.URL}/servers/" \
                                        f"{server_obj.uuid})"
                    embed.url = f"{settings.URL}/servers/{server_obj.uuid}/top5"
                    embed.timestamp = datetime.datetime.utcnow()
                    embed.colour = 8161513
                    embed.set_author(name=self.__bot.user.name,
                                     url=settings.URL,
                                     icon_url=self.__bot.user.avatar_url)

                    for member in top_5:
                        embed.add_field(
                            name=f"**{member.player.name}**",
                            value=f"- LVL: **{member.level.value}** "
                            f"- EXP: **{member.exp}**",
                            inline=False)

                    await self.__bot.get_channel(int(server_obj.channel)). \
                        send(embed=embed)
Exemple #11
0
    async def top(self, ctx, value=5):
        """
        Get Top N users with the most experience on this server.
        :param ctx:
        :param value: N
        :return:
        """
        async with ctx.message.channel.typing():
            async with session_lock:
                with Session() as session:

                    server = get_create(session,
                                        crud_server,
                                        obj_in=CreateServer(
                                            **{
                                                "discord_id": ctx.guild.id,
                                                "name": ctx.guild.name,
                                                "server_exp": 0,
                                                "channel": None
                                            }))
                    top_5 = crud_member.get_top(session, server.uuid, value)

                    embed = discord.Embed()
                    embed.title = f"**TOP {value}** on **{server.name}**"
                    embed.description = f"More data can be found [here]" \
                                        f"({settings.URL}/servers/{server.uuid})."
                    embed.url = f"{settings.URL}/servers/{server.uuid}/top5"
                    embed.timestamp = datetime.datetime.utcnow()
                    embed.colour = Colors.other
                    embed.set_author(name=self.__bot.user.name,
                                     url=settings.URL,
                                     icon_url=self.__bot.user.avatar_url)

                    for member in top_5:
                        if member.level is not None:
                            level_value = member.level.value
                        else:
                            level_value = 0

                        embed.add_field(name=f"**{member.player.name}**",
                                        value=f"- LVL: **{level_value}** "
                                        f"- EXP: **{member.exp}**",
                                        inline=False)

            await ctx.send(embed=embed)
Exemple #12
0
    async def steam_news_subscribe(self, ctx, app_id: int):
        """
        Subscribe to Steam News with App ID.

        :param ctx: Context
        :param app_id: ID of a Steam App (can be found in Steam)
        :return:
        """
        async with session_lock:
            with Session() as session:
                sub = crud_subscription.create(session, obj_in=CreateSubscription(**{
                    'channel_id': str(ctx.message.channel.id),
                    'app_id': app_id
                }))
                embed = discord.Embed()
                embed.set_author(name=self.__bot.user.name,
                                 url=settings.URL,
                                 icon_url=self.__bot.user.avatar_url)
                embed.title = f"Channel **{ctx.message.channel}** subscribed to Steam App **{sub.app_id}**!"
                embed.timestamp = datetime.datetime.utcnow()
                await ctx.send(embed=embed)
Exemple #13
0
    async def register(self, ctx):
        """
        Register yourself to be shown on bot.hellshade.fi.
        :param ctx:
        :return:
        """
        async with ctx.message.channel.typing():
            async with session_lock:
                with Session() as session:
                    player = get_create(
                        session,
                        crud_player,
                        obj_in=CreatePlayer(
                            **{
                                "discord_id": ctx.message.author.id,
                                "name": ctx.message.author.name,
                                "hidden": False
                            }))

                    if player.hidden:
                        crud_player.update(session,
                                           db_obj=player,
                                           obj_in={'hidden': False})

                    embed = discord.Embed()
                    embed.set_author(name=self.__bot.user.name,
                                     url=settings.URL,
                                     icon_url=self.__bot.user.avatar_url)

                    embed.title = "Success!"
                    embed.description = f"You have successfully registered " \
                                        f"yourself. You are now shown on " \
                                        f"[{settings.URL}]({settings.URL})"
                    embed.colour = Colors.success

                    await ctx.send(embed=embed)
Exemple #14
0
    async def heartbeat(self):
        await self.__bot.wait_until_ready()
        logger.info("Heartbeat.")

        async with session_lock:
            with Session() as session:
                for guild in self.__bot.guilds:
                    server = get_create(session,
                                        crud_server,
                                        obj_in=CreateServer(
                                            **{
                                                "discord_id": guild.id,
                                                "name": guild.name,
                                                "server_exp": 0,
                                                "channel": None
                                            }))

                    # Update last seen
                    now = datetime.now()

                    crud_server.update(
                        session,
                        db_obj=server,
                        obj_in=UpdateServer(**{"last_seen": now}))
Exemple #15
0
    async def on_raw_reaction_remove(self, payload):
        async with session_lock:
            with Session() as session:

                server = server_crud.get_by_discord(session, payload.guild_id)
                if server and str(payload.message_id) == server.role_message:
                    db_player = player_crud.get_by_discord(
                        session, payload.user_id
                    )

                    # Stop if player not registered
                    if db_player is None:
                        logger.error(
                            f"Player not found for {payload.user_id}."
                        )
                        return

                    db_member = member_crud.get_by_ids(
                        session, db_player.uuid, server.uuid
                    )

                    # Stop if member not registered
                    if db_member is None:
                        logger.error(
                            f"Member not found for {payload.user_id}."
                        )
                        return

                    e = payload.emoji.name
                    emoji = emoji_crud.get_by_identifier(session, e)

                    if not emoji:
                        logger.error(
                            f"Emoji requested with {e} not "
                            f"found on {server.name}."
                        )
                        return

                    found, d_id = remove_from_role(
                        session, db_member.uuid, role_uuid=emoji.role_uuid
                    )

                    # Stop if wasn't found
                    if not found:
                        logger.error(
                            f"Role not found for emoji {emoji.identifier} "
                            f"on {server.name}."
                        )
                        return

                    try:
                        guild = self.__bot.get_guild(payload.guild_id)
                        role = guild.get_role(int(d_id))
                        await guild.get_member(payload.user_id).remove_roles(
                            role,
                            reason="Removed through role reaction."
                        )
                    except Forbidden:
                        logger.error(
                            "Forbidden: Not enough permissions to manage roles."
                        )
                    except HTTPException:
                        logger.error(
                            "HTTPException: Something went wrong while changing roles"
                        )
Exemple #16
0
    async def online_experience(self):
        await self.__bot.wait_until_ready()
        async with session_lock:
            with Session() as session:
                leveled_up = {}
                for member in filter(gets_exp, self.__bot.get_all_members()):
                    player_obj = get_create(session,
                                            crud_player,
                                            obj_in=CreatePlayer(
                                                **{
                                                    "discord_id": member.id,
                                                    "name": member.name,
                                                    "hidden": True
                                                }))

                    server_obj = get_create(
                        session,
                        crud_server,
                        obj_in=CreateServer(
                            **{
                                "discord_id": member.guild.id,
                                "name": member.guild.name,
                                "server_exp": 0,
                                "channel": None
                            }))

                    member_obj = get_create(
                        session,
                        crud_member,
                        obj_in=CreateMember(
                            **{
                                "exp": 0,
                                "player_uuid": player_obj.uuid,
                                "server_uuid": server_obj.uuid,
                                "level_uuid": None
                            }))

                    base_exp = 5
                    special_multi = 1

                    now = datetime.datetime.utcnow()

                    # Weekend double voice experience
                    # Between Friday 15:00 -> Sunday 23:59 (UTC)
                    if now.weekday() > 4 or \
                            (now.weekday() == 4 and now.hour > 15):
                        special_multi = 2

                    exp = math.ceil(
                        special_multi *
                        (len(member.voice.channel.members) / 4 * base_exp))

                    if member_obj.level is not None:
                        next_level = crud_level.get_by_value(
                            session, member_obj.level.value + 1)
                    else:
                        next_level = crud_level.get_by_value(session, 1)

                    if next_level is None and member_obj.level is not None:
                        member_dict = {
                            "exp": level_exp(member_obj.level.value + 1),
                            "value": member_obj.level.value + 1
                        }

                        next_level = crud_level.create(
                            CreateMember(**member_dict))

                    if member_obj.exp + exp < next_level.exp:
                        crud_member.update(
                            session,
                            db_obj=member_obj,
                            obj_in={"exp": member_obj.exp + exp})
                    else:
                        member_obj = crud_member.update(
                            session,
                            db_obj=member_obj,
                            obj_in={
                                "exp": member_obj.exp + exp - next_level.exp,
                                "level_uuid": next_level.uuid
                            })
                        if server_obj.channel is not None:
                            if server_obj.channel in leveled_up:
                                leveled_up[server_obj.channel]. \
                                    append(member_obj)
                            else:
                                leveled_up[server_obj.channel] \
                                    = [member_obj]
                    crud_server.update(session,
                                       db_obj=server_obj,
                                       obj_in={
                                           "name":
                                           member.guild.name,
                                           "server_exp":
                                           server_obj.server_exp + exp
                                       })

                for channel in leveled_up:
                    embed = discord.Embed()
                    embed.set_author(name=self.__bot.user.name,
                                     url=settings.URL,
                                     icon_url=self.__bot.user.avatar_url)
                    if len(leveled_up) > 1:
                        embed.title = f"{len(leveled_up)} players leveled up!"
                        embed.description = f"{len(leveled_up)} players " \
                                            f"leveled up by being active on " \
                                            f"a voice channel."
                    else:
                        embed.title = f"1 player leveled up!"
                        embed.description = f"1 player leveled up by being " \
                                            f"active on a voice channel."

                    embed.colour = 9442302
                    for member in leveled_up[channel]:
                        embed.add_field(name=member.player.name,
                                        value=f"Leveled up to "
                                        f"**Level {member.level.value}**",
                                        inline=False)

                    await self.__bot.get_channel(int(channel)).send(embed=embed
                                                                    )

                logger.info("Experience calculated.")
Exemple #17
0
    async def load_dump(self, ctx, filename=None):
        embed = discord.Embed()
        embed.set_author(name=self.__bot.user.name,
                         url=settings.URL,
                         icon_url=self.__bot.user.avatar_url)

        updated = []
        if filename is None:
            filename = "/members.dump.json"
        try:
            with open(filename, "r") as dump_file:
                data = json.load(dump_file)
        except OSError:
            embed.colour = Colors.unauthorized
            embed.title = "File not found!"
            embed.description = "Be sure that you inserted the right " \
                                "filename and you have copied the file " \
                                "into the container!"
            embed.timestamp = datetime.datetime.utcnow()
            await ctx.send(embed=embed)
            return

        for member in data:
            async with session_lock:
                with Session() as session:
                    player_discord_id = member["player"]["discord_id"]
                    server_discord_id = member["server"]["discord_id"]
                    exp = int(member["exp"])
                    player = self.__bot.get_user(player_discord_id)
                    server = self.__bot.get_guild(server_discord_id)

                    db_player = crud_player.get_by_discord(
                        session, player_discord_id)

                    if db_player is None:
                        if player is None and "name" in member["player"]:
                            name = member["player"]["name"]
                        elif player is None and "name" not in member["player"]:
                            name = "UNKNOWN"
                        else:
                            name = player.name
                        db_player = crud_player.create(
                            session,
                            obj_in=CreatePlayer(
                                **{
                                    "discord_id":
                                    player_discord_id,
                                    "name":
                                    name,
                                    "hidden":
                                    "hidden" in member["player"]
                                    and member["player"]["hidden"] == 1
                                }))
                    else:
                        hidden = "hidden" in member["player"] and \
                                 member["player"]["hidden"] == 1
                        if hidden != db_player.hidden:
                            db_player = crud_player.update(
                                session,
                                db_obj=db_player,
                                obj_in={"hidden": hidden})

                    db_server = crud_server.get_by_discord(
                        session, server_discord_id)
                    if db_server is None:
                        if server is None and "name" in member["server"]:
                            name = member["server"]["name"]
                        elif server is None and "name" not in member["server"]:
                            name = "UNKNOWN"
                        else:
                            name = server.name

                        db_server = crud_server.create(
                            session,
                            obj_in=CreateServer(
                                **{
                                    "discord_id": server_discord_id,
                                    "name": name,
                                    "server_exp": 0,
                                    "channel": member["server"].get("channel")
                                }))
                    else:
                        if db_server.channel != member["server"]. \
                                get("channel"):
                            db_server = crud_server.update(
                                session,
                                db_obj=db_server,
                                obj_in={
                                    "channel": member["server"].get("channel")
                                })

                    db_member = crud_member.get_by_ids(session, db_player.uuid,
                                                       db_server.uuid)

                    if "level_id" in member:
                        logger.debug(member["level_id"])
                    if "level_id" in member and member["level_id"] != "NULL":
                        current_level = int(member["level_id"])
                    else:
                        current_level = 0

                    current_level, exp = process_exp(current_level, exp)
                    if current_level > 0:
                        db_level = get_create(
                            session,
                            crud_level,
                            obj_in=CreateLevel(
                                **{
                                    "value": current_level,
                                    "exp": level_exp(current_level),
                                    "title": None
                                }))
                        level_uuid = db_level.uuid
                    else:
                        level_uuid = None

                    if db_member is None:
                        db_member = crud_member.create(
                            session,
                            obj_in=CreateMember(
                                **{
                                    "exp": exp,
                                    "player_uuid": db_player.uuid,
                                    "server_uuid": db_server.uuid,
                                    "level_uuid": level_uuid
                                }))
                    else:
                        db_member = crud_member.update(session,
                                                       db_obj=db_member,
                                                       obj_in={
                                                           "level_uuid":
                                                           level_uuid,
                                                           "exp": exp
                                                       })

                    updated.append(db_member)
        embed.colour = Colors.other
        embed.title = "Members loaded from dump file."
        embed.description = f"Members updated: {len(updated)}"
        embed.timestamp = datetime.datetime.utcnow()
        await ctx.send(embed=embed)
Exemple #18
0
    async def init(self, ctx):
        """
        Initialize role message for current channel

        :param ctx: Context
        :return:
        """
        async with session_lock:
            with Session() as session:
                db_server = get_create_ctx(ctx, session, server_crud)

                embed = Embed()
                embed.title = f"Assignable roles for **{ctx.guild.name}**"
                embed.description = "Use reactions inorder to get " \
                                    "roles assigned to you, or use " \
                                    "`!role add roleName`"

                converter = commands.EmojiConverter()
                pconverter = commands.PartialEmojiConverter()

                # Get all roles on the server
                roles = role_crud.get_multi_by_server_uuid(
                    session, get_create_ctx(ctx, session, server_crud).uuid
                )

                # Gather all used emojis for future reactions
                emojis = []

                for r in roles:

                    emoji = emoji_crud.get_by_role(
                        session, r.uuid
                    )

                    if emoji is not None:

                        try:
                            # Convert into actual emoji
                            e = await converter.convert(
                                ctx, emoji.identifier
                            )
                        except commands.EmojiNotFound:
                            # Try partial emoji instead
                            try:
                                e = await pconverter.convert(
                                    ctx, emoji.identifier
                                )
                            except commands.PartialEmojiConversionFailure:
                                # Assume that it is an unicode emoji
                                e = emoji.identifier

                        # Add to message
                        embed.add_field(
                            name=f"{str(e)}  ==  {r.name}",
                            value=r.description,
                            inline=False
                        )

                        emojis.append(e)

                # Send message
                role_message = await ctx.send(embed=embed)

                # Add reaction to message with all used emojis
                for e in emojis:
                    await role_message.add_reaction(e)

                # Update server object to include role message data
                server_update = UpdateServer(**{
                    "role_message": str(role_message.id),
                    "role_channel": str(ctx.channel.id)
                })

                server_crud.update(
                    session, db_obj=db_server, obj_in=server_update
                )
Exemple #19
0
    async def levels_channel(self, ctx, channel_id=None):
        embed = discord.Embed()
        embed.set_author(name=self.__bot.user.name,
                         url=settings.URL,
                         icon_url=self.__bot.user.avatar_url)

        async with session_lock:
            with Session() as session:
                if channel_id is not None and \
                        self.__bot.get_channel(
                            int(channel_id)) is not None:

                    server = get_create(session,
                                        crud_server,
                                        obj_in=CreateServer(
                                            **{
                                                "discord_id": ctx.guild.id,
                                                "name": ctx.guild.name,
                                                "server_exp": 0,
                                                "channel": channel_id
                                            }))
                    if server.channel != channel_id:
                        crud_server.update(session,
                                           db_obj=server,
                                           obj_in={"channel": channel_id})
                    embed.title = "Success"
                    embed.colour = Colors.success
                    embed.description = "Channel successfully registered."
                elif channel_id is not None and \
                        self.__bot.get_channel(int(channel_id)) is None:
                    embed.colour = Colors.error
                    embed.title = "Error"
                    embed.description = "Channel not found."
                else:
                    server = get_create(session,
                                        crud_server,
                                        obj_in=CreateServer(
                                            **{
                                                "discord_id": ctx.guild.id,
                                                "name": ctx.guild.name,
                                                "server_exp": 0,
                                                "channel": None
                                            }))

                    embed.title = f"Levels channel for **{server.name}**"
                    if server.channel is not None:
                        embed.colour = Colors.other
                        channel = self.__bot.get_channel(int(server.channel))
                        embed.add_field(name="Levels channel:",
                                        value=channel.name)
                        embed.add_field(name="Creation date:",
                                        value=channel.created_at)
                    else:
                        embed.colour = Colors.unauthorized
                        embed.add_field(name="Levels channel:",
                                        value="No channel for levels.")
                        embed.add_field(
                            name="Setup",
                            value="Create a new text channel and run this "
                            "command with the channel_id as an argument.")

        embed.timestamp = datetime.datetime.utcnow()
        await ctx.send(embed=embed)
Exemple #20
0
    async def rank(self, ctx):
        """
        Get your current experience status on this server.
        :param ctx:
        :return:
        """
        async with ctx.message.channel.typing():
            message = ""
            if ctx.message.guild is None:
                message = "Please use this command on a server."
                embed = None
            else:
                async with session_lock:
                    with Session() as session:

                        db_server = get_create(
                            session,
                            crud_server,
                            obj_in=CreateServer(
                                **{
                                    "discord_id": ctx.guild.id,
                                    "name": ctx.guild.name,
                                    "server_exp": 0,
                                    "channel": None
                                }))

                        db_player = get_create(
                            session,
                            crud_player,
                            obj_in=CreatePlayer(
                                **{
                                    "discord_id": ctx.message.author.id,
                                    "name": ctx.message.author.name,
                                    "hidden": True
                                }))

                        member = get_create(
                            session,
                            crud_member,
                            obj_in=CreateMember(
                                **{
                                    "exp": 0,
                                    "player_uuid": db_player.uuid,
                                    "server_uuid": db_server.uuid,
                                    "level_uuid": None
                                }))

                        if member.level is not None:
                            next_level = get_create(
                                session,
                                crud_level,
                                obj_in=CreateLevel(
                                    **{
                                        "value": member.level.value + 1,
                                        "exp": level_exp(member.level.value +
                                                         1)
                                    }))
                        else:
                            next_level = get_create(
                                session,
                                crud_level,
                                obj_in=CreateLevel(**{
                                    "value": 1,
                                    "exp": level_exp(1)
                                }))

                        embed = discord.Embed()
                        embed.title = f"**{member.player.name}** on " \
                                      f"**{member.server.name}**"
                        embed.description = f"More data can be found [here]" \
                                            f"({settings.URL}/players/" \
                                            f"{member.player.uuid})."
                        embed.url = f"{settings.URL}/players/" \
                                    f"{member.player.uuid}/server/" \
                                    f"{member.server.uuid}"
                        embed.timestamp = datetime.datetime.utcnow()
                        embed.colour = Colors.success
                        embed.set_author(name=self.__bot.user.name,
                                         url=settings.URL,
                                         icon_url=self.__bot.user.avatar_url)
                        # embed.add_field(
                        #     name=f"**Level {next_level.value - 1}**",
                        #     value=f"Experience: **{member.exp}/{next_level.exp}**",
                        #     inline=False)

                        # embed.add_field(
                        #     name=f"Progress: "
                        #          f"**{member.exp / next_level.exp * 100:.2f}%**",
                        #     value=f"`{progress_bar(member.exp, next_level.exp)}`")

                        embed.set_image(url=f"{settings.URL}/api/level-image"
                                        f"?name={ctx.author.name}"
                                        f"&level={next_level.value - 1}"
                                        f"&current_exp={member.exp}"
                                        f"&needed_exp={next_level.exp}")

            if message != "" and embed is None:
                await ctx.send(message)
            else:
                await ctx.send(embed=embed)
Exemple #21
0
    async def create(
            self, ctx, discord_id: int, description: str, emoji: str = None
    ):
        """
        Create assignable role

        :param ctx: Context
        :param discord_id: Role Discord ID
        :param description: Description of role usage
        :param emoji: Emoji for assignment via reactions
        :return:
        """
        embed = Embed()
        embed.set_author(name=self.__bot.user.name,
                         url=settings.URL,
                         icon_url=self.__bot.user.avatar_url)
        async with session_lock:
            with Session() as session:
                d_role = ctx.guild.get_role(discord_id)
                db_role = role_crud.get_by_discord(session, discord_id)

                # TODO Add emoji parsing

                if d_role is None:
                    embed.title = "Role not found."
                    embed.colour = Colors.error
                elif db_role is not None:
                    embed.title = "Role already exists!"
                    embed.colour = Colors.other
                else:
                    role = CreateRole(**{
                        "discord_id": discord_id,
                        "name": d_role.name,
                        "description": description,
                        "server_uuid": get_create_ctx(
                            ctx, session, server_crud
                        ).uuid
                    })

                    db_role = role_crud.create(session, obj_in=role)

                    if emoji is not None:
                        converter = commands.EmojiConverter()
                        pconverter = commands.PartialEmojiConverter()

                        try:
                            # Convert into actual emoji
                            e = await converter.convert(
                                ctx, emoji
                            )
                        except commands.EmojiNotFound:
                            # Try partial emoji instead
                            try:
                                e = await pconverter.convert(
                                    ctx, emoji
                                )
                            except commands.PartialEmojiConversionFailure:
                                # Assume that it is an unicode emoji
                                e = emoji
                    else:
                        e = None

                    if e is not None and not isinstance(e, discord.partial_emoji.PartialEmoji):

                        if hasattr(e, 'name'):
                            e = e.name

                        db_e = CreateRoleEmoji(**{
                            "identifier": e,
                            "role_uuid": db_role.uuid
                        })
                        emoji_crud.create(session, obj_in=db_e)
                    elif isinstance(emoji, discord.partial_emoji.PartialEmoji):
                        embed.description = "**Note**: Role was created" \
                                            " without an emoji, because the bot " \
                                            "cannot use provided emoji..."
                    else:
                        embed.description = "**Note**: Role was created" \
                                            " without an emoji, so it " \
                                            "cannot be assigned with " \
                                            "reactions!"

                    embed.title = f"Role *{db_role.name}* created."
                    embed.colour = Colors.success
        embed.timestamp = datetime.utcnow()
        await ctx.send(embed=embed)
Exemple #22
0
    async def on_message(self, message):
        if message.author.id != self.__bot.user.id and not message.author.bot:
            async with session_lock:
                with Session() as session:
                    db_server = get_create(
                        session,
                        crud_server,
                        obj_in=CreateServer(
                            **{
                                "discord_id": message.guild.id,
                                "name": message.guild.name,
                                "server_exp": 0,
                                "channel": None
                            }))
                    db_player = get_create(
                        session,
                        crud_player,
                        obj_in=CreatePlayer(
                            **{
                                "discord_id": message.author.id,
                                "name": message.author.name,
                                "hidden": True
                            }))

                    db_member = get_create(
                        session,
                        crud_member,
                        obj_in=CreateMember(
                            **{
                                "exp": 0,
                                "player_uuid": db_player.uuid,
                                "server_uuid": db_server.uuid,
                                "level_uuid": None
                            }))

                    if db_member.level is not None:
                        level_value = db_member.level.value + 1
                    else:
                        level_value = 1

                    next_level = get_create(
                        session,
                        crud_level,
                        obj_in=CreateLevel(**{
                            "value": level_value,
                            "exp": level_exp(level_value)
                        }))

                    if db_member.exp + 25 < next_level.exp:
                        crud_member.update(session,
                                           db_obj=db_member,
                                           obj_in={"exp": db_member.exp + 25})
                    else:
                        db_member = crud_member.update(
                            session,
                            db_obj=db_member,
                            obj_in={
                                "exp": (db_member.exp + 25 - next_level.exp),
                                "level_uuid": next_level.uuid
                            })
                        if db_member.server.channel is not None:
                            embed = discord.Embed()
                            embed.set_author(
                                name=self.__bot.user.name,
                                url=settings.URL,
                                icon_url=self.__bot.user.avatar_url)
                            embed.title = f"**{db_member.player.name}** " \
                                          f"leveled up!"
                            embed.description = f"**{db_member.player.name}" \
                                                f"** leveled up to level " \
                                                f"**{db_member.level.value}" \
                                                f"** by sending messages!"
                            embed.colour = 9942302

                            await self.__bot.get_channel(
                                int(db_member.server.channel)).send(embed=embed
                                                                    )
Exemple #23
0
    async def role_update(self):
        """
        Update roles stored every 30 minutes
        :return:
        """
        await self.__bot.wait_until_ready()
        logger.info("Updating role messages...")

        async with session_lock:
            with Session() as session:

                # Go through all visible guilds
                for guild in self.__bot.guilds:

                    server = server_crud.get_by_discord(session, guild.id)

                    # Skip if server is not found
                    if server is None:
                        continue

                    # Get all roles for server
                    roles = role_crud.get_multi_by_server_uuid(
                        session, server.uuid
                    )

                    temp_roles = {}

                    for r in roles:
                        temp_roles[r.discord_id] = r

                    # Go through all roles of a guild
                    for r in guild.roles:

                        # Skip roles that are default or premium
                        if r.is_default or r.is_premium_subscriber:
                            continue

                        # Check that role is registered, otherwise skip
                        if r.id not in temp_roles:
                            continue

                        # If the name is the same, then skip
                        if r.name == temp_roles[r.id].name:
                            continue

                        role_update = UpdateRole(**{
                            "name": r.name
                        })

                        # Update role
                        role_crud.update(
                            session, temp_roles[r.id], role_update
                        )

                    # Update role message if it exists
                    if server.role_message is not None and \
                            server.role_channel is not None:
                        channel = self.__bot.get_channel(
                            int(server.role_channel)
                        )

                        # Continue if channel wasn't found
                        if channel is None:
                            logger.info(f"No channel found for {server.name}.")
                            continue

                        # Channel must not be bloated with messages
                        message = utils.find(
                            lambda m: (m.id == int(server.role_message)),
                            await channel.history(limit=10).flatten()
                        )

                        # Continue if message wasn't found
                        if message is None:
                            logger.info(f"No message found for {server.name}.")
                            continue

                        # Get context
                        ctx = await self.__bot.get_context(message)

                        embed = Embed()
                        embed.title = f"Assignable roles for " \
                                      f"**{message.guild.name}**"
                        embed.description = "Use reactions inorder to get " \
                                            "roles assigned to you, or use " \
                                            "`!role add roleName`"

                        converter = commands.EmojiConverter()
                        pconverter = commands.PartialEmojiConverter()

                        # Get all roles of a server
                        roles = role_crud.get_multi_by_server_uuid(
                            session, server.uuid
                        )

                        # Gather all used emojis for future reactions
                        emojis = []

                        for ro in roles:

                            emoji = emoji_crud.get_by_role(session, ro.uuid)

                            try:
                                # Convert into actual emoji
                                e = await converter.convert(
                                    ctx, emoji.identifier
                                )
                            except commands.EmojiNotFound:
                                # Try partial emoji instead
                                try:
                                    e = await pconverter.convert(
                                        ctx, emoji.identifier
                                    )
                                except commands.PartialEmojiConversionFailure:
                                    # Assume that it is an unicode emoji
                                    e = emoji.identifier

                            # Add to message
                            embed.add_field(
                                name=f"{str(e)}  ==  {ro.name}",
                                value=ro.description,
                                inline=False
                            )

                            emojis.append(e)

                        await message.edit(embed=embed)

                        # Check old reactions
                        old_emojis = []
                        for r in message.reactions:
                            old_emojis.append(r.emoji)

                        # Add new reactions to message
                        for e in emojis:
                            if isinstance(e, discord.partial_emoji.PartialEmoji):
                                logger.error(f"Emoji not cannot be used! Emoji: {e}")
                            elif e not in old_emojis:
                                await message.add_reaction(e)

                        logger.info(f"Message updated for {server.name}.")
Exemple #24
0
    async def get_steam_news(self):
        await self.__bot.wait_until_ready()
        logger.info("Fetching Steam news...")
        async with session_lock:
            with Session() as session:
                subs = crud_subscription.get_multi(session)
                all_new_posts = []
                async with ClientSession() as client:
                    for s in subs:
                        logger.info(
                            f"Fetching news: {s.channel_id=} {s.app_id=}"
                        )
                        async with client.get(f"https://api.steampowered.com/ISteamNews/GetNewsForApp/v0002/?appid={s.app_id}&count=100&maxlength=1500&format=json") as r:
                            if r.status >= 400:
                                logger.warning(
                                    f"Could not find news for app {s.app_id}!"
                                )
                                continue

                            data = await r.json()

                            if 'appnews' not in data or 'newsitems' not in data['appnews']:
                                logger.warning(
                                    f"Could not find news for app {s.app_id}!"
                                )
                                continue

                            new_posts = []

                            for p in data['appnews']['newsitems']:
                                if p['feed_type'] != 1:
                                    continue

                                db_post = crud_post.get_by_gid(session, p['gid'])

                                if db_post is not None:
                                    continue

                                new_posts.append(p)

                            for p in new_posts:
                                all_new_posts.append(p)

                                embed = discord.Embed()

                                embed.set_author(
                                    name=f"Steam News - {p['author']}",
                                    icon_url="https://logos-world.net/wp-content/uploads/2020/10/Steam-Logo.png"
                                )
                                embed.title = p['title']
                                embed.url = p['url']
                                desc = re.sub(r"\{\S*\}\/\S*", "\n", p['contents'])
                                embed.description = desc

                                channel = self.__bot.get_channel(
                                    int(s.channel_id)
                                )

                                await channel.send(embed=embed)
                                await asyncio.sleep(0.5)

                # Add all new posts to database so they wont be sent again
                for p in all_new_posts:
                    old_p = crud_post.get_by_gid(session, p['gid'])

                    # Skip if already added
                    if old_p is not None:
                        continue

                    crud_post.create(session, obj_in=CreatePost(**{
                        'steam_gid': p['gid'],
                        'title': p['title'],
                        'content': p['contents']
                    }))

        logger.info("Done fetching Steam news.")
Exemple #25
0
class BaseRepository(ABC):
    """Class representing the abstract base repository."""

    _session = Session()
    _model = None

    @classmethod
    async def paginate(cls, expressions=None, options={}):
        """Retrieve all data by expressions paginated."""

        response = {
            'data':
            await cls._prepare(expressions=expressions,
                               options=options,
                               paginate=True),
            'meta': {
                'current_page': cls._page,
                'per_page': cls._limit,
                'total': cls._count,
            },
            'links': {
                'first':
                await cls._get_url(1),
                'last':
                await cls._get_url(cls._page_count),
                'prev': (await cls._get_url(cls._page - 1)
                         if await cls._validate_page(cls._page - 1) else None),
                'next': (await cls._get_url(cls._page + 1)
                         if await cls._validate_page(cls._page + 1) else None),
            },
        }

        return response

    @classmethod
    async def get(cls, expressions=None, options={}):
        """Retrieve all data by expressions."""
        return await cls._prepare(expressions=expressions, options=options)

    @classmethod
    async def find(cls, pk):
        """Retrieve one data by pk."""
        data = cls._session.query(cls.get_model()).get(pk)
        cls._session.commit()
        return data

    @classmethod
    async def count(cls, expressions=None):
        """Count the number of registers by expressions."""
        query = cls._session.query(cls.get_model())

        if expressions is not None:
            query = query.filter(expressions)

        cls._session.commit()

        return query.count()

    @classmethod
    async def update(cls, pk_or_model, payload={}):
        """Update a register by pk or model."""
        data = pk_or_model if isinstance(
            pk_or_model, cls.get_model()) else await cls.find(pk_or_model)

        for column, value in payload.items():
            if hasattr(data, column):
                setattr(data, column, value)

        cls._session.commit()

        return data

    @classmethod
    async def create(cls, payload):
        """Save a new register."""
        data = await cls.__populate(**payload)

        cls._session.add(data)
        cls._session.commit()

        return data

    @classmethod
    async def delete(cls, pk_or_model):
        """Delete a register by pk or model."""
        data = pk_or_model if isinstance(
            pk_or_model, cls.get_model()) else await cls.find(pk_or_model)

        cls._session.delete(data)
        cls._session.commit()

        print('data_delete', data)

        return data

    @classmethod
    def get_model(cls):
        """Get the model."""
        if cls._model is None:
            raise ValueError('Model is required, set _model')
        return cls._model

    @classmethod
    async def _prepare(cls, expressions=None, options={}, paginate=False):
        cls._page = await cls._get_page(options)
        cls._limit = await cls._get_limit(options)
        cls._count = await cls.count(expressions)
        cls._page_count = int(math.ceil(cls._count / cls._limit))

        query = cls._session.query(cls.get_model()).limit(cls._limit)

        if paginate:
            query = query.offset(cls._limit * (cls._page - 1))

        if expressions is not None:
            query = query.filter(expressions)

        return query.all()

    @classmethod
    async def __populate(cls, **kwargs):
        """Get the model."""
        if cls._model is None:
            raise ValueError('Model is required, set _model')
        return cls._model(**kwargs)

    @classmethod
    async def _get_page(cls, options={}):
        """Get current page."""
        request = context.get('request')

        page = options.get('page') if 'page' in options else int(
            request.args.get('page', 1))
        return page if page > 0 else 1

    @classmethod
    async def _get_limit(cls, options={}):
        """Get retrieve limit of registers."""
        request = context.get('request')

        limit = options.get('limit') if 'limit' in options else int(
            request.args.get('limit',
                             cls.get_model().get_default_limit()))
        return limit if limit <= cls.get_model().get_max_limit(
        ) else cls.get_model().get_max_limit()

    @classmethod
    async def _validate_page(cls, page):
        if cls._count > 0:
            if page > cls._page_count or page < 1:
                return None
            return page
        return False

    @classmethod
    async def _get_url(cls, page):
        """"Get current URL with page query string."""
        request = context.get('request')
        url_parts = list(urllib.parse.urlparse(request.url))
        query = dict(urllib.parse.parse_qsl(url_parts[4]))
        query.update({'page': page})
        url_parts[4] = urllib.parse.urlencode(query)

        return urllib.parse.urlunparse(url_parts)