@@ -8,6 +8,7 @@ package event
8
8
9
9
import (
10
10
"encoding/json"
11
+ "time"
11
12
12
13
"maunium.net/go/mautrix/id"
13
14
)
@@ -59,12 +60,19 @@ func (ur UserReceipts) Set(userID id.UserID, receipt ReadReceipt) {
59
60
ur [userID ] = receipt
60
61
}
61
62
63
+ type ThreadID = id.EventID
64
+
65
+ const ReadReceiptThreadMain ThreadID = "main"
66
+
62
67
type ReadReceipt struct {
63
- Timestamp int64 `json:"ts"`
68
+ Timestamp time.Time
69
+
70
+ // Thread ID for thread-specific read receipts from MSC3771
71
+ ThreadID ThreadID
64
72
65
73
// Extra contains any unknown fields in the read receipt event.
66
74
// Most servers don't allow clients to set them, so this will be empty in most cases.
67
- Extra map [string ]interface {} `json:"-"`
75
+ Extra map [string ]interface {}
68
76
}
69
77
70
78
func (rr * ReadReceipt ) UnmarshalJSON (data []byte ) error {
@@ -84,15 +92,34 @@ func (rr *ReadReceipt) UnmarshalJSON(data []byte) error {
84
92
if err != nil {
85
93
return err
86
94
}
87
- ts , _ := parsed ["ts" ].(float64 )
95
+ threadID , _ := parsed ["thread_id" ].(string )
96
+ ts , tsOK := parsed ["ts" ].(float64 )
97
+ delete (parsed , "thread_id" )
88
98
delete (parsed , "ts" )
89
99
* rr = ReadReceipt {
90
- Timestamp : int64 (ts ),
91
- Extra : parsed ,
100
+ ThreadID : ThreadID (threadID ),
101
+ Extra : parsed ,
102
+ }
103
+ if tsOK {
104
+ rr .Timestamp = time .UnixMilli (int64 (ts ))
92
105
}
93
106
return nil
94
107
}
95
108
109
+ func (rr ReadReceipt ) MarshalJSON () ([]byte , error ) {
110
+ data := rr .Extra
111
+ if data == nil {
112
+ data = make (map [string ]interface {})
113
+ }
114
+ if rr .ThreadID != "" {
115
+ data ["thread_id" ] = rr .ThreadID
116
+ }
117
+ if ! rr .Timestamp .IsZero () {
118
+ data ["ts" ] = rr .Timestamp .UnixMilli ()
119
+ }
120
+ return json .Marshal (data )
121
+ }
122
+
96
123
type Presence string
97
124
98
125
const (
0 commit comments