#nullable enable using System.Linq; using System.Text.RegularExpressions; using NodaTime; using Newtonsoft.Json.Linq; namespace PluralKit.Core { public class MemberPatch: PatchObject { public Partial Name { get; set; } public Partial Hid { get; set; } public Partial DisplayName { get; set; } public Partial AvatarUrl { get; set; } public Partial BannerImage { get; set; } public Partial Color { get; set; } public Partial Birthday { get; set; } public Partial Pronouns { get; set; } public Partial Description { get; set; } public Partial ProxyTags { get; set; } public Partial KeepProxy { get; set; } public Partial MessageCount { get; set; } public Partial AllowAutoproxy { get; set; } public Partial Visibility { get; set; } public Partial NamePrivacy { get; set; } public Partial DescriptionPrivacy { get; set; } public Partial PronounPrivacy { get; set; } public Partial BirthdayPrivacy { get; set; } public Partial AvatarPrivacy { get; set; } public Partial MetadataPrivacy { get; set; } public override UpdateQueryBuilder Apply(UpdateQueryBuilder b) => b .With("name", Name) .With("hid", Hid) .With("display_name", DisplayName) .With("avatar_url", AvatarUrl) .With("banner_image", BannerImage) .With("color", Color) .With("birthday", Birthday) .With("pronouns", Pronouns) .With("description", Description) .With("proxy_tags", ProxyTags) .With("keep_proxy", KeepProxy) .With("message_count", MessageCount) .With("allow_autoproxy", AllowAutoproxy) .With("member_visibility", Visibility) .With("name_privacy", NamePrivacy) .With("description_privacy", DescriptionPrivacy) .With("pronoun_privacy", PronounPrivacy) .With("birthday_privacy", BirthdayPrivacy) .With("avatar_privacy", AvatarPrivacy) .With("metadata_privacy", MetadataPrivacy); public new void CheckIsValid() { if (AvatarUrl.Value != null && !MiscUtils.TryMatchUri(AvatarUrl.Value, out var avatarUri)) throw new InvalidPatchException("avatar_url"); if (BannerImage.Value != null && !MiscUtils.TryMatchUri(BannerImage.Value, out var bannerImage)) throw new InvalidPatchException("banner"); if (Color.Value != null && (!Regex.IsMatch(Color.Value, "^[0-9a-fA-F]{6}$"))) throw new InvalidPatchException("color"); } #nullable disable public static MemberPatch FromJSON(JObject o) { var patch = new MemberPatch(); if (o.ContainsKey("name") && o["name"].Type == JTokenType.Null) throw new JsonModelParseError("Member name can not be set to null."); if (o.ContainsKey("name")) patch.Name = o.Value("name").BoundsCheckField(Limits.MaxMemberNameLength, "Member name"); if (o.ContainsKey("color")) patch.Color = o.Value("color").NullIfEmpty()?.ToLower(); if (o.ContainsKey("display_name")) patch.DisplayName = o.Value("display_name").NullIfEmpty().BoundsCheckField(Limits.MaxMemberNameLength, "Member display name"); if (o.ContainsKey("avatar_url")) patch.AvatarUrl = o.Value("avatar_url").NullIfEmpty().BoundsCheckField(Limits.MaxUriLength, "Member avatar URL"); if (o.ContainsKey("banner")) patch.BannerImage = o.Value("banner").NullIfEmpty().BoundsCheckField(Limits.MaxUriLength, "Member banner URL"); if (o.ContainsKey("birthday")) { var str = o.Value("birthday").NullIfEmpty(); var res = DateTimeFormats.DateExportFormat.Parse(str); if (res.Success) patch.Birthday = res.Value; else if (str == null) patch.Birthday = null; else throw new JsonModelParseError("Could not parse member birthday."); } if (o.ContainsKey("pronouns")) patch.Pronouns = o.Value("pronouns").NullIfEmpty().BoundsCheckField(Limits.MaxPronounsLength, "Member pronouns"); if (o.ContainsKey("description")) patch.Description = o.Value("description").NullIfEmpty().BoundsCheckField(Limits.MaxDescriptionLength, "Member descriptoin"); if (o.ContainsKey("keep_proxy")) patch.KeepProxy = o.Value("keep_proxy"); // legacy: used in old export files and APIv1 // todo: should we parse `proxy_tags` first? if (o.ContainsKey("prefix") || o.ContainsKey("suffix") && !o.ContainsKey("proxy_tags")) patch.ProxyTags = new[] {new ProxyTag(o.Value("prefix"), o.Value("suffix"))}; else if (o.ContainsKey("proxy_tags")) { patch.ProxyTags = o.Value("proxy_tags") .OfType().Select(o => new ProxyTag(o.Value("prefix"), o.Value("suffix"))) .ToArray(); } if(o.ContainsKey("privacy")) //TODO: Deprecate this completely in api v2 { var plevel = o.Value("privacy").ParsePrivacy("member"); patch.Visibility = plevel; patch.NamePrivacy = plevel; patch.AvatarPrivacy = plevel; patch.DescriptionPrivacy = plevel; patch.BirthdayPrivacy = plevel; patch.PronounPrivacy = plevel; // member.ColorPrivacy = plevel; patch.MetadataPrivacy = plevel; } else { if (o.ContainsKey("visibility")) patch.Visibility = o.Value("visibility").ParsePrivacy("member"); if (o.ContainsKey("name_privacy")) patch.NamePrivacy = o.Value("name_privacy").ParsePrivacy("member"); if (o.ContainsKey("description_privacy")) patch.DescriptionPrivacy = o.Value("description_privacy").ParsePrivacy("member"); if (o.ContainsKey("avatar_privacy")) patch.AvatarPrivacy = o.Value("avatar_privacy").ParsePrivacy("member"); if (o.ContainsKey("birthday_privacy")) patch.BirthdayPrivacy = o.Value("birthday_privacy").ParsePrivacy("member"); if (o.ContainsKey("pronoun_privacy")) patch.PronounPrivacy = o.Value("pronoun_privacy").ParsePrivacy("member"); // if (o.ContainsKey("color_privacy")) member.ColorPrivacy = o.Value("color_privacy").ParsePrivacy("member"); if (o.ContainsKey("metadata_privacy")) patch.MetadataPrivacy = o.Value("metadata_privacy").ParsePrivacy("member"); } return patch; } } }