Files
go-lextwt-encoding/twt-avro/helper.go
2025-03-02 20:14:49 -07:00

216 lines
5.2 KiB
Go

package twt_avro
import (
"time"
"github.com/hamba/avro"
"go.yarn.social/lextwt"
"go.yarn.social/types"
)
const (
keySubject = "social.yarn.lextwt.subject"
keyCode = "social.yarn.lextwt.code"
keyMention = "social.yarn.lextwt.mention"
keyHashtag = "social.yarn.lextwt.hashtag"
keyLink = "social.yarn.lextwt.link"
keyBangmention = "social.yarn.lextwt.bangmention"
keyLinesep = "social.yarn.lextwt.linesep"
keyComment = "social.yarn.lextwt.comment"
keyText = "social.yarn.lextwt.text"
)
func Register() {
avro.Register(keyText, "")
avro.Register(keySubject, Subject{})
avro.Register(keyCode, Code{})
avro.Register(keyMention, Mention{})
avro.Register(keyHashtag, Hashtag{})
avro.Register(keyLink, Link{})
avro.Register(keyBangmention, Bangmention{})
avro.Register(keyLinesep, Linesep{})
avro.Register(keyComment, Comment{})
}
func Elem(o any) any {
key := "unknown"
switch o.(type) {
case Subject:
key = keySubject
case Code:
key = keyCode
case Mention:
key = keyMention
case Hashtag:
key = keyHashtag
case Link:
key = keyLink
case Bangmention:
key = keyBangmention
case Linesep:
key = keyLinesep
case Comment:
key = keyComment
case string:
return o
}
return map[string]any{key: o}
}
func Msg(items ...any) []any {
return items
}
func FromTwt(twt types.Twt) Lextwt {
return FromLextwt(twt.(*lextwt.Twt))
}
func FromLextwt(twt *lextwt.Twt) Lextwt {
if twt == nil {
return Lextwt{}
}
ts := twt.Created()
_, offset := ts.Zone()
l := Lextwt{
Nick: twt.Twter().Nick,
URI: twt.Twter().URI,
Created: ts.UnixMilli(),
CreatedOffset: offset,
CreatedZone: "",
}
for _, e := range twt.Elems() {
if e == nil {
continue
}
if e == lextwt.LineSeparator {
l.Msg = append(l.Msg, Elem(Linesep{}))
continue
}
switch e := e.(type) {
case *lextwt.Subject:
l.Msg = append(l.Msg, Elem(Subject{Subject: e.Subject(), Tag: e.Tag().Text(), Target: e.Tag().Target()}))
case *lextwt.Code:
l.Msg = append(l.Msg, Elem(Code{Code: e.Text()}))
case *lextwt.Mention:
l.Msg = append(l.Msg, Elem(Mention{Name: e.Name(), Domain: e.Domain(), Target: e.Target()}))
case *lextwt.Tag:
l.Msg = append(l.Msg, Elem(Hashtag{Tag: e.Text(), Target: e.Target()}))
case *lextwt.Link:
l.Msg = append(l.Msg, Elem(Link{LinkType: int(e.LinkType()), Text: e.Text(), Target: e.Target(), Title: e.Title()}))
case *lextwt.BangMention:
l.Msg = append(l.Msg, Elem(Bangmention{Name: e.Name(), Target: e.Target()}))
case *lextwt.Comment:
l.Msg = append(l.Msg, Elem(Comment{Comment: e.Text(), Key: e.Key(), Value: e.Value()}))
case *lextwt.Text:
l.Msg = append(l.Msg, Elem(e.Literal()))
}
}
return l
}
func (l Lextwt) ToTwt() types.Twt {
return l.ToLextwt()
}
func (lx Lextwt) ToLextwt() *lextwt.Twt {
twter := types.Twter{
Nick: lx.Nick,
URI: lx.URI,
}
ts := time.UnixMilli(lx.Created)
if tz := time.FixedZone(lx.CreatedZone, lx.CreatedOffset); tz != nil {
ts = ts.In(tz)
}
dt := lextwt.NewDateTime(ts, ts.Format(time.RFC3339))
elems := make([]lextwt.Elem, 0, len(lx.Msg))
for _, e := range lx.Msg {
switch e := e.(type) {
case map[string]any:
if text, ok := e["string"].(string); ok {
elems = append(elems, lextwt.NewText(text))
}
if e, ok := e[keySubject].(map[string]any); ok {
subject := read[string](e, "subject")
tag := read[string](e, "tag")
target := read[string](e, "target")
if subject == "" {
elems = append(elems, lextwt.NewSubjectTag(tag, target))
} else {
elems = append(elems, lextwt.NewSubject(subject))
}
}
if m, ok := e[keyCode].(map[string]any); ok {
code := read[string](m, "code")
codeType := lextwt.CodeType(read[int8](m, "codetype"))
elems = append(elems, lextwt.NewCode(code, codeType))
}
if e, ok := e[keyMention].(map[string]any); ok {
name := read[string](e, "name")
target := read[string](e, "target")
elems = append(elems, lextwt.NewMention(name, target))
}
if e, ok := e[keyHashtag].(map[string]any); ok {
tag := read[string](e, "tag")
target := read[string](e, "target")
elems = append(elems, lextwt.NewTag(tag, target))
}
if e, ok := e[keyLink].(map[string]any); ok {
text := read[string](e, "text")
target := read[string](e, "target")
linkType := lextwt.LinkType(read[int](e, "linkType"))
elems = append(elems, lextwt.NewLink(text, target, linkType))
}
if e, ok := e[keyBangmention].(map[string]any); ok {
name := read[string](e, "name")
target := read[string](e, "target")
elems = append(elems, lextwt.NewBangMention(name, target))
}
if e, ok := e[keyComment].(map[string]any); ok {
comment := read[string](e, "comment")
key := read[string](e, "key")
value := read[string](e, "value")
if key != "" {
elems = append(elems, lextwt.NewCommentValue(comment, key, value))
} else {
elems = append(elems, lextwt.NewComment(comment))
}
}
if _, ok := e[keyLinesep].(map[string]any); ok {
elems = append(elems, lextwt.LineSeparator)
}
}
}
return lextwt.NewTwt(twter, dt, elems...)
}
func read[T any](m map[string]any, k string) T {
val, ok := m[k].(T)
if !ok {
var zero T
return zero
}
return val
}