async def on_member_remove(self, member: discord.Member): if chan := member.guild.get_channel_or_thread( self.bot.config.getattr(member.guild.id, "join_leave_chan_id")): role_names = ", ".join( tuple(r.name for r in member.roles if not r.is_default())) if not role_names: role_names = "None" leave_embed = discord.Embed( color=discord.Color.red(), description=f"{member} left", timestamp=discord.utils.utcnow(), ) leave_embed.add_field( name="User Information", value=f"{member} ({member.id}) {member.mention}", inline=False, ) leave_embed.add_field(name="Roles", value=role_names, inline=False) if member.joined_at: leave_embed.add_field( name="Joined At", value= (f"{discord.utils.format_dt(member.joined_at, style='F')} ({discord.utils.format_dt(member.joined_at, 'R')})" ), inline=False, ) leave_embed.add_field( name="Created At", value= (f"{discord.utils.format_dt(member.created_at, style='F')} ({discord.utils.format_dt(member.created_at, 'R')})" ), inline=False, ) leave_embed.add_field(name="ID", value=f"```ini\nUser = {member.id}\n```", inline=False) leave_embed.set_author( name=str(member), icon_url=utils.get_icon_url(member._user.display_avatar), ) leave_embed.set_footer( text=str(self.bot.user), icon_url=utils.get_icon_url(member.guild.me.display_avatar), ) await chan.send(embed=leave_embed)
def embed_gen(self, ctx, description): selection_embed = discord.Embed(colour=discord.Colour(0x4378FC), description="\n".join(description)) selection_embed.set_author( name=f"{ctx.guild.me.name}", icon_url=utils.get_icon_url(ctx.guild.me.display_avatar), ) return selection_embed
async def run(self, ctx: utils.SeraContextBase): def check(m: discord.Message): return m.author == ctx.author and m.channel == ctx.channel wizard_embed = discord.Embed(title=self.embed_title, colour=self.color) wizard_embed.set_author( name=f"{ctx.bot.user.name}", icon_url=utils.get_icon_url(ctx.guild.me.display_avatar), ) wizard_embed.set_footer( text= "If you wish to stop this setup at any time, just type in 'exit'.") for question in self.questions: wizard_embed.description = question.question if not self.ori_mes: self.ori_mes = await ctx.reply(embed=wizard_embed) else: await self.ori_mes.edit(embed=wizard_embed) try: reply: discord.Message = await ctx.bot.wait_for( "message", check=check, timeout=self.timeout) except asyncio.TimeoutError: wizard_embed.description = "Failed to reply. Exiting..." wizard_embed.set_footer(text=None) await self.ori_mes.edit(embed=wizard_embed) return else: if reply.content.lower() == "exit": wizard_embed.description = "Exiting..." wizard_embed.set_footer(text=None) await self.ori_mes.edit(embed=wizard_embed) return try: converted = await discord.utils.maybe_coroutine( question.converter, ctx, reply.content) except Exception as e: # base exceptions really shouldn't be caught wizard_embed.description = ( f"Invalid input. Exiting...\n\nError: {str(e)}") wizard_embed.set_footer(text=None) await self.ori_mes.edit(embed=wizard_embed) return if not self.pass_self: await discord.utils.maybe_coroutine(question.action, ctx, converted) else: await discord.utils.maybe_coroutine(question.action, ctx, converted, self) wizard_embed.description = self.final_text wizard_embed.set_footer(text=None) await self.ori_mes.edit(embed=wizard_embed)
async def about(self, ctx): """Gives information about the bot.""" msg_list = ( collections.deque() ) # is this pointless? yeah, mostly (there's a slight performance boost), but why not msg_list.append("Hi! I'm Seraphim, Astrea's personal bot!") msg_list.append( "I was created initially as a starboard bot as other starboard bots had" " poor uptime, " + "but I've since been expanded to other functions, too." ) msg_list.append( "I tend to have features that are either done poorly by other bots, or" " features of bots " + "that tend to be offline/unresponsive for a decent amount of time." ) msg_list.append( "If you want to invite me, you're in luck. The link is:" " https://discord.com/api/oauth2/authorize?client_id=700857077672706120&permissions=8&scope=bot%20applications.commands" ) msg_list.append( "If you need support for me, maybe take a look at the support server" " here:\nhttps://discord.gg/NSdetwGjpK" ) about_embed = discord.Embed( title="About", colour=discord.Colour(0x4378FC), description="\n\n".join(msg_list), ) about_embed.set_author( name=f"{self.bot.user.name}", icon_url=utils.get_icon_url(ctx.guild.me.display_avatar), ) source_list = collections.deque() source_list.append( "My source code is [here!](https://github.com/Astrea49/Seraphim-Bot)" ) source_list.append( "This code might not be the best code out there, but you may have some use" " for it." ) about_embed.add_field( name="Source Code", value="\n".join(source_list), inline=False ) await ctx.reply(embed=about_embed)
async def pos( self, ctx: commands.Context, *, user: typing.Optional[fuzzys.FuzzyMemberConverter], ): """Allows you to get either your or whoever you mentioned’s position in the star leaderboard (like the top command, but only for one person). The user can be mentioned, searched up by ID, or you can say their name and the bot will attempt to search for that person.""" await ctx.trigger_typing() member = ctx.author if not user else user user_star_list = await self.get_star_rankings(f"guild_id = {ctx.guild.id}") if user_star_list: if user: placing = ( f"{member.display_name}'s" f" {self.get_user_placing(user_star_list, member.id)}" ) else: placing = f"Your {self.get_user_placing(user_star_list, member.id)}" place_embed = discord.Embed( colour=discord.Colour(0xCFCA76), description=placing, timestamp=discord.utils.utcnow(), ) place_embed.set_author( name=f"{self.bot.user.name}", icon_url=utils.get_icon_url(ctx.guild.me.display_avatar), ) place_embed.set_footer(text="Sent") await ctx.reply(embed=place_embed) else: raise utils.CustomCheckFailure( "There are no starboard entries for this server!" )
async def avatar( self, ctx: commands.Context, user: typing.Union[fuzzys.FuzzyMemberConverter, discord.User, None], *, flags: AvatarFlags, ): """Gets the avatar of the user. As Seraphim (or, well, me) is kept constatly up to date, this means you can get guild-specific \ avatars with this command. Defaults to getting the avatar of the user who ran the command if no user is provided. Due to limitations, if you wish to provide an input for the user you wish to get an icon of and \ it has spaces, you will need to wrap it with quotes. Optional flags: guild: <true/false> - whether to get the guild-specific avatar of a user or not. Defaults to getting \ the guild specific avatar. animated: <true/false> - whether to get the animated version or not, if it exists. Defaults to getting \ the animated version. size: <power of two between 16 and 4096> - the size of the image. Defaults to 4096 (or whatever the max \ size of the avatar is). """ if not user: user = ctx.author avatar_asset = user.display_avatar if flags.guild else user.avatar if not flags.animated: avatar_url = str(avatar_asset.replace(format="png", size=flags.size)) else: avatar_url = utils.get_icon_url(avatar_asset, size=flags.size) await ctx.reply( f"{user.mention}'s avatar: {avatar_url}", allowed_mentions=utils.deny_mentions(ctx.author), )
async def base_generate(bot: utils.SeraphimBase, mes: discord.Message, no_attachments: bool = False): # sourcery no-metrics # generates core of star messages image_url = "" if (mes.embeds and mes.author.id == bot.user.id and mes.embeds[0].author.name != bot.user.name and mes.embeds[0].fields and mes.embeds[0].footer.text and mes.embeds[0].footer.text.startswith("ID:") ): # all of this... for pinboard support send_embed = mes.embeds[0].copy( ) # it's using the same internal gen, so why not just copy it for x in range(len(send_embed.fields)): if send_embed.fields[x].name == "Original": send_embed.remove_field(x) break # next pieces of code make the embed more how a normally generated embed would be like send_embed.color = discord.Colour(0xCFCA76) send_embed.timestamp = mes.created_at send_embed.set_footer() # will set footer to default, aka none elif (mes.embeds != [] and mes.embeds[0].type == "rich" and mes.embeds[0].author.name != bot.user.name and isinstance(mes.embeds[0].author.icon_url, str) and "&userid=" in mes.embeds[0].author.icon_url ): # if message is sniped message that's supported snipe_embed = mes.embeds[0] entry = await bot.starboard.get(mes.id) if entry: author = await utils.user_from_id(bot, mes.guild, entry.author_id) else: author_id = star_utils.get_author_id(mes, bot) author = await utils.user_from_id(bot, mes.guild, author_id) author_str = "" if author is None or author.id == bot.user.id: author_str = mes.embeds[0].author.name else: author_str = f"{author.display_name} ({author})" icon = (snipe_embed.author.icon_url if author is None or author.id == bot.user.id else utils.get_icon_url(author.display_avatar)) content = snipe_embed.description send_embed = discord.Embed( title="Sniped:", colour=discord.Colour(0xCFCA76), description=content, timestamp=mes.created_at, ) send_embed.set_author(name=author_str, icon_url=icon) elif (mes.author.bot and mes.embeds != [] and mes.embeds[0].description and mes.embeds[0].type == "rich" and (mes.embeds[0].footer.url != "https://abs.twimg.com/icons/apple-touch-icon-192x192.png" and mes.embeds[0].footer.text != "Twitter")): author = f"{mes.author.display_name} ({mes.author})" icon = utils.get_icon_url(mes.author.display_avatar) send_embed = discord.Embed( colour=discord.Colour(0xCFCA76), description=mes.embeds[0].description, timestamp=mes.created_at, ) send_embed.set_author(name=author, icon_url=icon) else: content = utils.get_content(mes) author = f"{mes.author.display_name} ({mes.author})" icon = utils.get_icon_url(mes.author.display_avatar) if content: send_embed = discord.Embed( colour=discord.Colour(0xCFCA76), description=content, timestamp=mes.created_at, ) else: send_embed = discord.Embed( colour=discord.Colour(0xCFCA76), description=None, timestamp=mes.created_at, ) send_embed.set_author(name=author, icon_url=icon) if mes.type == discord.MessageType.reply: # checks if message has inline reply ref_mes_url = mes.reference.jump_url # type: ignore reply_msg = await utils.resolve_reply(bot, mes) ref_author = reply_msg.author if reply_msg else None ref_auth_str = ref_author.display_name if ref_author else "a message" send_embed.title = f"Replying to {ref_auth_str}:" send_embed.url = ref_mes_url if (mes.embeds != [] and mes.embeds[0].type == "image" and mes.embeds[0].thumbnail.url): image_url = mes.embeds[0].thumbnail.url if not no_attachments and mes.attachments: send_embed = cant_display(send_embed, mes.attachments, 0) elif not no_attachments and mes.attachments != []: if (mes.attachments[0].proxy_url.lower().endswith( bot.image_extensions) and not mes.attachments[0].is_spoiler()): image_url = mes.attachments[0].proxy_url if len(mes.attachments) > 1: send_embed = cant_display(send_embed, mes.attachments, 1) else: send_embed = cant_display(send_embed, mes.attachments, 0) else: if not mes.flags.suppress_embeds: # would suppress images too # http://urlregex.com/ urls = re.findall( r"http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+", content, ) if urls != []: first_url = urls[0] possible_url = await image_utils.get_image_url(first_url) if possible_url != None: image_url = possible_url # if the image url is still blank and the message has a gifv embed if (image_url == "" and mes.embeds != [] and mes.embeds[0].type == "gifv") and (mes.embeds[0].thumbnail.url ): # if there is a thumbnail url image_url = mes.embeds[0].thumbnail.url # if the image url is STILL blank and there's a youtube video if (image_url == "" and mes.embeds and mes.embeds[0].type == "video" and mes.embeds[0].provider and mes.embeds[0].provider.name and mes.embeds[0].provider.name == "YouTube"): image_url = mes.embeds[0].thumbnail.url send_embed.add_field( name="YouTube:", value=( f"{mes.embeds[0].author.name}:" f" [{mes.embeds[0].title}]({mes.embeds[0].url})"), inline=False, ) # if the image url is STILL blank and the message has a sticker if image_url == "" and mes.stickers: if mes.stickers[0].format != discord.StickerFormatType.lottie: image_url = str(mes.stickers[0].url) else: # as of right now, you cannot send content with a sticker, so we might as well send_embed.description = ( "*This message has a sticker that I cannot display. Please view" " the original message to see it.*") if not no_attachments and mes.attachments: send_embed = cant_display(send_embed, mes.attachments, 0) if image_url != "": send_embed.set_image(url=image_url) if utils.embed_check(send_embed): return send_embed else: # unlikely to happen, but who knows raise ValueError(f"Embed was too big to process for {mes.jump_url}!")
async def top(self, ctx: commands.Context, *, flags: TopFlags): """Allows you to view the top 10 people with the most stars on a server. Cooldown of once every 5 seconds per user. Flags: --role <role>: allows you to filter by the role specified, only counting those who have that role. --bots <true/false>: if bot messages will be on the leaderboard.""" await ctx.trigger_typing() optional_role = flags.role if optional_role: role_members = frozenset(str(r.id) for r in optional_role.members) user_star_list = await self.get_star_rankings( f"guild_id = {ctx.guild.id} AND author_id IN ({','.join(role_members)})" ) else: user_star_list = await self.get_star_rankings(f"guild_id = {ctx.guild.id}") if not user_star_list: raise utils.CustomCheckFailure( "There are no starboard entries for this server/role!" ) top_embed = discord.Embed( title=f"Star Leaderboard for {ctx.guild.name}", colour=discord.Colour(0xCFCA76), timestamp=discord.utils.utcnow(), ) top_embed.set_author( name=f"{self.bot.user.name}", icon_url=utils.get_icon_url(ctx.guild.me.display_avatar), ) actual_entry_count = 0 filtered_star_list = [] for entry in user_star_list: if actual_entry_count > 9 and flags.bots: break member = await utils.user_from_id(self.bot, ctx.guild, entry.author_id) if flags.bots or not member or not member.bot: filtered_star_list.append(entry) if actual_entry_count < 10: num_stars = entry.stars author_str = ( f"{member.display_name} ({member})" if member != None else f"User ID: {entry.author_id}" ) top_embed.add_field( name=f"#{actual_entry_count+1}: {author_str}", value=f"{num_stars} ⭐\n", inline=False, ) actual_entry_count += 1 if not top_embed.fields: raise utils.CustomCheckFailure( "There are no non-bot starboard entries for this server!" ) elif not flags.bots or optional_role: top_embed.set_footer( text=( "Your filtered" f" {self.get_user_placing(filtered_star_list, ctx.author.id)}" ) ) else: top_embed.set_footer( text=f"Your {self.get_user_placing(filtered_star_list, ctx.author.id)}" ) await ctx.reply(embed=top_embed)
async def msgtop(self, ctx: utils.SeraContextBase, *, flags: MsgTopFlags): """Allows you to view the top 10 starred messages on a server. Cooldown of once every 5 seconds per user. Optional flags: user: <user> - allows you to view the top starred messages by the user specified. role: <role> - allows you to view the top starred messages by users who have the role specified. bots: <true/false> - if bot messages will be on the leaderboard.""" if flags.role: role_members = frozenset(str(r.id) for r in flags.role.members) if flags.user and flags.user.bot and not flags.bots: raise commands.BadArgument( "You can't just specify a user who is a bot and then filter out bots." ) if flags.user and flags.role and str(flags.user.id) not in role_members: raise commands.BadArgument( "You can't just specify both a user and a role and have that user not" " have that role." ) await ctx.trigger_typing() conditions = "" if flags.user: conditions = f"guild_id = {ctx.guild.id} AND author_id = {flags.user.id}" elif flags.role: conditions = ( f"guild_id = {ctx.guild.id} AND author_id IN ({','.join(role_members)})" ) else: conditions = f"guild_id = {ctx.guild.id}" guild_entries = await self.bot.starboard.select_query( f"{conditions} AND star_var_id IS NOT NULL AND NOT (ori_reactors = '{{}}'" " AND var_reactors = '{}') ORDER BY cardinality(ori_reactors ||" " var_reactors) DESC" ) if not guild_entries: raise utils.CustomCheckFailure( "There are no starboard entries for this server, role, and/or for this" " user!" ) if flags.user: top_embed = discord.Embed( title=( f"Top starred messages in {ctx.guild.name} by" f" {flags.user.display_name} ({flags.user})" ), colour=discord.Colour(0xCFCA76), timestamp=discord.utils.utcnow(), ) else: top_embed = discord.Embed( title=f"Top starred messages in {ctx.guild.name}", colour=discord.Colour(0xCFCA76), timestamp=discord.utils.utcnow(), ) top_embed.set_author( name=f"{self.bot.user.name}", icon_url=utils.get_icon_url(ctx.guild.me.display_avatar), ) top_embed.set_footer(text="As of") actual_entry_count = 0 for entry in guild_entries: if actual_entry_count > 9: break starboard_id = entry.starboard_id url = f"https://discordapp.com/channels/{ctx.guild.id}/{starboard_id}/{entry.star_var_id}" num_stars = entry.num_reactors if flags.role: member = ( ctx.guild.get_member(entry.author_id) if not flags.user else flags.user ) else: member = ( await utils.user_from_id(self.bot, ctx.guild, entry.author_id) if not flags.user else flags.user ) if flags.bots or (not member or not member.bot): author_str = ( f"{member.display_name} ({member})" if member else f"User ID: {entry.author_id}" ) top_embed.add_field( name=f"#{actual_entry_count+1}: {num_stars} ⭐ from {author_str}", value=f"[Message]({url})\n", inline=False, ) actual_entry_count += 1 if not top_embed.fields: raise utils.CustomCheckFailure( "There are no non-bot starboard entries for this server/role!" ) await ctx.reply(embed=top_embed)