async def on_ready(**kargs: Any) -> None: inc_statistics_better(0, "on-ready", kargs["kernel_ramfs"]) Client: discord.Client = kargs["client"] print(f'{Client.user} has connected to Discord!') # Warn if user is not bot if not Client.user.bot: print( "WARNING: The connected account is not a bot, as it is against ToS we do not condone user botting" ) # bot start time check to not reparse timers on network disconnect if kargs["bot_start"] > (time.time() - 10): with db_hlapi(None) as db: mutes: List[Tuple[str, str, str, int]] = db.fetch_all_mutes() lost_mutes = sorted(mutes, key=lambda a: a[3]) ts = datetime_now().timestamp() lost_mute_timers = [i for i in lost_mutes if 0 != i[3]] if lost_mute_timers: print(f"Lost mutes: {len(lost_mute_timers)}") for i in lost_mute_timers: if i[3] < ts: await attempt_unmute(Client, i) lost_mute_timers = [i for i in lost_mute_timers if i[3] >= ts] if lost_mute_timers: print( f"Mute timers to recover: {len(lost_mute_timers)}\nThis process will end in {round(lost_mutes[-1][3]-time.time())} seconds" ) for i in lost_mute_timers: await asyncio.sleep(i[3] - datetime_now().timestamp()) with db_hlapi(int(i[0])) as db: if db.is_muted(infractionid=i[1]): await attempt_unmute(Client, i) print("Mutes recovered")
async def log_infraction( message: discord.Message, client: discord.Client, user: InterfacedUser, moderator: InterfacedUser, i_reason: str, i_type: str, to_dm: bool, ramfs: lexdpyk.ram_filesystem ) -> Tuple[str, Optional[Awaitable[None]]]: if not message.guild: raise GuildScopeError("How did we even get here") timestamp = datetime_now() # Infraction timestamp # Define db outputs scoped correctly generated_id: str log_channel: Optional[discord.TextChannel] with db_hlapi(message.guild.id) as db: # Infraction id collision test while db.grab_infraction(generated_id := generate_infractionid()):
async def on_message_edit(old_message: discord.Message, message: discord.Message, **kargs: Any) -> None: client: discord.Client = kargs["client"] ramfs: lexdpyk.ram_filesystem = kargs["ramfs"] kernel_ramfs: lexdpyk.ram_filesystem = kargs["kernel_ramfs"] # Ignore bots if parse_skip_message(client, message): return elif not message.guild: return inc_statistics_better(message.guild.id, "on-message-edit", kernel_ramfs) # Add to log with db_hlapi(message.guild.id) as db: message_log_str = db.grab_config("message-edit-log") or db.grab_config("message-log") # Skip logging if message is the same or mlog doesnt exist if message_log_str and not (old_message.content == message.content): if message_log := client.get_channel(int(message_log_str)): if not isinstance(message_log, discord.TextChannel): return lim: int = constants.embed.field.value message_embed = discord.Embed(title=f"Message edited in #{message.channel}", color=load_embed_color(message.guild, embed_colors.edit, ramfs)) message_embed.set_author(name=f"{message.author} ({message.author.id})", icon_url=user_avatar_url(message.author)) old_msg = (old_message.content or "NULL") message_embed.add_field(name="Old Message", value=(old_msg)[:lim], inline=False) if len(old_msg) > lim: message_embed.add_field(name="(Continued)", value=(old_msg)[lim:lim * 2], inline=False) msg = (message.content or "NULL") message_embed.add_field(name="New Message", value=(msg)[:lim], inline=False) if len(msg) > lim: message_embed.add_field(name="(Continued)", value=(msg)[lim:lim * 2], inline=False) message_embed.set_footer(text=f"Message ID: {message.id}") message_embed.timestamp = datetime_now() asyncio.create_task(catch_logging_error(message_log, message_embed, None))
async def on_member_update(before: discord.Member, after: discord.Member, **kargs: Any) -> None: inc_statistics_better(before.guild.id, "on-member-update", kargs["kernel_ramfs"]) username_log = load_message_config(before.guild.id, kargs["ramfs"], datatypes=join_leave_user_logs)["username-log"] if username_log and (channel := kargs["client"].get_channel(int(username_log))): if before.nick == after.nick: return message_embed = discord.Embed(title="Nickname updated", color=load_embed_color(before.guild, embed_colors.edit, kargs["ramfs"])) message_embed.set_author(name=f"{before} ({before.id})", icon_url=user_avatar_url(before)) message_embed.add_field(name=("Before" + " | False" * (not before.nick)), value=str(before.nick)) message_embed.add_field(name=("After" + " | False" * (not after.nick)), value=str(after.nick)) message_embed.timestamp = ts = datetime_now() message_embed.set_footer(text=f"unix: {int(ts.timestamp())}") await catch_logging_error(channel, message_embed)
async def avatar_function(message: discord.Message, args: List[str], client: discord.Client, **kwargs: Any) -> Any: if not message.guild: return 1 user, _ = await parse_user_member_noexcept(message, args, client, default_self=True) embed = discord.Embed(description=f"{user.mention}'s Avatar", color=load_embed_color(message.guild, embed_colors.primary, kwargs["ramfs"])) embed.set_image(url=user_avatar_url(user)) embed.timestamp = datetime_now() try: await message.channel.send(embed=embed) except discord.errors.Forbidden: raise lib_sonnetcommands.CommandError(constants.sonnet.error_embed)
async def query_mutedb(message: discord.Message, args: List[str], client: discord.Client, **kwargs: Any) -> Any: if not message.guild: return 1 # do page capture if len(args) >= 2 and args[0] in ["-p", "--page"]: try: page = int(args[1]) - 1 if page < 0: raise ValueError except ValueError: await message.channel.send("ERROR: Invalid page") return 1 else: page = 0 per_page = 10 with db_hlapi(message.guild.id) as db: table: List[Tuple[str, str, int]] = db.fetch_guild_mutes() if not table: await message.channel.send("No Muted users in database") return 0 # Test if page is valid if page > len(table) // per_page: await message.channel.send("ERROR: Page does not exist") return 1 fmt: List[str] = [] for i in sorted(table, key=lambda i: i[2])[page:page + per_page]: ts = "No Unmute" if i[2] == 0 else format_duration( i[2] - datetime_now().timestamp()) fmt.append(f"{i[1]}, {i[0]}, {ts}"[:150]) LF = "\n" await message.channel.send( f"Page {page+1} / {len(table)//per_page+1}, ({len(table)} mute{'s'*(len(table)!=1)})```css\nUid, InfractionID, Unmuted in\n{LF.join(fmt)}```" )
async def on_member_join(member: discord.Member, **kargs: Any) -> None: client: discord.Client = kargs["client"] ramfs: lexdpyk.ram_filesystem = kargs["ramfs"] inc_statistics_better(member.guild.id, "on-member-join", kargs["kernel_ramfs"]) notifier_cache = load_message_config(member.guild.id, ramfs, datatypes=join_notifier) issues: List[str] = [] # Handle notifer logging if member.id in notifier_cache["notifier-log-users"]: issues.append("User") if abs(discord_datetime_now().timestamp() - member.created_at.timestamp()) < int(notifier_cache["notifier-log-timestamp"]): issues.append("Timestamp") if int(notifier_cache["notifier-log-defaultpfp"]) and has_default_avatar(member): issues.append("Default pfp") if issues: asyncio.create_task(notify_problem(member, issues, notifier_cache["regex-notifier-log"], client, ramfs)) joinlog = load_message_config(member.guild.id, ramfs, datatypes=join_leave_user_logs)["join-log"] # Handle join logs if joinlog and (logging_channel := client.get_channel(int(joinlog))): embed = discord.Embed(title=f"{member} joined.", description=f"*{member.mention} joined the server.*", color=load_embed_color(member.guild, embed_colors.creation, ramfs)) embed.set_thumbnail(url=user_avatar_url(member)) embed.timestamp = ts = datetime_now() embed.set_footer(text=f"uid: {member.id}, unix: {int(ts.timestamp())}") embed.add_field(name="Created", value=parsedate(member.created_at), inline=True) if isinstance(logging_channel, discord.TextChannel): asyncio.create_task(catch_logging_error(logging_channel, embed))
async def on_member_remove(member: discord.Member, **kargs: Any) -> None: inc_statistics_better(member.guild.id, "on-member-remove", kargs["kernel_ramfs"]) log_channels = load_message_config(member.guild.id, kargs["ramfs"], datatypes=join_leave_user_logs) # Try for leave-log, default to join-log if (joinlog := (log_channels["leave-log"] or log_channels["join-log"])): if logging_channel := kargs["client"].get_channel(int(joinlog)): # Only run if in a TextChannel if not isinstance(logging_channel, discord.TextChannel): return embed = discord.Embed(title=f"{member} left.", description=f"*{member.mention} left the server.*", color=load_embed_color(member.guild, embed_colors.deletion, kargs["ramfs"])) embed.set_thumbnail(url=user_avatar_url(member)) embed.timestamp = ts = datetime_now() embed.set_footer(text=f"uid: {member.id}, unix: {int(ts.timestamp())}") embed.add_field(name="Created", value=parsedate(member.created_at), inline=True) embed.add_field(name="Joined", value=parsedate(member.joined_at), inline=True) await catch_logging_error(logging_channel, embed)
async def profile_function(message: discord.Message, args: List[str], client: discord.Client, **kwargs: Any) -> Any: if not message.guild: return 1 user, member = await parse_user_member_noexcept(message, args, client, default_self=True) # Status hashmap status_map = { "online": "🟢 (online)", "offline": "⚫ (offline)", "idle": "🟡 (idle)", "dnd": "🔴 (dnd)", "do_not_disturb": "🔴 (dnd)", "invisible": "⚫ (offline)" } embed = discord.Embed(title="User Information", description=f"User information for {user.mention}:", color=load_embed_color(message.guild, embed_colors.primary, kwargs["ramfs"])) embed.set_thumbnail(url=user_avatar_url(user)) embed.add_field(name="Username", value=str(user), inline=True) embed.add_field(name="User ID", value=str(user.id), inline=True) if member: embed.add_field(name="Status", value=status_map[member.raw_status], inline=True) embed.add_field(name="Highest Rank", value=f"{member.top_role.mention}", inline=True) embed.add_field(name="Created", value=parsedate(user.created_at), inline=True) if member: embed.add_field(name="Joined", value=parsedate(member.joined_at), inline=True) # Parse adding infraction count with db_hlapi(message.guild.id) as db: viewinfs = parse_boolean( db.grab_config("member-view-infractions") or "0") moderator = await parse_permissions(message, kwargs["conf_cache"], "moderator", verbose=False) if moderator or (viewinfs and user.id == message.author.id): embed.add_field( name="Infractions", value=f"{db.grab_filter_infractions(user=user.id, count=True)}" ) embed.timestamp = datetime_now() try: await message.channel.send(embed=embed) except discord.errors.Forbidden: raise lib_sonnetcommands.CommandError(constants.sonnet.error_embed)
async def mute_user(message: discord.Message, args: List[str], client: discord.Client, **kwargs: Any) -> Any: if not message.guild: return 1 ramfs: lexdpyk.ram_filesystem = kwargs["ramfs"] automod: bool = kwargs["automod"] verbose: bool = kwargs["verbose"] # Grab mute time if len(args) >= 2: try: mutetime = MustParseDuration(args[1]) del args[1] except lib_goparsers.errors.ParseFailureError: mutetime = 0 else: mutetime = 0 # This ones for you, curl if not 0 <= mutetime < 60 * 60 * 256: mutetime = 0 try: mute_role = await grab_mute_role(message, ramfs) member, _, reason, infractionID, _ = await process_infraction( message, args, client, "mute", ramfs, automod=automod) except (NoMuteRole, InfractionGenerationError): return 1 # Check they are in the guild if not member: await message.channel.send("User is not in this guild") return 1 # Attempt to mute user try: await member.add_roles(mute_role) except discord.errors.Forbidden: await message.channel.send( f"{BOT_NAME} does not have permission to mute this user.") return 1 if verbose and not mutetime: await message.channel.send( f"Muted {member.mention} with ID {member.id} for {reason}", allowed_mentions=discord.AllowedMentions.none()) # if mutetime call db timed mute if mutetime: if verbose: asyncio.create_task( message.channel.send( f"Muted {member.mention} with ID {member.id} for {format_duration(mutetime)} for {reason}", allowed_mentions=discord.AllowedMentions.none())) # Stop other mute timers and add to mutedb with db_hlapi(message.guild.id) as db: db.unmute_user(userid=member.id) db.mute_user(member.id, int(datetime_now().timestamp() + mutetime), infractionID) # Create in other thread to not block command execution asyncio.create_task( sleep_and_unmute(message.guild, member, infractionID, mute_role, mutetime, ramfs)) else: # When muted with no unmute add to db as 0 timestamp to unmute, program should treat 0 as invalid with db_hlapi(message.guild.id) as db: db.unmute_user(userid=member.id) db.mute_user(member.id, 0, infractionID)