-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathutils.go
149 lines (126 loc) · 3.39 KB
/
utils.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package linkpearl
import (
"errors"
"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))
}
// EventReplaceID returns replace_id of a matrix event (if any)
// i.e. when the evt was replaced by another event, this returns the ID of the replacing event
func EventReplaceID(evt *event.Event) id.EventID {
ParseContent(evt, nil)
relatable, ok := evt.Content.Parsed.(event.Relatable)
if !ok {
return ""
}
relation := relatable.GetRelatesTo()
if relation == nil {
return ""
}
return relation.GetReplaceID()
}
// 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
}
return EventField[T](&evt.Content, field) == value
}
// 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 {
var httpErr mautrix.HTTPError
if errors.As(err, &httpErr) {
uwerr := httpErr.Unwrap()
if uwerr != nil {
return uwerr
}
}
return err
}