mirror of
https://github.com/versia-pub/versia-go.git
synced 2026-03-13 04:29:15 +01:00
chore: rename everything to versia
This commit is contained in:
parent
0223ea0535
commit
3876ad2738
112 changed files with 587 additions and 576 deletions
150
pkg/versia/utils/content_map.go
Normal file
150
pkg/versia/utils/content_map.go
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
package versiautils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"slices"
|
||||
)
|
||||
|
||||
var (
|
||||
validTextContentTypes = []string{"text/html", "text/plain"}
|
||||
validImageContentTypes = []string{"image/png", "image/jpeg", "image/gif", "image/svg+xml"}
|
||||
)
|
||||
|
||||
// ContentMap is a map of content types to their respective content.
|
||||
type ContentMap[T any] map[string]T
|
||||
|
||||
type UnexpectedContentTypeError struct {
|
||||
MIMEType string
|
||||
}
|
||||
|
||||
func (e UnexpectedContentTypeError) Error() string {
|
||||
return fmt.Sprintf("unexpected content type: %s", e.MIMEType)
|
||||
}
|
||||
|
||||
func (m ContentMap[T]) unmarshalJSON(raw []byte, valid []string) error {
|
||||
var cm map[string]json.RawMessage
|
||||
if err := json.Unmarshal(raw, &cm); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m = make(ContentMap[T])
|
||||
|
||||
errs := make([]error, 0)
|
||||
for k, v := range cm {
|
||||
if valid != nil {
|
||||
if !slices.Contains(valid, k) {
|
||||
errs = append(errs, UnexpectedContentTypeError{k})
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
var c T
|
||||
if err := json.Unmarshal(v, &c); err != nil {
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
m[k] = c
|
||||
}
|
||||
if len(errs) > 0 {
|
||||
return MultipleError{errs}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m ContentMap[T]) getPreferred(preferred []string) *T {
|
||||
for _, v := range preferred {
|
||||
if c, ok := m[v]; ok {
|
||||
return &c
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TextContent is embedded string. For more information, see the [Spec].
|
||||
//
|
||||
// [Spec]: https://versia.pub/structures/content-format
|
||||
type TextContent struct {
|
||||
Content string `json:"content"`
|
||||
|
||||
// Remote is always false
|
||||
Remote bool `json:"remote"`
|
||||
}
|
||||
type TextContentTypeMap ContentMap[TextContent]
|
||||
|
||||
func (t TextContentTypeMap) UnmarshalJSON(data []byte) error {
|
||||
return (ContentMap[TextContent])(t).unmarshalJSON(data, validTextContentTypes)
|
||||
}
|
||||
|
||||
func (t TextContentTypeMap) String() string {
|
||||
if c := (ContentMap[TextContent])(t).getPreferred(validTextContentTypes); c != nil {
|
||||
return c.Content
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// File is a file or other piece of content. For more information, see the [Spec].
|
||||
//
|
||||
// [Spec]: https://versia.pub/structures/content-format
|
||||
type File struct {
|
||||
// Remote is always true
|
||||
Remote bool `json:"remote"`
|
||||
|
||||
// URL to the attachment
|
||||
Content *URL `json:"content"`
|
||||
Description string `json:"description"`
|
||||
Hash DataHash `json:"hash"`
|
||||
Size int `json:"size"`
|
||||
|
||||
// BlurHash is available when the content type is an image
|
||||
BlurHash *string `json:"blurhash,omitempty"`
|
||||
// BlurHash is available when the content type is an image
|
||||
Height *int `json:"height,omitempty"`
|
||||
// BlurHash is available when the content type is an image
|
||||
Width *int `json:"width,omitempty"`
|
||||
|
||||
FPS *int `json:"fps,omitempty"`
|
||||
}
|
||||
type DataHash struct {
|
||||
SHA256 string `json:"sha256"`
|
||||
}
|
||||
|
||||
type ImageContentMap ContentMap[File]
|
||||
|
||||
func (i ImageContentMap) UnmarshalJSON(data []byte) error {
|
||||
return (ContentMap[File])(i).unmarshalJSON(data, validImageContentTypes)
|
||||
}
|
||||
|
||||
func (i ImageContentMap) String() string {
|
||||
if c := (ContentMap[File])(i).getPreferred(validImageContentTypes); c != nil {
|
||||
return c.Content.String()
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
type NoteAttachmentContentMap ContentMap[File]
|
||||
|
||||
var ErrContentMapEntryNotRemote = errors.New("content map entry not remote")
|
||||
|
||||
func (i NoteAttachmentContentMap) UnmarshalJSON(data []byte) error {
|
||||
if err := (ContentMap[File])(i).unmarshalJSON(data, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
errs := make([]error, 0)
|
||||
for _, a := range i {
|
||||
if !a.Remote {
|
||||
errs = append(errs, ErrContentMapEntryNotRemote)
|
||||
}
|
||||
}
|
||||
if len(errs) > 0 {
|
||||
return MultipleError{errs}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
package versiautils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"slices"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
var (
|
||||
validTextContentTypes = []string{"text/html", "text/plain"}
|
||||
validImageContentTypes = []string{"image/png", "image/jpeg", "image/gif", "image/svg+xml"}
|
||||
)
|
||||
|
||||
// ContentTypeMap is a map of content types to their respective content.
|
||||
type ContentTypeMap[T any] map[string]T
|
||||
|
||||
func (m *ContentTypeMap[T]) unmarshalJSON(raw []byte, valid []string) error {
|
||||
var cm map[string]json.RawMessage
|
||||
if err := json.Unmarshal(raw, &cm); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*m = make(ContentTypeMap[T])
|
||||
|
||||
for k, v := range cm {
|
||||
if !slices.Contains(valid, k) {
|
||||
// TODO: replace with logr
|
||||
log.Debug().Caller().Str("mimetype", k).Msg("unexpected content type, skipping")
|
||||
continue
|
||||
}
|
||||
|
||||
var c T
|
||||
if err := json.Unmarshal(v, &c); err != nil {
|
||||
return err
|
||||
}
|
||||
(*m)[k] = c
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m ContentTypeMap[T]) getPreferred(preferred []string) *T {
|
||||
for _, v := range preferred {
|
||||
if c, ok := m[v]; ok {
|
||||
return &c
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type TextContent struct {
|
||||
Content string `json:"content"`
|
||||
}
|
||||
type TextContentTypeMap ContentTypeMap[TextContent]
|
||||
|
||||
func (t *TextContentTypeMap) UnmarshalJSON(data []byte) error {
|
||||
return (*ContentTypeMap[TextContent])(t).unmarshalJSON(data, validTextContentTypes)
|
||||
}
|
||||
|
||||
func (t TextContentTypeMap) String() string {
|
||||
if c := (ContentTypeMap[TextContent])(t).getPreferred(validTextContentTypes); c != nil {
|
||||
return c.Content
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
type ImageContent struct {
|
||||
Content *URL `json:"content"`
|
||||
}
|
||||
type ImageContentTypeMap ContentTypeMap[ImageContent]
|
||||
|
||||
func (i *ImageContentTypeMap) UnmarshalJSON(data []byte) error {
|
||||
return (*ContentTypeMap[ImageContent])(i).unmarshalJSON(data, validImageContentTypes)
|
||||
}
|
||||
|
||||
func (i ImageContentTypeMap) String() string {
|
||||
if c := (ContentTypeMap[ImageContent])(i).getPreferred(validImageContentTypes); c != nil {
|
||||
return c.Content.String()
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
22
pkg/versia/utils/errors.go
Normal file
22
pkg/versia/utils/errors.go
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
package versiautils
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
type MultipleError struct {
|
||||
Errors []error
|
||||
}
|
||||
|
||||
func (e MultipleError) Error() string {
|
||||
s := strings.Builder{}
|
||||
for i, err := range e.Errors {
|
||||
s.WriteString(err.Error())
|
||||
|
||||
if i != len(e.Errors) {
|
||||
s.WriteRune('\n')
|
||||
}
|
||||
}
|
||||
|
||||
return s.String()
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue