From c7f8f1ec291faa9d3163e03f699a39e797f75f6d Mon Sep 17 00:00:00 2001 From: Charles Iliya Krempeaux Date: Thu, 28 Sep 2023 06:13:25 +0900 Subject: [PATCH] initial commits --- ent/account.go | 395 ++++++++++++++++++++++++-- ent/accountholder.go | 52 ++++ ent/accountholder_marshaljson_test.go | 210 ++++++++++++++ ent/errors.go | 2 +- 4 files changed, 635 insertions(+), 24 deletions(-) create mode 100644 ent/accountholder.go create mode 100644 ent/accountholder_marshaljson_test.go diff --git a/ent/account.go b/ent/account.go index b78c6fb..4c18e00 100644 --- a/ent/account.go +++ b/ent/account.go @@ -1,36 +1,385 @@ package ent import ( + "encoding/json" + + "sourcecode.social/reiver/go-erorr" + "sourcecode.social/reiver/go-nul" "sourcecode.social/reiver/go-opt" "sourcecode.social/reiver/go-jsonint" ) +var _ json.Marshaler = Account{} + // Account represents a Mastodon API "Account". // // See: // https://docs.joinmastodon.org/entities/Account/ type Account struct { - ID opt.Optional[string] `json:"id"` - UserName opt.Optional[string] `json:"username"` - Acct opt.Optional[string] `json:"acct"` - DisplayName opt.Optional[string] `json:"display_name"` - Locked opt.Optional[bool] `json:"locked"` - Bot opt.Optional[bool] `json:"bot"` - Discoverable opt.Optional[bool] `json:"discoverable"` - CreatedAt opt.Optional[string] `json:"created_at"` - Note opt.Optional[string] `json:"note"` - URL opt.Optional[string] `json:"url"` - URI opt.Optional[string] `json:"uri"` - Avatar opt.Optional[string] `json:"avatar"` - AvatarStatic opt.Optional[string] `json:"avatar_static"` - Header opt.Optional[string] `json:"header"` - HeaderStatic opt.Optional[string] `json:"header_static"` - FollowersCount opt.Optional[jsonint.Int] `json:"followers_count"` - FollowingCount opt.Optional[jsonint.Int] `json:"following_count"` - StatusesCount opt.Optional[jsonint.Int] `json:"statuses_count"` - LastStatusAt opt.Optional[string] `json:"last_status_at"` - NoIndex opt.Optional[bool] `json:"noindex"` - Emojis []CustomEmoji `json:"emojis"` - Roles []Role `json:"roles"` - Fields []Field `json:"fields"` + ID opt.Optional[string] `json:"id"` + UserName opt.Optional[string] `json:"username"` + Acct opt.Optional[string] `json:"acct"` + URL opt.Optional[string] `json:"url"` + URI opt.Optional[string] `json:"uri"` // currently undocumented, but is included in in account JSON returned from the Mastodon API on mastodon.social. + DisplayName opt.Optional[string] `json:"display_name"` + Note opt.Optional[string] `json:"note"` + Avatar opt.Optional[string] `json:"avatar"` + AvatarStatic opt.Optional[string] `json:"avatar_static"` + Header opt.Optional[string] `json:"header"` + HeaderStatic opt.Optional[string] `json:"header_static"` + Locked opt.Optional[bool] `json:"locked"` + Fields []Field `json:"fields"` + Emojis []CustomEmoji `json:"emojis"` + Bot opt.Optional[bool] `json:"bot"` + Group opt.Optional[bool] `json:"group"` + Discoverable nul.Nullable[bool] `json:"discoverable"` + NoIndex nul.Nullable[bool] `json:"noindex"` + Moved nul.Nullable[AccountHolder] `json:"moved"` + Suspended opt.Optional[bool] `json:"suspended"` + Limited opt.Optional[bool] `json:"limited"` + CreatedAt opt.Optional[string] `json:"created_at"` + LastStatusAt nul.Nullable[string] `json:"last_status_at"` + StatusesCount opt.Optional[jsonint.Int] `json:"statuses_count"` + FollowersCount opt.Optional[jsonint.Int] `json:"followers_count"` + FollowingCount opt.Optional[jsonint.Int] `json:"following_count"` + Roles []Role `json:"roles"` + MuteExpiresAt nul.Nullable[string] `json:"mute_expires_at"` +} + +func (receiver Account) MarshalJSON() ([]byte, error) { + + var buffer []byte + + buffer = append(buffer, "{"...) + + { + buffer = append(buffer, `"id":`...) + + marshaled, err := json.Marshal(receiver.ID) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.ID as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + + { + buffer = append(buffer, `,"username":`...) + + marshaled, err := json.Marshal(receiver.UserName) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.UserName as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + + { + buffer = append(buffer, `,"acct":`...) + + marshaled, err := json.Marshal(receiver.Acct) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.Acct as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + + { + buffer = append(buffer, `,"url":`...) + + marshaled, err := json.Marshal(receiver.URL) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.URL as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + + { + buffer = append(buffer, `,"uri":`...) + + marshaled, err := json.Marshal(receiver.URI) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.URI as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + + { + buffer = append(buffer, `,"display_name":`...) + + marshaled, err := json.Marshal(receiver.DisplayName) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.DisplayName as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + + { + buffer = append(buffer, `,"note":`...) + + marshaled, err := json.Marshal(receiver.Note) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.Note as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + + { + buffer = append(buffer, `,"avatar":`...) + + marshaled, err := json.Marshal(receiver.Avatar) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.Avatar as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + + { + buffer = append(buffer, `,"avatar_static":`...) + + marshaled, err := json.Marshal(receiver.AvatarStatic) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.AvatarStatic as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + + { + buffer = append(buffer, `,"header":`...) + + marshaled, err := json.Marshal(receiver.Header) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.Header as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + + { + buffer = append(buffer, `,"header_static":`...) + + marshaled, err := json.Marshal(receiver.HeaderStatic) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.HeaderStatic as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + + { + buffer = append(buffer, `,"locked":`...) + + marshaled, err := json.Marshal(receiver.Locked) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.Locked as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + + { + buffer = append(buffer, `,"fields":`...) + + marshaled, err := json.Marshal(receiver.Fields) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.Fields as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + + { + buffer = append(buffer, `,"emojis":`...) + + marshaled, err := json.Marshal(receiver.Emojis) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.Emojis as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + + { + buffer = append(buffer, `,"bot":`...) + + marshaled, err := json.Marshal(receiver.Bot) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.Bot as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + + { + buffer = append(buffer, `,"group":`...) + + marshaled, err := json.Marshal(receiver.Group) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.Group as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + + { + buffer = append(buffer, `,"discoverable":`...) + + marshaled, err := json.Marshal(receiver.Discoverable) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.Discoverable as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + + { + if nul.Nothing[bool]() != receiver.Discoverable { + + buffer = append(buffer, `,"noindex":`...) + + marshaled, err := json.Marshal(receiver.Discoverable) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.Discoverable as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + } + + { + if nul.Nothing[AccountHolder]() != receiver.Moved { + + buffer = append(buffer, `,"moved":`...) + + marshaled, err := json.Marshal(receiver.Moved) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.Moved as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + } + + { + if opt.Nothing[bool]() != receiver.Suspended { + + buffer = append(buffer, `,"suspended":`...) + + marshaled, err := json.Marshal(receiver.Suspended) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.Suspended as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + } + + { + if opt.Nothing[bool]() != receiver.Limited { + + buffer = append(buffer, `,"limited":`...) + + marshaled, err := json.Marshal(receiver.Limited) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.Limited as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + } + + { + buffer = append(buffer, `,"created_at":`...) + + marshaled, err := json.Marshal(receiver.CreatedAt) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.CreatedAt as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + + { + buffer = append(buffer, `,"last_status_at":`...) + + marshaled, err := json.Marshal(receiver.LastStatusAt) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.LastStatusAt as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + + { + buffer = append(buffer, `,"statuses_count":`...) + + marshaled, err := json.Marshal(receiver.StatusesCount) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.StatusesCount as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + + { + buffer = append(buffer, `,"followers_count":`...) + + marshaled, err := json.Marshal(receiver.FollowersCount) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.FollowersCount as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + + { + buffer = append(buffer, `,"following_count":`...) + + marshaled, err := json.Marshal(receiver.FollowingCount) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.FollowingCount as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + + { + if nil != receiver.Roles { + + buffer = append(buffer, `,"roles":`...) + + marshaled, err := json.Marshal(receiver.Roles) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.Roles as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + } + + { + if nul.Nothing[string]() != receiver.MuteExpiresAt { + + buffer = append(buffer, `,"mute_expires_at":`...) + + marshaled, err := json.Marshal(receiver.MuteExpiresAt) + if nil != err { + return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.MuteExpiresAt as JSON: %w", err) + } + + buffer = append(buffer, marshaled...) + } + } + + + buffer = append(buffer, "}"...) + + return buffer, nil } diff --git a/ent/accountholder.go b/ent/accountholder.go new file mode 100644 index 0000000..871e936 --- /dev/null +++ b/ent/accountholder.go @@ -0,0 +1,52 @@ +package ent + +import ( + "encoding/json" +) + +var _ json.Marshaler = AccountHolder{} +var _ json.Unmarshaler = new(AccountHolder) + +// AccountHolder is a holder for a Mastodon API "Account". +// +// The way that Account and AccountHolder is different is that — +// AccountHolder just stores the JSON it receives from a UnmarshalJSON. +// It does not try to parse it or validate it. +// +// AccountHolder is useful for situations where you have a recursive type. +// Such as with Account.Moved. +// +// See: +// https://docs.joinmastodon.org/entities/Account/ +// +// And in particular see: +// https://docs.joinmastodon.org/entities/Account/#moved +type AccountHolder struct { + json string +} + +//func (receiver AccountHolder) Account() (Account, error) { +// +//} + +func (receiver AccountHolder) MarshalJSON() ([]byte, error) { + if "" == receiver.json { + return []byte("{}"), nil + } + + return []byte(receiver.json), nil +} + +func (receiver *AccountHolder) UnmarshalJSON(data []byte) error { + if nil == receiver { + return errNilReceiver + } + + if 2 == len(data) && '{' == data[0] && '}' == data[1] { + receiver.json = "" + return nil + } + + receiver.json = string(data) + return nil +} diff --git a/ent/accountholder_marshaljson_test.go b/ent/accountholder_marshaljson_test.go new file mode 100644 index 0000000..f7e35f3 --- /dev/null +++ b/ent/accountholder_marshaljson_test.go @@ -0,0 +1,210 @@ +package ent + +import ( + "testing" + + "encoding/json" +) + +func TestAccountHolder_MarshalJSON(t *testing.T) { + + tests := []struct{ + AccountHolder AccountHolder + Expected string + }{ + { + AccountHolder: AccountHolder{ + json: ``, + }, + Expected:`{}`, + }, + { + AccountHolder: AccountHolder{ + json: `{}`, + }, + Expected:`{}`, + }, + + + + { + AccountHolder: AccountHolder{ + json: `{"once":1,"twice":"two","thrice":"٣","fource":"𐌠𐌡"}`, + }, + Expected: `{"once":1,"twice":"two","thrice":"٣","fource":"𐌠𐌡"}`, + }, + + + + { + AccountHolder: AccountHolder{ + json: `{`+ + `"id":1234567890123`+ + `,`+ + `"username":"jowblow"`+ + `,`+ + `"acct":"joeblow"`+ + `,`+ + `"display_name":"Joe Blow :-)"`+ + `,`+ + `"locked":false`+ + `,`+ + `"bot":false`+ + `,`+ + `"discoverable":true`+ + `,`+ + `"group":false`+ + `,`+ + `"created_at":"1970-01-01T00:00:00.000Z"`+ + `}`, + }, + Expected: `{`+ + `"id":1234567890123`+ + `,`+ + `"username":"jowblow"`+ + `,`+ + `"acct":"joeblow"`+ + `,`+ + `"display_name":"Joe Blow :-)"`+ + `,`+ + `"locked":false`+ + `,`+ + `"bot":false`+ + `,`+ + `"discoverable":true`+ + `,`+ + `"group":false`+ + `,`+ + `"created_at":"1970-01-01T00:00:00.000Z"`+ + `}`, + }, + + + + { + AccountHolder: AccountHolder{ + json: `{`+ + `"id":"108116990725247731"`+ + `,`+ + `"username":"reiver"`+ + `,`+ + `"acct":"reiver"`+ + `,`+ + `"display_name":"@reiver ⊼ (Charles) :batman:"`+ + `,`+ + `"locked":false`+ + `,`+ + `"bot":false`+ + `,`+ + `"discoverable":true`+ + `,`+ + `"group":false`+ + `,`+ + `"created_at":"2022-04-12T00:00:00.000Z"`+ + `,`+ + `"note":"\u003cp\u003e\u003ca href=\"https://mastodon.social/tags/Fediverse\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003eFediverse\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/Tech\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003eTech\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/Privacy\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003ePrivacy\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/SciFiArt\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003eSciFiArt\u003c/span\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003e\u003ca href=\"https://mastodon.social/tags/FediverseAcademy\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003eFediverseAcademy\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/FediverseCity\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003eFediverseCity\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/FingerProtocol\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003eFingerProtocol\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/GreatApe\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003eGreatApe\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/PostFreely\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003ePostFreely\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/SpaceHost\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003eSpaceHost\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/StarSeed\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003eStarSeed\u003c/span\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003eOnce upon a time, was a mathematician, computer scientist, data scientist, software engineer, industrial researcher 🌞 \u003c/p\u003e\u003cp\u003eVlogger 🌞\u003c/p\u003e\u003cp\u003eOther foci \u003ca href=\"https://mastodon.social/tags/anthropology\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003eanthropology\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/artificialLife\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003eartificialLife\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/biology\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003ebiology\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/egyptology\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003eegyptology\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/evolutionaryAlgorithms\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003eevolutionaryAlgorithms\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/geneticGenealogy\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003egeneticGenealogy\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/humanBehavior\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003ehumanBehavior\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/mythology\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003emythology\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/p2p\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003ep2p\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/paleoGenetics\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003epaleoGenetics\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/populationGenetics\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003epopulationGenetics\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/strongAI\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003estrongAI\u003c/span\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003eThe meaning of life — first survive, then reproduce 🌞\u003c/p\u003e"`+ + `,`+ + `"url":"https://mastodon.social/@reiver"`+ + `,`+ + `"uri":"https://mastodon.social/users/reiver"`+ + `,`+ + `"avatar":"https://files.mastodon.social/accounts/avatars/108/116/990/725/247/731/original/2e097b7812894201.png"`+ + `,`+ + `"avatar_static":"https://files.mastodon.social/accounts/avatars/108/116/990/725/247/731/original/2e097b7812894201.png"`+ + `,`+ + `"header":"https://files.mastodon.social/accounts/headers/108/116/990/725/247/731/original/7713e4efcfcb9c47.png"`+ + `,`+ + `"header_static":"https://files.mastodon.social/accounts/headers/108/116/990/725/247/731/original/7713e4efcfcb9c47.png"`+ + `,`+ + `"followers_count":1342`+ + `,`+ + `"following_count":845`+ + `,`+ + `"statuses_count":11631`+ + `,`+ + `"last_status_at":"2023-09-27"`+ + `,`+ + `"noindex":false`+ + `,`+ + `"emojis":[{"shortcode":"batman","url":"https://files.mastodon.social/custom_emojis/images/000/005/163/original/8iGbkB7aT.png","static_url":"https://files.mastodon.social/custom_emojis/images/000/005/163/static/8iGbkB7aT.png","visible_in_picker":true}]`+ + `,`+ + `"roles":[]`+ + `,`+ + `"fields":[{"name":"Bio","value":"\u003ca href=\"https://changelog.ca/\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\" translate=\"no\"\u003e\u003cspan class=\"invisible\"\u003ehttps://\u003c/span\u003e\u003cspan class=\"\"\u003echangelog.ca/\u003c/span\u003e\u003cspan class=\"invisible\"\u003e\u003c/span\u003e\u003c/a\u003e","verified_at":"2023-04-07T03:44:01.580+00:00"},{"name":"Alt (life-casting)","value":"\u003ca href=\"https://firefish.lol/@reiver\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\" translate=\"no\"\u003e\u003cspan class=\"invisible\"\u003ehttps://\u003c/span\u003e\u003cspan class=\"\"\u003efirefish.lol/@reiver\u003c/span\u003e\u003cspan class=\"invisible\"\u003e\u003c/span\u003e\u003c/a\u003e","verified_at":null},{"name":"Alt (#SpaceHost)","value":"\u003ca href=\"https://spacehost.team/@charles\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\" translate=\"no\"\u003e\u003cspan class=\"invisible\"\u003ehttps://\u003c/span\u003e\u003cspan class=\"\"\u003espacehost.team/@charles\u003c/span\u003e\u003cspan class=\"invisible\"\u003e\u003c/span\u003e\u003c/a\u003e","verified_at":"2023-09-16T07:20:38.250+00:00"},{"name":"Location","value":"Metro Vancouver 🇨🇦","verified_at":null}]`+ + `}`, + }, + Expected: `{`+ + `"id":"108116990725247731"`+ + `,`+ + `"username":"reiver"`+ + `,`+ + `"acct":"reiver"`+ + `,`+ + `"display_name":"@reiver ⊼ (Charles) :batman:"`+ + `,`+ + `"locked":false`+ + `,`+ + `"bot":false`+ + `,`+ + `"discoverable":true`+ + `,`+ + `"group":false`+ + `,`+ + `"created_at":"2022-04-12T00:00:00.000Z"`+ + `,`+ + `"note":"\u003cp\u003e\u003ca href=\"https://mastodon.social/tags/Fediverse\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003eFediverse\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/Tech\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003eTech\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/Privacy\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003ePrivacy\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/SciFiArt\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003eSciFiArt\u003c/span\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003e\u003ca href=\"https://mastodon.social/tags/FediverseAcademy\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003eFediverseAcademy\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/FediverseCity\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003eFediverseCity\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/FingerProtocol\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003eFingerProtocol\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/GreatApe\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003eGreatApe\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/PostFreely\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003ePostFreely\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/SpaceHost\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003eSpaceHost\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/StarSeed\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003eStarSeed\u003c/span\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003eOnce upon a time, was a mathematician, computer scientist, data scientist, software engineer, industrial researcher 🌞 \u003c/p\u003e\u003cp\u003eVlogger 🌞\u003c/p\u003e\u003cp\u003eOther foci \u003ca href=\"https://mastodon.social/tags/anthropology\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003eanthropology\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/artificialLife\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003eartificialLife\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/biology\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003ebiology\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/egyptology\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003eegyptology\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/evolutionaryAlgorithms\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003eevolutionaryAlgorithms\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/geneticGenealogy\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003egeneticGenealogy\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/humanBehavior\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003ehumanBehavior\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/mythology\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003emythology\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/p2p\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003ep2p\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/paleoGenetics\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003epaleoGenetics\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/populationGenetics\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003epopulationGenetics\u003c/span\u003e\u003c/a\u003e \u003ca href=\"https://mastodon.social/tags/strongAI\" class=\"mention hashtag\" rel=\"tag\"\u003e#\u003cspan\u003estrongAI\u003c/span\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003eThe meaning of life — first survive, then reproduce 🌞\u003c/p\u003e"`+ + `,`+ + `"url":"https://mastodon.social/@reiver"`+ + `,`+ + `"uri":"https://mastodon.social/users/reiver"`+ + `,`+ + `"avatar":"https://files.mastodon.social/accounts/avatars/108/116/990/725/247/731/original/2e097b7812894201.png"`+ + `,`+ + `"avatar_static":"https://files.mastodon.social/accounts/avatars/108/116/990/725/247/731/original/2e097b7812894201.png"`+ + `,`+ + `"header":"https://files.mastodon.social/accounts/headers/108/116/990/725/247/731/original/7713e4efcfcb9c47.png"`+ + `,`+ + `"header_static":"https://files.mastodon.social/accounts/headers/108/116/990/725/247/731/original/7713e4efcfcb9c47.png"`+ + `,`+ + `"followers_count":1342`+ + `,`+ + `"following_count":845`+ + `,`+ + `"statuses_count":11631`+ + `,`+ + `"last_status_at":"2023-09-27"`+ + `,`+ + `"noindex":false`+ + `,`+ + `"emojis":[{"shortcode":"batman","url":"https://files.mastodon.social/custom_emojis/images/000/005/163/original/8iGbkB7aT.png","static_url":"https://files.mastodon.social/custom_emojis/images/000/005/163/static/8iGbkB7aT.png","visible_in_picker":true}]`+ + `,`+ + `"roles":[]`+ + `,`+ + `"fields":[{"name":"Bio","value":"\u003ca href=\"https://changelog.ca/\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\" translate=\"no\"\u003e\u003cspan class=\"invisible\"\u003ehttps://\u003c/span\u003e\u003cspan class=\"\"\u003echangelog.ca/\u003c/span\u003e\u003cspan class=\"invisible\"\u003e\u003c/span\u003e\u003c/a\u003e","verified_at":"2023-04-07T03:44:01.580+00:00"},{"name":"Alt (life-casting)","value":"\u003ca href=\"https://firefish.lol/@reiver\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\" translate=\"no\"\u003e\u003cspan class=\"invisible\"\u003ehttps://\u003c/span\u003e\u003cspan class=\"\"\u003efirefish.lol/@reiver\u003c/span\u003e\u003cspan class=\"invisible\"\u003e\u003c/span\u003e\u003c/a\u003e","verified_at":null},{"name":"Alt (#SpaceHost)","value":"\u003ca href=\"https://spacehost.team/@charles\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\" translate=\"no\"\u003e\u003cspan class=\"invisible\"\u003ehttps://\u003c/span\u003e\u003cspan class=\"\"\u003espacehost.team/@charles\u003c/span\u003e\u003cspan class=\"invisible\"\u003e\u003c/span\u003e\u003c/a\u003e","verified_at":"2023-09-16T07:20:38.250+00:00"},{"name":"Location","value":"Metro Vancouver 🇨🇦","verified_at":null}]`+ + `}`, + }, + } + + for testNumber, test := range tests { + + actualBytes, err := json.Marshal(test.AccountHolder) + if nil != err { + t.Errorf("For test #%d, did not expect an error but actually got one.", testNumber) + t.Logf("ERROR: (%T) %s", err, err) + t.Logf("ACCOUNT-HOLDER: %#v", test.AccountHolder) + continue + } + + { + actual := string(actualBytes) + expected := test.Expected + + if expected != actual { + t.Errorf("For test #%d, the actual value is not what was expected", testNumber) + t.Logf("EXPECTED:\n%s", expected) + t.Logf("ACTUAL:\n%s", actual) + continue + } + } + } +} diff --git a/ent/errors.go b/ent/errors.go index 6092fe9..413ebf8 100644 --- a/ent/errors.go +++ b/ent/errors.go @@ -5,5 +5,5 @@ import ( ) const ( - errNilReceiver = erorr.Error("mstdn: nil receiver") + errNilReceiver = erorr.Error("mstdn/ent: nil receiver") )