Compare commits
	
		
			No commits in common. "4e1137d17eb222e94e2d7ccd15370100329feea9" and "eca6289ce55e7ea43eea18121c0a84e12d089f18" have entirely different histories. 
		
	
	
		
			4e1137d17e
			...
			eca6289ce5
		
	
		| 
						 | 
				
			
			@ -1,130 +0,0 @@
 | 
			
		|||
package local
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
 | 
			
		||||
	"github.com/reiver/go-httpsse"
 | 
			
		||||
	"github.com/reiver/go-opt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Client represenrs a client for interacting with the "/api/v1/streaming/public/local" API end-point.
 | 
			
		||||
//
 | 
			
		||||
// That API end-point will return a series of events.
 | 
			
		||||
//
 | 
			
		||||
// Client will let you iterate through those events.
 | 
			
		||||
type Client = httpsse.Client
 | 
			
		||||
 | 
			
		||||
type internalClient struct {
 | 
			
		||||
	sseclient httpsse.Client
 | 
			
		||||
	data []string
 | 
			
		||||
	err error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ Client = &internalClient{}
 | 
			
		||||
 | 
			
		||||
func (receiver *internalClient) Close() error {
 | 
			
		||||
	if nil == receiver {
 | 
			
		||||
		return errNilReceiver
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var sseclient httpsse.Client = receiver.sseclient
 | 
			
		||||
 | 
			
		||||
	if nil == sseclient {
 | 
			
		||||
		return errNilHTTPSSEClient
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return sseclient.Close()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (receiver *internalClient) Decode(dst interface{}) error {
 | 
			
		||||
 | 
			
		||||
	if nil == dst {
 | 
			
		||||
		return errNilDestination
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var event *Event
 | 
			
		||||
	{
 | 
			
		||||
		var casted bool
 | 
			
		||||
		event, casted = dst.(*Event)
 | 
			
		||||
		if !casted {
 | 
			
		||||
			
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(receiver.data) <= 0 {
 | 
			
		||||
		
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var datum string
 | 
			
		||||
	{
 | 
			
		||||
		datum, receiver.data = receiver.data[0], receiver.data[1:]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(datum) <= 0 {
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch datum[0] {
 | 
			
		||||
	case '0','1','2','3','4','5','6','7','8','9':
 | 
			
		||||
		event.Name="delete"
 | 
			
		||||
		event.Status.ID = opt.Something(datum)
 | 
			
		||||
	default:
 | 
			
		||||
		event.Name="update"
 | 
			
		||||
 | 
			
		||||
		var bytes []byte = []byte(datum)
 | 
			
		||||
 | 
			
		||||
		{
 | 
			
		||||
			err := json.Unmarshal(bytes, &(event.Status))
 | 
			
		||||
			if nil != err {
 | 
			
		||||
				
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (receiver *internalClient) Err() error {
 | 
			
		||||
	if nil == receiver {
 | 
			
		||||
		return errNilReceiver
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if nil != receiver.err {
 | 
			
		||||
		return receiver.err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return receiver.sseclient.Err()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (receiver *internalClient) Next() bool {
 | 
			
		||||
	if nil == receiver {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if 0 < len(receiver.data) {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	more := receiver.sseclient.Next()
 | 
			
		||||
	if !more {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var event httpsse.Event
 | 
			
		||||
	{
 | 
			
		||||
		err := receiver.sseclient.Decode(&event)
 | 
			
		||||
		if nil != err {
 | 
			
		||||
			receiver.err = err
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	receiver.data = append(receiver.data, event.EventData()...)
 | 
			
		||||
 | 
			
		||||
//@TODO: what if event.EventData() returns an empty array?
 | 
			
		||||
//       which could happen.
 | 
			
		||||
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,46 +0,0 @@
 | 
			
		|||
package local
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/url"
 | 
			
		||||
 | 
			
		||||
	"github.com/reiver/go-httpsse"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func DialHost(host string) (Client, error) {
 | 
			
		||||
	var urloc = url.URL{
 | 
			
		||||
		Scheme:"https",
 | 
			
		||||
		Host:host,
 | 
			
		||||
		Path:Path,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sseclient, err := httpsse.DialURL(urloc.String())
 | 
			
		||||
	if nil != err {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &internalClient{
 | 
			
		||||
		sseclient:sseclient,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Dial(req *http.Request) (Client, error) {
 | 
			
		||||
	if nil == req {
 | 
			
		||||
		return nil, errNilHTTPRequest
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if nil == req.URL {
 | 
			
		||||
		req.URL = new(url.URL)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	req.URL.Path = Path
 | 
			
		||||
 | 
			
		||||
	sseclient, err :=httpsse.Dial(req)
 | 
			
		||||
	if nil != err {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &internalClient{
 | 
			
		||||
		sseclient:sseclient,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,12 +0,0 @@
 | 
			
		|||
package local
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/reiver/go-erorr"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	errNilDestination   = erorr.Error("mstdn: nil destination")
 | 
			
		||||
	errNilHTTPRequest   = erorr.Error("mstdn: nil http-request")
 | 
			
		||||
	errNilHTTPSSEClient = erorr.Error("mstdn: nil http-sse-client")
 | 
			
		||||
	errNilReceiver      = erorr.Error("mstdn: nil receiver")
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -1,24 +0,0 @@
 | 
			
		|||
package local
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/reiver/go-mstdn/ent"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// The "/api/v1/streaming/public/local" API end-points returns a series of events.
 | 
			
		||||
// Event is used to represent one of those events.
 | 
			
		||||
//
 | 
			
		||||
// And event has a 'name'.
 | 
			
		||||
// Currently the possible names are:
 | 
			
		||||
//
 | 
			
		||||
// • "delete"
 | 
			
		||||
// • "update"
 | 
			
		||||
//
 | 
			
		||||
// And event also has a status.
 | 
			
		||||
//
 | 
			
		||||
// If the event is an "update", then all of (or most of) the 'status' should be filled in.
 | 
			
		||||
//
 | 
			
		||||
// If the event is a "delete", then only the 'ID' will be filled in.
 | 
			
		||||
type Event struct {
 | 
			
		||||
	Name string
 | 
			
		||||
	Status ent.Status
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +0,0 @@
 | 
			
		|||
package local
 | 
			
		||||
 | 
			
		||||
const Path string = "/api/v1/streaming/public/local"
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +0,0 @@
 | 
			
		|||
Use "github.com/reiver/go-json" rather than the Go built-in "encoding/json".
 | 
			
		||||
 | 
			
		||||
(Need it so `omitempty` works with more types.)
 | 
			
		||||
							
								
								
									
										406
									
								
								ent/account.go
								
								
								
								
							
							
						
						
									
										406
									
								
								ent/account.go
								
								
								
								
							| 
						 | 
				
			
			@ -1,42 +1,394 @@
 | 
			
		|||
package ent
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
 | 
			
		||||
	"github.com/reiver/go-erorr"
 | 
			
		||||
	"github.com/reiver/go-nul"
 | 
			
		||||
	"github.com/reiver/go-jsonint"
 | 
			
		||||
	"github.com/reiver/go-opt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
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,omitempty"`
 | 
			
		||||
	Acct           opt.Optional[string]        `json:"acct,omitempty"`
 | 
			
		||||
	URL            opt.Optional[string]        `json:"url,omitempty"`
 | 
			
		||||
	URI            opt.Optional[string]        `json:"uri,omitempty"` // currently undocumented, but is included in in account JSON returned from the Mastodon API on mastodon.social.
 | 
			
		||||
	DisplayName    opt.Optional[string]        `json:"display_name,omitempty"`
 | 
			
		||||
	Note           opt.Optional[string]        `json:"note,omitempty"`
 | 
			
		||||
	Avatar         opt.Optional[string]        `json:"avatar,omitempty"`
 | 
			
		||||
	AvatarStatic   opt.Optional[string]        `json:"avatar_static,omitempty"`
 | 
			
		||||
	Header         opt.Optional[string]        `json:"header,omitempty"`
 | 
			
		||||
	HeaderStatic   opt.Optional[string]        `json:"header_static,omitempty"`
 | 
			
		||||
	Fields       []Field                       `json:"fields,omitempty"`
 | 
			
		||||
	Emojis       []CustomEmoji                 `json:"emojis,omitempty"`
 | 
			
		||||
	Locked         opt.Optional[bool]          `json:"locked,omitempty"`
 | 
			
		||||
	Bot            opt.Optional[bool]          `json:"bot,omitempty"`
 | 
			
		||||
	Group          opt.Optional[bool]          `json:"group,omitempty"`
 | 
			
		||||
	Discoverable   nul.Nullable[bool]          `json:"discoverable,omitempty"`
 | 
			
		||||
	NoIndex        nul.Nullable[bool]          `json:"noindex,omitempty"`
 | 
			
		||||
	Moved          nul.Nullable[AccountHolder] `json:"moved,omitempty"`
 | 
			
		||||
	Suspended      opt.Optional[bool]          `json:"suspended,omitempty"`
 | 
			
		||||
	Limited        opt.Optional[bool]          `json:"limited,omitempty"`
 | 
			
		||||
	CreatedAt      opt.Optional[string]        `json:"created_at,omitempty"`
 | 
			
		||||
	LastStatusAt   nul.Nullable[string]        `json:"last_status_at,omitempty"`
 | 
			
		||||
	StatusesCount  opt.Optional[jsonint.Int]   `json:"statuses_count,omitempty"`
 | 
			
		||||
	FollowersCount opt.Optional[jsonint.Int]   `json:"followers_count,omitempty"`
 | 
			
		||||
	FollowingCount opt.Optional[jsonint.Int]   `json:"following_count,omitempty"`
 | 
			
		||||
	Roles        []Role                        `json:"roles,omitempty"`
 | 
			
		||||
	MuteExpiresAt  nul.Nullable[string]        `json:"mute_expires_at,omitempty"`
 | 
			
		||||
	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"`
 | 
			
		||||
	Fields       []Field                       `json:"fields"`
 | 
			
		||||
	Emojis       []CustomEmoji                 `json:"emojis"`
 | 
			
		||||
	Locked         opt.Optional[bool]          `json:"locked"`
 | 
			
		||||
	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, `,"fields":`...)
 | 
			
		||||
 | 
			
		||||
		var src interface{} = receiver.Fields
 | 
			
		||||
		if nil == receiver.Fields {
 | 
			
		||||
			src = []Field{}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		marshaled, err := json.Marshal(src)
 | 
			
		||||
		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":`...)
 | 
			
		||||
 | 
			
		||||
		var src interface{} = receiver.Emojis
 | 
			
		||||
		if nil == receiver.Emojis {
 | 
			
		||||
			src = []CustomEmoji{}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		marshaled, err := json.Marshal(src)
 | 
			
		||||
		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, `,"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, `,"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.NoIndex {
 | 
			
		||||
 | 
			
		||||
			buffer = append(buffer, `,"noindex":`...)
 | 
			
		||||
 | 
			
		||||
			marshaled, err := json.Marshal(receiver.NoIndex)
 | 
			
		||||
			if nil != err {
 | 
			
		||||
				return nil, erorr.Errorf("mstdn/ent: could not marshal ent.Account.NoIndex 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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -3,7 +3,7 @@ package ent
 | 
			
		|||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/reiver/go-json"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestAccountHolder_MarshalJSON(t *testing.T) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,18 +1,140 @@
 | 
			
		|||
package ent
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
 | 
			
		||||
	"github.com/reiver/go-erorr"
 | 
			
		||||
	"github.com/reiver/go-opt"
 | 
			
		||||
	"github.com/reiver/go-nul"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var _ json.Marshaler = Application{}
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	errCannotMashalApplicationAsJSONNoName     = erorr.Error("cannot marshal ent.Application to JSON — no ‘name’ set")
 | 
			
		||||
	errCannotMashalApplicationAsJSONNoVapidKey = erorr.Error("cannot marshal ent.Application to JSON — no ‘vapid_key’ set")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Appication represents a Mastodon API "Appication".
 | 
			
		||||
//
 | 
			
		||||
// See:
 | 
			
		||||
// https://docs.joinmastodon.org/entities/Application/
 | 
			
		||||
type Application struct {
 | 
			
		||||
	Name         opt.Optional[string] `json:"name,omitempty"`
 | 
			
		||||
	WebSite      nul.Nullable[string] `json:"website,omitempty"`       // optional — field has JSON null value in JSON if not set
 | 
			
		||||
	VapidKey     opt.Optional[string] `json:"vapid_key,omitempty"`     // optional — field not included in JSON if not set
 | 
			
		||||
	ClientID     opt.Optional[string] `json:"client_id,omitempty"`     // optional — field not included in JSON if not set
 | 
			
		||||
	ClientSecret opt.Optional[string] `json:"client_secret,omitempty"` // optional — field not included in JSON if not set
 | 
			
		||||
	Name         opt.Optional[string] `json:"name"`
 | 
			
		||||
	WebSite      nul.Nullable[string] `json:"website"`       // optional — field has JSON null value in JSON if not set
 | 
			
		||||
	VapidKey     opt.Optional[string] `json:"vapid_key"`
 | 
			
		||||
	ClientID     opt.Optional[string] `json:"client_id"`     // optional — field not included in JSON if not set
 | 
			
		||||
	ClientSecret opt.Optional[string] `json:"client_secret"` // optional — field not included in JSON if not set
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (receiver Application) MarshalJSON() ([]byte, error) {
 | 
			
		||||
 | 
			
		||||
	var array [512]byte
 | 
			
		||||
	var buffer []byte = array[0:0]
 | 
			
		||||
 | 
			
		||||
	buffer = append(buffer, "{"...)
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
		val, found := receiver.Name.Get()
 | 
			
		||||
		if !found {
 | 
			
		||||
			return nil, errCannotMashalApplicationAsJSONNoName
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		buffer = append(buffer, `"name":`...)
 | 
			
		||||
 | 
			
		||||
		{
 | 
			
		||||
			marshaled, err := json.Marshal(val)
 | 
			
		||||
			if nil != err {
 | 
			
		||||
				return nil, erorr.Errorf("ent: could not marshal ent.Application.Name as JSON: %w", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			buffer = append(buffer, marshaled...)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
		buffer = append(buffer, `,"website":`...)
 | 
			
		||||
 | 
			
		||||
		switch receiver.WebSite {
 | 
			
		||||
		case nul.Nothing[string](), nul.Null[string]():
 | 
			
		||||
			buffer = append(buffer, `null`...)
 | 
			
		||||
		default:
 | 
			
		||||
			website, found := receiver.WebSite.Get()
 | 
			
		||||
			if !found {
 | 
			
		||||
				return nil, erorr.Error("ent: could not marshal ent.Application.WebSite as JSON: internal error")
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			marshaled, err := json.Marshal(website)
 | 
			
		||||
			if nil != err {
 | 
			
		||||
				return nil, erorr.Errorf("ent: could not marshal ent.Application.WebSite as JSON: %w", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			buffer = append(buffer, marshaled...)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
		val, found := receiver.VapidKey.Get()
 | 
			
		||||
		if !found {
 | 
			
		||||
			return nil, errCannotMashalApplicationAsJSONNoVapidKey
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		buffer = append(buffer, `,"vapid_key":`...)
 | 
			
		||||
 | 
			
		||||
		{
 | 
			
		||||
			marshaled, err := json.Marshal(val)
 | 
			
		||||
			if nil != err {
 | 
			
		||||
				return nil, erorr.Errorf("ent: could not marshal ent.Application.VapidKey as JSON: %w", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			buffer = append(buffer, marshaled...)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
		switch receiver.ClientID {
 | 
			
		||||
		case opt.Nothing[string]():
 | 
			
		||||
			// Nothing here.
 | 
			
		||||
		default:
 | 
			
		||||
			clientID, found := receiver.ClientID.Get()
 | 
			
		||||
			if !found {
 | 
			
		||||
				return nil, erorr.Error("ent: could not marshal ent.Application.ClientID as JSON: internal error")
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			buffer = append(buffer, `,"client_id":`...)
 | 
			
		||||
 | 
			
		||||
			marshaled, err := json.Marshal(clientID)
 | 
			
		||||
			if nil != err {
 | 
			
		||||
				return nil, erorr.Errorf("ent: could not marshal ent.Application.ClientID as JSON: %w", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			buffer = append(buffer, marshaled...)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
		switch receiver.ClientSecret {
 | 
			
		||||
		case opt.Nothing[string]():
 | 
			
		||||
			// Nothing here.
 | 
			
		||||
		default:
 | 
			
		||||
			clientSecret, found := receiver.ClientSecret.Get()
 | 
			
		||||
			if !found {
 | 
			
		||||
				return nil, erorr.Error("ent: could not marshal ent.Application.ClientSecret as JSON: internal error")
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			buffer = append(buffer, `,"client_secret":`...)
 | 
			
		||||
 | 
			
		||||
			marshaled, err := json.Marshal(clientSecret)
 | 
			
		||||
			if nil != err {
 | 
			
		||||
				return nil, erorr.Errorf("ent: could not marshal ent.Application.ClientSecret as JSON: %w", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			buffer = append(buffer, marshaled...)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	buffer = append(buffer, "}"...)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	return buffer, nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,8 @@ package ent_test
 | 
			
		|||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/reiver/go-json"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
 | 
			
		||||
	"github.com/reiver/go-jsonpp"
 | 
			
		||||
	"github.com/reiver/go-nul"
 | 
			
		||||
	"github.com/reiver/go-opt"
 | 
			
		||||
| 
						 | 
				
			
			@ -17,17 +18,9 @@ func TestApplication_MarshalJSON(t *testing.T) {
 | 
			
		|||
		Application ent.Application
 | 
			
		||||
		Expected string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			Application: ent.Application{},
 | 
			
		||||
			Expected: "{}",
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		{
 | 
			
		||||
			Application: ent.Application{
 | 
			
		||||
				Name:     opt.Something("acme app"),
 | 
			
		||||
				WebSite: nul.Null[string](),
 | 
			
		||||
				VapidKey: opt.Something("BHgNMADAUjgYgM4PZtHkY3yTQRYD-ibS_qrWYg2KPBRidocowKcOc-8YpyItumamkGph2bk8FuryT4-p3Eymwz8"),
 | 
			
		||||
			},
 | 
			
		||||
			Expected:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,17 +1,91 @@
 | 
			
		|||
package ent
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
 | 
			
		||||
	"github.com/reiver/go-erorr"
 | 
			
		||||
	"github.com/reiver/go-opt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var _ json.Marshaler = CustomEmoji{}
 | 
			
		||||
 | 
			
		||||
// CustomEmoji represents a Mastodon API "CustomEmoji".
 | 
			
		||||
//
 | 
			
		||||
// See:
 | 
			
		||||
// https://docs.joinmastodon.org/entities/CustomEmoji/
 | 
			
		||||
type CustomEmoji struct {
 | 
			
		||||
	ShortCode       opt.Optional[string] `json:"shortcode,omitempty"`
 | 
			
		||||
	URL             opt.Optional[string] `json:"url,omitempty"`
 | 
			
		||||
	StaticURL       opt.Optional[string] `json:"static_url,omitempty"`
 | 
			
		||||
	VisibleInPicker opt.Optional[bool]   `json:"visible_in_picker,omitempty"`
 | 
			
		||||
	Category        opt.Optional[string] `json:"category,omitempty"`
 | 
			
		||||
	ShortCode       opt.Optional[string] `json:"shortcode"`
 | 
			
		||||
	URL             opt.Optional[string] `json:"url"`
 | 
			
		||||
	StaticURL       opt.Optional[string] `json:"static_url"`
 | 
			
		||||
	VisibleInPicker opt.Optional[bool]   `json:"visible_in_picker"`
 | 
			
		||||
	Category        opt.Optional[string] `json:"category"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (receiver CustomEmoji) MarshalJSON() ([]byte, error) {
 | 
			
		||||
 | 
			
		||||
	var buffer []byte
 | 
			
		||||
 | 
			
		||||
	buffer = append(buffer, "{"...)
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
                buffer = append(buffer, `"shortcode":`...)
 | 
			
		||||
 | 
			
		||||
                marshaled, err := json.Marshal(receiver.ShortCode)
 | 
			
		||||
                if nil != err {
 | 
			
		||||
                        return nil, erorr.Errorf("mstdn/ent: could not marshal ent.CustomEmoji.ShortCode 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.CustomEmoji.URL as JSON: %w", err)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                buffer = append(buffer, marshaled...)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
                buffer = append(buffer, `,"static_url":`...)
 | 
			
		||||
 | 
			
		||||
                marshaled, err := json.Marshal(receiver.StaticURL)
 | 
			
		||||
                if nil != err {
 | 
			
		||||
                        return nil, erorr.Errorf("mstdn/ent: could not marshal ent.CustomEmoji.StaticURL as JSON: %w", err)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                buffer = append(buffer, marshaled...)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
                buffer = append(buffer, `,"visible_in_picker":`...)
 | 
			
		||||
 | 
			
		||||
                marshaled, err := json.Marshal(receiver.VisibleInPicker)
 | 
			
		||||
                if nil != err {
 | 
			
		||||
                        return nil, erorr.Errorf("mstdn/ent: could not marshal ent.CustomEmoji.VisibleInPicker as JSON: %w", err)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                buffer = append(buffer, marshaled...)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
		if opt.Nothing[string]() != receiver.Category {
 | 
			
		||||
 | 
			
		||||
	                buffer = append(buffer, `,"category":`...)
 | 
			
		||||
 | 
			
		||||
        	        marshaled, err := json.Marshal(receiver.Category)
 | 
			
		||||
                	if nil != err {
 | 
			
		||||
                        	return nil, erorr.Errorf("mstdn/ent: could not marshal ent.CustomEmoji.Category as JSON: %w", err)
 | 
			
		||||
	                }
 | 
			
		||||
 | 
			
		||||
        	        buffer = append(buffer, marshaled...)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	buffer = append(buffer, "}"...)
 | 
			
		||||
 | 
			
		||||
	return buffer, nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,8 +4,8 @@ import (
 | 
			
		|||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
 | 
			
		||||
	"github.com/reiver/go-json"
 | 
			
		||||
	"github.com/reiver/go-opt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -93,31 +93,11 @@ func TestCustomEmoji_MarshalJSON(t *testing.T) {
 | 
			
		|||
				"\t"+  `"visible_in_picker":` +`true`   +""   +"\n"+
 | 
			
		||||
				"}"                                           +"\n",
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		{
 | 
			
		||||
			Value: CustomEmoji{
 | 
			
		||||
				ShortCode:       opt.Something[string](""),
 | 
			
		||||
				URL:             opt.Something[string](""),
 | 
			
		||||
				StaticURL:       opt.Something[string](""),
 | 
			
		||||
				VisibleInPicker: opt.Something[bool](false),
 | 
			
		||||
				Category:        opt.Something[string]("super-heroes"),
 | 
			
		||||
			},
 | 
			
		||||
			Expected:
 | 
			
		||||
				"{"                                                  +"\n"+
 | 
			
		||||
				"\t"+  `"shortcode":`         +`""`             +"," +"\n"+
 | 
			
		||||
				"\t"+  `"url":`               +`""`             +"," +"\n"+
 | 
			
		||||
				"\t"+  `"static_url":`        +`""`             +"," +"\n"+
 | 
			
		||||
				"\t"+  `"visible_in_picker":` +`false`          +"," +"\n"+
 | 
			
		||||
				"\t"+  `"category":`          +`"super-heroes"` +""  +"\n"+
 | 
			
		||||
				"}"                                                  +"\n",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for testNumber, test := range tests {
 | 
			
		||||
 | 
			
		||||
		actualBytes, err := json.Marshal(test.Value)
 | 
			
		||||
		actualBytes, err := test.Value.MarshalJSON()
 | 
			
		||||
		if nil != err {
 | 
			
		||||
			t.Errorf("For test #%d, did not expect to get an error but actually got one.", testNumber)
 | 
			
		||||
			t.Logf("ERROR: (%T) %s", err, err)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,5 +6,4 @@ import (
 | 
			
		|||
 | 
			
		||||
const (
 | 
			
		||||
	errNilReceiver = erorr.Error("mstdn/ent: nil receiver")
 | 
			
		||||
	errNothingID   = erorr.Error("mstdn/ent: nothing id")
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										78
									
								
								ent/field.go
								
								
								
								
							
							
						
						
									
										78
									
								
								ent/field.go
								
								
								
								
							| 
						 | 
				
			
			@ -1,18 +1,34 @@
 | 
			
		|||
package ent
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
 | 
			
		||||
	"github.com/reiver/go-erorr"
 | 
			
		||||
	"github.com/reiver/go-opt"
 | 
			
		||||
	"github.com/reiver/go-nul"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var _ json.Marshaler = Field{}
 | 
			
		||||
var _ json.Unmarshaler = &Field{}
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	errCannotMashalFieldAsJSONNoName  = erorr.Error("cannot marshal ent.Field to JSON — no ‘name’ set")
 | 
			
		||||
	errCannotMashalFieldAsJSONNoValue = erorr.Error("cannot marshal ent.Field to JSON — no ‘value’ set")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Field represents a Mastodon API "Field".
 | 
			
		||||
//
 | 
			
		||||
// See:
 | 
			
		||||
// https://docs.joinmastodon.org/entities/Field/
 | 
			
		||||
type Field struct {
 | 
			
		||||
	Name         opt.Optional[string] `json:"name,omitempty"`
 | 
			
		||||
	Value        opt.Optional[string] `json:"value,omitempty"`
 | 
			
		||||
	Name         opt.Optional[string]
 | 
			
		||||
	Value        opt.Optional[string]
 | 
			
		||||
	VerifiedAt   nul.Nullable[string]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type field struct {
 | 
			
		||||
	Name         opt.Optional[string] `json:"name"`
 | 
			
		||||
	Value        opt.Optional[string] `json:"value"`
 | 
			
		||||
	VerifiedAt   nul.Nullable[string] `json:"verified_at"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -20,7 +36,6 @@ func FieldNameValue(name string, value string) Field {
 | 
			
		|||
	return Field{
 | 
			
		||||
		Name:  opt.Something(name),
 | 
			
		||||
		Value: opt.Something(value),
 | 
			
		||||
		VerifiedAt: nul.Null[string](),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -31,3 +46,60 @@ func FieldVerifiedNameValue(when string, name string, value string) Field {
 | 
			
		|||
		VerifiedAt: nul.Something(when),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (receiver Field) MarshalJSON() ([]byte, error) {
 | 
			
		||||
 | 
			
		||||
	var data = map[string]interface{}{}
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
		val, found := receiver.Name.Get()
 | 
			
		||||
		if !found {
 | 
			
		||||
				return nil, errCannotMashalFieldAsJSONNoName
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		data["name"] = val
 | 
			
		||||
	}
 | 
			
		||||
	{
 | 
			
		||||
		val, found := receiver.Value.Get()
 | 
			
		||||
		if !found {
 | 
			
		||||
			return nil, errCannotMashalFieldAsJSONNoValue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		data["value"] = val
 | 
			
		||||
	}
 | 
			
		||||
	{
 | 
			
		||||
		val, found := receiver.VerifiedAt.Get()
 | 
			
		||||
		if !found {
 | 
			
		||||
			data["verified_at"] = nil
 | 
			
		||||
		} else {
 | 
			
		||||
			data["verified_at"] = val
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return json.Marshal(data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (receiver *Field) UnmarshalJSON(data []byte) error {
 | 
			
		||||
	if nil == receiver {
 | 
			
		||||
		return errNilReceiver
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var f field
 | 
			
		||||
 | 
			
		||||
	err := json.Unmarshal(data, &f)
 | 
			
		||||
	if nil != err {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if nul.Null[string]() == f.VerifiedAt {
 | 
			
		||||
		f.VerifiedAt = nul.Nothing[string]()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*receiver = Field{
 | 
			
		||||
		Name: f.Name,
 | 
			
		||||
		Value: f.Value,
 | 
			
		||||
		VerifiedAt: f.VerifiedAt,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,8 +4,8 @@ import (
 | 
			
		|||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
 | 
			
		||||
	"github.com/reiver/go-json"
 | 
			
		||||
	"github.com/reiver/go-mstdn/ent"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -112,7 +112,7 @@ func TestField_MarshalJSON(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	for testNumber, test := range tests {
 | 
			
		||||
 | 
			
		||||
		actualBytes, err := json.Marshal(test.Value)
 | 
			
		||||
		actualBytes, err := test.Value.MarshalJSON()
 | 
			
		||||
		if nil != err {
 | 
			
		||||
			t.Errorf("For test #%d, did not expect to get an error but actually got one.", testNumber)
 | 
			
		||||
			t.Logf("ERROR: (%T) %s", err, err)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,10 @@ func TestField_UnmarshalJSON(t *testing.T) {
 | 
			
		|||
		JSON string
 | 
			
		||||
		Expected ent.Field
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			JSON: `{"name":"Location","value":"Metro Vancouver"}`,
 | 
			
		||||
			Expected: ent.FieldNameValue("Location", "Metro Vancouver"),
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			JSON: `{"name":"Location","value":"Metro Vancouver", "verified_at":null}`,
 | 
			
		||||
			Expected: ent.FieldNameValue("Location", "Metro Vancouver"),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										20
									
								
								ent/poll.go
								
								
								
								
							
							
						
						
									
										20
									
								
								ent/poll.go
								
								
								
								
							| 
						 | 
				
			
			@ -7,14 +7,14 @@ import (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
type Poll struct {
 | 
			
		||||
	ID          opt.Optional[string]      `json:"id,omitempty"`
 | 
			
		||||
	ExpiresAt   nul.Nullable[string]      `json:"expires_at,omitempty"`
 | 
			
		||||
	Expired     opt.Optional[bool]        `json:"expired,omitempty"`
 | 
			
		||||
	Multiple    opt.Optional[bool]        `json:"multiple,omitempty"`
 | 
			
		||||
	VotesCount  opt.Optional[jsonint.Int] `json:"votes_count,omitempty"`
 | 
			
		||||
	VotersCount opt.Optional[jsonint.Int] `json:"voters_count,omitempty"`
 | 
			
		||||
	Options   []PollOption                `json:"options,omitempty"`
 | 
			
		||||
	Emojis    []CustomEmoji               `json:"emojis,omitempty"`
 | 
			
		||||
	Voted       opt.Optional[bool]        `json:"voted,omitempty"`
 | 
			
		||||
	OwnVotes  []jsonint.Int               `json:"own_votes,omitempty"`
 | 
			
		||||
	ID          opt.Optional[string]      `json:"id"`
 | 
			
		||||
	ExpiresAt   nul.Nullable[string]      `json:"expires_at"`
 | 
			
		||||
	Expired     opt.Optional[bool]        `json:"expired"`
 | 
			
		||||
	Multiple    opt.Optional[bool]        `json:"multiple"`
 | 
			
		||||
	VotesCount  opt.Optional[jsonint.Int] `json:"votes_count"`
 | 
			
		||||
	VotersCount opt.Optional[jsonint.Int] `json:"voters_count"`
 | 
			
		||||
	Options   []PollOption                `json:"options"`
 | 
			
		||||
	Emojis    []CustomEmoji               `json:"emojis"`
 | 
			
		||||
	Voted       opt.Optional[bool]        `json:"voted"`
 | 
			
		||||
	OwnVotes  []jsonint.Int              `json:"own_votes"`
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,14 +11,14 @@ import (
 | 
			
		|||
// See:
 | 
			
		||||
// https://docs.joinmastodon.org/entities/Report/
 | 
			
		||||
type Report struct {
 | 
			
		||||
	ID            opt.Optional[string]          `json:"id,omitempty"`
 | 
			
		||||
	ActionTaken   opt.Optional[bool]            `json:"action_taken,omitempty"`
 | 
			
		||||
	ActionTakenAt nul.Nullable[string]          `json:"action_taken_at,omitempty"`
 | 
			
		||||
	Category      opt.Optional[string]          `json:"category,omitempty"`
 | 
			
		||||
	Comment       opt.Optional[string]          `json:"comment,omitempty"`
 | 
			
		||||
	Forwarded     opt.Optional[bool]            `json:"forwarded,omitempty"`
 | 
			
		||||
	CreatedAt     opt.Optional[string]          `json:"created_at,omitempty"`
 | 
			
		||||
	StatusIDs     nul.Nullable[jsonstr.Strings] `json:"status_ids,omitempty"`
 | 
			
		||||
	RuleIDs       nul.Nullable[jsonstr.Strings] `json:"rule_ids,omitempty"`
 | 
			
		||||
	TargetAccount opt.Optional[Account]         `json:"target_account,omitempty"`
 | 
			
		||||
	ID            opt.Optional[string]          `json:"id"`
 | 
			
		||||
	ActionTaken   opt.Optional[bool]            `json:"action_taken"`
 | 
			
		||||
	ActionTakenAt nul.Nullable[string]          `json:"action_taken_at"`
 | 
			
		||||
	Category      opt.Optional[string]          `json:"category"`
 | 
			
		||||
	Comment       opt.Optional[string]          `json:"comment"`
 | 
			
		||||
	Forwarded     opt.Optional[bool]            `json:"forwarded"`
 | 
			
		||||
	CreatedAt     opt.Optional[string]          `json:"created_at"`
 | 
			
		||||
	StatusIDs     nul.Nullable[jsonstr.Strings] `json:"status_ids"`
 | 
			
		||||
	RuleIDs       nul.Nullable[jsonstr.Strings] `json:"rule_ids"`
 | 
			
		||||
	TargetAccount Account                       `json:"target_account"`
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,9 @@ package ent_test
 | 
			
		|||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/reiver/go-json"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
 | 
			
		||||
	"github.com/reiver/go-jsonint"
 | 
			
		||||
	"github.com/reiver/go-jsonpp"
 | 
			
		||||
	"github.com/reiver/go-jsonstr"
 | 
			
		||||
	"github.com/reiver/go-nul"
 | 
			
		||||
| 
						 | 
				
			
			@ -29,7 +31,32 @@ func TestReport_MarshalJSON(t *testing.T) {
 | 
			
		|||
				CreatedAt:     opt.Something("2023-09-27T00:31:59Z"),
 | 
			
		||||
				StatusIDs:     nul.Null[jsonstr.Strings](),
 | 
			
		||||
				RuleIDs:       nul.Null[jsonstr.Strings](),
 | 
			
		||||
				TargetAccount: opt.Something(demoAccount1()),
 | 
			
		||||
				TargetAccount: ent.Account{
 | 
			
		||||
					ID:             opt.Something("12345"),
 | 
			
		||||
					UserName:       opt.Something("joeblow"),
 | 
			
		||||
					Acct:           opt.Something("joeblow@example.com"),
 | 
			
		||||
					URL:            opt.Something("https://example.com/@joeblow"),
 | 
			
		||||
					URI:            opt.Something("https://example.com/users/joeblow"),
 | 
			
		||||
					DisplayName:    opt.Something("Joe Blow :-)"),
 | 
			
		||||
					Note:           opt.Something("<p>I came. I saw. I conquered!</p>"),
 | 
			
		||||
					Avatar:         opt.Something("https://files.example.com/avatar/joeblow.png"),
 | 
			
		||||
					AvatarStatic:   opt.Something("https://files.example.com/avatar-static/joeblow.png"),
 | 
			
		||||
					Header:         opt.Something("https://files.example.com/header/joeblow.png"),
 | 
			
		||||
					HeaderStatic:   opt.Something("https://files.example.com/header-static/joeblow/png"),
 | 
			
		||||
					//Fields       []Field                     `json:"fields"`
 | 
			
		||||
					//Emojis       []CustomEmoji               `json:"emojis"`
 | 
			
		||||
					Locked:         opt.Something(false),
 | 
			
		||||
					Bot:            opt.Something(false),
 | 
			
		||||
					Group:          opt.Something(false),
 | 
			
		||||
					Discoverable:   nul.Something(true),
 | 
			
		||||
					CreatedAt:      opt.Something("2017-02-08T02:00:53.274Z"),
 | 
			
		||||
					LastStatusAt:   nul.Something("2023-09-27T00:31:59Z"),
 | 
			
		||||
					StatusesCount:  opt.Something(jsonint.Int64(9876543210)),
 | 
			
		||||
					FollowersCount: opt.Something(jsonint.Int64(12345)),
 | 
			
		||||
					FollowingCount: opt.Something(jsonint.Int64(210)),
 | 
			
		||||
					NoIndex:        nul.Nothing[bool](),
 | 
			
		||||
					//Roles        []Role                      `json:"roles"`
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Expected :
 | 
			
		||||
			`{`+
 | 
			
		||||
| 
						 | 
				
			
			@ -51,7 +78,51 @@ func TestReport_MarshalJSON(t *testing.T) {
 | 
			
		|||
				`,`+
 | 
			
		||||
				`"rule_ids":null`+
 | 
			
		||||
				`,`+
 | 
			
		||||
				`"target_account":`+toJSON(demoAccount1())+
 | 
			
		||||
				`"target_account":{`+
 | 
			
		||||
					`"id":"12345"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"username":"joeblow"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"acct":"joeblow@example.com"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"url":"https://example.com/@joeblow"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"uri":"https://example.com/users/joeblow"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"display_name":"Joe Blow :-)"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"note":"\u003cp\u003eI came. I saw. I conquered!\u003c/p\u003e"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"avatar":"https://files.example.com/avatar/joeblow.png"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"avatar_static":"https://files.example.com/avatar-static/joeblow.png"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"header":"https://files.example.com/header/joeblow.png"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"header_static":"https://files.example.com/header-static/joeblow/png"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"fields":[]`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"emojis":[]`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"locked":false`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"bot":false`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"group":false`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"discoverable":true`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"created_at":"2017-02-08T02:00:53.274Z"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"last_status_at":"2023-09-27T00:31:59Z"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"statuses_count":9876543210`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"followers_count":12345`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"following_count":210`+
 | 
			
		||||
				`}`+
 | 
			
		||||
			`}`,
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -74,7 +145,32 @@ func TestReport_MarshalJSON(t *testing.T) {
 | 
			
		|||
				CreatedAt:     opt.Something("2023-09-27T00:31:59Z"),
 | 
			
		||||
				StatusIDs:     nul.Null[jsonstr.Strings](),
 | 
			
		||||
				RuleIDs:       nul.Null[jsonstr.Strings](),
 | 
			
		||||
				TargetAccount: opt.Something(demoAccount1()),
 | 
			
		||||
				TargetAccount: ent.Account{
 | 
			
		||||
					ID:             opt.Something("12345"),
 | 
			
		||||
					UserName:       opt.Something("joeblow"),
 | 
			
		||||
					Acct:           opt.Something("joeblow@example.com"),
 | 
			
		||||
					URL:            opt.Something("https://example.com/@joeblow"),
 | 
			
		||||
					URI:            opt.Something("https://example.com/users/joeblow"),
 | 
			
		||||
					DisplayName:    opt.Something("Joe Blow :-)"),
 | 
			
		||||
					Note:           opt.Something("<p>I came. I saw. I conquered!</p>"),
 | 
			
		||||
					Avatar:         opt.Something("https://files.example.com/avatar/joeblow.png"),
 | 
			
		||||
					AvatarStatic:   opt.Something("https://files.example.com/avatar-static/joeblow.png"),
 | 
			
		||||
					Header:         opt.Something("https://files.example.com/header/joeblow.png"),
 | 
			
		||||
					HeaderStatic:   opt.Something("https://files.example.com/header-static/joeblow/png"),
 | 
			
		||||
					//Fields       []Field                     `json:"fields"`
 | 
			
		||||
					//Emojis       []CustomEmoji               `json:"emojis"`
 | 
			
		||||
					Locked:         opt.Something(false),
 | 
			
		||||
					Bot:            opt.Something(false),
 | 
			
		||||
					Group:          opt.Something(false),
 | 
			
		||||
					Discoverable:   nul.Something(true),
 | 
			
		||||
					CreatedAt:      opt.Something("2017-02-08T02:00:53.274Z"),
 | 
			
		||||
					LastStatusAt:   nul.Something("2023-09-27T00:31:59Z"),
 | 
			
		||||
					StatusesCount:  opt.Something(jsonint.Int64(9876543210)),
 | 
			
		||||
					FollowersCount: opt.Something(jsonint.Int64(12345)),
 | 
			
		||||
					FollowingCount: opt.Something(jsonint.Int64(210)),
 | 
			
		||||
					NoIndex:        nul.Nothing[bool](),
 | 
			
		||||
					//Roles        []Role                      `json:"roles"`
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Expected :
 | 
			
		||||
			`{`+
 | 
			
		||||
| 
						 | 
				
			
			@ -96,7 +192,51 @@ func TestReport_MarshalJSON(t *testing.T) {
 | 
			
		|||
				`,`+
 | 
			
		||||
				`"rule_ids":null`+
 | 
			
		||||
				`,`+
 | 
			
		||||
				`"target_account":`+toJSON(demoAccount1())+
 | 
			
		||||
				`"target_account":{`+
 | 
			
		||||
					`"id":"12345"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"username":"joeblow"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"acct":"joeblow@example.com"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"url":"https://example.com/@joeblow"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"uri":"https://example.com/users/joeblow"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"display_name":"Joe Blow :-)"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"note":"\u003cp\u003eI came. I saw. I conquered!\u003c/p\u003e"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"avatar":"https://files.example.com/avatar/joeblow.png"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"avatar_static":"https://files.example.com/avatar-static/joeblow.png"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"header":"https://files.example.com/header/joeblow.png"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"header_static":"https://files.example.com/header-static/joeblow/png"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"fields":[]`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"emojis":[]`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"locked":false`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"bot":false`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"group":false`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"discoverable":true`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"created_at":"2017-02-08T02:00:53.274Z"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"last_status_at":"2023-09-27T00:31:59Z"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"statuses_count":9876543210`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"followers_count":12345`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"following_count":210`+
 | 
			
		||||
				`}`+
 | 
			
		||||
			`}`,
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -119,7 +259,32 @@ func TestReport_MarshalJSON(t *testing.T) {
 | 
			
		|||
				CreatedAt:     opt.Something("2023-09-27T00:31:59Z"),
 | 
			
		||||
				StatusIDs:     nul.Null[jsonstr.Strings](),
 | 
			
		||||
				RuleIDs:       nul.Null[jsonstr.Strings](),
 | 
			
		||||
				TargetAccount: opt.Something(demoAccount1()),
 | 
			
		||||
				TargetAccount: ent.Account{
 | 
			
		||||
					ID:             opt.Something("12345"),
 | 
			
		||||
					UserName:       opt.Something("joeblow"),
 | 
			
		||||
					Acct:           opt.Something("joeblow@example.com"),
 | 
			
		||||
					URL:            opt.Something("https://example.com/@joeblow"),
 | 
			
		||||
					URI:            opt.Something("https://example.com/users/joeblow"),
 | 
			
		||||
					DisplayName:    opt.Something("Joe Blow :-)"),
 | 
			
		||||
					Note:           opt.Something("<p>I came. I saw. I conquered!</p>"),
 | 
			
		||||
					Avatar:         opt.Something("https://files.example.com/avatar/joeblow.png"),
 | 
			
		||||
					AvatarStatic:   opt.Something("https://files.example.com/avatar-static/joeblow.png"),
 | 
			
		||||
					Header:         opt.Something("https://files.example.com/header/joeblow.png"),
 | 
			
		||||
					HeaderStatic:   opt.Something("https://files.example.com/header-static/joeblow/png"),
 | 
			
		||||
					//Fields       []Field                     `json:"fields"`
 | 
			
		||||
					//Emojis       []CustomEmoji               `json:"emojis"`
 | 
			
		||||
					Locked:         opt.Something(false),
 | 
			
		||||
					Bot:            opt.Something(false),
 | 
			
		||||
					Group:          opt.Something(false),
 | 
			
		||||
					Discoverable:   nul.Something(true),
 | 
			
		||||
					CreatedAt:      opt.Something("2017-02-08T02:00:53.274Z"),
 | 
			
		||||
					LastStatusAt:   nul.Something("2023-09-27T00:31:59Z"),
 | 
			
		||||
					StatusesCount:  opt.Something(jsonint.Int64(9876543210)),
 | 
			
		||||
					FollowersCount: opt.Something(jsonint.Int64(12345)),
 | 
			
		||||
					FollowingCount: opt.Something(jsonint.Int64(210)),
 | 
			
		||||
					NoIndex:        nul.Nothing[bool](),
 | 
			
		||||
					//Roles        []Role                      `json:"roles"`
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Expected :
 | 
			
		||||
			`{`+
 | 
			
		||||
| 
						 | 
				
			
			@ -141,14 +306,58 @@ func TestReport_MarshalJSON(t *testing.T) {
 | 
			
		|||
				`,`+
 | 
			
		||||
				`"rule_ids":null`+
 | 
			
		||||
				`,`+
 | 
			
		||||
				`"target_account":`+toJSON(demoAccount1())+
 | 
			
		||||
				`"target_account":{`+
 | 
			
		||||
					`"id":"12345"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"username":"joeblow"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"acct":"joeblow@example.com"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"url":"https://example.com/@joeblow"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"uri":"https://example.com/users/joeblow"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"display_name":"Joe Blow :-)"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"note":"\u003cp\u003eI came. I saw. I conquered!\u003c/p\u003e"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"avatar":"https://files.example.com/avatar/joeblow.png"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"avatar_static":"https://files.example.com/avatar-static/joeblow.png"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"header":"https://files.example.com/header/joeblow.png"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"header_static":"https://files.example.com/header-static/joeblow/png"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"fields":[]`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"emojis":[]`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"locked":false`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"bot":false`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"group":false`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"discoverable":true`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"created_at":"2017-02-08T02:00:53.274Z"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"last_status_at":"2023-09-27T00:31:59Z"`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"statuses_count":9876543210`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"followers_count":12345`+
 | 
			
		||||
					`,`+
 | 
			
		||||
					`"following_count":210`+
 | 
			
		||||
				`}`+
 | 
			
		||||
			`}`,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for testNumber, test := range tests {
 | 
			
		||||
 | 
			
		||||
		actualBytes, err := json.Marshal(&test.Report)
 | 
			
		||||
		actualBytes, err := json.Marshal(test.Report)
 | 
			
		||||
		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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										67
									
								
								ent/role.go
								
								
								
								
							
							
						
						
									
										67
									
								
								ent/role.go
								
								
								
								
							| 
						 | 
				
			
			@ -1,18 +1,75 @@
 | 
			
		|||
package ent
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
 | 
			
		||||
	"github.com/reiver/go-opt"
 | 
			
		||||
	"github.com/reiver/go-jsonint"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var _ json.Marshaler = Role{}
 | 
			
		||||
var _ json.Unmarshaler = new(Role)
 | 
			
		||||
 | 
			
		||||
// Role represents a Mastodon API "Role".
 | 
			
		||||
//
 | 
			
		||||
// See:
 | 
			
		||||
// https://docs.joinmastodon.org/entities/Role/
 | 
			
		||||
type Role struct {
 | 
			
		||||
	ID          opt.Optional[jsonint.Int] `json:"id,omitempty"`
 | 
			
		||||
	Name        opt.Optional[string]      `json:"name,omitempty"`
 | 
			
		||||
	Color       opt.Optional[string]      `json:"color,omitempty"`
 | 
			
		||||
	Permissions opt.Optional[jsonint.Int] `json:"permissions,omitempty"`
 | 
			
		||||
	Highlighted opt.Optional[bool]        `json:"highlighted,omitempty"`
 | 
			
		||||
	ID          opt.Optional[jsonint.Int]
 | 
			
		||||
	Name        opt.Optional[string]
 | 
			
		||||
	Color       opt.Optional[string]
 | 
			
		||||
	Permissions opt.Optional[jsonint.Int]
 | 
			
		||||
	Highlighted opt.Optional[bool]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type role struct {
 | 
			
		||||
	ID          opt.Optional[jsonint.Int] `json:"id"`
 | 
			
		||||
	Name        opt.Optional[string]      `json:"name"`
 | 
			
		||||
	Color       opt.Optional[string]      `json:"color"`
 | 
			
		||||
	Permissions opt.Optional[jsonint.Int] `json:"permissions"`
 | 
			
		||||
	Highlighted opt.Optional[bool]        `json:"highlighted"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (receiver Role) MarshalJSON() ([]byte, error) {
 | 
			
		||||
 | 
			
		||||
	var src role
 | 
			
		||||
 | 
			
		||||
	src.ID          = receiver.ID
 | 
			
		||||
	src.Name        = receiver.Name
 | 
			
		||||
	src.Permissions = receiver.Permissions
 | 
			
		||||
	src.Highlighted = receiver.Highlighted
 | 
			
		||||
 | 
			
		||||
	src.Color = receiver.Color
 | 
			
		||||
	src.Color.WhenNothing(func(){
 | 
			
		||||
		src.Color = opt.Something("")
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return json.Marshal(src)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (receiver *Role) UnmarshalJSON(data []byte) error {
 | 
			
		||||
	if nil == receiver {
 | 
			
		||||
		return errNilReceiver
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var dst role
 | 
			
		||||
 | 
			
		||||
	if err := json.Unmarshal(data, &dst); nil != err {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	receiver.ID          = dst.ID
 | 
			
		||||
	receiver.Name        = dst.Name
 | 
			
		||||
	receiver.Permissions = dst.Permissions
 | 
			
		||||
	receiver.Highlighted = dst.Highlighted
 | 
			
		||||
 | 
			
		||||
	dst.Color.WhenSomething(func(value string){
 | 
			
		||||
		if "" == value {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		receiver.Color = opt.Something(value)
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -66,7 +66,6 @@ func TestRole_MarshalJSON(t *testing.T) {
 | 
			
		|||
			Expected: ent.Role{
 | 
			
		||||
				ID:          opt.Something(jsonint.Int64(87)),
 | 
			
		||||
				Name:        opt.Something("QA Specialist"),
 | 
			
		||||
				Color:       opt.Something(""),
 | 
			
		||||
				Permissions: opt.Something(jsonint.Int64(218)),
 | 
			
		||||
				Highlighted: opt.Something(true),
 | 
			
		||||
			},
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
package ent
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	gojson "encoding/json"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
 | 
			
		||||
	"github.com/reiver/go-jsonint"
 | 
			
		||||
	"github.com/reiver/go-opt"
 | 
			
		||||
| 
						 | 
				
			
			@ -9,35 +9,34 @@ import (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
type Status struct {
 | 
			
		||||
	ID                 opt.Optional[string]      `json:"id,omitempty"`
 | 
			
		||||
	URI                nul.Nullable[string]      `json:"uri,omitempty"`
 | 
			
		||||
	URL                nul.Nullable[string]      `json:"url,omitempty"`
 | 
			
		||||
	CreatedAt          opt.Optional[string]      `json:"created_at,omitempty"`
 | 
			
		||||
	Account            Account                   `json:"account,omitempty"`
 | 
			
		||||
	Content            opt.Optional[string]      `json:"content,omitempty"`
 | 
			
		||||
	Visibility         opt.Optional[string]      `json:"visibility,omitempty"`
 | 
			
		||||
	Sensitive          opt.Optional[bool]        `json:"sensitive,omitempty"`
 | 
			
		||||
	SpoilerText        opt.Optional[string]      `json:"spoiler_text,omitempty"`
 | 
			
		||||
	MediaAttachments []MediaAttachment           `json:"media_attachments,omitempty"`
 | 
			
		||||
	Application        nul.Nullable[Application] `json:"application,omitempty"`
 | 
			
		||||
	Mentions         []Mention                   `json:"mentions,omitempty"`
 | 
			
		||||
	Tags             []Tag                       `json:"tags,omitempty"`
 | 
			
		||||
	Emojis           []CustomEmoji               `json:"emojis,omitempty"`
 | 
			
		||||
	ReblogsCount       opt.Optional[jsonint.Int] `json:"reblogs_count,omitempty"`
 | 
			
		||||
	FavouritesCount    opt.Optional[jsonint.Int] `json:"favourites_count,omitempty"`
 | 
			
		||||
	RepliesCount       opt.Optional[jsonint.Int] `json:"replies_count,omitempty"`
 | 
			
		||||
	InReplyToID        nul.Nullable[string]      `json:"in_reply_to_id,omitempty"`
 | 
			
		||||
	InReplyToAccountID nul.Nullable[string]      `json:"in_reply_to_account_id,omitempty"`
 | 
			
		||||
	Reblog             gojson.RawMessage         `json:"reblog,omitempty"`
 | 
			
		||||
	Poll               nul.Nullable[Poll]        `json:"poll,omitempty"`
 | 
			
		||||
	Card               nul.Nullable[PreviewCard] `json:"card,omitempty"`
 | 
			
		||||
	Language           nul.Nullable[string]      `json:"language,omitempty"`
 | 
			
		||||
	Text               nul.Nullable[string]      `json:"text,omitempty"`
 | 
			
		||||
	EditedAt           nul.Nullable[string]      `json:"edited_at,omitempty"`
 | 
			
		||||
	Favourited         opt.Optional[bool]        `json:"favourited,omitempty"`
 | 
			
		||||
	Reblogged          opt.Optional[bool]        `json:"reblogged,omitempty"`
 | 
			
		||||
	Muted              opt.Optional[bool]        `json:"muted,omitempty"`
 | 
			
		||||
	Bookmarked         opt.Optional[bool]        `json:"bookmarked,omitempty"`
 | 
			
		||||
	Pinned             opt.Optional[bool]        `json:"pinned,omitempty"`
 | 
			
		||||
	Filtered           gojson.RawMessage         `json:"filtered,omitempty"`
 | 
			
		||||
	ID                 opt.Optional[string]      `json:"id"`
 | 
			
		||||
	URL                nul.Nullable[string]      `json:"uri"`
 | 
			
		||||
	CreatedAt          opt.Optional[string]      `json:"created_at"`
 | 
			
		||||
	Account            Account                   `json:"account"`
 | 
			
		||||
	Content            opt.Optional[string]      `json:"content"`
 | 
			
		||||
	Visibility         opt.Optional[string]      `json:"visibility"`
 | 
			
		||||
	Sensitive          opt.Optional[bool]        `json:"sensitive"`
 | 
			
		||||
	SpoilerText        opt.Optional[string]      `json:"spoiler_text"`
 | 
			
		||||
	MediaAttachments []MediaAttachment           `json:"media_attachments"`
 | 
			
		||||
	Application        nul.Nullable[Application] `json:"application"`
 | 
			
		||||
	Mentions         []Mention                   `json:"mentions"`
 | 
			
		||||
	Tags             []Tag                       `json:"tags"`
 | 
			
		||||
	Emojis           []CustomEmoji               `json:"emojis"`
 | 
			
		||||
	ReblogsCount       opt.Optional[jsonint.Int] `json:"reblogs_count"`
 | 
			
		||||
	FavouritesCount    opt.Optional[jsonint.Int] `json:"favourites_count"`
 | 
			
		||||
	RepliesCount       opt.Optional[jsonint.Int] `json:"replies_count"`
 | 
			
		||||
	InReplyToID        nul.Nullable[string]      `json:"in_reply_to_id"`
 | 
			
		||||
	InReplyToAccountID nul.Nullable[string]      `json:"in_reply_to_account_id"`
 | 
			
		||||
	Reblog             json.RawMessage           `json:"reblog"`
 | 
			
		||||
	Poll               nul.Nullable[Poll]        `json:"poll"`
 | 
			
		||||
	Card               nul.Nullable[PreviewCard] `json:"card"`
 | 
			
		||||
	Language           nul.Nullable[string]      `json:"language"`
 | 
			
		||||
	Text               nul.Nullable[string]      `json:"text"`
 | 
			
		||||
	EditedAt           nul.Nullable[string]      `json:"edited_at"`
 | 
			
		||||
	Favourited         opt.Optional[bool]        `json:"favourited"`
 | 
			
		||||
	Reblogged          opt.Optional[bool]        `json:"reblogged"`
 | 
			
		||||
	Muted              opt.Optional[bool]        `json:"muted"`
 | 
			
		||||
	Bookmarked         opt.Optional[bool]        `json:"bookmarked"`
 | 
			
		||||
	Pinned             opt.Optional[bool]        `json:"pinned"`
 | 
			
		||||
	Filtered           json.RawMessage           `json:"filtered"`
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,198 +0,0 @@
 | 
			
		|||
package ent
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	gojson "encoding/json"
 | 
			
		||||
 | 
			
		||||
	"github.com/reiver/go-json"
 | 
			
		||||
	"github.com/reiver/go-nul"
 | 
			
		||||
	"github.com/reiver/go-opt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestStatus_JSON(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	tests := []struct{
 | 
			
		||||
			Status Status
 | 
			
		||||
			Expected string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			Status:Status{
 | 
			
		||||
				ID: opt.Something("123"),
 | 
			
		||||
			},
 | 
			
		||||
			Expected: `{"id":"123"}`,
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		{
 | 
			
		||||
			Status:Status{
 | 
			
		||||
				ID: opt.Something("123"),
 | 
			
		||||
				URI: nul.Something("https://example.com/status/123"),
 | 
			
		||||
			},
 | 
			
		||||
			Expected: `{"id":"123","uri":"https://example.com/status/123"}`,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			Status:Status{
 | 
			
		||||
				ID: opt.Something("123"),
 | 
			
		||||
				URL: nul.Something("https://example.com/@joeblow/status/123"),
 | 
			
		||||
			},
 | 
			
		||||
			Expected: `{"id":"123","url":"https://example.com/@joeblow/status/123"}`,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			Status:Status{
 | 
			
		||||
				ID: opt.Something("123"),
 | 
			
		||||
				CreatedAt: opt.Something("yesterday"),
 | 
			
		||||
			},
 | 
			
		||||
			Expected: `{"id":"123","created_at":"yesterday"}`,
 | 
			
		||||
		},
 | 
			
		||||
//@TODO: Account
 | 
			
		||||
		{
 | 
			
		||||
			Status:Status{
 | 
			
		||||
				ID: opt.Something("123"),
 | 
			
		||||
				Content: opt.Something("Hello world!"),
 | 
			
		||||
			},
 | 
			
		||||
			Expected: `{"id":"123","content":"Hello world!"}`,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			Status:Status{
 | 
			
		||||
				ID: opt.Something("123"),
 | 
			
		||||
				Visibility: opt.Something("public"),
 | 
			
		||||
			},
 | 
			
		||||
			Expected: `{"id":"123","visibility":"public"}`,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			Status:Status{
 | 
			
		||||
				ID: opt.Something("123"),
 | 
			
		||||
				Sensitive: opt.Something(true),
 | 
			
		||||
			},
 | 
			
		||||
			Expected: `{"id":"123","sensitive":true}`,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			Status:Status{
 | 
			
		||||
				ID: opt.Something("123"),
 | 
			
		||||
				SpoilerText: opt.Something("the rabbit did it"),
 | 
			
		||||
			},
 | 
			
		||||
			Expected: `{"id":"123","spoiler_text":"the rabbit did it"}`,
 | 
			
		||||
		},
 | 
			
		||||
//@TODO: MediaAttachments
 | 
			
		||||
//@TODO: Application
 | 
			
		||||
//@TODO: Mentions
 | 
			
		||||
 | 
			
		||||
		{
 | 
			
		||||
			Status:Status{
 | 
			
		||||
				ID: opt.Something("123"),
 | 
			
		||||
				Tags: []Tag{
 | 
			
		||||
					Tag{
 | 
			
		||||
						Name:opt.Something("akkoma"),
 | 
			
		||||
						URL:opt.Something("https://example.com/tags/akkoma"),
 | 
			
		||||
					},
 | 
			
		||||
					Tag{
 | 
			
		||||
						Name:opt.Something("fediverse"),
 | 
			
		||||
						URL:opt.Something("https://example.com/tags/fediverse"),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Expected: `{"id":"123","tags":[{"name":"akkoma","url":"https://example.com/tags/akkoma"},{"name":"fediverse","url":"https://example.com/tags/fediverse"}]}`,
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
//@TODO: Emojis
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		{
 | 
			
		||||
			Status:Status{
 | 
			
		||||
				ID: opt.Something("123"),
 | 
			
		||||
				Language: nul.Something("en"),
 | 
			
		||||
			},
 | 
			
		||||
			Expected: `{"id":"123","language":"en"}`,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			Status:Status{
 | 
			
		||||
				ID: opt.Something("123"),
 | 
			
		||||
				Text: nul.Something("bing bong bang"),
 | 
			
		||||
			},
 | 
			
		||||
			Expected: `{"id":"123","text":"bing bong bang"}`,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			Status:Status{
 | 
			
		||||
				ID: opt.Something("123"),
 | 
			
		||||
				EditedAt: nul.Something("today"),
 | 
			
		||||
			},
 | 
			
		||||
			Expected: `{"id":"123","edited_at":"today"}`,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			Status:Status{
 | 
			
		||||
				ID: opt.Something("123"),
 | 
			
		||||
				Favourited: opt.Something(true),
 | 
			
		||||
			},
 | 
			
		||||
			Expected: `{"id":"123","favourited":true}`,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			Status:Status{
 | 
			
		||||
				ID: opt.Something("123"),
 | 
			
		||||
				Reblogged: opt.Something(true),
 | 
			
		||||
			},
 | 
			
		||||
			Expected: `{"id":"123","reblogged":true}`,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			Status:Status{
 | 
			
		||||
				ID: opt.Something("123"),
 | 
			
		||||
				Muted: opt.Something(true),
 | 
			
		||||
			},
 | 
			
		||||
			Expected: `{"id":"123","muted":true}`,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			Status:Status{
 | 
			
		||||
				ID: opt.Something("123"),
 | 
			
		||||
				Bookmarked: opt.Something(true),
 | 
			
		||||
			},
 | 
			
		||||
			Expected: `{"id":"123","bookmarked":true}`,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			Status:Status{
 | 
			
		||||
				ID: opt.Something("123"),
 | 
			
		||||
				Pinned: opt.Something(true),
 | 
			
		||||
			},
 | 
			
		||||
			Expected: `{"id":"123","pinned":true}`,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			Status:Status{
 | 
			
		||||
				ID: opt.Something("123"),
 | 
			
		||||
				Filtered: gojson.RawMessage([]byte(`{"once":1,"twice":2,"thrice":3,"fource":4}`)),
 | 
			
		||||
			},
 | 
			
		||||
			Expected: `{"id":"123","filtered":{"once":1,"twice":2,"thrice":3,"fource":4}}`,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for testNumber, test := range tests {
 | 
			
		||||
 | 
			
		||||
		actualBytes, err := json.Marshal(test.Status)
 | 
			
		||||
 | 
			
		||||
		if nil != err {
 | 
			
		||||
			t.Errorf("For test #%d, did not expect to get an error but actually did.", testNumber)
 | 
			
		||||
			t.Logf("ERROR: (%T) %s", err, err)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		actual := string(actualBytes)
 | 
			
		||||
 | 
			
		||||
		expected := test.Expected
 | 
			
		||||
 | 
			
		||||
		if expected != actual {
 | 
			
		||||
			t.Errorf("For test #%d, the actual string-serialized form is not what was expected.", testNumber)
 | 
			
		||||
			t.Logf("EXPECTED: %q", expected)
 | 
			
		||||
			t.Logf("ACTUAL:   %q", actual)
 | 
			
		||||
			t.Logf("EXPECTED:\n%s", expected)
 | 
			
		||||
			t.Logf("ACTUAL:\n%s", actual)
 | 
			
		||||
			t.Logf("STATUS:\n%#v", test.Status)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										19
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										19
									
								
								go.mod
								
								
								
								
							| 
						 | 
				
			
			@ -1,12 +1,12 @@
 | 
			
		|||
module github.com/reiver/go-mstdn
 | 
			
		||||
 | 
			
		||||
go 1.22.4
 | 
			
		||||
go 1.20
 | 
			
		||||
 | 
			
		||||
require github.com/reiver/go-opt v0.0.0-20240809032727-8e60e8ea3e8f
 | 
			
		||||
require github.com/reiver/go-opt v0.0.0-20240704165441-4ce81358adfc
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/reiver/go-jsonint v0.0.0-20240801233651-21b9c52057ee
 | 
			
		||||
	github.com/reiver/go-nul v0.0.0-20240809033544-506ae7916afa
 | 
			
		||||
	github.com/reiver/go-nul v0.0.0-20240801233226-90d138095e48
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
require github.com/reiver/go-jsonstr v0.0.0-20240802000653-a5a8363975f1
 | 
			
		||||
| 
						 | 
				
			
			@ -15,15 +15,4 @@ require github.com/reiver/go-jsonpp v0.0.0-20240802002345-16cd4c5a34ee
 | 
			
		|||
 | 
			
		||||
require github.com/reiver/go-erorr v0.0.0-20240801233437-8cbde6d1fa3f
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/reiver/go-httpsse v0.0.0-20240806223648-6ed5a785f3f8
 | 
			
		||||
	github.com/reiver/go-json v0.0.0-20240808191545-fa5fbb1bb3f6
 | 
			
		||||
	github.com/reiver/go-pathmatch v1.0.1-0.20240802004530-0dc31d85afa8
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/reiver/go-ascii v0.0.0-20240302002050-442843e5ea02 // indirect
 | 
			
		||||
	github.com/reiver/go-errhttp v1.1.1-0.20240513035723-daf47d264c9c // indirect
 | 
			
		||||
	github.com/reiver/go-lck v0.0.0-20240808133902-b56df221c39f // indirect
 | 
			
		||||
	github.com/reiver/go-utf8 v2.0.2-0.20240806185936-5dd7c5557d34+incompatible // indirect
 | 
			
		||||
)
 | 
			
		||||
require github.com/reiver/go-pathmatch v1.0.1-0.20240802004530-0dc31d85afa8
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										21
									
								
								go.sum
								
								
								
								
							
							
						
						
									
										21
									
								
								go.sum
								
								
								
								
							| 
						 | 
				
			
			@ -1,28 +1,15 @@
 | 
			
		|||
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
 | 
			
		||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
 | 
			
		||||
github.com/reiver/go-ascii v0.0.0-20240302002050-442843e5ea02 h1:YviUVCHZw6gaxvLznXQTXp7LwaWzly80TXUsWxwPPi4=
 | 
			
		||||
github.com/reiver/go-ascii v0.0.0-20240302002050-442843e5ea02/go.mod h1:f43/Y1zpLvqorZN0BelarPzO2GrotAQrBy3T08NUSTM=
 | 
			
		||||
github.com/reiver/go-erorr v0.0.0-20240801233437-8cbde6d1fa3f h1:D1QSxKHm8U73XhjsW3SFLkT0zT5pKJi+1KGboMhY1Rk=
 | 
			
		||||
github.com/reiver/go-erorr v0.0.0-20240801233437-8cbde6d1fa3f/go.mod h1:F0HbBf+Ak2ZlE8YkDW4Y+KxaUmT0KaaIJK6CXY3cJxE=
 | 
			
		||||
github.com/reiver/go-errhttp v1.1.1-0.20240513035723-daf47d264c9c h1:C/ALE5tUOywYv2tqweTLOjH0BVkN5TTMDKY6qDTD/3Q=
 | 
			
		||||
github.com/reiver/go-errhttp v1.1.1-0.20240513035723-daf47d264c9c/go.mod h1:J55rONfn+39379roH0KxMCGv6w9ifhZIoSKaVswRUDk=
 | 
			
		||||
github.com/reiver/go-httpsse v0.0.0-20240806223648-6ed5a785f3f8 h1:HOpgKCgKqWYub73sQvWxamDqJ7G8P0tMk5wYBFUDblE=
 | 
			
		||||
github.com/reiver/go-httpsse v0.0.0-20240806223648-6ed5a785f3f8/go.mod h1:hABgQXG6IXrFbcy8C+VKEM3/tDZg3nZ4u82N/QvvH70=
 | 
			
		||||
github.com/reiver/go-json v0.0.0-20240808191545-fa5fbb1bb3f6 h1:Ty3b38DeA5BKi42+3f3o8Bl4zEAKlJsF0ozArGJmo9k=
 | 
			
		||||
github.com/reiver/go-json v0.0.0-20240808191545-fa5fbb1bb3f6/go.mod h1:IHoQXCaObMGCDoTKko/XzDk8QbpNzepuCLMt7KKCLBs=
 | 
			
		||||
github.com/reiver/go-jsonint v0.0.0-20240801233651-21b9c52057ee h1:DfEj/iGAIU8CtTcnttyU6t3lae0jl760fUGjxZhIHNU=
 | 
			
		||||
github.com/reiver/go-jsonint v0.0.0-20240801233651-21b9c52057ee/go.mod h1:1lW12ILqOxqtylQBMezy6oRuMQWlzFjeWF/Wbz/9U8g=
 | 
			
		||||
github.com/reiver/go-jsonpp v0.0.0-20240802002345-16cd4c5a34ee h1:KhA+fe6qjEw6ZbN3vjPICGL0NqR+rghYre4SQB0WWVs=
 | 
			
		||||
github.com/reiver/go-jsonpp v0.0.0-20240802002345-16cd4c5a34ee/go.mod h1:iubeYYU+lR1wqKssI6Sz1DK/Aw/N/qmRcam0wf8hYIs=
 | 
			
		||||
github.com/reiver/go-jsonstr v0.0.0-20240802000653-a5a8363975f1 h1:32ulBfhFKQIaRMuwCo2vi7FLOphgyKTZzJIk+LWmMOE=
 | 
			
		||||
github.com/reiver/go-jsonstr v0.0.0-20240802000653-a5a8363975f1/go.mod h1:/msMJNY8TjDYgO/h06wEuzTWGs1b37xbUo8FH/2aZqQ=
 | 
			
		||||
github.com/reiver/go-lck v0.0.0-20240808133902-b56df221c39f h1:KBVWBoNIM8mHkUR3dP64hm2p2vxoD5xHZ6wUllCjFTc=
 | 
			
		||||
github.com/reiver/go-lck v0.0.0-20240808133902-b56df221c39f/go.mod h1:PFseSi8S0CBkc+YB6jYWtogPk83LumclnYJZZBQJJhs=
 | 
			
		||||
github.com/reiver/go-nul v0.0.0-20240809033544-506ae7916afa h1:Owi2PuvHrN3KaCyNsXxgN5deGISkVwmmO0tWXZgHtfE=
 | 
			
		||||
github.com/reiver/go-nul v0.0.0-20240809033544-506ae7916afa/go.mod h1:aXT75/yMqcZA2wN/hW52vb5CQjUCEKGoyikjSi02oS8=
 | 
			
		||||
github.com/reiver/go-opt v0.0.0-20240809032727-8e60e8ea3e8f h1:EKHU13RjaUjg67RaIbqNr/4Mb+4qyfQRJAX+DiR05Dw=
 | 
			
		||||
github.com/reiver/go-opt v0.0.0-20240809032727-8e60e8ea3e8f/go.mod h1:iXlSKwDjhyF10Fdd2J5PYKwBFlWgfq7OTRxCHU+yTUY=
 | 
			
		||||
github.com/reiver/go-nul v0.0.0-20240801233226-90d138095e48 h1:+x7mICqo/GBI0B7I5obJM51wve8zcIsTW5kdctlO9pw=
 | 
			
		||||
github.com/reiver/go-nul v0.0.0-20240801233226-90d138095e48/go.mod h1:hN0edxyC/F7HMB86sn/ljqTJ0CrAeOCGMpCZJ2Nmtc4=
 | 
			
		||||
github.com/reiver/go-opt v0.0.0-20240704165441-4ce81358adfc h1:9ARo75fNaZDaGy6zzTrCnJWtkDMNigM7uMRRK8sUERM=
 | 
			
		||||
github.com/reiver/go-opt v0.0.0-20240704165441-4ce81358adfc/go.mod h1:Yu6dFKh0IZ0evP9U5QiBlxBa5BhlBzGEn7EZ1kP/pkA=
 | 
			
		||||
github.com/reiver/go-pathmatch v1.0.1-0.20240802004530-0dc31d85afa8 h1:3mxWa4FELLc6TbC00ZZTe30tYUZ8HN4IHaH0m7Y3SPc=
 | 
			
		||||
github.com/reiver/go-pathmatch v1.0.1-0.20240802004530-0dc31d85afa8/go.mod h1:SveMAOrJP7XCL3UlazOjQdKNCGG2T/E1zE6gDHfs3cA=
 | 
			
		||||
github.com/reiver/go-utf8 v2.0.2-0.20240806185936-5dd7c5557d34+incompatible h1:Ewax9SN/f+OibeHNDBPI2lsf1t17YRBvKDA4X7CU4vA=
 | 
			
		||||
github.com/reiver/go-utf8 v2.0.2-0.20240806185936-5dd7c5557d34+incompatible/go.mod h1:tfGntNDUeEZIAsz0mTu0lF7/IlErc+BpQgO6yxYmJig=
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue