def get_db(): db = Session() try: yield db finally: db.close()
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)
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)
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)
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 }))
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)
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 }))
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)
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)
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)
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)
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)
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)
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}))
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" )
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.")
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)
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 )
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)
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"¤t_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)
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)
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 )
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}.")
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.")
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)