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 }