Add member avatar privacy

This commit is contained in:
Ske 2020-06-20 16:00:50 +02:00
parent 27c8100cac
commit ae4e8f97d0
13 changed files with 61 additions and 14 deletions

View File

@ -50,7 +50,7 @@ namespace PluralKit.API
o.Add("display_name", member.NamePrivacy.CanAccess(ctx) ? member.DisplayName : null); o.Add("display_name", member.NamePrivacy.CanAccess(ctx) ? member.DisplayName : null);
o.Add("birthday", member.BirthdayPrivacy.CanAccess(ctx) && member.Birthday.HasValue ? DateTimeFormats.DateExportFormat.Format(member.Birthday.Value) : null); o.Add("birthday", member.BirthdayPrivacy.CanAccess(ctx) && member.Birthday.HasValue ? DateTimeFormats.DateExportFormat.Format(member.Birthday.Value) : null);
o.Add("pronouns", member.PronounPrivacy.CanAccess(ctx) ? member.Pronouns : null); o.Add("pronouns", member.PronounPrivacy.CanAccess(ctx) ? member.Pronouns : null);
o.Add("avatar_url", member.AvatarUrl); o.Add("avatar_url", member.AvatarPrivacy.CanAccess(ctx) ? member.AvatarUrl : null);
o.Add("description", member.DescriptionPrivacy.CanAccess(ctx) ? member.Description : null); o.Add("description", member.DescriptionPrivacy.CanAccess(ctx) ? member.Description : null);
var tagArray = new JArray(); var tagArray = new JArray();
@ -67,6 +67,7 @@ namespace PluralKit.API
o.Add("description_privacy", ctx == LookupContext.ByOwner ? (member.DescriptionPrivacy == PrivacyLevel.Private ? "private" : "public") : null); o.Add("description_privacy", ctx == LookupContext.ByOwner ? (member.DescriptionPrivacy == PrivacyLevel.Private ? "private" : "public") : null);
o.Add("birthday_privacy", ctx == LookupContext.ByOwner ? (member.BirthdayPrivacy == PrivacyLevel.Private ? "private" : "public") : null); o.Add("birthday_privacy", ctx == LookupContext.ByOwner ? (member.BirthdayPrivacy == PrivacyLevel.Private ? "private" : "public") : null);
o.Add("pronoun_privacy", ctx == LookupContext.ByOwner ? (member.PronounPrivacy == PrivacyLevel.Private ? "private" : "public") : null); o.Add("pronoun_privacy", ctx == LookupContext.ByOwner ? (member.PronounPrivacy == PrivacyLevel.Private ? "private" : "public") : null);
o.Add("avatar_privacy", ctx == LookupContext.ByOwner ? (member.AvatarPrivacy == PrivacyLevel.Private ? "private" : "public") : null);
// o.Add("color_privacy", ctx == LookupContext.ByOwner ? (member.ColorPrivacy == PrivacyLevel.Private ? "private" : "public") : null); // o.Add("color_privacy", ctx == LookupContext.ByOwner ? (member.ColorPrivacy == PrivacyLevel.Private ? "private" : "public") : null);
o.Add("metadata_privacy", ctx == LookupContext.ByOwner ? (member.MetadataPrivacy == PrivacyLevel.Private ? "private" : "public") : null); o.Add("metadata_privacy", ctx == LookupContext.ByOwner ? (member.MetadataPrivacy == PrivacyLevel.Private ? "private" : "public") : null);
@ -122,6 +123,7 @@ namespace PluralKit.API
member.MemberVisibility = plevel; member.MemberVisibility = plevel;
member.NamePrivacy = plevel; member.NamePrivacy = plevel;
member.AvatarPrivacy = plevel;
member.DescriptionPrivacy = plevel; member.DescriptionPrivacy = plevel;
member.BirthdayPrivacy = plevel; member.BirthdayPrivacy = plevel;
member.PronounPrivacy = plevel; member.PronounPrivacy = plevel;
@ -133,6 +135,7 @@ namespace PluralKit.API
if (o.ContainsKey("visibility")) member.MemberVisibility = o.Value<string>("visibility").ParsePrivacy("member"); if (o.ContainsKey("visibility")) member.MemberVisibility = o.Value<string>("visibility").ParsePrivacy("member");
if (o.ContainsKey("name_privacy")) member.NamePrivacy = o.Value<string>("name_privacy").ParsePrivacy("member"); if (o.ContainsKey("name_privacy")) member.NamePrivacy = o.Value<string>("name_privacy").ParsePrivacy("member");
if (o.ContainsKey("description_privacy")) member.DescriptionPrivacy = o.Value<string>("description_privacy").ParsePrivacy("member"); if (o.ContainsKey("description_privacy")) member.DescriptionPrivacy = o.Value<string>("description_privacy").ParsePrivacy("member");
if (o.ContainsKey("avatar_privacy")) member.AvatarPrivacy = o.Value<string>("avatar_privacy").ParsePrivacy("member");
if (o.ContainsKey("birthday_privacy")) member.BirthdayPrivacy = o.Value<string>("birthday_privacy").ParsePrivacy("member"); if (o.ContainsKey("birthday_privacy")) member.BirthdayPrivacy = o.Value<string>("birthday_privacy").ParsePrivacy("member");
if (o.ContainsKey("pronoun_privacy")) member.PronounPrivacy = o.Value<string>("pronoun_privacy").ParsePrivacy("member"); if (o.ContainsKey("pronoun_privacy")) member.PronounPrivacy = o.Value<string>("pronoun_privacy").ParsePrivacy("member");
// if (o.ContainsKey("color_privacy")) member.ColorPrivacy = o.Value<string>("color_privacy").ParsePrivacy("member"); // if (o.ContainsKey("color_privacy")) member.ColorPrivacy = o.Value<string>("color_privacy").ParsePrivacy("member");

View File

@ -625,6 +625,19 @@ components:
Because of this, there is no way for an unauthorized user to tell the difference between a private description and a `null` description - this is intentional. Because of this, there is no way for an unauthorized user to tell the difference between a private description and a `null` description - this is intentional.
example: public example: public
avatar_privacy:
allOf:
- $ref: "#/components/schemas/PrivacySetting"
- description: |
The member's current avatar privacy setting, either "public" or "private".
If this is set to "private", the field `avatar_url` will be returned as `null` on all requests not authorized with this system's token.
In addition, this field will be returned as `null` if the request is not authorized with this system's token.
Because of this, there is no way for an unauthorized user to tell the difference between a private avatar and a `null` avatar - this is intentional.
example: public
pronouns_privacy: pronouns_privacy:
allOf: allOf:
- $ref: "#/components/schemas/PrivacySetting" - $ref: "#/components/schemas/PrivacySetting"

View File

@ -47,7 +47,8 @@ namespace PluralKit.Bot
var cmd = location == AvatarLocation.Server ? "serveravatar" : "avatar"; var cmd = location == AvatarLocation.Server ? "serveravatar" : "avatar";
var currentValue = location == AvatarLocation.Member ? target.AvatarUrl : guildData?.AvatarUrl; var currentValue = location == AvatarLocation.Member ? target.AvatarUrl : guildData?.AvatarUrl;
if (string.IsNullOrEmpty(currentValue)) var canAccess = location != AvatarLocation.Member || target.AvatarPrivacy.CanAccess(ctx.LookupContextFor(target));
if (string.IsNullOrEmpty(currentValue) && !canAccess)
{ {
if (location == AvatarLocation.Member) if (location == AvatarLocation.Member)
{ {

View File

@ -378,12 +378,13 @@ namespace PluralKit.Bot
.WithTitle($"Current privacy settings for {member.NameFor(ctx)}") .WithTitle($"Current privacy settings for {member.NameFor(ctx)}")
.AddField("Name (replaces name with display name if member has one)",PrivacyLevelString(member.NamePrivacy)) .AddField("Name (replaces name with display name if member has one)",PrivacyLevelString(member.NamePrivacy))
.AddField("Description", PrivacyLevelString(member.DescriptionPrivacy)) .AddField("Description", PrivacyLevelString(member.DescriptionPrivacy))
.AddField("Avatar", PrivacyLevelString(member.AvatarPrivacy))
.AddField("Birthday", PrivacyLevelString(member.BirthdayPrivacy)) .AddField("Birthday", PrivacyLevelString(member.BirthdayPrivacy))
.AddField("Pronouns", PrivacyLevelString(member.PronounPrivacy)) .AddField("Pronouns", PrivacyLevelString(member.PronounPrivacy))
// .AddField("Color", PrivacyLevelString(target.ColorPrivacy)) // .AddField("Color", PrivacyLevelString(target.ColorPrivacy))
.AddField("Meta (message count, last front, last message)", PrivacyLevelString(member.MetadataPrivacy)) .AddField("Meta (message count, last front, last message)", PrivacyLevelString(member.MetadataPrivacy))
.AddField("Visibility", PrivacyLevelString(member.MemberVisibility)) .AddField("Visibility", PrivacyLevelString(member.MemberVisibility))
.WithDescription("To edit privacy settings, use the command:\n`pk;member <member> privacy <subject> <level>`\n\n- `subject` is one of `name`, `description`, `birthday`, `pronouns`, `created`, `messages`, `visibility`, or `all`\n- `level` is either `public` or `private`."); .WithDescription("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`.");
return eb.Build(); return eb.Build();
} }
@ -432,6 +433,7 @@ namespace PluralKit.Bot
{ {
(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.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.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.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.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.Metadata, PrivacyLevel.Private) => "This member's metadata (eg. created timestamp, message count, etc) is now hidden from other systems.",
@ -439,6 +441,7 @@ namespace PluralKit.Bot
(MemberPrivacySubject.Name, PrivacyLevel.Public) => "This member's name is no longer hidden from other systems.", (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.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.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.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.Metadata, PrivacyLevel.Public) => "This member's metadata (eg. created timestamp, message count, etc) is no longer hidden from other systems.",
@ -462,7 +465,7 @@ namespace PluralKit.Bot
} }
else else
{ {
var subjectList = "`name`, `description`, `birthday`, `pronouns`, `metadata`, `visibility`, or `all`"; var subjectList = "`name`, `description`, `avatar`, `birthday`, `pronouns`, `metadata`, `visibility`, or `all`";
throw new PKSyntaxError($"Invalid privacy subject `{ctx.PopArgument().SanitizeMentions()}` (must be {subjectList})."); throw new PKSyntaxError($"Invalid privacy subject `{ctx.PopArgument().SanitizeMentions()}` (must be {subjectList}).");
} }

View File

@ -72,8 +72,8 @@ namespace PluralKit.Bot {
var timestamp = DiscordUtils.SnowflakeToInstant(messageId); var timestamp = DiscordUtils.SnowflakeToInstant(messageId);
var name = member.NameFor(LookupContext.ByNonOwner); var name = member.NameFor(LookupContext.ByNonOwner);
return new DiscordEmbedBuilder() return new DiscordEmbedBuilder()
.WithAuthor($"#{channel.Name}: {name}", iconUrl: DiscordUtils.WorkaroundForUrlBug(member.AvatarUrl)) .WithAuthor($"#{channel.Name}: {name}", iconUrl: DiscordUtils.WorkaroundForUrlBug(member.AvatarFor(LookupContext.ByNonOwner)))
.WithThumbnailUrl(member.AvatarUrl) .WithThumbnailUrl(member.AvatarFor(LookupContext.ByNonOwner))
.WithDescription(content?.NormalizeLineEndSpacing()) .WithDescription(content?.NormalizeLineEndSpacing())
.WithFooter($"System ID: {system.Hid} | Member ID: {member.Hid} | Sender: {sender.Username}#{sender.Discriminator} ({sender.Id}) | Message ID: {messageId} | Original Message ID: {originalMsgId}") .WithFooter($"System ID: {system.Hid} | Member ID: {member.Hid} | Sender: {sender.Username}#{sender.Discriminator} ({sender.Id}) | Message ID: {messageId} | Original Message ID: {originalMsgId}")
.WithTimestamp(timestamp.ToDateTimeOffset()) .WithTimestamp(timestamp.ToDateTimeOffset())
@ -103,7 +103,7 @@ namespace PluralKit.Bot {
var guildSettings = guild != null ? await _db.Execute(c => c.QueryOrInsertMemberGuildConfig(guild.Id, member.Id)) : null; var guildSettings = guild != null ? await _db.Execute(c => c.QueryOrInsertMemberGuildConfig(guild.Id, member.Id)) : null;
var guildDisplayName = guildSettings?.DisplayName; var guildDisplayName = guildSettings?.DisplayName;
var avatar = guildSettings?.AvatarUrl ?? member.AvatarUrl; var avatar = guildSettings?.AvatarUrl ?? member.AvatarFor(ctx);
var proxyTagsStr = string.Join('\n', member.ProxyTags.Select(t => $"`{t.ProxyString}`")); var proxyTagsStr = string.Join('\n', member.ProxyTags.Select(t => $"`{t.ProxyString}`"));
@ -117,7 +117,7 @@ namespace PluralKit.Bot {
var description = ""; var description = "";
if (member.MemberVisibility == PrivacyLevel.Private) description += "*(this member is hidden)*\n"; if (member.MemberVisibility == PrivacyLevel.Private) description += "*(this member is hidden)*\n";
if (guildSettings?.AvatarUrl != null) if (guildSettings?.AvatarUrl != null)
if (member.AvatarUrl != null) if (member.AvatarFor(ctx) != null)
description += $"*(this member has a server-specific avatar set; [click here]({member.AvatarUrl}) to see the global avatar)*\n"; description += $"*(this member has a server-specific avatar set; [click here]({member.AvatarUrl}) to see the global avatar)*\n";
else else
description += "*(this member has a server-specific avatar set)*\n"; description += "*(this member has a server-specific avatar set)*\n";
@ -179,7 +179,7 @@ namespace PluralKit.Bot {
// Put it all together // Put it all together
var eb = new DiscordEmbedBuilder() var eb = new DiscordEmbedBuilder()
.WithAuthor(msg.Member.NameFor(ctx), iconUrl: DiscordUtils.WorkaroundForUrlBug(msg.Member.AvatarUrl)) .WithAuthor(msg.Member.NameFor(ctx), iconUrl: DiscordUtils.WorkaroundForUrlBug(msg.Member.AvatarFor(ctx)))
.WithDescription(serverMsg?.Content?.NormalizeLineEndSpacing() ?? "*(message contents deleted or inaccessible)*") .WithDescription(serverMsg?.Content?.NormalizeLineEndSpacing() ?? "*(message contents deleted or inaccessible)*")
.WithImageUrl(serverMsg?.Attachments?.FirstOrDefault()?.Url) .WithImageUrl(serverMsg?.Attachments?.FirstOrDefault()?.Url)
.AddField("System", .AddField("System",

View File

@ -7,6 +7,9 @@ namespace PluralKit.Bot
public static string NameFor(this PKMember member, Context ctx) => public static string NameFor(this PKMember member, Context ctx) =>
member.NameFor(ctx.LookupContextFor(member)); member.NameFor(ctx.LookupContextFor(member));
public static string AvatarFor(this PKMember member, Context ctx) =>
member.AvatarFor(ctx.LookupContextFor(member));
public static string DisplayName(this PKMember member) => public static string DisplayName(this PKMember member) =>
member.DisplayName ?? member.Name; member.DisplayName ?? member.Name;
} }

View File

@ -2,6 +2,7 @@
-- Create new columns -- -- Create new columns --
alter table members add column description_privacy integer check (description_privacy in (1, 2)) not null default 1; alter table members add column description_privacy integer check (description_privacy in (1, 2)) not null default 1;
alter table members add column name_privacy integer check (name_privacy in (1, 2)) not null default 1; alter table members add column name_privacy integer check (name_privacy in (1, 2)) not null default 1;
alter table members add column avatar_privacy integer check (avatar_privacy in (1, 2)) not null default 1;
alter table members add column birthday_privacy integer check (birthday_privacy in (1, 2)) not null default 1; alter table members add column birthday_privacy integer check (birthday_privacy in (1, 2)) not null default 1;
alter table members add column pronoun_privacy integer check (pronoun_privacy in (1, 2)) not null default 1; alter table members add column pronoun_privacy integer check (pronoun_privacy in (1, 2)) not null default 1;
alter table members add column metadata_privacy integer check (metadata_privacy in (1, 2)) not null default 1; alter table members add column metadata_privacy integer check (metadata_privacy in (1, 2)) not null default 1;
@ -10,6 +11,7 @@ alter table members add column metadata_privacy integer check (metadata_privacy
-- Transfer existing settings -- -- Transfer existing settings --
update members set description_privacy = member_privacy; update members set description_privacy = member_privacy;
update members set name_privacy = member_privacy; update members set name_privacy = member_privacy;
update members set avatar_privacy = member_privacy;
update members set birthday_privacy = member_privacy; update members set birthday_privacy = member_privacy;
update members set pronoun_privacy = member_privacy; update members set pronoun_privacy = member_privacy;
update members set metadata_privacy = member_privacy; update members set metadata_privacy = member_privacy;

View File

@ -4,5 +4,8 @@
{ {
public static string NameFor(this PKMember member, LookupContext ctx) => public static string NameFor(this PKMember member, LookupContext ctx) =>
member.NamePrivacy.CanAccess(ctx) ? member.Name : member.DisplayName ?? member.Name; member.NamePrivacy.CanAccess(ctx) ? member.Name : member.DisplayName ?? member.Name;
public static string AvatarFor(this PKMember member, LookupContext ctx) =>
member.AvatarPrivacy.CanAccess(ctx) ? member.AvatarUrl : null;
} }
} }

View File

@ -25,6 +25,7 @@ namespace PluralKit.Core {
public PrivacyLevel MemberVisibility { get; set; } public PrivacyLevel MemberVisibility { get; set; }
public PrivacyLevel DescriptionPrivacy { get; set; } public PrivacyLevel DescriptionPrivacy { get; set; }
public PrivacyLevel AvatarPrivacy { get; set; }
public PrivacyLevel NamePrivacy { get; set; } //ignore setting if no display name is set public PrivacyLevel NamePrivacy { get; set; } //ignore setting if no display name is set
public PrivacyLevel BirthdayPrivacy { get; set; } public PrivacyLevel BirthdayPrivacy { get; set; }
public PrivacyLevel PronounPrivacy { get; set; } public PrivacyLevel PronounPrivacy { get; set; }

View File

@ -150,7 +150,7 @@ namespace PluralKit.Core {
public async Task SaveMember(PKMember member) { public async Task SaveMember(PKMember member) {
using (var conn = await _conn.Obtain()) using (var conn = await _conn.Obtain())
await conn.ExecuteAsync("update members set name = @Name, display_name = @DisplayName, description = @Description, color = @Color, avatar_url = @AvatarUrl, birthday = @Birthday, pronouns = @Pronouns, proxy_tags = @ProxyTags, keep_proxy = @KeepProxy, member_visibility = @MemberVisibility, description_privacy = @DescriptionPrivacy, name_privacy = @NamePrivacy, birthday_privacy = @BirthdayPrivacy, pronoun_privacy = @PronounPrivacy, metadata_privacy = @MetadataPrivacy where id = @Id", member); await conn.ExecuteAsync("update members set name = @Name, display_name = @DisplayName, description = @Description, color = @Color, avatar_url = @AvatarUrl, birthday = @Birthday, pronouns = @Pronouns, proxy_tags = @ProxyTags, keep_proxy = @KeepProxy, member_visibility = @MemberVisibility, description_privacy = @DescriptionPrivacy, name_privacy = @NamePrivacy, avatar_privacy = @AvatarPrivacy, birthday_privacy = @BirthdayPrivacy, pronoun_privacy = @PronounPrivacy, metadata_privacy = @MetadataPrivacy where id = @Id", member);
_logger.Information("Updated member {@Member}", member); _logger.Information("Updated member {@Member}", member);
} }

View File

@ -6,6 +6,7 @@ namespace PluralKit.Core
Visibility, Visibility,
Name, Name,
Description, Description,
Avatar,
Birthday, Birthday,
Pronouns, Pronouns,
Metadata Metadata
@ -17,6 +18,7 @@ namespace PluralKit.Core
{ {
MemberPrivacySubject.Name => "name", MemberPrivacySubject.Name => "name",
MemberPrivacySubject.Description => "description", MemberPrivacySubject.Description => "description",
MemberPrivacySubject.Avatar => "avatar",
MemberPrivacySubject.Pronouns => "pronouns", MemberPrivacySubject.Pronouns => "pronouns",
MemberPrivacySubject.Birthday => "birthday", MemberPrivacySubject.Birthday => "birthday",
MemberPrivacySubject.Metadata => "metadata", MemberPrivacySubject.Metadata => "metadata",
@ -31,6 +33,7 @@ namespace PluralKit.Core
{ {
MemberPrivacySubject.Name => member.NamePrivacy = level, MemberPrivacySubject.Name => member.NamePrivacy = level,
MemberPrivacySubject.Description => member.DescriptionPrivacy = level, MemberPrivacySubject.Description => member.DescriptionPrivacy = level,
MemberPrivacySubject.Avatar => member.AvatarPrivacy = level,
MemberPrivacySubject.Pronouns => member.PronounPrivacy = level, MemberPrivacySubject.Pronouns => member.PronounPrivacy = level,
MemberPrivacySubject.Birthday => member.BirthdayPrivacy= level, MemberPrivacySubject.Birthday => member.BirthdayPrivacy= level,
MemberPrivacySubject.Metadata => member.MetadataPrivacy = level, MemberPrivacySubject.Metadata => member.MetadataPrivacy = level,
@ -43,6 +46,7 @@ namespace PluralKit.Core
{ {
member.NamePrivacy = level; member.NamePrivacy = level;
member.DescriptionPrivacy = level; member.DescriptionPrivacy = level;
member.AvatarPrivacy = level;
member.PronounPrivacy = level; member.PronounPrivacy = level;
member.BirthdayPrivacy = level; member.BirthdayPrivacy = level;
member.MetadataPrivacy = level; member.MetadataPrivacy = level;
@ -62,6 +66,12 @@ namespace PluralKit.Core
case "info": case "info":
subject = MemberPrivacySubject.Description; subject = MemberPrivacySubject.Description;
break; break;
case "avatar":
case "pfp":
case "pic":
case "icon":
subject = MemberPrivacySubject.Avatar;
break;
case "birthday": case "birthday":
case "birth": case "birth":
case "bday": case "bday":

View File

@ -449,10 +449,11 @@ For example:
When the **member list** is **private**, other users will not be able to view the full member list of your system, but they can still query individual members given their 5-letter ID. If **current fronter** is private, but **front history** isn't, someone can still see the current fronter by looking at the history (this combination doesn't make much sense). When the **member list** is **private**, other users will not be able to view the full member list of your system, but they can still query individual members given their 5-letter ID. If **current fronter** is private, but **front history** isn't, someone can still see the current fronter by looking at the history (this combination doesn't make much sense).
### Member privacy ### Member privacy
There are also six options for configuring member privacy; There are also seven options for configuring member privacy;
- Name - Name
- Description - Description
- Avatar
- Birthday - Birthday
- Pronouns - Pronouns
- Metadata *(message count, creation date, etc)* - Metadata *(message count, creation date, etc)*
@ -468,8 +469,8 @@ To update a members privacy you can use the command:
member <member> privacy <subject> <level> member <member> privacy <subject> <level>
where `<member>` is the name or the id of a member in your system, `<subject>` is either `name`, `description`, `birthday`, `pronouns`, `metadata`, or `visiblity` corresponding to the options above, and `<level>` is either `public` or `private`. `<subject>` can also be `all` in order to change all subjects at once. where `<member>` is the name or the id of a member in your system, `<subject>` is either `name`, `description`, `avatar`, `birthday`, `pronouns`, `metadata`, or `visiblity` corresponding to the options above, and `<level>` is either `public` or `private`. `<subject>` can also be `all` in order to change all subjects at once.
`metatdata` will affect the message count, the date created, the last fronted, and the last message information. `metadata` will affect the message count, the date created, the last fronted, and the last message information.
For example: For example:

View File

@ -68,6 +68,7 @@ The following three models (usually represented in JSON format) represent the va
|visibility|string?|Yes|Patching with `private` will set it to private; `public` or `null` will set it to public.| |visibility|string?|Yes|Patching with `private` will set it to private; `public` or `null` will set it to public.|
|name_privacy|string?|Yes|Patching with `private` will set it to private; `public` or `null` will set it to public.| |name_privacy|string?|Yes|Patching with `private` will set it to private; `public` or `null` will set it to public.|
|description_privacy|string?|Yes|Patching with `private` will set it to private; `public` or `null` will set it to public.| |description_privacy|string?|Yes|Patching with `private` will set it to private; `public` or `null` will set it to public.|
|avatar_privacy|string?|Yes|Patching with `private` will set it to private; `public` or `null` will set it to public.|
|birthday_privacy|string?|Yes|Patching with `private` will set it to private; `public` or `null` will set it to public.| |birthday_privacy|string?|Yes|Patching with `private` will set it to private; `public` or `null` will set it to public.|
|pronoun_privacy|string?|Yes|Patching with `private` will set it to private; `public` or `null` will set it to public.| |pronoun_privacy|string?|Yes|Patching with `private` will set it to private; `public` or `null` will set it to public.|
|metadata_privacy|string?|Yes|Patching with `private` will set it to private; `public` or `null` will set it to public.| |metadata_privacy|string?|Yes|Patching with `private` will set it to private; `public` or `null` will set it to public.|
@ -234,6 +235,7 @@ If the system has chosen to hide its current fronters, this will return `403 For
"visibility": null, "visibility": null,
"name_privacy": null, "name_privacy": null,
"description_privacy": null, "description_privacy": null,
"avatar_privacy": null,
"birthday_privacy": null, "birthday_privacy": null,
"pronoun_privacy": null, "pronoun_privacy": null,
"metadata_privacy": null, "metadata_privacy": null,
@ -322,6 +324,7 @@ If this member is marked private, and the request isn't authenticated with the m
"visibility": "public", "visibility": "public",
"name_privacy": "public", "name_privacy": "public",
"description_privacy": "private", "description_privacy": "private",
"avatar_privacy": "private",
"birthday_privacy": "private", "birthday_privacy": "private",
"pronoun_privacy": "public", "pronoun_privacy": "public",
"metadata_privacy": "public" "metadata_privacy": "public"
@ -349,6 +352,7 @@ Creates a new member with the information given. Missing fields (except for name
"visibility": "public", "visibility": "public",
"name_privacy": "public", "name_privacy": "public",
"description_privacy": "private", "description_privacy": "private",
"avatar_privacy": "private",
"birthday_privacy": "private", "birthday_privacy": "private",
"pronoun_privacy": "public", "pronoun_privacy": "public",
"metadata_privacy": "private" "metadata_privacy": "private"
@ -400,6 +404,7 @@ Edits a member's information. Missing fields will keep their current values. Wil
"visibility": "public", "visibility": "public",
"name_privacy": "public", "name_privacy": "public",
"description_privacy": "private", "description_privacy": "private",
"avatar_privacy": "private",
"birthday_privacy": "private", "birthday_privacy": "private",
"pronoun_privacy": "public", "pronoun_privacy": "public",
"metadata_privacy": "private" "metadata_privacy": "private"
@ -424,6 +429,7 @@ Edits a member's information. Missing fields will keep their current values. Wil
"visibility": "public", "visibility": "public",
"name_privacy": "public", "name_privacy": "public",
"description_privacy": "private", "description_privacy": "private",
"avatar_privacy": "private",
"birthday_privacy": "private", "birthday_privacy": "private",
"pronoun_privacy": "public", "pronoun_privacy": "public",
"metadata_privacy": "private" "metadata_privacy": "private"
@ -505,6 +511,7 @@ The returned system and member's privacy settings will be respected, and as such
"visibility": "public", "visibility": "public",
"name_privacy": "public", "name_privacy": "public",
"description_privacy": "private", "description_privacy": "private",
"avatar_privacy": "private",
"birthday_privacy": "private", "birthday_privacy": "private",
"pronoun_privacy": "public", "pronoun_privacy": "public",
"metadata_privacy": "private" "metadata_privacy": "private"
@ -514,7 +521,7 @@ The returned system and member's privacy settings will be respected, and as such
## Version history ## Version history
* 2020-06-17 (v1.1) * 2020-06-17 (v1.1)
* The API now has values for granular member privacy. The new fields are as follows: `visibility`, `name_privacy`, `description_privacy`, `birthday_privacy`, `pronoun_privacy`, `metadata_privacy`. All are strings and accept the values of `public`, `private` and `null` * The API now has values for granular member privacy. The new fields are as follows: `visibility`, `name_privacy`, `description_privacy`, `avatar_privacy`, `birthday_privacy`, `pronoun_privacy`, `metadata_privacy`. All are strings and accept the values of `public`, `private` and `null`.
* The `privacy` field has now been deprecated and should not be used. It's still returned (mirroring the `visibility` field), and writing to it will write to *all privacy options*. * The `privacy` field has now been deprecated and should not be used. It's still returned (mirroring the `visibility` field), and writing to it will write to *all privacy options*.
* 2020-05-07 * 2020-05-07
* The API (v1) is now formally(ish) defined with OpenAPI v3.0. [The definition file can be found here.](https://github.com/xSke/PluralKit/blob/master/PluralKit.API/openapi.yaml) * The API (v1) is now formally(ish) defined with OpenAPI v3.0. [The definition file can be found here.](https://github.com/xSke/PluralKit/blob/master/PluralKit.API/openapi.yaml)