async def searchMember(cls: "PhaazebotWeb", WebRequest: ExtendedRequest, Data: WebRequestContent) -> Response: search_term: str = Data.getStr("term", "") guild_id: str = Data.getStr("guild_id", "", must_be_digit=True) if not guild_id: return await apiMissingData(cls, WebRequest, msg="invalid or missing 'guild_id'") Guild: discord.Guild = discord.utils.get(cls.BASE.Discord.guilds, id=int(guild_id)) if not Guild: return await apiDiscordGuildUnknown(cls, WebRequest) Member: discord.Member = getDiscordMemberFromString( cls.BASE.Discord, Guild, search_term) if not Member: return await apiDiscordMemberNotFound(cls, WebRequest) data: dict = { "name": str(Member.name), "nick": Member.nick, "id": str(Member.id), "discriminator": Member.discriminator, "avatar": Member.avatar } return cls.response(text=json.dumps(dict(result=data, status=200)), content_type="application/json", status=200)
async def pruneMessages(cls: "PhaazebotDiscord", Command: DiscordCommand, CommandContext: DiscordCommandContext) -> dict: Perm: discord.Permissions = CommandContext.Message.channel.permissions_for( CommandContext.Message.guild.me) if not Perm.manage_messages: return { "content": ":no_entry_sign: Phaaze need the `Manage messages` permissions to execute prune" } search_by: str = " ".join([x for x in CommandContext.parts[1:]]) if not search_by: return { "content": ":warning: Please add a message amount or a member query string" } elif search_by.isdigit() and len(search_by) < 5: # digits that are not a id return await pruneMessagesByAmount(cls, Command, CommandContext, int(search_by)) else: SearchMember = getDiscordMemberFromString( cls, CommandContext.Message.guild, search_by, Message=CommandContext.Message) if not SearchMember: return {"content": ":warning: Could not find a member..."} return await pruneMessagesByMember(cls, Command, CommandContext, SearchMember)
async def loggingOnLevelmedalDelete(cls: "PhaazebotDiscord", Settings: DiscordServerSettings, **kwargs) -> None: """ Logs the event when someone deletes a discordmember medal via web. If track option `Levelmedal.delete` is active, it will send a message to discord Required keywords: ------------------ * `Deleter` - discord.Member * `medal_member_id` - str * `medal_name` - str """ logging_signature: str = "Levelmedal.delete" Deleter: discord.Member = kwargs["Deleter"] medal_member_id: str = kwargs["medal_member_id"] medal_name: str = kwargs["medal_name"] MedalMember: discord.Member = getDiscordMemberFromString( cls, Deleter.guild, medal_member_id) medal_member_name: str = MedalMember.name if MedalMember else "(Unknown)" new_log_id: int = cls.BASE.PhaazeDB.insertQuery( table="discord_log", content={ "guild_id": Settings.server_id, "event_value": TRACK_OPTIONS[logging_signature], "initiator_id": str(Deleter.id), "content": f"{Deleter.name} removed a medal from: {medal_member_name}, old medal: {medal_name}" }) if not (TRACK_OPTIONS[logging_signature] & Settings.track_value): return # track option not active, skip message to discord server TargetChannel: discord.TextChannel = getDiscordChannelFromString( cls, Deleter.guild, Settings.track_channel, required_type="text") if not TargetChannel: return # no channel found Emb: discord.Embed = discord.Embed( title=f"Log Event - [{logging_signature}]", description=f"{Deleter.name} removed a medal", timestamp=datetime.datetime.now(), color=EVENT_COLOR_NEGATIVE, url=makeWebAccessLink(cls, Deleter.guild.id, new_log_id)) Emb.set_thumbnail(url=Deleter.avatar_url or Deleter.default_avatar_url) Emb.add_field(name="Target member:", value=medal_member_name, inline=False) Emb.add_field(name="Medal:", value=medal_name, inline=False) try: await TargetChannel.send(embed=Emb) except Exception as E: cls.BASE.Logger.warning( f"Can't log message: {E} {traceback.format_exc()}")
async def levelStatus(cls:"PhaazebotDiscord", Command:DiscordCommand, CommandContext:DiscordCommandContext) -> dict: # other than, normal, mod or regular commands that get blocked in commands.py # we can not tell if that command is a level command until now, so we end it now # owner disabled level commands serverwide if CommandContext.ServerSettings.owner_disable_level: return {} # same as above just for a a specific channel if CommandContext.Message.channel.id in CommandContext.ServerSettings.disabled_levelchannels: return {} search_from:str = " ".join([x for x in CommandContext.parts[1:]]) # no search use author if not search_from: Member:discord.Member = CommandContext.Message.author # try a search else: Member:Optional[discord.Member] = getDiscordMemberFromString(cls, Guild=CommandContext.Message.guild, search=search_from, Message=CommandContext.Message) if not Member: return {"content": ":warning: Could not find a user with your query"} users:list = await getDiscordServerUsers(cls, guild_id=Command.server_id, member_id=Member.id) if not users: return {"content": f":warning: Seems like there are no statistics for `{Member.name}`\nMaybe the user never typed anything or got deleted."} LevelUser:DiscordUserStats = users.pop(0) exp_current:int = LevelUser.exp lvl_current:int = LevelCalc.getLevel(exp_current) exp_next:int = LevelCalc.getExp(lvl_current+1) rank:str = prettifyNumbers(LevelUser.rank) if LevelUser.rank else "[N/A]" avatar:str = Member.avatar_url if Member.avatar_url else Member.default_avatar_url Emb:discord.Embed = discord.Embed(color=0x00ffdd) Emb.set_author(name=Member.name, icon_url=avatar) Emb.add_field(name="Level:", value=f"{prettifyNumbers(lvl_current)}", inline=True) Emb.add_field(name="Exp:", value=f"{prettifyNumbers(exp_current)} / {prettifyNumbers(exp_next)}", inline=True) Emb.add_field(name="Rank:", value=f"# {rank}", inline=True) if LevelUser.edited: Emb.add_field(name=":warning: EDITED",value="Exp value got edited.", inline=False) if LevelUser.medals: Emb.add_field(name="Medals:",value="\n".join(m for m in LevelUser.medals), inline=False) return {"embed": Emb}
async def whois(cls:"PhaazebotDiscord", Command:DiscordCommand, CommandContext:DiscordCommandContext) -> dict: Member:discord.Member = None search_from:str = " ".join([x for x in CommandContext.parts[1:]]) # no search use author if not search_from: Member = CommandContext.Message.author # try a search else: Member:discord.Member = getDiscordMemberFromString(cls, Guild=CommandContext.Message.guild, search=search_from, Message=CommandContext.Message) if not Member: return {"content": ":warning: Could not find a user with your query"} nickname:str = None status:str = None roles:list = list() # nickname if Member.nick: nickname = f"Nickname: {Member.nick}" # status if str(Member.status) == "online": status = "Online" elif str(Member.status) == "offline": status = "Offline" elif str(Member.status) == "idle": status = "AFK" elif str(Member.status) == "dnd": status = "Do not disturb" else: status = str(Member.status) for Role in sorted(Member.roles, key=lambda role: role.position, reverse=True): if Role.name != "@everyone": roles.append([Role.position, Role.name]) Now:datetime.datetime = datetime.datetime.now() create_date:str = Member.created_at.strftime("%Y-%m-%d (%H:%M)") join_date:str = Member.joined_at.strftime("%Y-%m-%d (%H:%M)") create_days:str = (Now - Member.created_at).days join_days:str = (Now - Member.joined_at).days main_info:str = f"**ID**: {Member.id}\n"\ f"**Discriminator**: {Member.discriminator}\n"\ f"**Acc. created at**: {create_date} *[{create_days} days ago]*\n"\ f"**Joined at**: {join_date} *[{join_days} days ago]*" Emb = discord.Embed ( title=nickname, color=Member.color.value, description=main_info) Emb.set_author(name=f"Name: {Member.name}") Emb.add_field(name=":satellite: Status:",value=status,inline=True) if Member.activity: if type(Member.activity) == discord.activity.Game: Emb.add_field(name=":game_die: Playing:", value=str(Member.activity),inline=True) elif type(Member.activity) == discord.activity.Streaming: Emb.add_field(name=":video_camera: Currently Streaming:",value=str(Member.activity),inline=True) if Member.bot: Emb.add_field(name=":robot: Bot-account:",value="True",inline=True) if len(roles) >= 1: formated_list:str = tabulate.tabulate(roles, tablefmt="plain") Emb.add_field(name=":notepad_spiral: Roles:", value=f"```{formated_list}```", inline=False) else: Emb.add_field(name=":notepad_spiral: Roles:", value="None", inline=False) if Member.avatar_url: Emb.set_image(url=Member.avatar_url) else: Emb.set_image(url=Member.default_avatar_url) return {"embed": Emb}
async def loggingOnLevelEdit(cls: "PhaazebotDiscord", Settings: DiscordServerSettings, **kwargs) -> None: """ Logs the event when someone edits a discordmember-level via web. If track option `Level.edit` is active, it will send a message to discord Required keywords: ------------------ * `Remover` - discord.Member * `changed_member_id` - str * `changes` - dict """ logging_signature: str = "Level.edit" Editor: discord.Member = kwargs["Editor"] changed_member_id: str = kwargs["changed_member_id"] changes: dict = kwargs["changes"] LevelMember: discord.Member = getDiscordMemberFromString( cls, Editor.guild, changed_member_id) level_member_name: str = LevelMember.name if LevelMember else "(Unknown)" new_log_id: int = cls.BASE.PhaazeDB.insertQuery( table="discord_log", content={ "guild_id": Settings.server_id, "event_value": TRACK_OPTIONS[logging_signature], "initiator_id": str(Editor.id), "content": f"{Editor.name} edited the level stats of: {level_member_name} changes: {str(changes)}" }) if not (TRACK_OPTIONS[logging_signature] & Settings.track_value): return # track option not active, skip message to discord server TargetChannel: discord.TextChannel = getDiscordChannelFromString( cls, Editor.guild, Settings.track_channel, required_type="text") if not TargetChannel: return # no channel found Emb: discord.Embed = discord.Embed( title=f"Log Event - [{logging_signature}]", description=f"{Editor.name} edited level stats", timestamp=datetime.datetime.now(), color=EVENT_COLOR_WARNING, url=makeWebAccessLink(cls, Editor.guild.id, new_log_id)) Emb.set_thumbnail(url=Editor.avatar_url or Editor.default_avatar_url) Emb.add_field(name="Edited member:", value=level_member_name, inline=False) if changes.get("edited", False): Emb.add_field( name="Warning:", value="EXP got changed, this member now has a [EDITED] mark", inline=False) try: await TargetChannel.send(embed=Emb) except Exception as E: cls.BASE.Logger.warning( f"Can't log message: {E} {traceback.format_exc()}")
async def apiDiscordRegularsCreate(cls: "PhaazebotWeb", WebRequest: ExtendedRequest) -> Response: """ Default url: /api/discord/regulars/create """ Data: WebRequestContent = WebRequestContent(WebRequest) await Data.load() # get required stuff Create: StorageTransformer = StorageTransformer() Create["guild_id"] = Data.getStr("guild_id", UNDEFINED, must_be_digit=True) Create["member_id"] = Data.getStr("member_id", UNDEFINED, must_be_digit=True) # checks if not Create["guild_id"]: return await cls.Tree.Api.errors.apiMissingData( cls, WebRequest, msg="missing or invalid 'guild_id'") if not Create["member_id"]: return await cls.Tree.Api.errors.apiMissingData( cls, WebRequest, msg="missing or invalid 'member_id'") # get/check discord PhaazeDiscord: "PhaazebotDiscord" = cls.BASE.Discord Guild: discord.Guild = discord.utils.get(PhaazeDiscord.guilds, id=int(Create["guild_id"])) if not Guild: return await cls.Tree.Api.Discord.errors.apiDiscordGuildUnknown( cls, WebRequest) ActionMember: discord.Member = getDiscordMemberFromString( PhaazeDiscord, Guild, Create["member_id"]) if not ActionMember: return await cls.Tree.Api.Discord.errors.apiDiscordMemberNotFound( cls, WebRequest, user_id=Create["member_id"]) # check if already exists and limits res: list = cls.BASE.PhaazeDB.selectQuery( """ SELECT COUNT(*) AS `all`, SUM( CASE WHEN `discord_regular`.`member_id` = %s THEN 1 ELSE 0 END ) AS `match` FROM `discord_regular` WHERE `discord_regular`.`guild_id` = %s""", (str(ActionMember.id), str(ActionMember.guild.id))) if res[0]["match"]: return await cls.Tree.Api.Discord.Regulars.errors.apiDiscordRegularExists( cls, WebRequest) if res[0]["all"] >= cls.BASE.Limit.discord_regular_amount: return await cls.Tree.Api.Discord.Regulars.errors.apiDiscordRegularLimit( cls, WebRequest) # get user info AuthDiscord: AuthDiscordWebUser = await authDiscordWebUser(cls, WebRequest) if not AuthDiscord.found: return await cls.Tree.Api.errors.apiMissingAuthorisation( cls, WebRequest) # get member CheckMember: discord.Member = Guild.get_member( int(AuthDiscord.User.user_id)) if not CheckMember: return await cls.Tree.Api.Discord.errors.apiDiscordMemberNotFound( cls, WebRequest, guild_id=Create["guild_id"], user_id=AuthDiscord.User.user_id) # check permissions if not (CheckMember.guild_permissions.administrator or CheckMember.guild_permissions.manage_guild): return await cls.Tree.Api.Discord.errors.apiDiscordMissingPermission( cls, WebRequest, guild_id=Create["guild_id"], user_id=AuthDiscord.User.user_id) cls.BASE.PhaazeDB.insertQuery(table="discord_regular", content={ "guild_id": str(ActionMember.guild.id), "member_id": str(ActionMember.id) }) # logging GuildSettings: DiscordServerSettings = await getDiscordSeverSettings( PhaazeDiscord, Create["guild_id"], prevent_new=True) log_coro: Coroutine = loggingOnRegularCreate(PhaazeDiscord, GuildSettings, Creator=CheckMember, NewRegular=ActionMember) asyncio.ensure_future(log_coro, loop=cls.BASE.DiscordLoop) cls.BASE.Logger.debug( f"(API/Discord) Regular: {Create['guild_id']=} added new entry {Create['member_id']=}", require="discord:regulars") return cls.response(text=json.dumps( dict(msg="Regulars: Added new entry", entry=ActionMember.name, status=200)), content_type="application/json", status=200)