コード例 #1
0
ファイル: MemberAvatar.cs プロジェクト: xSke/PluralKit
    private async Task AvatarCommandTree(AvatarLocation location, Context ctx, PKMember target,
                                         MemberGuildSettings?guildData)
    {
        // First, see if we need to *clear*
        if (await ctx.MatchClear(location == AvatarLocation.Server
                ? "this member's server avatar"
                : "this member's avatar"))
        {
            ctx.CheckSystem().CheckOwnMember(target);
            await AvatarClear(location, ctx, target, guildData);

            return;
        }

        // Then, parse an image from the command (from various sources...)
        var avatarArg = await ctx.MatchImage();

        if (avatarArg == null)
        {
            // If we didn't get any, just show the current avatar
            await AvatarShow(location, ctx, target, guildData);

            return;
        }

        ctx.CheckSystem().CheckOwnMember(target);
        await AvatarUtils.VerifyAvatarOrThrow(_client, avatarArg.Value.Url);

        await UpdateAvatar(location, ctx, target, avatarArg.Value.Url);
        await PrintResponse(location, ctx, target, avatarArg.Value, guildData);
    }
コード例 #2
0
    public async Task BannerImage(Context ctx, PKMember target)
    {
        ctx.CheckOwnMember(target);

        async Task ClearBannerImage()
        {
            await ctx.Repository.UpdateMember(target.Id, new MemberPatch { BannerImage = null });

            await ctx.Reply($"{Emojis.Success} Member banner image cleared.");
        }

        async Task SetBannerImage(ParsedImage img)
        {
            await AvatarUtils.VerifyAvatarOrThrow(_client, img.Url, true);

            await ctx.Repository.UpdateMember(target.Id, new MemberPatch { BannerImage = img.Url });

            var msg = img.Source switch
            {
                AvatarSource.Url => $"{Emojis.Success} Member banner image changed to the image at the given URL.",
                AvatarSource.Attachment =>
                $"{Emojis.Success} Member banner image changed to attached image.\n{Emojis.Warn} If you delete the message containing the attachment, the banner image will stop working.",
                AvatarSource.User => throw new PKError("Cannot set a banner image to an user's avatar."),
                      _ => throw new ArgumentOutOfRangeException()
            };

            // The attachment's already right there, no need to preview it.
            var hasEmbed = img.Source != AvatarSource.Attachment;

            await(hasEmbed
                ? ctx.Reply(msg, new EmbedBuilder().Image(new Embed.EmbedImage(img.Url)).Build())
                : ctx.Reply(msg));
        }

        async Task ShowBannerImage()
        {
            if ((target.BannerImage?.Trim() ?? "").Length > 0)
            {
                var eb = new EmbedBuilder()
                         .Title($"{target.NameFor(ctx)}'s banner image")
                         .Image(new Embed.EmbedImage(target.BannerImage))
                         .Description($"To clear, use `pk;member {target.Hid} banner clear`.");
                await ctx.Reply(embed : eb.Build());
            }
            else
            {
                throw new PKSyntaxError(
                          "This member does not have a banner image set. Set one by attaching an image to this command, or by passing an image URL or @mention.");
            }
        }

        if (await ctx.MatchClear("this member's banner image"))
        {
            await ClearBannerImage();
        }
        else if (await ctx.MatchImage() is { } img)
        {
            await SetBannerImage(img);
        }
コード例 #3
0
ファイル: Member.cs プロジェクト: xSke/PluralKit
    public async Task NewMember(Context ctx)
    {
        if (ctx.System == null)
        {
            throw Errors.NoSystemError;
        }
        var memberName = ctx.RemainderOrNull() ?? throw new PKSyntaxError("You must pass a member name.");

        // Hard name length cap
        if (memberName.Length > Limits.MaxMemberNameLength)
        {
            throw Errors.StringTooLongError("Member name", memberName.Length, Limits.MaxMemberNameLength);
        }

        // Warn if there's already a member by this name
        var existingMember = await ctx.Repository.GetMemberByName(ctx.System.Id, memberName);

        if (existingMember != null)
        {
            var msg = $"{Emojis.Warn} You already have a member in your system with the name \"{existingMember.NameFor(ctx)}\" (with ID `{existingMember.Hid}`). Do you want to create another member with the same name?";
            if (!await ctx.PromptYesNo(msg, "Create"))
            {
                throw new PKError("Member creation cancelled.");
            }
        }

        await using var conn = await ctx.Database.Obtain();

        // Enforce per-system member limit
        var memberCount = await ctx.Repository.GetSystemMemberCount(ctx.System.Id);

        var memberLimit = ctx.Config.MemberLimitOverride ?? Limits.MaxMemberCount;

        if (memberCount >= memberLimit)
        {
            throw Errors.MemberLimitReachedError(memberLimit);
        }

        // Create the member
        var member = await ctx.Repository.CreateMember(ctx.System.Id, memberName, conn);

        memberCount++;

        JObject dispatchData = new JObject();

        dispatchData.Add("name", memberName);

        if (ctx.Config.MemberDefaultPrivate)
        {
            var patch = new MemberPatch().WithAllPrivacy(PrivacyLevel.Private);
            await ctx.Repository.UpdateMember(member.Id, patch, conn);

            dispatchData.Merge(patch.ToJson());
        }

        // Try to match an image attached to the message
        var       avatarArg       = ctx.Message.Attachments.FirstOrDefault();
        Exception imageMatchError = null;

        if (avatarArg != null)
        {
            try
            {
                await AvatarUtils.VerifyAvatarOrThrow(_client, avatarArg.Url);

                await ctx.Repository.UpdateMember(member.Id, new MemberPatch { AvatarUrl = avatarArg.Url }, conn);

                dispatchData.Add("avatar_url", avatarArg.Url);
            }
            catch (Exception e)
            {
                imageMatchError = e;
            }
        }

        _ = _dispatch.Dispatch(member.Id, new UpdateDispatchData
        {
            Event     = DispatchEvent.CREATE_MEMBER,
            EventData = dispatchData,
        });

        // Send confirmation and space hint
        await ctx.Reply(
            $"{Emojis.Success} Member \"{memberName}\" (`{member.Hid}`) registered! Check out the getting started page for how to get a member up and running: https://pluralkit.me/start#create-a-member");

        // todo: move this to ModelRepository
        if (await ctx.Database.Execute(conn => conn.QuerySingleAsync <bool>("select has_private_members(@System)",
                                                                            new { System = ctx.System.Id })) && !ctx.Config.MemberDefaultPrivate) //if has private members
        {
            await ctx.Reply(
                $"{Emojis.Warn} This member is currently **public**. To change this, use `pk;member {member.Hid} private`.");
        }
        if (avatarArg != null)
        {
            if (imageMatchError == null)
            {
                await ctx.Reply(
                    $"{Emojis.Success} Member avatar set to attached image.\n{Emojis.Warn} If you delete the message containing the attachment, the avatar will stop working.");
            }
            else
            {
                await ctx.Reply($"{Emojis.Error} Couldn't set avatar: {imageMatchError.Message}");
            }
        }
        if (memberName.Contains(" "))
        {
            await ctx.Reply(
                $"{Emojis.Note} Note that this member's name contains spaces. You will need to surround it with \"double quotes\" when using commands referring to it, or just use the member's 5-character ID (which is `{member.Hid}`).");
        }
        if (memberCount >= memberLimit)
        {
            await ctx.Reply(
                $"{Emojis.Warn} You have reached the per-system member limit ({memberLimit}). You will be unable to create additional members until existing members are deleted.");
        }
        else if (memberCount >= Limits.WarnThreshold(memberLimit))
        {
            await ctx.Reply(
                $"{Emojis.Warn} You are approaching the per-system member limit ({memberCount} / {memberLimit} members). Please review your member list for unused or duplicate members.");
        }
    }
コード例 #4
0
    public async Task Avatar(Context ctx, PKSystem target)
    {
        async Task ClearIcon()
        {
            ctx.CheckOwnSystem(target);

            await ctx.Repository.UpdateSystem(target.Id, new SystemPatch { AvatarUrl = null });

            await ctx.Reply($"{Emojis.Success} System icon cleared.");
        }

        async Task SetIcon(ParsedImage img)
        {
            ctx.CheckOwnSystem(target);

            await AvatarUtils.VerifyAvatarOrThrow(_client, img.Url);

            await ctx.Repository.UpdateSystem(target.Id, new SystemPatch { AvatarUrl = img.Url });

            var msg = img.Source switch
            {
                AvatarSource.User =>
                $"{Emojis.Success} System icon changed to {img.SourceUser?.Username}'s avatar!\n{Emojis.Warn} If {img.SourceUser?.Username} changes their avatar, the system icon will need to be re-set.",
                AvatarSource.Url => $"{Emojis.Success} System icon changed to the image at the given URL.",
                AvatarSource.Attachment =>
                $"{Emojis.Success} System icon changed to attached image.\n{Emojis.Warn} If you delete the message containing the attachment, the system icon will stop working.",
                _ => throw new ArgumentOutOfRangeException()
            };

            // The attachment's already right there, no need to preview it.
            var hasEmbed = img.Source != AvatarSource.Attachment;

            await(hasEmbed
                ? ctx.Reply(msg, new EmbedBuilder().Image(new Embed.EmbedImage(img.Url)).Build())
                : ctx.Reply(msg));
        }

        async Task ShowIcon()
        {
            if ((target.AvatarUrl?.Trim() ?? "").Length > 0)
            {
                var eb = new EmbedBuilder()
                         .Title("System icon")
                         .Image(new Embed.EmbedImage(target.AvatarUrl.TryGetCleanCdnUrl()));
                if (target.Id == ctx.System?.Id)
                {
                    eb.Description("To clear, use `pk;system icon clear`.");
                }
                await ctx.Reply(embed : eb.Build());
            }
            else
            {
                throw new PKSyntaxError(
                          "This system does not have an icon set. Set one by attaching an image to this command, or by passing an image URL or @mention.");
            }
        }

        if (target != null && target?.Id != ctx.System?.Id)
        {
            await ShowIcon();

            return;
        }

        if (await ctx.MatchClear("your system's icon"))
        {
            await ClearIcon();
        }
        else if (await ctx.MatchImage() is { } img)
        {
            await SetIcon(img);
        }