コード例 #1
0
ファイル: GroupMember.cs プロジェクト: xSke/PluralKit
    public async Task ListMemberGroups(Context ctx, PKMember target)
    {
        var pctx = ctx.DirectLookupContextFor(target.System);

        var groups = await ctx.Repository.GetMemberGroups(target.Id)
                     .Where(g => g.Visibility.CanAccess(pctx))
                     .OrderBy(g => (g.DisplayName ?? g.Name), StringComparer.InvariantCultureIgnoreCase)
                     .ToListAsync();

        var description = "";
        var msg         = "";

        if (groups.Count == 0)
        {
            description = "This member has no groups.";
        }
        else
        {
            description = string.Join("\n", groups.Select(g => $"[`{g.Hid}`] **{g.DisplayName ?? g.Name}**"));
        }

        if (pctx == LookupContext.ByOwner)
        {
            msg +=
                $"\n\nTo add this member to one or more groups, use `pk;m {target.Reference(ctx)} group add <group> [group 2] [group 3...]`";
            if (groups.Count > 0)
            {
                msg +=
                    $"\nTo remove this member from one or more groups, use `pk;m {target.Reference(ctx)} group remove <group> [group 2] [group 3...]`";
            }
        }

        await ctx.Reply(msg, new EmbedBuilder().Title($"{target.Name}'s groups").Description(description).Build());
    }
コード例 #2
0
        private async Task AvatarShow(AvatarLocation location, Context ctx, PKMember target, MemberGuildSettings?guildData)
        {
            var currentValue = location == AvatarLocation.Member ? target.AvatarUrl : guildData?.AvatarUrl;
            var canAccess    = location != AvatarLocation.Member || target.AvatarPrivacy.CanAccess(ctx.LookupContextFor(target));

            if (string.IsNullOrEmpty(currentValue) || !canAccess)
            {
                if (location == AvatarLocation.Member)
                {
                    if (target.System == ctx.System?.Id)
                    {
                        throw new PKSyntaxError("This member does not have an avatar set. Set one by attaching an image to this command, or by passing an image URL or @mention.");
                    }
                    throw new PKError("This member does not have an avatar set.");
                }

                if (location == AvatarLocation.Server)
                {
                    throw new PKError($"This member does not have a server avatar set. Type `pk;member {target.Reference()} avatar` to see their global avatar.");
                }
            }

            var field = location == AvatarLocation.Server ? $"server avatar (for {ctx.Guild.Name})" : "avatar";
            var cmd   = location == AvatarLocation.Server ? "serveravatar" : "avatar";

            var eb = new DiscordEmbedBuilder()
                     .WithTitle($"{target.NameFor(ctx)}'s {field}")
                     .WithImageUrl(currentValue);

            if (target.System == ctx.System?.Id)
            {
                eb.WithDescription($"To clear, use `pk;member {target.Reference()} {cmd} clear`.");
            }
            await ctx.Reply(embed : eb.Build());
        }
コード例 #3
0
ファイル: MemberEdit.cs プロジェクト: guccigang17/PluralKit
        public async Task DisplayName(Context ctx, PKMember target)
        {
            async Task PrintSuccess(string text)
            {
                var successStr = text;

                if (ctx.Guild != null)
                {
                    var memberGuildConfig = await _db.Execute(c => _repo.GetMemberGuild(c, ctx.Guild.Id, target.Id));

                    if (memberGuildConfig.DisplayName != null)
                    {
                        successStr += $" However, this member has a server name set in this server ({ctx.Guild.Name}), and will be proxied using that name, \"{memberGuildConfig.DisplayName}\", here.";
                    }
                }

                await ctx.Reply(successStr);
            }

            if (await ctx.MatchClear("this member's display name"))
            {
                ctx.CheckOwnMember(target);

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

                await PrintSuccess($"{Emojis.Success} Member display name cleared. This member will now be proxied using their member name \"{target.NameFor(ctx)}\".");
            }
            else if (!ctx.HasNext())
            {
                // No perms check, display name isn't covered by member privacy
                var eb = await CreateMemberNameInfoEmbed(ctx, target);

                if (ctx.System?.Id == target.System)
                {
                    eb.Description($"To change display name, type `pk;member {target.Reference()} displayname <display name>`.\nTo clear it, type `pk;member {target.Reference()} displayname -clear`.");
                }
                await ctx.Reply(embed : eb.Build());
            }
            else
            {
                ctx.CheckOwnMember(target);

                var newDisplayName = ctx.RemainderOrNull();

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

                await PrintSuccess($"{Emojis.Success} Member display name changed. This member will now be proxied using the name \"{newDisplayName}\".");
            }
        }
コード例 #4
0
ファイル: MemberEdit.cs プロジェクト: guccigang17/PluralKit
        public async Task ServerName(Context ctx, PKMember target)
        {
            ctx.CheckGuildContext();

            if (await ctx.MatchClear("this member's server name"))
            {
                ctx.CheckOwnMember(target);

                var patch = new MemberGuildPatch {
                    DisplayName = null
                };
                await _db.Execute(conn => _repo.UpsertMemberGuild(conn, target.Id, ctx.Guild.Id, patch));

                if (target.DisplayName != null)
                {
                    await ctx.Reply($"{Emojis.Success} Member server name cleared. This member will now be proxied using their global display name \"{target.DisplayName}\" in this server ({ctx.Guild.Name}).");
                }
                else
                {
                    await ctx.Reply($"{Emojis.Success} Member server name cleared. This member will now be proxied using their member name \"{target.NameFor(ctx)}\" in this server ({ctx.Guild.Name}).");
                }
            }
            else if (!ctx.HasNext())
            {
                // No perms check, server name isn't covered by member privacy
                var eb = await CreateMemberNameInfoEmbed(ctx, target);

                if (ctx.System?.Id == target.System)
                {
                    eb.Description($"To change server name, type `pk;member {target.Reference()} servername <server name>`.\nTo clear it, type `pk;member {target.Reference()} servername -clear`.");
                }
                await ctx.Reply(embed : eb.Build());
            }
            else
            {
                ctx.CheckOwnMember(target);

                var newServerName = ctx.RemainderOrNull();

                var patch = new MemberGuildPatch {
                    DisplayName = newServerName
                };
                await _db.Execute(conn => _repo.UpsertMemberGuild(conn, target.Id, ctx.Guild.Id, patch));

                await ctx.Reply($"{Emojis.Success} Member server name changed. This member will now be proxied using the name \"{newServerName}\" in this server ({ctx.Guild.Name}).");
            }
        }
コード例 #5
0
ファイル: MemberAvatar.cs プロジェクト: xSke/PluralKit
    private async Task AvatarShow(AvatarLocation location, Context ctx, PKMember target,
                                  MemberGuildSettings?guildData)
    {
        // todo: this privacy code is really confusing
        // for now, we skip privacy flag/config parsing for this, but it would be good to fix that at some point

        var currentValue = location == AvatarLocation.Member ? target.AvatarUrl : guildData?.AvatarUrl;
        var canAccess    = location != AvatarLocation.Member ||
                           target.AvatarPrivacy.CanAccess(ctx.DirectLookupContextFor(target.System));

        if (string.IsNullOrEmpty(currentValue) || !canAccess)
        {
            if (location == AvatarLocation.Member)
            {
                if (target.System == ctx.System?.Id)
                {
                    throw new PKSyntaxError(
                              "This member does not have an avatar set. Set one by attaching an image to this command, or by passing an image URL or @mention.");
                }
                throw new PKError("This member does not have an avatar set.");
            }

            if (location == AvatarLocation.Server)
            {
                throw new PKError(
                          $"This member does not have a server avatar set. Type `pk;member {target.Reference(ctx)} avatar` to see their global avatar.");
            }
        }

        var field = location == AvatarLocation.Server ? $"server avatar (for {ctx.Guild.Name})" : "avatar";
        var cmd   = location == AvatarLocation.Server ? "serveravatar" : "avatar";

        var eb = new EmbedBuilder()
                 .Title($"{target.NameFor(ctx)}'s {field}")
                 .Image(new Embed.EmbedImage(currentValue?.TryGetCleanCdnUrl()));

        if (target.System == ctx.System?.Id)
        {
            eb.Description($"To clear, use `pk;member {target.Reference(ctx)} {cmd} clear`.");
        }
        await ctx.Reply(embed : eb.Build());
    }
コード例 #6
0
ファイル: MemberEdit.cs プロジェクト: guccigang17/PluralKit
        public async Task Description(Context ctx, PKMember target)
        {
            if (await ctx.MatchClear("this member's description"))
            {
                ctx.CheckOwnMember(target);

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

                await ctx.Reply($"{Emojis.Success} Member description cleared.");
            }
            else if (!ctx.HasNext())
            {
                if (!target.DescriptionPrivacy.CanAccess(ctx.LookupContextFor(target.System)))
                {
                    throw Errors.LookupNotAllowed;
                }
                if (target.Description == null)
                {
                    if (ctx.System?.Id == target.System)
                    {
                        await ctx.Reply($"This member does not have a description set. To set one, type `pk;member {target.Reference()} description <description>`.");
                    }
                    else
                    {
                        await ctx.Reply("This member 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 EmbedBuilder()
                                    .Title("Member description")
                                    .Description(target.Description)
                                    .Field(new("\u200B", $"To print the description with formatting, type `pk;member {target.Reference()} description -raw`."
                                               + (ctx.System?.Id == target.System ? $" To clear it, type `pk;member {target.Reference()} description -clear`." : "")))
                                    .Build());
                }
            }
            else
            {
                ctx.CheckOwnMember(target);

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

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

                await ctx.Reply($"{Emojis.Success} Member description changed.");
            }
        }
コード例 #7
0
ファイル: MemberEdit.cs プロジェクト: guccigang17/PluralKit
        public async Task Privacy(Context ctx, PKMember target, PrivacyLevel?newValueFromCommand)
        {
            ctx.CheckSystem().CheckOwnMember(target);

            // Display privacy settings
            if (!ctx.HasNext() && newValueFromCommand == null)
            {
                await ctx.Reply(embed : new EmbedBuilder()
                                .Title($"Current privacy settings for {target.NameFor(ctx)}")
                                .Field(new("Name (replaces name with display name if member has one)", target.NamePrivacy.Explanation()))
                                .Field(new("Description", target.DescriptionPrivacy.Explanation()))
                                .Field(new("Avatar", target.AvatarPrivacy.Explanation()))
                                .Field(new("Birthday", target.BirthdayPrivacy.Explanation()))
                                .Field(new("Pronouns", target.PronounPrivacy.Explanation()))
                                .Field(new("Meta (message count, last front, last message)", target.MetadataPrivacy.Explanation()))
                                .Field(new("Visibility", target.MemberVisibility.Explanation()))
                                .Description("To edit privacy settings, use the command:\n`pk;member <member> privacy <subject> <level>`\n\n- `subject` is one of `name`, `description`, `avatar`, `birthday`, `pronouns`, `created`, `messages`, `visibility`, or `all`\n- `level` is either `public` or `private`.")
                                .Build());

                return;
            }

            // Get guild settings (mostly for warnings and such)
            MemberGuildSettings guildSettings = null;

            if (ctx.Guild != null)
            {
                guildSettings = await _db.Execute(c => _repo.GetMemberGuild(c, ctx.Guild.Id, target.Id));
            }

            async Task SetAll(PrivacyLevel level)
            {
                await _db.Execute(c => _repo.UpdateMember(c, target.Id, new MemberPatch().WithAllPrivacy(level)));

                if (level == PrivacyLevel.Private)
                {
                    await ctx.Reply($"{Emojis.Success} All {target.NameFor(ctx)}'s privacy settings have been set to **{level.LevelName()}**. Other accounts will now see nothing on the member card.");
                }
                else
                {
                    await ctx.Reply($"{Emojis.Success} All {target.NameFor(ctx)}'s privacy settings have been set to **{level.LevelName()}**. Other accounts will now see everything on the member card.");
                }
            }

            async Task SetLevel(MemberPrivacySubject subject, PrivacyLevel level)
            {
                await _db.Execute(c => _repo.UpdateMember(c, target.Id, new MemberPatch().WithPrivacy(subject, level)));

                var subjectName = subject switch
                {
                    MemberPrivacySubject.Name => "name privacy",
                    MemberPrivacySubject.Description => "description privacy",
                    MemberPrivacySubject.Avatar => "avatar privacy",
                    MemberPrivacySubject.Pronouns => "pronoun privacy",
                    MemberPrivacySubject.Birthday => "birthday privacy",
                    MemberPrivacySubject.Metadata => "metadata privacy",
                    MemberPrivacySubject.Visibility => "visibility",
                    _ => throw new ArgumentOutOfRangeException($"Unknown privacy subject {subject}")
                };

                var explanation = (subject, level) switch
                {
                    (MemberPrivacySubject.Name, PrivacyLevel.Private) => "This member's name is now hidden from other systems, and will be replaced by the member's display name.",
                    (MemberPrivacySubject.Description, PrivacyLevel.Private) => "This member's description is now hidden from other systems.",
                    (MemberPrivacySubject.Avatar, PrivacyLevel.Private) => "This member's avatar is now hidden from other systems.",
                    (MemberPrivacySubject.Birthday, PrivacyLevel.Private) => "This member's birthday is now hidden from other systems.",
                    (MemberPrivacySubject.Pronouns, PrivacyLevel.Private) => "This member's pronouns are now hidden from other systems.",
                    (MemberPrivacySubject.Metadata, PrivacyLevel.Private) => "This member's metadata (eg. created timestamp, message count, etc) is now hidden from other systems.",
                    (MemberPrivacySubject.Visibility, PrivacyLevel.Private) => "This member is now hidden from member lists.",

                    (MemberPrivacySubject.Name, PrivacyLevel.Public) => "This member's name is no longer hidden from other systems.",
                    (MemberPrivacySubject.Description, PrivacyLevel.Public) => "This member's description is no longer hidden from other systems.",
                    (MemberPrivacySubject.Avatar, PrivacyLevel.Public) => "This member's avatar is no longer hidden from other systems.",
                    (MemberPrivacySubject.Birthday, PrivacyLevel.Public) => "This member's birthday is no longer hidden from other systems.",
                    (MemberPrivacySubject.Pronouns, PrivacyLevel.Public) => "This member's pronouns are no longer hidden other systems.",
                    (MemberPrivacySubject.Metadata, PrivacyLevel.Public) => "This member's metadata (eg. created timestamp, message count, etc) is no longer hidden from other systems.",
                    (MemberPrivacySubject.Visibility, PrivacyLevel.Public) => "This member is no longer hidden from member lists.",

                    _ => throw new InvalidOperationException($"Invalid subject/level tuple ({subject}, {level})")
                };

                await ctx.Reply($"{Emojis.Success} {target.NameFor(ctx)}'s **{subjectName}** has been set to **{level.LevelName()}**. {explanation}");

                // Name privacy only works given a display name
                if (subject == MemberPrivacySubject.Name && level == PrivacyLevel.Private && target.DisplayName == null)
                {
                    await ctx.Reply($"{Emojis.Warn} This member does not have a display name set, and name privacy **will not take effect**.");
                }

                // Avatar privacy doesn't apply when proxying if no server avatar is set
                if (subject == MemberPrivacySubject.Avatar && level == PrivacyLevel.Private && guildSettings?.AvatarUrl == null)
                {
                    await ctx.Reply($"{Emojis.Warn} This member does not have a server avatar set, so *proxying* will **still show the member avatar**. If you want to hide your avatar when proxying here, set a server avatar: `pk;member {target.Reference()} serveravatar`");
                }
            }

            if (ctx.Match("all") || newValueFromCommand != null)
            {
                await SetAll(newValueFromCommand ?? ctx.PopPrivacyLevel());
            }
            else
            {
                await SetLevel(ctx.PopMemberPrivacySubject(), ctx.PopPrivacyLevel());
            }
        }
コード例 #8
0
ファイル: MemberEdit.cs プロジェクト: guccigang17/PluralKit
        public async Task Birthday(Context ctx, PKMember target)
        {
            if (await ctx.MatchClear("this member's birthday"))
            {
                ctx.CheckOwnMember(target);

                var patch = new MemberPatch {
                    Birthday = Partial <LocalDate?> .Null()
                };
                await _db.Execute(conn => _repo.UpdateMember(conn, target.Id, patch));

                await ctx.Reply($"{Emojis.Success} Member birthdate cleared.");
            }
            else if (!ctx.HasNext())
            {
                if (!target.BirthdayPrivacy.CanAccess(ctx.LookupContextFor(target.System)))
                {
                    throw Errors.LookupNotAllowed;
                }

                if (target.Birthday == null)
                {
                    await ctx.Reply("This member does not have a birthdate set."
                                    + (ctx.System?.Id == target.System ? $" To set one, type `pk;member {target.Reference()} birthdate <birthdate>`." : ""));
                }
                else
                {
                    await ctx.Reply($"This member's birthdate is **{target.BirthdayString}**."
                                    + (ctx.System?.Id == target.System ? $" To clear it, type `pk;member {target.Reference()} birthdate -clear`." : ""));
                }
            }
            else
            {
                ctx.CheckOwnMember(target);

                var birthdayStr = ctx.RemainderOrNull();
                var birthday    = DateUtils.ParseDate(birthdayStr, true);
                if (birthday == null)
                {
                    throw Errors.BirthdayParseError(birthdayStr);
                }

                var patch = new MemberPatch {
                    Birthday = Partial <LocalDate?> .Present(birthday)
                };
                await _db.Execute(conn => _repo.UpdateMember(conn, target.Id, patch));

                await ctx.Reply($"{Emojis.Success} Member birthdate changed.");
            }
        }
コード例 #9
0
ファイル: MemberEdit.cs プロジェクト: guccigang17/PluralKit
        public async Task Color(Context ctx, PKMember target)
        {
            var color = ctx.RemainderOrNull();

            if (await ctx.MatchClear())
            {
                ctx.CheckOwnMember(target);

                var patch = new MemberPatch {
                    Color = Partial <string> .Null()
                };
                await _db.Execute(conn => _repo.UpdateMember(conn, target.Id, patch));

                await ctx.Reply($"{Emojis.Success} Member color cleared.");
            }
            else if (!ctx.HasNext())
            {
                // if (!target.ColorPrivacy.CanAccess(ctx.LookupContextFor(target.System)))
                //     throw Errors.LookupNotAllowed;

                if (target.Color == null)
                {
                    if (ctx.System?.Id == target.System)
                    {
                        await ctx.Reply(
                            $"This member does not have a color set. To set one, type `pk;member {target.Reference()} color <color>`.");
                    }
                    else
                    {
                        await ctx.Reply("This member does not have a color set.");
                    }
                }
                else
                {
                    await ctx.Reply(embed : new EmbedBuilder()
                                    .Title("Member color")
                                    .Color(target.Color.ToDiscordColor())
                                    .Thumbnail(new($"https://fakeimg.pl/256x256/{target.Color}/?text=%20"))
                                    .Description($"This member's color is **#{target.Color}**."
                                                 + (ctx.System?.Id == target.System ? $" To clear it, type `pk;member {target.Reference()} color -clear`." : ""))
                                    .Build());
                }
            }
            else
            {
                ctx.CheckOwnMember(target);

                if (color.StartsWith("#"))
                {
                    color = color.Substring(1);
                }
                if (!Regex.IsMatch(color, "^[0-9a-fA-F]{6}$"))
                {
                    throw Errors.InvalidColorError(color);
                }

                var patch = new MemberPatch {
                    Color = Partial <string> .Present(color.ToLowerInvariant())
                };
                await _db.Execute(conn => _repo.UpdateMember(conn, target.Id, patch));

                await ctx.Reply(embed : new EmbedBuilder()
                                .Title($"{Emojis.Success} Member color changed.")
                                .Color(color.ToDiscordColor())
                                .Thumbnail(new($"https://fakeimg.pl/256x256/{color}/?text=%20"))
                                .Build());
            }
        }
コード例 #10
0
ファイル: MemberEdit.cs プロジェクト: guccigang17/PluralKit
        public async Task Pronouns(Context ctx, PKMember target)
        {
            if (await ctx.MatchClear("this member's pronouns"))
            {
                ctx.CheckOwnMember(target);

                var patch = new MemberPatch {
                    Pronouns = Partial <string> .Null()
                };
                await _db.Execute(conn => _repo.UpdateMember(conn, target.Id, patch));

                await ctx.Reply($"{Emojis.Success} Member pronouns cleared.");
            }
            else if (!ctx.HasNext())
            {
                if (!target.PronounPrivacy.CanAccess(ctx.LookupContextFor(target.System)))
                {
                    throw Errors.LookupNotAllowed;
                }
                if (target.Pronouns == null)
                {
                    if (ctx.System?.Id == target.System)
                    {
                        await ctx.Reply($"This member does not have pronouns set. To set some, type `pk;member {target.Reference()} pronouns <pronouns>`.");
                    }
                    else
                    {
                        await ctx.Reply("This member does not have pronouns set.");
                    }
                }
                else
                {
                    await ctx.Reply($"**{target.NameFor(ctx)}**'s pronouns are **{target.Pronouns}**."
                                    + (ctx.System?.Id == target.System ? $" To clear them, type `pk;member {target.Reference()} pronouns -clear`." : ""));
                }
            }
            else
            {
                ctx.CheckOwnMember(target);

                var pronouns = ctx.RemainderOrNull().NormalizeLineEndSpacing();
                if (pronouns.IsLongerThan(Limits.MaxPronounsLength))
                {
                    throw Errors.MemberPronounsTooLongError(pronouns.Length);
                }

                var patch = new MemberPatch {
                    Pronouns = Partial <string> .Present(pronouns)
                };
                await _db.Execute(conn => _repo.UpdateMember(conn, target.Id, patch));

                await ctx.Reply($"{Emojis.Success} Member pronouns changed.");
            }
        }
コード例 #11
0
 public static PKError EmptyProxyTags(PKMember member) => new PKError($"The example proxy `text` is equivalent to having no proxy tags at all, since there are no symbols or brackets on either end. If you'd like to clear your proxy tags, use `pk;member {member.Reference()} proxy clear`.");
コード例 #12
0
 public static PKError LegacyAlreadyHasProxyTag(ProxyTag requested, PKMember member) => new PKError($"This member already has more than one proxy tag set: {member.ProxyTagsString()}\nConsider using the {$"pk;member {member.Reference()} proxy add {requested.ProxyString}".AsCode()} command instead.");
コード例 #13
0
ファイル: MemberAvatar.cs プロジェクト: xSke/PluralKit
    private async Task AvatarClear(AvatarLocation location, Context ctx, PKMember target, MemberGuildSettings?mgs)
    {
        await UpdateAvatar(location, ctx, target, null);

        if (location == AvatarLocation.Server)
        {
            if (target.AvatarUrl != null)
            {
                await ctx.Reply(
                    $"{Emojis.Success} Member server avatar cleared. This member will now use the global avatar in this server (**{ctx.Guild.Name}**).");
            }
            else
            {
                await ctx.Reply($"{Emojis.Success} Member server avatar cleared. This member now has no avatar.");
            }
        }
        else
        {
            if (mgs?.AvatarUrl != null)
            {
                await ctx.Reply(
                    $"{Emojis.Success} Member avatar cleared. Note that this member has a server-specific avatar set here, type `pk;member {target.Reference(ctx)} serveravatar clear` if you wish to clear that too.");
            }
            else
            {
                await ctx.Reply($"{Emojis.Success} Member avatar cleared.");
            }
        }
    }
コード例 #14
0
    public async Task Description(Context ctx, PKMember target)
    {
        ctx.CheckSystemPrivacy(target.System, target.DescriptionPrivacy);

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

        if (ctx.System?.Id == target.System)
        {
            noDescriptionSetMessage +=
                $" To set one, type `pk;member {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("Member description")
                                .Description(target.Description)
                                .Field(new Embed.Field("\u200B",
                                                       $"To print the description with formatting, type `pk;member {target.Reference(ctx)} description -raw`."
                                                       + (ctx.System?.Id == target.System
                            ? $" To clear it, type `pk;member {target.Reference(ctx)} description -clear`."
                            : "")))
                                .Build());
            }
            return;
        }

        ctx.CheckOwnMember(target);

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

            await ctx.Reply($"{Emojis.Success} Member 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 MemberPatch {
                Description = Partial <string> .Present(description)
            };
            await ctx.Repository.UpdateMember(target.Id, patch);

            await ctx.Reply($"{Emojis.Success} Member description changed.");
        }
    }
コード例 #15
0
    public async Task Pronouns(Context ctx, PKMember target)
    {
        var noPronounsSetMessage = "This member does not have pronouns set.";

        if (ctx.System?.Id == target.System)
        {
            noPronounsSetMessage += $"To set some, type `pk;member {target.Reference(ctx)} pronouns <pronouns>`.";
        }

        ctx.CheckSystemPrivacy(target.System, target.PronounPrivacy);

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

        if (!ctx.HasNext(false))
        {
            if (target.Pronouns == null)
            {
                await ctx.Reply(noPronounsSetMessage);
            }
            else
            {
                await ctx.Reply(
                    $"**{target.NameFor(ctx)}**'s pronouns are **{target.Pronouns}**.\nTo print the pronouns with formatting, type `pk;member {target.Reference(ctx)} pronouns -raw`."
                    + (ctx.System?.Id == target.System
                        ? $" To clear them, type `pk;member {target.Reference(ctx)} pronouns -clear`."
                        : ""));
            }
            return;
        }

        ctx.CheckOwnMember(target);

        if (await ctx.MatchClear("this member's pronouns"))
        {
            var patch = new MemberPatch {
                Pronouns = Partial <string> .Null()
            };
            await ctx.Repository.UpdateMember(target.Id, patch);

            await ctx.Reply($"{Emojis.Success} Member pronouns cleared.");
        }
        else
        {
            var pronouns = ctx.RemainderOrNull(false).NormalizeLineEndSpacing();
            if (pronouns.IsLongerThan(Limits.MaxPronounsLength))
            {
                throw Errors.StringTooLongError("Pronouns", pronouns.Length, Limits.MaxPronounsLength);
            }

            var patch = new MemberPatch {
                Pronouns = Partial <string> .Present(pronouns)
            };
            await ctx.Repository.UpdateMember(target.Id, patch);

            await ctx.Reply($"{Emojis.Success} Member pronouns changed.");
        }
    }