Exemplo n.º 1
0
        public async Task <Embed> CreateGroupEmbed(Context ctx, PKSystem system, PKGroup target)
        {
            await using var conn = await _db.Obtain();

            var pctx        = ctx.LookupContextFor(system);
            var memberCount = ctx.MatchPrivateFlag(pctx) ? await _repo.GetGroupMemberCount(conn, target.Id, PrivacyLevel.Public) : await _repo.GetGroupMemberCount(conn, target.Id);

            var nameField = target.Name;

            if (system.Name != null)
            {
                nameField = $"{nameField} ({system.Name})";
            }

            var eb = new EmbedBuilder()
                     .Author(new(nameField, IconUrl: DiscordUtils.WorkaroundForUrlBug(target.IconFor(pctx))))
                     .Footer(new($"System ID: {system.Hid} | Group ID: {target.Hid} | Created on {target.Created.FormatZoned(system)}"));

            if (target.DisplayName != null)
            {
                eb.Field(new("Display Name", target.DisplayName));
            }

            if (target.ListPrivacy.CanAccess(pctx))
            {
                if (memberCount == 0 && pctx == LookupContext.ByOwner)
                {
                    // Only suggest the add command if this is actually the owner lol
                    eb.Field(new("Members (0)", $"Add one with `pk;group {target.Reference()} add <member>`!", true));
                }
                else
                {
                    eb.Field(new($"Members ({memberCount})", $"(see `pk;group {target.Reference()} list`)", true));
                }
            }

            if (target.DescriptionFor(pctx) is { } desc)
            {
                eb.Field(new("Description", desc));
            }

            if (target.IconFor(pctx) is {} icon)
            {
                eb.Thumbnail(new(icon));
            }

            return(eb.Build());
        }
Exemplo n.º 2
0
        public async Task GroupDisplayName(Context ctx, PKGroup target)
        {
            if (await ctx.MatchClear("this group's display name"))
            {
                ctx.CheckOwnGroup(target);

                var patch = new GroupPatch {
                    DisplayName = Partial <string> .Null()
                };
                await _db.Execute(conn => _repo.UpdateGroup(conn, target.Id, patch));

                await ctx.Reply($"{Emojis.Success} Group display name cleared.");
            }
            else if (!ctx.HasNext())
            {
                // No perms check, display name isn't covered by member privacy
                var eb = new DiscordEmbedBuilder()
                         .AddField("Name", target.Name)
                         .AddField("Display Name", target.DisplayName ?? "*(none)*");

                if (ctx.System?.Id == target.System)
                {
                    eb.WithDescription($"To change display name, type `pk;group {target.Reference()} displayname <display name>`.\nTo clear it, type `pk;group {target.Reference()} displayname -clear`.");
                }

                await ctx.Reply(embed : eb.Build());
            }
            else
            {
                ctx.CheckOwnGroup(target);

                var newDisplayName = ctx.RemainderOrNull();

                var patch = new GroupPatch {
                    DisplayName = Partial <string> .Present(newDisplayName)
                };
                await _db.Execute(conn => _repo.UpdateGroup(conn, target.Id, patch));

                await ctx.Reply($"{Emojis.Success} Group display name changed.");
            }
        }
Exemplo n.º 3
0
        public async Task GroupIcon(Context ctx, PKGroup target)
        {
            async Task ClearIcon()
            {
                ctx.CheckOwnGroup(target);

                await _db.Execute(c => _repo.UpdateGroup(c, target.Id, new GroupPatch {
                    Icon = null
                }));

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

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

                await AvatarUtils.VerifyAvatarOrThrow(img.Url);

                await _db.Execute(c => _repo.UpdateGroup(c, target.Id, new GroupPatch {
                    Icon = img.Url
                }));

                var msg = img.Source switch
                {
                    AvatarSource.User => $"{Emojis.Success} Group icon changed to {img.SourceUser?.Username}'s avatar!\n{Emojis.Warn} If {img.SourceUser?.Username} changes their avatar, the group icon will need to be re-set.",
                    AvatarSource.Url => $"{Emojis.Success} Group icon changed to the image at the given URL.",
                    AvatarSource.Attachment => $"{Emojis.Success} Group icon changed to attached image.\n{Emojis.Warn} If you delete the message containing the attachment, the group 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, embed: new DiscordEmbedBuilder().WithImageUrl(img.Url).Build())
                    : ctx.Reply(msg));
            }

            async Task ShowIcon()
            {
                if ((target.Icon?.Trim() ?? "").Length > 0)
                {
                    var eb = new DiscordEmbedBuilder()
                             .WithTitle("Group icon")
                             .WithImageUrl(target.Icon);

                    if (target.System == ctx.System?.Id)
                    {
                        eb.WithDescription($"To clear, use `pk;group {target.Reference()} icon -clear`.");
                    }

                    await ctx.Reply(embed : eb.Build());
                }
                else
                {
                    throw new PKSyntaxError("This group does not have an icon set. Set one by attaching an image to this command, or by passing an image URL or @mention.");
                }
            }

            if (await ctx.MatchClear("this group's icon"))
            {
                await ClearIcon();
            }
            else if (await ctx.MatchImage() is {} img)
            {
                await SetIcon(img);
            }
Exemplo n.º 4
0
        public async Task GroupDescription(Context ctx, PKGroup target)
        {
            if (await ctx.MatchClear("this group's description"))
            {
                ctx.CheckOwnGroup(target);

                var patch = new GroupPatch {
                    Description = Partial <string> .Null()
                };
                await _db.Execute(conn => _repo.UpdateGroup(conn, target.Id, patch));

                await ctx.Reply($"{Emojis.Success} Group description cleared.");
            }
            else if (!ctx.HasNext())
            {
                if (target.Description == null)
                {
                    if (ctx.System?.Id == target.System)
                    {
                        await ctx.Reply($"This group does not have a description set. To set one, type `pk;group {target.Reference()} description <description>`.");
                    }
                    else
                    {
                        await ctx.Reply("This group does not have a description set.");
                    }
                }
                else if (ctx.MatchFlag("r", "raw"))
                {
                    await ctx.Reply($"```\n{target.Description}\n```");
                }
                else
                {
                    await ctx.Reply(embed : new DiscordEmbedBuilder()
                                    .WithTitle("Group description")
                                    .WithDescription(target.Description)
                                    .AddField("\u200B", $"To print the description with formatting, type `pk;group {target.Reference()} description -raw`."
                                              + (ctx.System?.Id == target.System ? $" To clear it, type `pk;group {target.Reference()} description -clear`." : ""))
                                    .Build());
                }
            }
            else
            {
                ctx.CheckOwnGroup(target);

                var description = ctx.RemainderOrNull().NormalizeLineEndSpacing();
                if (description.IsLongerThan(Limits.MaxDescriptionLength))
                {
                    throw Errors.DescriptionTooLongError(description.Length);
                }

                var patch = new GroupPatch {
                    Description = Partial <string> .Present(description)
                };
                await _db.Execute(conn => _repo.UpdateGroup(conn, target.Id, patch));

                await ctx.Reply($"{Emojis.Success} Group description changed.");
            }
        }
Exemplo n.º 5
0
    public async Task <Embed> CreateGroupEmbed(Context ctx, PKSystem system, PKGroup target)
    {
        var pctx = ctx.LookupContextFor(system.Id);

        var countctx = LookupContext.ByNonOwner;

        if (ctx.MatchFlag("a", "all"))
        {
            if (system.Id == ctx.System.Id)
            {
                countctx = LookupContext.ByOwner;
            }
            else
            {
                throw Errors.LookupNotAllowed;
            }
        }

        var memberCount = await _repo.GetGroupMemberCount(target.Id, countctx == LookupContext.ByOwner?null : PrivacyLevel.Public);

        var nameField = target.NamePrivacy.Get(pctx, target.Name, target.DisplayName ?? target.Name);

        if (system.Name != null)
        {
            nameField = $"{nameField} ({system.Name})";
        }

        uint color;

        try
        {
            color = target.Color?.ToDiscordColor() ?? DiscordUtils.Gray;
        }
        catch (ArgumentException)
        {
            // There's no API for group colors yet, but defaulting to a blank color regardless
            color = DiscordUtils.Gray;
        }

        var eb = new EmbedBuilder()
                 .Author(new Embed.EmbedAuthor(nameField, IconUrl: target.IconFor(pctx), Url: $"https://dash.pluralkit.me/profile/g/{target.Hid}"))
                 .Color(color);

        eb.Footer(new Embed.EmbedFooter($"System ID: {system.Hid} | Group ID: {target.Hid}{(target.MetadataPrivacy.CanAccess(pctx) ? $" | Created on {target.Created.FormatZoned(ctx.Zone)}" : "")}"));

        if (target.DescriptionPrivacy.CanAccess(pctx))
        {
            eb.Image(new Embed.EmbedImage(target.BannerImage));
        }

        if (target.NamePrivacy.CanAccess(pctx) && target.DisplayName != null)
        {
            eb.Field(new Embed.Field("Display Name", target.DisplayName, true));
        }

        if (!target.Color.EmptyOrNull())
        {
            eb.Field(new Embed.Field("Color", $"#{target.Color}", true));
        }

        if (target.ListPrivacy.CanAccess(pctx))
        {
            if (memberCount == 0 && pctx == LookupContext.ByOwner)
            {
                // Only suggest the add command if this is actually the owner lol
                eb.Field(new Embed.Field("Members (0)",
                                         $"Add one with `pk;group {target.Reference(ctx)} add <member>`!"));
            }
            else
            {
                var name = pctx == LookupContext.ByOwner
                    ? target.Reference(ctx)
                    : target.Hid;
                eb.Field(new Embed.Field($"Members ({memberCount})", $"(see `pk;group {name} list`)"));
            }
        }

        if (target.DescriptionFor(pctx) is { } desc)
        {
            eb.Field(new Embed.Field("Description", desc));
        }

        if (target.IconFor(pctx) is { } icon)
        {
            eb.Thumbnail(new Embed.EmbedThumbnail(icon.TryGetCleanCdnUrl()));
        }

        return(eb.Build());
    }
Exemplo n.º 6
0
    public async Task GroupDescription(Context ctx, PKGroup target)
    {
        ctx.CheckSystemPrivacy(target.System, target.DescriptionPrivacy);

        var noDescriptionSetMessage = "This group does not have a description set.";

        if (ctx.System?.Id == target.System)
        {
            noDescriptionSetMessage +=
                $" To set one, type `pk;group {target.Reference(ctx)} description <description>`.";
        }

        if (ctx.MatchRaw())
        {
            if (target.Description == null)
            {
                await ctx.Reply(noDescriptionSetMessage);
            }
            else
            {
                await ctx.Reply($"```\n{target.Description}\n```");
            }
            return;
        }

        if (!ctx.HasNext(false))
        {
            if (target.Description == null)
            {
                await ctx.Reply(noDescriptionSetMessage);
            }
            else
            {
                await ctx.Reply(embed : new EmbedBuilder()
                                .Title("Group description")
                                .Description(target.Description)
                                .Field(new Embed.Field("\u200B",
                                                       $"To print the description with formatting, type `pk;group {target.Reference(ctx)} description -raw`."
                                                       + (ctx.System?.Id == target.System
                            ? $" To clear it, type `pk;group {target.Reference(ctx)} description -clear`."
                            : "")))
                                .Build());
            }
            return;
        }

        ctx.CheckOwnGroup(target);

        if (await ctx.MatchClear("this group's description"))
        {
            var patch = new GroupPatch {
                Description = Partial <string> .Null()
            };
            await ctx.Repository.UpdateGroup(target.Id, patch);

            await ctx.Reply($"{Emojis.Success} Group description cleared.");
        }
        else
        {
            var description = ctx.RemainderOrNull(false).NormalizeLineEndSpacing();
            if (description.IsLongerThan(Limits.MaxDescriptionLength))
            {
                throw Errors.StringTooLongError("Description", description.Length, Limits.MaxDescriptionLength);
            }

            var patch = new GroupPatch {
                Description = Partial <string> .Present(description)
            };
            await ctx.Repository.UpdateGroup(target.Id, patch);

            await ctx.Reply($"{Emojis.Success} Group description changed.");
        }
    }
Exemplo n.º 7
0
    public async Task GroupDisplayName(Context ctx, PKGroup target)
    {
        var noDisplayNameSetMessage = "This group does not have a display name set.";

        if (ctx.System?.Id == target.System)
        {
            noDisplayNameSetMessage +=
                $" To set one, type `pk;group {target.Reference(ctx)} displayname <display name>`.";
        }

        // No perms check, display name isn't covered by member privacy

        if (ctx.MatchRaw())
        {
            if (target.DisplayName == null)
            {
                await ctx.Reply(noDisplayNameSetMessage);
            }
            else
            {
                await ctx.Reply($"```\n{target.DisplayName}\n```");
            }
            return;
        }

        if (!ctx.HasNext(false))
        {
            if (target.DisplayName == null)
            {
                await ctx.Reply(noDisplayNameSetMessage);
            }
            else
            {
                var eb = new EmbedBuilder()
                         .Field(new Embed.Field("Name", target.Name))
                         .Field(new Embed.Field("Display Name", target.DisplayName));

                var reference = target.Reference(ctx);

                if (ctx.System?.Id == target.System)
                {
                    eb.Description(
                        $"To change display name, type `pk;group {reference} displayname <display name>`."
                        + $"To clear it, type `pk;group {reference} displayname -clear`."
                        + $"To print the raw display name, type `pk;group {reference} displayname -raw`.");
                }

                await ctx.Reply(embed : eb.Build());
            }

            return;
        }

        ctx.CheckOwnGroup(target);

        if (await ctx.MatchClear("this group's display name"))
        {
            var patch = new GroupPatch {
                DisplayName = Partial <string> .Null()
            };
            await ctx.Repository.UpdateGroup(target.Id, patch);

            await ctx.Reply($"{Emojis.Success} Group display name cleared.");

            if (target.NamePrivacy == PrivacyLevel.Private)
            {
                await ctx.Reply($"{Emojis.Warn} Since this group no longer has a display name set, their name privacy **can no longer take effect**.");
            }
        }
        else
        {
            var newDisplayName = ctx.RemainderOrNull(false).NormalizeLineEndSpacing();

            var patch = new GroupPatch {
                DisplayName = Partial <string> .Present(newDisplayName)
            };
            await ctx.Repository.UpdateGroup(target.Id, patch);

            await ctx.Reply($"{Emojis.Success} Group display name changed.");
        }
    }