/
payload.go
158 lines (124 loc) · 3.84 KB
/
payload.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
150
151
152
153
154
155
156
157
158
package events
import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"sort"
"strings"
"time"
"github.com/seventv/common/utils"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type AnyPayload interface {
json.RawMessage | HelloPayload | AckPayload | HeartbeatPayload | ReconnectPayload | ResumePayload |
SubscribePayload | UnsubscribePayload | DispatchPayload | SignalPayload |
ErrorPayload | EndOfStreamPayload | BridgedCommandBody
}
type HelloPayload struct {
HeartbeatInterval uint32 `json:"heartbeat_interval"`
SessionID string `json:"session_id"`
SubscriptionLimit int32 `json:"subscription_limit"`
Actor *primitive.ObjectID `json:"actor,omitempty"`
Instance HelloPayloadInstanceInfo `json:"instance,omitempty"`
}
type HelloPayloadInstanceInfo struct {
Name string `json:"name"`
Population int32 `json:"population"`
}
type AckPayload struct {
Command string `json:"command"`
Data json.RawMessage `json:"data"`
}
type HeartbeatPayload struct {
Count uint64 `json:"count"`
}
type ReconnectPayload struct {
Reason string `json:"reason"`
}
type ResumePayload struct {
SessionID string `json:"session_id"`
}
type SubscribePayload struct {
Type EventType `json:"type"`
Condition map[string]string `json:"condition"`
TTL time.Duration `json:"ttl,omitempty"`
}
type UnsubscribePayload struct {
Type EventType `json:"type"`
Condition map[string]string `json:"condition"`
}
type DispatchPayload struct {
Type EventType `json:"type"`
// Detailed changes to an object
Body ChangeMap `json:"body"`
// Hash is a hash of the target object, used for deduping
Hash *uint32 `json:"hash,omitempty"`
// A list of effects to apply to the session when this dispatch is received
Effect *SessionEffect `json:"effect,omitempty"`
// A list of subscriptions that match this dispatch
Matches []uint32 `json:"matches,omitempty"`
// A list of conditions where at least one must have all its fields match a subscription in order for this dispatch to be delivered
Conditions []EventCondition `json:"condition,omitempty"`
// This dispatch is a whisper to a specific session, usually as a response to a command
Whisper string `json:"whisper,omitempty"`
}
func CreateDispatchKey(t EventType, condition EventCondition) string {
s := strings.Builder{}
s.WriteString(OpcodeDispatch.PublishKey())
s.WriteString(".type.")
s.WriteString(string(t))
if len(condition) > 0 {
s.WriteString(".")
sorted := make([]string, len(condition))
h := sha256.New()
i := 0
for k := range condition {
sorted[i] = k
i++
}
sort.Strings(sorted)
for _, k := range sorted {
v := condition[k]
h.Write(utils.S2B(k))
h.Write(utils.S2B(v))
}
s.WriteString(hex.EncodeToString(h.Sum(nil)))
}
return s.String()
}
type EventCondition map[string]string
func (evc EventCondition) SetObjectID(id primitive.ObjectID) EventCondition {
evc["object_id"] = id.Hex()
return evc
}
func (evc EventCondition) Set(key string, value string) EventCondition {
evc[key] = value
return evc
}
func (evc EventCondition) Match(other EventCondition) bool {
for k, v := range other {
if evc[k] != v {
return false
}
}
return true
}
type SignalPayload struct {
Sender SignalUser `json:"sender"`
Host SignalUser `json:"host"`
}
type SignalUser struct {
ID primitive.ObjectID `json:"id"`
ChannelID string `json:"channel_id"`
Username string `json:"username"`
DisplayName string `json:"display_name"`
}
type ErrorPayload struct {
Message string `json:"message"`
MessageLocale string `json:"message_locale,omitempty"`
Fields map[string]any `json:"fields"`
}
type EndOfStreamPayload struct {
Code CloseCode `json:"code"`
Message string `json:"message"`
}