async def on_usertrust_message(message: discord.Message, **kargs: Any) -> None:

    if parse_skip_message(kargs["client"], message):
        return

    trusted = get_trust_pool(message.guild, kargs["kernel_ramfs"])

    # Give up if user is already trusted
    if message.author.id in trusted:
        return

    utrust_cache = load_message_config(message.guild.id,
                                       kargs["ramfs"],
                                       datatypes=trust_types)

    if not bool(int(utrust_cache["usertrust-enabled"])):
        return

    with db_hlapi(message.guild.id) as db:

        db.inject_enum("usertrust", [("userID", str), ("count", int)])

        # Inc counter
        if ucol := db.grab_enum("usertrust", str(message.author.id)):
            count = int(ucol[1]) + 1
        else:
Esempio n. 2
0
async def set_starboard_count(message: discord.Message, args: List[str],
                              client: discord.Client, **kwargs: Any) -> Any:
    if not message.guild:
        return 1

    if args:

        try:
            count = int(args[0])

            if count > 100:
                await message.channel.send(
                    "ERROR: Cannot set a starboard count higher than 100")
                return 1

            with db_hlapi(message.guild.id) as database:
                database.add_config("starboard-count", str(int(count)))

            if kwargs["verbose"]:
                await message.channel.send(
                    f"Updated starboard count to {count}")

        except ValueError:
            await message.channel.send("ERROR: Invalid input, enter a number")
            return 1

    else:
        mconf = load_message_config(message.guild.id,
                                    kwargs["ramfs"],
                                    datatypes=starboard_cache)
        count = int(mconf["starboard-count"])
        await message.channel.send(f"Starboard count is {count}")
async def on_raw_reaction_remove(payload: discord.RawReactionActionEvent,
                                 **kargs: Any) -> None:

    if not payload.guild_id: return

    inc_statistics_better(payload.guild_id, "on-raw-reaction-remove",
                          kargs["kernel_ramfs"])

    client = kargs["client"]
    rrconf: Optional[Dict[str, Dict[str, int]]] = load_message_config(
        payload.guild_id, kargs["ramfs"],
        datatypes=reactionrole_types)["reaction-role-data"]

    if rrconf:
        emojiname = emojifrompayload(payload)
        if str(payload.message_id) in rrconf and emojiname in rrconf[str(
                payload.message_id)]:
            role_id = rrconf[str(payload.message_id)][emojiname]
            if (guild := (await client.fetch_guild(
                    payload.guild_id
            ))) and (member := (await guild.fetch_member(
                    payload.user_id))) and (role := guild.get_role(role_id)):
                try:
                    await member.remove_roles(role)
                except discord.errors.Forbidden:
                    pass
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_usertrust_member_join(member: discord.Member,
                                   **kargs: Any) -> None:

    if member.id in get_trust_pool(member.guild, kargs["kernel_ramfs"]):

        utrust_cache = load_message_config(member.guild.id,
                                           kargs["ramfs"],
                                           datatypes=trust_types)

        if r := utrust_cache["usertrust-trusted-role"]:
            if drole := member.guild.get_role(int(r)):
                try:
                    await member.add_roles(drole)
                except discord.errors.Forbidden:
                    pass
Esempio n. 6
0
async def force_starboard(message: discord.Message, args: List[str],
                          client: discord.Client, **kwargs: Any) -> Any:
    if not message.guild:
        return 1

    mconf = load_message_config(message.guild.id,
                                kwargs["ramfs"],
                                datatypes=starboard_cache)

    try:
        starmessage, _ = await parse_channel_message(message, args, client)
    except lib_parsers.errors.message_parse_failure:
        return 1

    if (channel_id := mconf["starboard-channel"]) and (channel :=
                                                       client.get_channel(
                                                           int(channel_id))):
Esempio n. 7
0
async def set_starboard_use(message: discord.Message, args: List[str],
                            client: discord.Client, **kwargs: Any) -> Any:
    if not message.guild:
        return 1

    if args:
        gate = parse_boolean(args[0])
        with db_hlapi(message.guild.id) as database:
            database.add_config("starboard-enabled", str(int(gate)))
            if kwargs["verbose"]:
                await message.channel.send(
                    f"Set starboard enabled to {bool(gate)}")
    else:
        mconf = load_message_config(message.guild.id,
                                    kwargs["ramfs"],
                                    datatypes=starboard_cache)
        gate = bool(int(mconf["starboard-enabled"]))
        await message.channel.send(f"Starboard enabled is {bool(gate)}")
Esempio n. 8
0
async def set_starboard_emoji(message: discord.Message, args: List[str],
                              client: discord.Client, **kwargs: Any) -> Any:
    if not message.guild:
        return 1

    if args:
        emoji = args[0]
        with db_hlapi(message.guild.id) as database:
            database.add_config("starboard-emoji", emoji)
            if kwargs["verbose"]:
                await message.channel.send(
                    f"Updated starboard emoji to {emoji}")
    else:
        mconf = load_message_config(message.guild.id,
                                    kwargs["ramfs"],
                                    datatypes=starboard_cache)
        emoji = mconf["starboard-emoji"]
        await message.channel.send(f"Starboard emoji is {emoji}")
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)
Esempio n. 10
0
async def on_reaction_add(reaction: discord.Reaction, user: discord.User,
                          **kargs: Any) -> None:

    client: discord.Client = kargs["client"]
    kernel_ramfs: lexdpyk.ram_filesystem = kargs["kernel_ramfs"]
    ramfs: lexdpyk.ram_filesystem = kargs["ramfs"]

    message = reaction.message

    # Skip if not a guild
    if not message.guild:
        return

    inc_statistics_better(message.guild.id, "on-reaction-add", kernel_ramfs)
    mconf = load_message_config(message.guild.id,
                                ramfs,
                                datatypes=starboard_cache)

    if bool(
            int(mconf["starboard-enabled"])
    ) and reaction.emoji == mconf["starboard-emoji"] and reaction.count >= int(
            mconf["starboard-count"]):
        if (channel_id :=
                mconf["starboard-channel"]) and (channel := client.get_channel(
                    int(channel_id))) and isinstance(channel,
                                                     discord.TextChannel):

            with db_hlapi(message.guild.id) as db:
                with db.inject_enum_context("starboard",
                                            [("messageID", str)]) as starboard:
                    if not (starboard.grab(str(message.id))) and not (
                            int(channel_id) == message.channel.id):

                        # Add to starboard
                        starboard.set([str(message.id)])

                        try:
                            await channel.send(
                                embed=(await build_starboard_embed(message)))
                        except discord.errors.Forbidden:
                            pass
Esempio n. 11
0
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)
Esempio n. 12
0
async def on_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"]
    main_version_info: str = kargs["kernel_version"]
    bot_start_time: float = kargs["bot_start"]

    command_modules: List[lexdpyk.cmd_module]
    command_modules_dict: lexdpyk.cmd_modules_dict

    command_modules, command_modules_dict = kargs["command_modules"]

    # Statistics.
    stats: Dict[str, int] = {"start": round(time.time() * 100000)}

    if parse_skip_message(client, message):
        return
    elif not message.guild:
        return

    inc_statistics_better(message.guild.id, "on-message", kernel_ramfs)

    # Load message conf
    stats["start-load-blacklist"] = round(time.time() * 100000)
    mconf = load_message_config(message.guild.id, ramfs)
    stats["end-load-blacklist"] = round(time.time() * 100000)

    # Check message against automod
    stats["start-automod"] = round(time.time() * 100000)

    spammer, spamstr = antispam_check(message, ramfs, mconf["antispam"], mconf["char-antispam"])

    message_deleted: bool = False

    command_ctx = CommandCtx(
        stats=stats,
        cmds=command_modules,
        ramfs=ramfs,
        bot_start=bot_start_time,
        dlibs=kargs["dynamiclib_modules"][0],
        main_version=main_version_info,
        kernel_ramfs=kargs["kernel_ramfs"],
        conf_cache=mconf,
        verbose=True,
        cmds_dict=command_modules_dict,
        automod=False
        )

    automod_ctx = pycopy.copy(command_ctx)
    automod_ctx.verbose = False
    automod_ctx.automod = True

    # If blacklist broken generate infraction
    broke_blacklist, notify, infraction_type = parse_blacklist((message, mconf, ramfs), )
    if broke_blacklist:
        message_deleted = True
        asyncio.create_task(attempt_message_delete(message))
        execargs = [str(message.author.id), "[AUTOMOD]", ", ".join(infraction_type), "Blacklist"]
        asyncio.create_task(CallCtx(command_modules_dict[mconf["blacklist-action"]]['execute'])(message, execargs, client, automod_ctx))

    if spammer:
        message_deleted = True
        asyncio.create_task(attempt_message_delete(message))
        with db_hlapi(message.guild.id) as db:
            if not db.is_muted(userid=message.author.id):
                execargs = [str(message.author.id), mconf["antispam-time"], "[AUTOMOD]", spamstr]
                asyncio.create_task(CallCtx(command_modules_dict["mute"]["execute"])(message, execargs, client, automod_ctx))

    if notify:
        asyncio.create_task(grab_an_adult(message, message.guild, client, mconf, ramfs))

    stats["end-automod"] = round(time.time() * 100000)

    # Log files if not deleted
    if not message_deleted:
        asyncio.create_task(log_message_files(message, kernel_ramfs))

    # Check if this is meant for us.
    if not (message.content.startswith(mconf["prefix"])) or message_deleted:
        if client.user.mentioned_in(message) and str(client.user.id) == message.content.strip("<@!>"):
            try:
                await message.channel.send(f"My prefix for this guild is {mconf['prefix']}")
            except discord.errors.Forbidden:
                pass  # Nothing we can do if we lack perms to speak
        return

    # Split into cmds and arguments.
    arguments = message.content.split()
    command = arguments[0][len(mconf["prefix"]):]

    # Remove command from the arguments.
    del arguments[0]

    # Process commands
    if command in command_modules_dict:

        if "alias" in command_modules_dict[command]:  # Do alias mapping
            command = command_modules_dict[command]["alias"]

        cmd = SonnetCommand(command_modules_dict[command])

        if not await parse_permissions(message, mconf, cmd.permission):
            return  # Return on no perms

        try:
            stats["end"] = round(time.time() * 100000)

            try:
                await cmd.execute_ctx(message, arguments, client, command_ctx)
            except lib_sonnetcommands.CommandError as ce:
                try:
                    await message.channel.send(ce)
                except discord.errors.Forbidden:
                    pass

            # Regenerate cache
            if cmd.cache in ["purge", "regenerate"]:
                for i in ["caches", "regex"]:
                    try:
                        ramfs.rmdir(f"{message.guild.id}/{i}")
                    except FileNotFoundError:
                        pass

            elif cmd.cache.startswith("direct:"):
                for i in cmd.cache[len('direct:'):].split(";"):
                    try:
                        if i.startswith("(d)"):
                            ramfs.rmdir(f"{message.guild.id}/{i[3:]}")
                        elif i.startswith("(f)"):
                            ramfs.remove_f(f"{message.guild.id}/{i[3:]}")
                        else:
                            raise RuntimeError("Cache directive is invalid")
                    except FileNotFoundError:
                        pass

        except discord.errors.Forbidden as e:

            try:
                await message.channel.send(f"ERROR: Encountered a uncaught permission error while processing {command}")
                terr = True
            except discord.errors.Forbidden:
                terr = False  # Nothing we can do if we lack perms to speak

            if terr:  # If the error was not caused by message send perms then raise
                raise e

        except Exception as e:
            try:
                await message.channel.send(f"FATAL ERROR: uncaught exception while processing {command}")
            except discord.errors.Forbidden:
                pass
            raise e
Esempio n. 13
0
            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))

    # Check against blacklist
    mconf = load_message_config(message.guild.id, ramfs)
    broke_blacklist, notify, infraction_type = parse_blacklist((message, mconf, ramfs), )

    if broke_blacklist:

        command_ctx = CommandCtx(
            stats={},
            cmds=kargs["command_modules"][0],
            ramfs=ramfs,
            bot_start=kargs["bot_start"],
            dlibs=kargs["dynamiclib_modules"][0],
            main_version=kargs["kernel_version"],
            kernel_ramfs=kernel_ramfs,
            conf_cache={},
            verbose=False,
            cmds_dict=kargs["command_modules"][1],