Files
postmoogle/vendor/gitlab.com/etke.cc/linkpearl/utils.go
2023-09-29 16:37:46 +03:00

150 lines
3.2 KiB
Go

package linkpearl
import (
"github.com/rs/zerolog"
"maunium.net/go/mautrix"
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/id"
)
// EventRelatesTo uses evt as source for EventParent() and RelatesTo()
func EventRelatesTo(evt *event.Event) *event.RelatesTo {
ParseContent(evt, nil)
relatable, ok := evt.Content.Parsed.(event.Relatable)
if !ok {
return nil
}
return RelatesTo(EventParent(evt.ID, relatable))
}
// RelatesTo returns relation object of a matrix event (either threads with reply-to fallback or plain reply-to)
func RelatesTo(parentID id.EventID, noThreads ...bool) *event.RelatesTo {
if parentID == "" {
return nil
}
var nothreads bool
if len(noThreads) > 0 {
nothreads = noThreads[0]
}
if nothreads {
return &event.RelatesTo{
InReplyTo: &event.InReplyTo{
EventID: parentID,
},
}
}
return &event.RelatesTo{
Type: event.RelThread,
EventID: parentID,
InReplyTo: &event.InReplyTo{
EventID: parentID,
},
IsFallingBack: true,
}
}
// GetParent is nil-safe version of evt.Content.AsMessage().RelatesTo.(GetThreadParent()|GetReplyTo())
func GetParent(evt *event.Event) id.EventID {
ParseContent(evt, nil)
content, ok := evt.Content.Parsed.(event.Relatable)
if !ok {
return ""
}
relation := content.GetRelatesTo()
if relation == nil {
return ""
}
if parentID := relation.GetThreadParent(); parentID != "" {
return parentID
}
if parentID := relation.GetReplyTo(); parentID != "" {
return parentID
}
return ""
}
// EventParent returns parent event ID (either from thread or from reply-to relation), like GetRelatesTo(), but with content and default return value
func EventParent(currentID id.EventID, content event.Relatable) id.EventID {
if parentID := GetParent(&event.Event{Content: event.Content{Parsed: content}}); parentID != "" {
return parentID
}
return currentID
}
// EventContains checks if raw event content contains specified field with specified values
func EventContains[T comparable](evt *event.Event, field string, value T) bool {
if evt.Content.Raw == nil {
return false
}
if EventField[T](&evt.Content, field) != value {
return false
}
return true
}
// EventField returns field value from raw event content
func EventField[T comparable](content *event.Content, field string) T {
var zero T
raw, ok := content.Raw[field]
if !ok {
return zero
}
if raw == nil {
return zero
}
v, ok := raw.(T)
if !ok {
return zero
}
return v
}
// ParseContent parses event content according to evt.Type
func ParseContent(evt *event.Event, log *zerolog.Logger) {
if evt.Content.Parsed != nil {
return
}
perr := evt.Content.ParseRaw(evt.Type)
if perr != nil && log != nil {
log.Error().Err(perr).Msg("cannot parse event content")
}
}
// UnwrapError tries to unwrap a error into something meaningful, like mautrix.HTTPError or mautrix.RespError
func UnwrapError(err error) error {
switch err.(type) {
case nil:
return nil
case mautrix.HTTPError:
return unwrapHTTPError(err)
default:
return err
}
}
func unwrapHTTPError(err error) error {
httperr, ok := err.(mautrix.HTTPError)
if !ok {
return err
}
uwerr := httperr.Unwrap()
if uwerr != nil {
return uwerr
}
return httperr
}