goap/tags.go

153 lines
3.8 KiB
Go

package goap
import "time"
type Tag interface {
Marshal() map[string]any
sealed()
}
type TagEmoji struct {
Id string
Icon Media
Name string
LastUpdated time.Time
}
func (t TagEmoji) sealed() {}
func (t TagEmoji) Marshal() map[string]any {
m := map[string]any{
KEY_ID: t.Id,
KEY_TYPE: []string{KEY_MASTO_EMOJI},
KEY_ACTIVITYSTREAMS_ICON: []map[string]any{t.Icon.Marshal()},
KEY_ACTIVITYSTREAMS_NAME: []map[string]any{{KEY_VALUE: t.Name}},
}
return m
}
type TagMention struct {
TargetId string
TargetName string
}
func (t TagMention) sealed() {}
func (t TagMention) Marshal() map[string]any {
return map[string]any{
KEY_TYPE: []string{KEY_ACTIVITYSTREAMS_MENTION},
KEY_ACTIVITYSTREAMS_HREF: []map[string]any{{KEY_ID: t.TargetId}},
KEY_ACTIVITYSTREAMS_NAME: []map[string]any{{KEY_VALUE: t.TargetName}},
}
}
type TagHashtag struct {
Url string
Name string
}
func (t TagHashtag) sealed() {}
func (t TagHashtag) Marshal() map[string]any {
return map[string]any{
KEY_TYPE: []string{KEY_ACTIVITYSTREAMS_HASHTAG},
KEY_ACTIVITYSTREAMS_HREF: []map[string]any{{KEY_ID: t.Url}},
KEY_ACTIVITYSTREAMS_NAME: []map[string]any{{KEY_VALUE: t.Name}},
}
}
func ParseTag(raw map[string]any) (Tag, error) {
rawTypeArr, ok := raw[KEY_TYPE]
if !ok {
return nil, NoRequiredFieldError{KEY_TYPE}
}
typeArr, ok := rawTypeArr.([]string)
if !ok {
return nil, BadFieldValueError[[]string]{KEY_TYPE, rawTypeArr, typeArr}
}
if len(typeArr) != 1 {
return nil, BadFieldArrayLengthError{KEY_TYPE, 1, len(typeArr)}
}
tagType := typeArr[0]
switch tagType {
case KEY_MASTO_EMOJI:
return parseEmojiTag(raw)
case KEY_ACTIVITYSTREAMS_MENTION:
return parseMentionTag(raw)
case KEY_ACTIVITYSTREAMS_HASHTAG:
return parseHashtagTag(raw)
default:
return nil, UnknownTagType{TagType: tagType}
}
}
func parseEmojiTag(raw map[string]any) (*TagEmoji, error) {
rawId, ok := raw[KEY_ID]
if !ok {
return nil, NoRequiredFieldError{KEY_ID}
}
id, ok := rawId.(string)
if !ok {
return nil, BadFieldValueError[string]{KEY_ID, rawId, id}
}
media, err := ParseASIconData(raw, nil)
if err != nil {
return nil, err
}
rawName1, ok := raw[KEY_ACTIVITYSTREAMS_NAME]
if !ok {
return nil, NoRequiredFieldError{KEY_ACTIVITYSTREAMS_NAME}
}
name1, ok := rawName1.([]map[string]any)
if !ok {
return nil, BadFieldValueError[[]map[string]any]{KEY_ACTIVITYSTREAMS_NAME, rawName1, name1}
}
if len(name1) != 1 {
return nil, BadFieldArrayLengthError{KEY_ACTIVITYSTREAMS_NAME, 1, len(name1)}
}
rawName2, ok := name1[0][KEY_VALUE]
if !ok {
return nil, NoRequiredSubFieldError{KEY_ACTIVITYSTREAMS_NAME, KEY_VALUE}
}
name2, ok := rawName2.(string)
if !ok {
return nil, BadFieldValueError[string]{KEY_VALUE, rawName2, name2}
}
// Casting media to ASIconData without check is ok here
// Reason: ParseASIconData returns an BaseAPChain, an interface.
// However, the function guarantees that, if it doesn't error out, you get an ASIconData struct back
return &TagEmoji{Id: id, Icon: media.(*ASIconData).Media, Name: name2}, nil
}
func parseMentionTag(raw map[string]any) (*TagMention, error) {
rawHref, err := ParseASHrefData(raw, nil)
if err != nil {
return nil, err
}
href := rawHref.(*ASHrefData)
rawName, err := ParseASNameData(raw, nil)
if err != nil {
return nil, err
}
name := rawName.(*ASNameData)
return &TagMention{
TargetId: href.Id,
TargetName: name.Value.Value,
}, nil
}
func parseHashtagTag(raw map[string]any) (*TagHashtag, error) {
rawHref, err := ParseASHrefData(raw, nil)
if err != nil {
return nil, err
}
href := rawHref.(*ASHrefData)
rawName, err := ParseASNameData(raw, nil)
if err != nil {
return nil, err
}
name := rawName.(*ASNameData)
return &TagHashtag{
Url: href.Id,
Name: name.Value.Value,
}, nil
}