summaryrefslogtreecommitdiffstats
path: root/vendor/maunium.net/go/mautrix/event
diff options
context:
space:
mode:
authormsglm <msglm@techchud.xyz>2023-10-27 07:08:25 -0500
committermsglm <msglm@techchud.xyz>2023-10-27 07:08:25 -0500
commit032a7e0c1188d3507b8d9a9571f2446a43cf775b (patch)
tree2bd38c01bc7761a6195e426082ce7191ebc765a1 /vendor/maunium.net/go/mautrix/event
parent56e7bd01ca09ad52b0c4f48f146a20a4f1b78696 (diff)
downloadmatterbridge-msglm-1.26.0+0.1.0.tar.gz
matterbridge-msglm-1.26.0+0.1.0.tar.bz2
matterbridge-msglm-1.26.0+0.1.0.zip
apply https://github.com/42wim/matterbridge/pull/1864v1.26.0+0.1.0
Diffstat (limited to 'vendor/maunium.net/go/mautrix/event')
-rw-r--r--vendor/maunium.net/go/mautrix/event/accountdata.go45
-rw-r--r--vendor/maunium.net/go/mautrix/event/beeper.go51
-rw-r--r--vendor/maunium.net/go/mautrix/event/content.go506
-rw-r--r--vendor/maunium.net/go/mautrix/event/encryption.go149
-rw-r--r--vendor/maunium.net/go/mautrix/event/ephemeral.go140
-rw-r--r--vendor/maunium.net/go/mautrix/event/events.go149
-rw-r--r--vendor/maunium.net/go/mautrix/event/member.go53
-rw-r--r--vendor/maunium.net/go/mautrix/event/message.go276
-rw-r--r--vendor/maunium.net/go/mautrix/event/powerlevels.go149
-rw-r--r--vendor/maunium.net/go/mautrix/event/relations.go234
-rw-r--r--vendor/maunium.net/go/mautrix/event/reply.go100
-rw-r--r--vendor/maunium.net/go/mautrix/event/state.go176
-rw-r--r--vendor/maunium.net/go/mautrix/event/type.go256
-rw-r--r--vendor/maunium.net/go/mautrix/event/verification.go307
-rw-r--r--vendor/maunium.net/go/mautrix/event/voip.go116
15 files changed, 2707 insertions, 0 deletions
diff --git a/vendor/maunium.net/go/mautrix/event/accountdata.go b/vendor/maunium.net/go/mautrix/event/accountdata.go
new file mode 100644
index 00000000..6637fcfe
--- /dev/null
+++ b/vendor/maunium.net/go/mautrix/event/accountdata.go
@@ -0,0 +1,45 @@
+// Copyright (c) 2020 Tulir Asokan
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package event
+
+import (
+ "encoding/json"
+
+ "maunium.net/go/mautrix/id"
+)
+
+// TagEventContent represents the content of a m.tag room account data event.
+// https://spec.matrix.org/v1.2/client-server-api/#mtag
+type TagEventContent struct {
+ Tags Tags `json:"tags"`
+}
+
+type Tags map[string]Tag
+
+type Tag struct {
+ Order json.Number `json:"order,omitempty"`
+}
+
+// DirectChatsEventContent represents the content of a m.direct account data event.
+// https://spec.matrix.org/v1.2/client-server-api/#mdirect
+type DirectChatsEventContent map[id.UserID][]id.RoomID
+
+// FullyReadEventContent represents the content of a m.fully_read account data event.
+// https://spec.matrix.org/v1.2/client-server-api/#mfully_read
+type FullyReadEventContent struct {
+ EventID id.EventID `json:"event_id"`
+}
+
+// IgnoredUserListEventContent represents the content of a m.ignored_user_list account data event.
+// https://spec.matrix.org/v1.2/client-server-api/#mignored_user_list
+type IgnoredUserListEventContent struct {
+ IgnoredUsers map[id.UserID]IgnoredUser `json:"ignored_users"`
+}
+
+type IgnoredUser struct {
+ // This is an empty object
+}
diff --git a/vendor/maunium.net/go/mautrix/event/beeper.go b/vendor/maunium.net/go/mautrix/event/beeper.go
new file mode 100644
index 00000000..2ee72073
--- /dev/null
+++ b/vendor/maunium.net/go/mautrix/event/beeper.go
@@ -0,0 +1,51 @@
+// Copyright (c) 2022 Tulir Asokan
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package event
+
+import (
+ "maunium.net/go/mautrix/id"
+)
+
+type MessageStatusReason string
+
+const (
+ MessageStatusGenericError MessageStatusReason = "m.event_not_handled"
+ MessageStatusUnsupported MessageStatusReason = "com.beeper.unsupported_event"
+ MessageStatusUndecryptable MessageStatusReason = "com.beeper.undecryptable_event"
+ MessageStatusTooOld MessageStatusReason = "m.event_too_old"
+ MessageStatusNetworkError MessageStatusReason = "m.foreign_network_error"
+ MessageStatusNoPermission MessageStatusReason = "m.no_permission"
+ MessageStatusBridgeUnavailable MessageStatusReason = "m.bridge_unavailable"
+)
+
+type MessageStatus string
+
+const (
+ MessageStatusSuccess MessageStatus = "SUCCESS"
+ MessageStatusPending MessageStatus = "PENDING"
+ MessageStatusRetriable MessageStatus = "FAIL_RETRIABLE"
+ MessageStatusFail MessageStatus = "FAIL_PERMANENT"
+)
+
+type BeeperMessageStatusEventContent struct {
+ Network string `json:"network"`
+ RelatesTo RelatesTo `json:"m.relates_to"`
+ Status MessageStatus `json:"status"`
+ Reason MessageStatusReason `json:"reason,omitempty"`
+ Error string `json:"error,omitempty"`
+ Message string `json:"message,omitempty"`
+
+ LastRetry id.EventID `json:"last_retry,omitempty"`
+
+ MutateEventKey string `json:"mutate_event_key,omitempty"`
+}
+
+type BeeperRetryMetadata struct {
+ OriginalEventID id.EventID `json:"original_event_id"`
+ RetryCount int `json:"retry_count"`
+ // last_retry is also present, but not used by bridges
+}
diff --git a/vendor/maunium.net/go/mautrix/event/content.go b/vendor/maunium.net/go/mautrix/event/content.go
new file mode 100644
index 00000000..5624fd59
--- /dev/null
+++ b/vendor/maunium.net/go/mautrix/event/content.go
@@ -0,0 +1,506 @@
+// Copyright (c) 2021 Tulir Asokan
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package event
+
+import (
+ "encoding/gob"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "reflect"
+)
+
+// TypeMap is a mapping from event type to the content struct type.
+// This is used by Content.ParseRaw() for creating the correct type of struct.
+var TypeMap = map[Type]reflect.Type{
+ StateMember: reflect.TypeOf(MemberEventContent{}),
+ StatePowerLevels: reflect.TypeOf(PowerLevelsEventContent{}),
+ StateCanonicalAlias: reflect.TypeOf(CanonicalAliasEventContent{}),
+ StateRoomName: reflect.TypeOf(RoomNameEventContent{}),
+ StateRoomAvatar: reflect.TypeOf(RoomAvatarEventContent{}),
+ StateServerACL: reflect.TypeOf(ServerACLEventContent{}),
+ StateTopic: reflect.TypeOf(TopicEventContent{}),
+ StateTombstone: reflect.TypeOf(TombstoneEventContent{}),
+ StateCreate: reflect.TypeOf(CreateEventContent{}),
+ StateJoinRules: reflect.TypeOf(JoinRulesEventContent{}),
+ StateHistoryVisibility: reflect.TypeOf(HistoryVisibilityEventContent{}),
+ StateGuestAccess: reflect.TypeOf(GuestAccessEventContent{}),
+ StatePinnedEvents: reflect.TypeOf(PinnedEventsEventContent{}),
+ StatePolicyRoom: reflect.TypeOf(ModPolicyContent{}),
+ StatePolicyServer: reflect.TypeOf(ModPolicyContent{}),
+ StatePolicyUser: reflect.TypeOf(ModPolicyContent{}),
+ StateEncryption: reflect.TypeOf(EncryptionEventContent{}),
+ StateBridge: reflect.TypeOf(BridgeEventContent{}),
+ StateHalfShotBridge: reflect.TypeOf(BridgeEventContent{}),
+ StateSpaceParent: reflect.TypeOf(SpaceParentEventContent{}),
+ StateSpaceChild: reflect.TypeOf(SpaceChildEventContent{}),
+ StateInsertionMarker: reflect.TypeOf(InsertionMarkerContent{}),
+
+ EventMessage: reflect.TypeOf(MessageEventContent{}),
+ EventSticker: reflect.TypeOf(MessageEventContent{}),
+ EventEncrypted: reflect.TypeOf(EncryptedEventContent{}),
+ EventRedaction: reflect.TypeOf(RedactionEventContent{}),
+ EventReaction: reflect.TypeOf(ReactionEventContent{}),
+
+ BeeperMessageStatus: reflect.TypeOf(BeeperMessageStatusEventContent{}),
+
+ AccountDataRoomTags: reflect.TypeOf(TagEventContent{}),
+ AccountDataDirectChats: reflect.TypeOf(DirectChatsEventContent{}),
+ AccountDataFullyRead: reflect.TypeOf(FullyReadEventContent{}),
+ AccountDataIgnoredUserList: reflect.TypeOf(IgnoredUserListEventContent{}),
+
+ EphemeralEventTyping: reflect.TypeOf(TypingEventContent{}),
+ EphemeralEventReceipt: reflect.TypeOf(ReceiptEventContent{}),
+ EphemeralEventPresence: reflect.TypeOf(PresenceEventContent{}),
+
+ InRoomVerificationStart: reflect.TypeOf(VerificationStartEventContent{}),
+ InRoomVerificationReady: reflect.TypeOf(VerificationReadyEventContent{}),
+ InRoomVerificationAccept: reflect.TypeOf(VerificationAcceptEventContent{}),
+ InRoomVerificationKey: reflect.TypeOf(VerificationKeyEventContent{}),
+ InRoomVerificationMAC: reflect.TypeOf(VerificationMacEventContent{}),
+ InRoomVerificationCancel: reflect.TypeOf(VerificationCancelEventContent{}),
+
+ ToDeviceRoomKey: reflect.TypeOf(RoomKeyEventContent{}),
+ ToDeviceForwardedRoomKey: reflect.TypeOf(ForwardedRoomKeyEventContent{}),
+ ToDeviceRoomKeyRequest: reflect.TypeOf(RoomKeyRequestEventContent{}),
+ ToDeviceEncrypted: reflect.TypeOf(EncryptedEventContent{}),
+ ToDeviceRoomKeyWithheld: reflect.TypeOf(RoomKeyWithheldEventContent{}),
+ ToDeviceDummy: reflect.TypeOf(DummyEventContent{}),
+
+ ToDeviceVerificationStart: reflect.TypeOf(VerificationStartEventContent{}),
+ ToDeviceVerificationAccept: reflect.TypeOf(VerificationAcceptEventContent{}),
+ ToDeviceVerificationKey: reflect.TypeOf(VerificationKeyEventContent{}),
+ ToDeviceVerificationMAC: reflect.TypeOf(VerificationMacEventContent{}),
+ ToDeviceVerificationCancel: reflect.TypeOf(VerificationCancelEventContent{}),
+ ToDeviceVerificationRequest: reflect.TypeOf(VerificationRequestEventContent{}),
+
+ ToDeviceOrgMatrixRoomKeyWithheld: reflect.TypeOf(RoomKeyWithheldEventContent{}),
+
+ CallInvite: reflect.TypeOf(CallInviteEventContent{}),
+ CallCandidates: reflect.TypeOf(CallCandidatesEventContent{}),
+ CallAnswer: reflect.TypeOf(CallAnswerEventContent{}),
+ CallReject: reflect.TypeOf(CallRejectEventContent{}),
+ CallSelectAnswer: reflect.TypeOf(CallSelectAnswerEventContent{}),
+ CallNegotiate: reflect.TypeOf(CallNegotiateEventContent{}),
+ CallHangup: reflect.TypeOf(CallHangupEventContent{}),
+}
+
+// Content stores the content of a Matrix event.
+//
+// By default, the raw JSON bytes are stored in VeryRaw and parsed into a map[string]interface{} in the Raw field.
+// Additionally, you can call ParseRaw with the correct event type to parse the (VeryRaw) content into a nicer struct,
+// which you can then access from Parsed or via the helper functions.
+//
+// When being marshaled into JSON, the data in Parsed will be marshaled first and then recursively merged
+// with the data in Raw. Values in Raw are preferred, but nested objects will be recursed into before merging,
+// rather than overriding the whole object with the one in Raw).
+// If one of them is nil, the only the other is used. If both (Parsed and Raw) are nil, VeryRaw is used instead.
+type Content struct {
+ VeryRaw json.RawMessage
+ Raw map[string]interface{}
+ Parsed interface{}
+}
+
+type Relatable interface {
+ GetRelatesTo() *RelatesTo
+ OptionalGetRelatesTo() *RelatesTo
+ SetRelatesTo(rel *RelatesTo)
+}
+
+func (content *Content) UnmarshalJSON(data []byte) error {
+ content.VeryRaw = data
+ err := json.Unmarshal(data, &content.Raw)
+ return err
+}
+
+func (content *Content) MarshalJSON() ([]byte, error) {
+ if content.Raw == nil {
+ if content.Parsed == nil {
+ if content.VeryRaw == nil {
+ return []byte("{}"), nil
+ }
+ return content.VeryRaw, nil
+ }
+ return json.Marshal(content.Parsed)
+ } else if content.Parsed != nil {
+ // TODO this whole thing is incredibly hacky
+ // It needs to produce JSON, where:
+ // * content.Parsed is applied after content.Raw
+ // * MarshalJSON() is respected inside content.Parsed
+ // * Custom field inside nested objects of content.Raw are preserved,
+ // even if content.Parsed contains the higher-level objects.
+ // * content.Raw is not modified
+
+ unparsed, err := json.Marshal(content.Parsed)
+ if err != nil {
+ return nil, err
+ }
+
+ var rawParsed map[string]interface{}
+ err = json.Unmarshal(unparsed, &rawParsed)
+ if err != nil {
+ return nil, err
+ }
+
+ output := make(map[string]interface{})
+ for key, value := range content.Raw {
+ output[key] = value
+ }
+
+ mergeMaps(output, rawParsed)
+ return json.Marshal(output)
+ }
+ return json.Marshal(content.Raw)
+}
+
+// Deprecated: use errors.Is directly
+func IsUnsupportedContentType(err error) bool {
+ return errors.Is(err, ErrUnsupportedContentType)
+}
+
+var ErrContentAlreadyParsed = errors.New("content is already parsed")
+var ErrUnsupportedContentType = errors.New("unsupported event type")
+
+func (content *Content) ParseRaw(evtType Type) error {
+ if content.Parsed != nil {
+ return ErrContentAlreadyParsed
+ }
+ structType, ok := TypeMap[evtType]
+ if !ok {
+ return fmt.Errorf("%w %s", ErrUnsupportedContentType, evtType.Repr())
+ }
+ content.Parsed = reflect.New(structType).Interface()
+ return json.Unmarshal(content.VeryRaw, &content.Parsed)
+}
+
+func mergeMaps(into, from map[string]interface{}) {
+ for key, newValue := range from {
+ existingValue, ok := into[key]
+ if !ok {
+ into[key] = newValue
+ continue
+ }
+ existingValueMap, okEx := existingValue.(map[string]interface{})
+ newValueMap, okNew := newValue.(map[string]interface{})
+ if okEx && okNew {
+ mergeMaps(existingValueMap, newValueMap)
+ } else {
+ into[key] = newValue
+ }
+ }
+}
+
+func init() {
+ gob.Register(&MemberEventContent{})
+ gob.Register(&PowerLevelsEventContent{})
+ gob.Register(&CanonicalAliasEventContent{})
+ gob.Register(&EncryptionEventContent{})
+ gob.Register(&BridgeEventContent{})
+ gob.Register(&SpaceChildEventContent{})
+ gob.Register(&SpaceParentEventContent{})
+ gob.Register(&RoomNameEventContent{})
+ gob.Register(&RoomAvatarEventContent{})
+ gob.Register(&TopicEventContent{})
+ gob.Register(&TombstoneEventContent{})
+ gob.Register(&CreateEventContent{})
+ gob.Register(&JoinRulesEventContent{})
+ gob.Register(&HistoryVisibilityEventContent{})
+ gob.Register(&GuestAccessEventContent{})
+ gob.Register(&PinnedEventsEventContent{})
+ gob.Register(&MessageEventContent{})
+ gob.Register(&MessageEventContent{})
+ gob.Register(&EncryptedEventContent{})
+ gob.Register(&RedactionEventContent{})
+ gob.Register(&ReactionEventContent{})
+ gob.Register(&TagEventContent{})
+ gob.Register(&DirectChatsEventContent{})
+ gob.Register(&FullyReadEventContent{})
+ gob.Register(&IgnoredUserListEventContent{})
+ gob.Register(&TypingEventContent{})
+ gob.Register(&ReceiptEventContent{})
+ gob.Register(&PresenceEventContent{})
+ gob.Register(&RoomKeyEventContent{})
+ gob.Register(&ForwardedRoomKeyEventContent{})
+ gob.Register(&RoomKeyRequestEventContent{})
+ gob.Register(&RoomKeyWithheldEventContent{})
+}
+
+// Helper cast functions below
+
+func (content *Content) AsMember() *MemberEventContent {
+ casted, ok := content.Parsed.(*MemberEventContent)
+ if !ok {
+ return &MemberEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsPowerLevels() *PowerLevelsEventContent {
+ casted, ok := content.Parsed.(*PowerLevelsEventContent)
+ if !ok {
+ return &PowerLevelsEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsCanonicalAlias() *CanonicalAliasEventContent {
+ casted, ok := content.Parsed.(*CanonicalAliasEventContent)
+ if !ok {
+ return &CanonicalAliasEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsRoomName() *RoomNameEventContent {
+ casted, ok := content.Parsed.(*RoomNameEventContent)
+ if !ok {
+ return &RoomNameEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsRoomAvatar() *RoomAvatarEventContent {
+ casted, ok := content.Parsed.(*RoomAvatarEventContent)
+ if !ok {
+ return &RoomAvatarEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsTopic() *TopicEventContent {
+ casted, ok := content.Parsed.(*TopicEventContent)
+ if !ok {
+ return &TopicEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsTombstone() *TombstoneEventContent {
+ casted, ok := content.Parsed.(*TombstoneEventContent)
+ if !ok {
+ return &TombstoneEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsCreate() *CreateEventContent {
+ casted, ok := content.Parsed.(*CreateEventContent)
+ if !ok {
+ return &CreateEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsJoinRules() *JoinRulesEventContent {
+ casted, ok := content.Parsed.(*JoinRulesEventContent)
+ if !ok {
+ return &JoinRulesEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsHistoryVisibility() *HistoryVisibilityEventContent {
+ casted, ok := content.Parsed.(*HistoryVisibilityEventContent)
+ if !ok {
+ return &HistoryVisibilityEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsGuestAccess() *GuestAccessEventContent {
+ casted, ok := content.Parsed.(*GuestAccessEventContent)
+ if !ok {
+ return &GuestAccessEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsPinnedEvents() *PinnedEventsEventContent {
+ casted, ok := content.Parsed.(*PinnedEventsEventContent)
+ if !ok {
+ return &PinnedEventsEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsEncryption() *EncryptionEventContent {
+ casted, ok := content.Parsed.(*EncryptionEventContent)
+ if !ok {
+ return &EncryptionEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsBridge() *BridgeEventContent {
+ casted, ok := content.Parsed.(*BridgeEventContent)
+ if !ok {
+ return &BridgeEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsSpaceChild() *SpaceChildEventContent {
+ casted, ok := content.Parsed.(*SpaceChildEventContent)
+ if !ok {
+ return &SpaceChildEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsSpaceParent() *SpaceParentEventContent {
+ casted, ok := content.Parsed.(*SpaceParentEventContent)
+ if !ok {
+ return &SpaceParentEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsMessage() *MessageEventContent {
+ casted, ok := content.Parsed.(*MessageEventContent)
+ if !ok {
+ return &MessageEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsEncrypted() *EncryptedEventContent {
+ casted, ok := content.Parsed.(*EncryptedEventContent)
+ if !ok {
+ return &EncryptedEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsRedaction() *RedactionEventContent {
+ casted, ok := content.Parsed.(*RedactionEventContent)
+ if !ok {
+ return &RedactionEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsReaction() *ReactionEventContent {
+ casted, ok := content.Parsed.(*ReactionEventContent)
+ if !ok {
+ return &ReactionEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsTag() *TagEventContent {
+ casted, ok := content.Parsed.(*TagEventContent)
+ if !ok {
+ return &TagEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsDirectChats() *DirectChatsEventContent {
+ casted, ok := content.Parsed.(*DirectChatsEventContent)
+ if !ok {
+ return &DirectChatsEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsFullyRead() *FullyReadEventContent {
+ casted, ok := content.Parsed.(*FullyReadEventContent)
+ if !ok {
+ return &FullyReadEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsIgnoredUserList() *IgnoredUserListEventContent {
+ casted, ok := content.Parsed.(*IgnoredUserListEventContent)
+ if !ok {
+ return &IgnoredUserListEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsTyping() *TypingEventContent {
+ casted, ok := content.Parsed.(*TypingEventContent)
+ if !ok {
+ return &TypingEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsReceipt() *ReceiptEventContent {
+ casted, ok := content.Parsed.(*ReceiptEventContent)
+ if !ok {
+ return &ReceiptEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsPresence() *PresenceEventContent {
+ casted, ok := content.Parsed.(*PresenceEventContent)
+ if !ok {
+ return &PresenceEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsRoomKey() *RoomKeyEventContent {
+ casted, ok := content.Parsed.(*RoomKeyEventContent)
+ if !ok {
+ return &RoomKeyEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsForwardedRoomKey() *ForwardedRoomKeyEventContent {
+ casted, ok := content.Parsed.(*ForwardedRoomKeyEventContent)
+ if !ok {
+ return &ForwardedRoomKeyEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsRoomKeyRequest() *RoomKeyRequestEventContent {
+ casted, ok := content.Parsed.(*RoomKeyRequestEventContent)
+ if !ok {
+ return &RoomKeyRequestEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsRoomKeyWithheld() *RoomKeyWithheldEventContent {
+ casted, ok := content.Parsed.(*RoomKeyWithheldEventContent)
+ if !ok {
+ return &RoomKeyWithheldEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsCallInvite() *CallInviteEventContent {
+ casted, ok := content.Parsed.(*CallInviteEventContent)
+ if !ok {
+ return &CallInviteEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsCallCandidates() *CallCandidatesEventContent {
+ casted, ok := content.Parsed.(*CallCandidatesEventContent)
+ if !ok {
+ return &CallCandidatesEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsCallAnswer() *CallAnswerEventContent {
+ casted, ok := content.Parsed.(*CallAnswerEventContent)
+ if !ok {
+ return &CallAnswerEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsCallReject() *CallRejectEventContent {
+ casted, ok := content.Parsed.(*CallRejectEventContent)
+ if !ok {
+ return &CallRejectEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsCallSelectAnswer() *CallSelectAnswerEventContent {
+ casted, ok := content.Parsed.(*CallSelectAnswerEventContent)
+ if !ok {
+ return &CallSelectAnswerEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsCallNegotiate() *CallNegotiateEventContent {
+ casted, ok := content.Parsed.(*CallNegotiateEventContent)
+ if !ok {
+ return &CallNegotiateEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsCallHangup() *CallHangupEventContent {
+ casted, ok := content.Parsed.(*CallHangupEventContent)
+ if !ok {
+ return &CallHangupEventContent{}
+ }
+ return casted
+}
+func (content *Content) AsModPolicy() *ModPolicyContent {
+ casted, ok := content.Parsed.(*ModPolicyContent)
+ if !ok {
+ return &ModPolicyContent{}
+ }
+ return casted
+}
diff --git a/vendor/maunium.net/go/mautrix/event/encryption.go b/vendor/maunium.net/go/mautrix/event/encryption.go
new file mode 100644
index 00000000..2506ad57
--- /dev/null
+++ b/vendor/maunium.net/go/mautrix/event/encryption.go
@@ -0,0 +1,149 @@
+// Copyright (c) 2020 Tulir Asokan
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package event
+
+import (
+ "encoding/json"
+
+ "maunium.net/go/mautrix/id"
+)
+
+// EncryptionEventContent represents the content of a m.room.encryption state event.
+// https://spec.matrix.org/v1.2/client-server-api/#mroomencryption
+type EncryptionEventContent struct {
+ // The encryption algorithm to be used to encrypt messages sent in this room. Must be 'm.megolm.v1.aes-sha2'.
+ Algorithm id.Algorithm `json:"algorithm"`
+ // How long the session should be used before changing it. 604800000 (a week) is the recommended default.
+ RotationPeriodMillis int64 `json:"rotation_period_ms,omitempty"`
+ // How many messages should be sent before changing the session. 100 is the recommended default.
+ RotationPeriodMessages int `json:"rotation_period_msgs,omitempty"`
+}
+
+// EncryptedEventContent represents the content of a m.room.encrypted message event.
+// https://spec.matrix.org/v1.2/client-server-api/#mroomencrypted
+//
+// Note that sender_key and device_id are deprecated in Megolm events as of https://github.com/matrix-org/matrix-spec-proposals/pull/3700
+type EncryptedEventContent struct {
+ Algorithm id.Algorithm `json:"algorithm"`
+ SenderKey id.SenderKey `json:"sender_key,omitempty"`
+ // Deprecated: Matrix v1.3
+ DeviceID id.DeviceID `json:"device_id,omitempty"`
+ // Only present for Megolm events
+ SessionID id.SessionID `json:"session_id,omitempty"`
+
+ Ciphertext json.RawMessage `json:"ciphertext"`
+
+ MegolmCiphertext []byte `json:"-"`
+ OlmCiphertext OlmCiphertexts `json:"-"`
+
+ RelatesTo *RelatesTo `json:"m.relates_to,omitempty"`
+ Mentions *Mentions `json:"m.mentions,omitempty"`
+}
+
+type OlmCiphertexts map[id.Curve25519]struct {
+ Body string `json:"body"`
+ Type id.OlmMsgType `json:"type"`
+}
+
+type serializableEncryptedEventContent EncryptedEventContent
+
+func (content *EncryptedEventContent) UnmarshalJSON(data []byte) error {
+ err := json.Unmarshal(data, (*serializableEncryptedEventContent)(content))
+ if err != nil {
+ return err
+ }
+ switch content.Algorithm {
+ case id.AlgorithmOlmV1:
+ content.OlmCiphertext = make(OlmCiphertexts)
+ return json.Unmarshal(content.Ciphertext, &content.OlmCiphertext)
+ case id.AlgorithmMegolmV1:
+ if len(content.Ciphertext) == 0 || content.Ciphertext[0] != '"' || content.Ciphertext[len(content.Ciphertext)-1] != '"' {
+ return id.InputNotJSONString
+ }
+ content.MegolmCiphertext = content.Ciphertext[1 : len(content.Ciphertext)-1]
+ }
+ return nil
+}
+
+func (content *EncryptedEventContent) MarshalJSON() ([]byte, error) {
+ var err error
+ switch content.Algorithm {
+ case id.AlgorithmOlmV1:
+ content.Ciphertext, err = json.Marshal(content.OlmCiphertext)
+ case id.AlgorithmMegolmV1:
+ content.Ciphertext = make([]byte, len(content.MegolmCiphertext)+2)
+ content.Ciphertext[0] = '"'
+ content.Ciphertext[len(content.Ciphertext)-1] = '"'
+ copy(content.Ciphertext[1:len(content.Ciphertext)-1], content.MegolmCiphertext)
+ }
+ if err != nil {
+ return nil, err
+ }
+ return json.Marshal((*serializableEncryptedEventContent)(content))
+}
+
+// RoomKeyEventContent represents the content of a m.room_key to_device event.
+// https://spec.matrix.org/v1.2/client-server-api/#mroom_key
+type RoomKeyEventContent struct {
+ Algorithm id.Algorithm `json:"algorithm"`
+ RoomID id.RoomID `json:"room_id"`
+ SessionID id.SessionID `json:"session_id"`
+ SessionKey string `json:"session_key"`
+}
+
+// ForwardedRoomKeyEventContent represents the content of a m.forwarded_room_key to_device event.
+// https://spec.matrix.org/v1.2/client-server-api/#mforwarded_room_key
+type ForwardedRoomKeyEventContent struct {
+ RoomKeyEventContent
+ SenderKey id.SenderKey `json:"sender_key"`
+ SenderClaimedKey id.Ed25519 `json:"sender_claimed_ed25519_key"`
+ ForwardingKeyChain []string `json:"forwarding_curve25519_key_chain"`
+}
+
+type KeyRequestAction string
+
+const (
+ KeyRequestActionRequest = "request"
+ KeyRequestActionCancel = "request_cancellation"
+)
+
+// RoomKeyRequestEventContent represents the content of a m.room_key_request to_device event.
+// https://spec.matrix.org/v1.2/client-server-api/#mroom_key_request
+type RoomKeyRequestEventContent struct {
+ Body RequestedKeyInfo `json:"body"`
+ Action KeyRequestAction `json:"action"`
+ RequestingDeviceID id.DeviceID `json:"requesting_device_id"`
+ RequestID string `json:"request_id"`
+}
+
+type RequestedKeyInfo struct {
+ Algorithm id.Algorithm `json:"algorithm"`
+ RoomID id.RoomID `json:"room_id"`
+ SenderKey id.SenderKey `json:"sender_key"`
+ SessionID id.SessionID `json:"session_id"`
+}
+
+type RoomKeyWithheldCode string
+
+const (
+ RoomKeyWithheldBlacklisted RoomKeyWithheldCode = "m.blacklisted"
+ RoomKeyWithheldUnverified RoomKeyWithheldCode = "m.unverified"
+ RoomKeyWithheldUnauthorized RoomKeyWithheldCode = "m.unauthorised"
+ RoomKeyWithheldUnavailable RoomKeyWithheldCode = "m.unavailable"
+ RoomKeyWithheldNoOlmSession RoomKeyWithheldCode = "m.no_olm"
+)
+
+type RoomKeyWithheldEventContent struct {
+ RoomID id.RoomID `json:"room_id,omitempty"`
+ Algorithm id.Algorithm `json:"algorithm"`
+ SessionID id.SessionID `json:"session_id,omitempty"`
+ SenderKey id.SenderKey `json:"sender_key"`
+ Code RoomKeyWithheldCode `json:"code"`
+ Reason string `json:"reason,omitempty"`
+}
+
+type DummyEventContent struct{}
diff --git a/vendor/maunium.net/go/mautrix/event/ephemeral.go b/vendor/maunium.net/go/mautrix/event/ephemeral.go
new file mode 100644
index 00000000..f447404b
--- /dev/null
+++ b/vendor/maunium.net/go/mautrix/event/ephemeral.go
@@ -0,0 +1,140 @@
+// Copyright (c) 2020 Tulir Asokan
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package event
+
+import (
+ "encoding/json"
+ "time"
+
+ "maunium.net/go/mautrix/id"
+)
+
+// TypingEventContent represents the content of a m.typing ephemeral event.
+// https://spec.matrix.org/v1.2/client-server-api/#mtyping
+type TypingEventContent struct {
+ UserIDs []id.UserID `json:"user_ids"`
+}
+
+// ReceiptEventContent represents the content of a m.receipt ephemeral event.
+// https://spec.matrix.org/v1.2/client-server-api/#mreceipt
+type ReceiptEventContent map[id.EventID]Receipts
+
+func (rec ReceiptEventContent) Set(evtID id.EventID, receiptType ReceiptType, userID id.UserID, receipt ReadReceipt) {
+ rec.GetOrCreate(evtID).GetOrCreate(receiptType).Set(userID, receipt)
+}
+
+func (rec ReceiptEventContent) GetOrCreate(evt id.EventID) Receipts {
+ receipts, ok := rec[evt]
+ if !ok {
+ receipts = make(Receipts)
+ rec[evt] = receipts
+ }
+ return receipts
+}
+
+type ReceiptType string
+
+const (
+ ReceiptTypeRead ReceiptType = "m.read"
+ ReceiptTypeReadPrivate ReceiptType = "m.read.private"
+)
+
+type Receipts map[ReceiptType]UserReceipts
+
+func (rps Receipts) GetOrCreate(receiptType ReceiptType) UserReceipts {
+ read, ok := rps[receiptType]
+ if !ok {
+ read = make(UserReceipts)
+ rps[receiptType] = read
+ }
+ return read
+}
+
+type UserReceipts map[id.UserID]ReadReceipt
+
+func (ur UserReceipts) Set(userID id.UserID, receipt ReadReceipt) {
+ ur[userID] = receipt
+}
+
+type ThreadID = id.EventID
+
+const ReadReceiptThreadMain ThreadID = "main"
+
+type ReadReceipt struct {
+ Timestamp time.Time
+
+ // Thread ID for thread-specific read receipts from MSC3771
+ ThreadID ThreadID
+
+ // Extra contains any unknown fields in the read receipt event.
+ // Most servers don't allow clients to set them, so this will be empty in most cases.
+ Extra map[string]interface{}
+}
+
+func (rr *ReadReceipt) UnmarshalJSON(data []byte) error {
+ // Hacky compatibility hack against crappy clients that send double-encoded read receipts.
+ // TODO is this actually needed? clients can't currently set custom content in receipts 🤔
+ if data[0] == '"' && data[len(data)-1] == '"' {
+ var strData string
+ err := json.Unmarshal(data, &strData)
+ if err != nil {
+ return err
+ }
+ data = []byte(strData)
+ }
+
+ var parsed map[string]interface{}
+ err := json.Unmarshal(data, &parsed)
+ if err != nil {
+ return err
+ }
+ threadID, _ := parsed["thread_id"].(string)
+ ts, tsOK := parsed["ts"].(float64)
+ delete(parsed, "thread_id")
+ delete(parsed, "ts")
+ *rr = ReadReceipt{
+ ThreadID: ThreadID(threadID),
+ Extra: parsed,
+ }
+ if tsOK {
+ rr.Timestamp = time.UnixMilli(int64(ts))
+ }
+ return nil
+}
+
+func (rr ReadReceipt) MarshalJSON() ([]byte, error) {
+ data := rr.Extra
+ if data == nil {
+ data = make(map[string]interface{})
+ }
+ if rr.ThreadID != "" {
+ data["thread_id"] = rr.ThreadID
+ }
+ if !rr.Timestamp.IsZero() {
+ data["ts"] = rr.Timestamp.UnixMilli()
+ }
+ return json.Marshal(data)
+}
+
+type Presence string
+
+const (
+ PresenceOnline Presence = "online"
+ PresenceOffline Presence = "offline"
+ PresenceUnavailable Presence = "unavailable"
+)
+
+// PresenceEventContent represents the content of a m.presence ephemeral event.
+// https://spec.matrix.org/v1.2/client-server-api/#mpresence
+type PresenceEventContent struct {
+ Presence Presence `json:"presence"`
+ Displayname string `json:"displayname,omitempty"`
+ AvatarURL id.ContentURIString `json:"avatar_url,omitempty"`
+ LastActiveAgo int64 `json:"last_active_ago,omitempty"`
+ CurrentlyActive bool `json:"currently_active,omitempty"`
+ StatusMessage string `json:"status_msg,omitempty"`
+}
diff --git a/vendor/maunium.net/go/mautrix/event/events.go b/vendor/maunium.net/go/mautrix/event/events.go
new file mode 100644
index 00000000..d2b61046
--- /dev/null
+++ b/vendor/maunium.net/go/mautrix/event/events.go
@@ -0,0 +1,149 @@
+// Copyright (c) 2020 Tulir Asokan
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package event
+
+import (
+ "encoding/json"
+ "time"
+
+ "maunium.net/go/mautrix/id"
+)
+
+// Event represents a single Matrix event.
+type Event struct {
+ StateKey *string `json:"state_key,omitempty"` // The state key for the event. Only present on State Events.
+ Sender id.UserID `json:"sender,omitempty"` // The user ID of the sender of the event
+ Type Type `json:"type"` // The event type
+ Timestamp int64 `json:"origin_server_ts,omitempty"` // The unix timestamp when this message was sent by the origin server
+ ID id.EventID `json:"event_id,omitempty"` // The unique ID of this event
+ RoomID id.RoomID `json:"room_id,omitempty"` // The room the event was sent to. May be nil (e.g. for presence)
+ Content Content `json:"content"` // The JSON content of the event.
+ Redacts id.EventID `json:"redacts,omitempty"` // The event ID that was redacted if a m.room.redaction event
+ Unsigned Unsigned `json:"unsigned,omitempty"` // Unsigned content set by own homeserver.
+
+ Mautrix MautrixInfo `json:"-"`
+
+ ToUserID id.UserID `json:"to_user_id,omitempty"` // The user ID that the to-device event was sent to. Only present in MSC2409 appservice transactions.
+ ToDeviceID id.DeviceID `json:"to_device_id,omitempty"` // The device ID that the to-device event was sent to. Only present in MSC2409 appservice transactions.
+}
+
+type eventForMarshaling struct {
+ StateKey *string `json:"state_key,omitempty"`
+ Sender id.UserID `json:"sender,omitempty"`
+ Type Type `json:"type"`
+ Timestamp int64 `json:"origin_server_ts,omitempty"`
+ ID id.EventID `json:"event_id,omitempty"`
+ RoomID id.RoomID `json:"room_id,omitempty"`
+ Content Content `json:"content"`
+ Redacts id.EventID `json:"redacts,omitempty"`
+ Unsigned *Unsigned `json:"unsigned,omitempty"`
+
+ PrevContent *Content `json:"prev_content,omitempty"`
+ ReplacesState *id.EventID `json:"replaces_state,omitempty"`
+
+ ToUserID id.UserID `json:"to_user_id,omitempty"`
+ ToDeviceID id.DeviceID `json:"to_device_id,omitempty"`
+}
+
+// UnmarshalJSON unmarshals the event, including moving prev_content from the top level to inside unsigned.
+func (evt *Event) UnmarshalJSON(data []byte) error {
+ var efm eventForMarshaling
+ err := json.Unmarshal(data, &efm)
+ if err != nil {
+ return err
+ }
+ evt.StateKey = efm.StateKey
+ evt.Sender = efm.Sender
+ evt.Type = efm.Type
+ evt.Timestamp = efm.Timestamp
+ evt.ID = efm.ID
+ evt.RoomID = efm.RoomID
+ evt.Content = efm.Content
+ evt.Redacts = efm.Redacts
+ if efm.Unsigned != nil {
+ evt.Unsigned = *efm.Unsigned
+ }
+ if efm.PrevContent != nil && evt.Unsigned.PrevContent == nil {
+ evt.Unsigned.PrevContent = efm.PrevContent
+ }
+ if efm.ReplacesState != nil && *efm.ReplacesState != "" && evt.Unsigned.ReplacesState == "" {
+ evt.Unsigned.ReplacesState = *efm.ReplacesState
+ }
+ evt.ToUserID = efm.ToUserID
+ evt.ToDeviceID = efm.ToDeviceID
+ return nil
+}
+
+// MarshalJSON marshals the event, including omitting the unsigned field if it's empty.
+//
+// This is necessary because Unsigned is not a pointer (for convenience reasons),
+// and encoding/json doesn't know how to check if a non-pointer struct is empty.
+//
+// TODO(tulir): maybe it makes more sense to make Unsigned a pointer and make an easy and safe way to access it?
+func (evt *Event) MarshalJSON() ([]byte, error) {
+ unsigned := &evt.Unsigned
+ if unsigned.IsEmpty() {
+ unsigned = nil
+ }
+ return json.Marshal(&eventForMarshaling{
+ StateKey: evt.StateKey,
+ Sender: evt.Sender,
+ Type: evt.Type,
+ Timestamp: evt.Timestamp,
+ ID: evt.ID,
+ RoomID: evt.RoomID,
+ Content: evt.Content,
+ Redacts: evt.Redacts,
+ Unsigned: unsigned,
+ ToUserID: evt.ToUserID,
+ ToDeviceID: evt.ToDeviceID,
+ })
+}
+
+type MautrixInfo struct {
+ TrustState id.TrustState
+ ForwardedKeys bool
+ WasEncrypted bool
+ TrustSource *id.Device
+
+ ReceivedAt time.Time
+ DecryptionDuration time.Duration
+
+ CheckpointSent bool
+}
+
+func (evt *Event) GetStateKey() string {
+ if evt.StateKey != nil {
+ return *evt.StateKey
+ }
+ return ""
+}
+
+type StrippedState struct {
+ Content Content `json:"content"`
+ Type Type `json:"type"`
+ StateKey string `json:"state_key"`
+ Sender id.UserID `json:"sender"`
+}
+
+type Unsigned struct {
+ PrevContent *Content `json:"prev_content,omitempty"`
+ PrevSender id.UserID `json:"prev_sender,omitempty"`
+ ReplacesState id.EventID `json:"replaces_state,omitempty"`
+ Age int64 `json:"age,omitempty"`
+ TransactionID string `json:"transaction_id,omitempty"`
+ Relations *Relations `json:"m.relations,omitempty"`
+ RedactedBecause *Event `json:"redacted_because,omitempty"`
+ InviteRoomState []StrippedState `json:"invite_room_state,omitempty"`
+
+ BeeperHSOrder int64 `json:"com.beeper.hs.order,omitempty"`
+}
+
+func (us *Unsigned) IsEmpty() bool {
+ return us.PrevContent == nil && us.PrevSender == "" && us.ReplacesState == "" && us.Age == 0 &&
+ us.TransactionID == "" && us.RedactedBecause == nil && us.InviteRoomState == nil && us.Relations == nil
+}
diff --git a/vendor/maunium.net/go/mautrix/event/member.go b/vendor/maunium.net/go/mautrix/event/member.go
new file mode 100644
index 00000000..ebafdcb7
--- /dev/null
+++ b/vendor/maunium.net/go/mautrix/event/member.go
@@ -0,0 +1,53 @@
+// Copyright (c) 2020 Tulir Asokan
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package event
+
+import (
+ "encoding/json"
+
+ "maunium.net/go/mautrix/id"
+)
+
+// Membership is an enum specifying the membership state of a room member.
+type Membership string
+
+func (ms Membership) IsInviteOrJoin() bool {
+ return ms == MembershipJoin || ms == MembershipInvite
+}
+
+func (ms Membership) IsLeaveOrBan() bool {
+ return ms == MembershipLeave || ms == MembershipBan
+}
+
+// The allowed membership states as specified in spec section 10.5.5.
+const (
+ MembershipJoin Membership = "join"
+ MembershipLeave Membership = "leave"
+ MembershipInvite Membership = "invite"
+ MembershipBan Membership = "ban"
+ MembershipKnock Membership = "knock"
+)
+
+// MemberEventContent represents the content of a m.room.member state event.
+// https://spec.matrix.org/v1.2/client-server-api/#mroommember
+type MemberEventContent struct {
+ Membership Membership `json:"membership"`
+ AvatarURL id.ContentURIString `json:"avatar_url,omitempty"`
+ Displayname string `json:"displayname,omitempty"`
+ IsDirect bool `json:"is_direct,omitempty"`
+ ThirdPartyInvite *ThirdPartyInvite `json:"third_party_invite,omitempty"`
+ Reason string `json:"reason,omitempty"`
+}
+
+type ThirdPartyInvite struct {
+ DisplayName string `json:"display_name"`
+ Signed struct {
+ Token string `json:"token"`
+ Signatures json.RawMessage `json:"signatures"`
+ MXID string `json:"mxid"`
+ }
+}
diff --git a/vendor/maunium.net/go/mautrix/event/message.go b/vendor/maunium.net/go/mautrix/event/message.go
new file mode 100644
index 00000000..a5f5ec0e
--- /dev/null
+++ b/vendor/maunium.net/go/mautrix/event/message.go
@@ -0,0 +1,276 @@
+// Copyright (c) 2023 Tulir Asokan
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package event
+
+import (
+ "encoding/json"
+ "strconv"
+ "strings"
+
+ "golang.org/x/net/html"
+
+ "maunium.net/go/mautrix/crypto/attachment"
+ "maunium.net/go/mautrix/id"
+)
+
+// MessageType is the sub-type of a m.room.message event.
+// https://spec.matrix.org/v1.2/client-server-api/#mroommessage-msgtypes
+type MessageType string
+
+// Msgtypes
+const (
+ MsgText MessageType = "m.text"
+ MsgEmote MessageType = "m.emote"
+ MsgNotice MessageType = "m.notice"
+ MsgImage MessageType = "m.image"
+ MsgLocation MessageType = "m.location"
+ MsgVideo MessageType = "m.video"
+ MsgAudio MessageType = "m.audio"
+ MsgFile MessageType = "m.file"
+
+ MsgVerificationRequest MessageType = "m.key.verification.request"
+)
+
+// Format specifies the format of the formatted_body in m.room.message events.
+// https://spec.matrix.org/v1.2/client-server-api/#mroommessage-msgtypes
+type Format string
+
+// Message formats
+const (
+ FormatHTML Format = "org.matrix.custom.html"
+)
+
+// RedactionEventContent represents the content of a m.room.redaction message event.
+//
+// The redacted event ID is still at the top level, but will move in a future room version.
+// See https://github.com/matrix-org/matrix-doc/pull/2244 and https://github.com/matrix-org/matrix-doc/pull/2174
+//
+// https://spec.matrix.org/v1.2/client-server-api/#mroomredaction
+type RedactionEventContent struct {
+ Reason string `json:"reason,omitempty"`
+}
+
+// ReactionEventContent represents the content of a m.reaction message event.
+// This is not yet in a spec release, see https://github.com/matrix-org/matrix-doc/pull/1849
+type ReactionEventContent struct {
+ RelatesTo RelatesTo `json:"m.relates_to"`
+}
+
+func (content *ReactionEventContent) GetRelatesTo() *RelatesTo {
+ return &content.RelatesTo
+}
+
+func (content *ReactionEventContent) OptionalGetRelatesTo() *RelatesTo {
+ return &content.RelatesTo
+}
+
+func (content *ReactionEventContent) SetRelatesTo(rel *RelatesTo) {
+ content.RelatesTo = *rel
+}
+
+// MessageEventContent represents the content of a m.room.message event.
+//
+// It is also used to represent m.sticker events, as they are equivalent to m.room.message
+// with the exception of the msgtype field.
+//
+// https://spec.matrix.org/v1.2/client-server-api/#mroommessage
+type MessageEventContent struct {
+ // Base m.room.message fields
+ MsgType MessageType `json:"msgtype,omitempty"`
+ Body string `json:"body"`
+
+ // Extra fields for text types
+ Format Format `json:"format,omitempty"`
+ FormattedBody string `json:"formatted_body,omitempty"`
+
+ // Extra field for m.location
+ GeoURI string `json:"geo_uri,omitempty"`
+
+ // Extra fields for media types
+ URL id.ContentURIString `json:"url,omitempty"`
+ Info *FileInfo `json:"info,omitempty"`
+ File *EncryptedFileInfo `json:"file,omitempty"`
+
+ FileName string `json:"filename,omitempty"`
+
+ Mentions *Mentions `json:"m.mentions,omitempty"`
+ UnstableMentions *Mentions `json:"org.matrix.msc3952.mentions,omitempty"`
+
+ // Edits and relations
+ NewContent *MessageEventContent `json:"m.new_content,omitempty"`
+ RelatesTo *RelatesTo `json:"m.relates_to,omitempty"`
+
+ // In-room verification
+ To id.UserID `json:"to,omitempty"`
+ FromDevice id.DeviceID `json:"from_device,omitempty"`
+ Methods []VerificationMethod `json:"methods,omitempty"`
+
+ replyFallbackRemoved bool
+
+ MessageSendRetry *BeeperRetryMetadata `json:"com.beeper.message_send_retry,omitempty"`
+}
+
+func (content *MessageEventContent) GetRelatesTo() *RelatesTo {
+ if content.RelatesTo == nil {
+ content.RelatesTo = &RelatesTo{}
+ }
+ return content.RelatesTo
+}
+
+func (content *MessageEventContent) OptionalGetRelatesTo() *RelatesTo {
+ return content.RelatesTo
+}
+
+func (content *MessageEventContent) SetRelatesTo(rel *RelatesTo) {
+ content.RelatesTo = rel
+}
+
+func (content *MessageEventContent) SetEdit(original id.EventID) {
+ newContent := *content
+ content.NewContent = &newContent
+ content.RelatesTo = (&RelatesTo{}).SetReplace(original)
+ if content.MsgType == MsgText || content.MsgType == MsgNotice {
+ content.Body = "* " + content.Body
+ if content.Format == FormatHTML && len(content.FormattedBody) > 0 {
+ content.FormattedBody = "* " + content.FormattedBody
+ }
+ // If the message is long, remove most of the useless edit fallback to avoid event size issues.
+ if len(content.Body) > 10000 {
+ content.FormattedBody = ""
+ content.Format = ""
+ content.Body = content.Body[:50] + "[edit fallback cut…]"
+ }
+ }
+}
+
+func TextToHTML(text string) string {
+ return strings.ReplaceAll(html.EscapeString(text), "\n", "<br/>")
+}
+
+func (content *MessageEventContent) EnsureHasHTML() {
+ if len(content.FormattedBody) == 0 || content.Format != FormatHTML {
+ content.FormattedBody = TextToHTML(content.Body)
+ content.Format = FormatHTML
+ }
+}
+
+func (content *MessageEventContent) GetFile() *EncryptedFileInfo {
+ if content.File == nil {
+ content.File = &EncryptedFileInfo{}
+ }
+ return content.File
+}
+
+func (content *MessageEventContent) GetInfo() *FileInfo {
+ if content.Info == nil {
+ content.Info = &FileInfo{}
+ }
+ return content.Info
+}
+
+type Mentions struct {
+ UserIDs []id.UserID `json:"user_ids,omitempty"`
+ Room bool `json:"room,omitempty"`
+}
+
+type EncryptedFileInfo struct {
+ attachment.EncryptedFile
+ URL id.ContentURIString `json:"url"`
+}
+
+type FileInfo struct {
+ MimeType string `json:"mimetype,omitempty"`
+ ThumbnailInfo *FileInfo `json:"thumbnail_info,omitempty"`
+ ThumbnailURL id.ContentURIString `json:"thumbnail_url,omitempty"`
+ ThumbnailFile *EncryptedFileInfo `json:"thumbnail_file,omitempty"`
+ Width int `json:"-"`
+ Height int `json:"-"`
+ Duration int `json:"-"`
+ Size int `json:"-"`
+}
+
+type serializableFileInfo struct {
+ MimeType string `json:"mimetype,omitempty"`
+ ThumbnailInfo *serializableFileInfo `json:"thumbnail_info,omitempty"`
+ ThumbnailURL id.ContentURIString `json:"thumbnail_url,omitempty"`
+ ThumbnailFile *EncryptedFileInfo `json:"thumbnail_file,omitempty"`
+
+ Width json.Number `json:"w,omitempty"`
+ Height json.Number `json:"h,omitempty"`
+ Duration json.Number `json:"duration,omitempty"`
+ Size json.Number `json:"size,omitempty"`
+}
+
+func (sfi *serializableFileInfo) CopyFrom(fileInfo *FileInfo) *serializableFileInfo {
+ if fileInfo == nil {
+ return nil
+ }
+ *sfi = serializableFileInfo{
+ MimeType: fileInfo.MimeType,
+ ThumbnailURL: fileInfo.ThumbnailURL,
+ ThumbnailInfo: (&serializableFileInfo{}).CopyFrom(fileInfo.ThumbnailInfo),
+ ThumbnailFile: fileInfo.ThumbnailFile,
+ }
+ if fileInfo.Width > 0 {
+ sfi.Width = json.Number(strconv.Itoa(fileInfo.Width))
+ }
+ if fileInfo.Height > 0 {
+ sfi.Height = json.Number(strconv.Itoa(fileInfo.Height))
+ }
+ if fileInfo.Size > 0 {
+ sfi.Size = json.Number(strconv.Itoa(fileInfo.Size))
+
+ }
+ if fileInfo.Duration > 0 {
+ sfi.Duration = json.Number(strconv.Itoa(int(fileInfo.Duration)))
+ }
+ return sfi
+}
+
+func (sfi *serializableFileInfo) CopyTo(fileInfo *FileInfo) {
+ *fileInfo = FileInfo{
+ Width: numberToInt(sfi.Width),
+ Height: numberToInt(sfi.Height),
+ Size: numberToInt(sfi.Size),
+ Duration: numberToInt(sfi.Duration),
+ MimeType: sfi.MimeType,
+ ThumbnailURL: sfi.ThumbnailURL,
+ ThumbnailFile: sfi.ThumbnailFile,
+ }
+ if sfi.ThumbnailInfo != nil {
+ fileInfo.ThumbnailInfo = &FileInfo{}
+ sfi.ThumbnailInfo.CopyTo(fileInfo.ThumbnailInfo)
+ }
+}
+
+func (fileInfo *FileInfo) UnmarshalJSON(data []byte) error {
+ sfi := &serializableFileInfo{}
+ if err := json.Unmarshal(data, sfi); err != nil {
+ return err
+ }
+ sfi.CopyTo(fileInfo)
+ return nil
+}
+
+func (fileInfo *FileInfo) MarshalJSON() ([]byte, error) {
+ return json.Marshal((&serializableFileInfo{}).CopyFrom(fileInfo))
+}
+
+func numberToInt(val json.Number) int {
+ f64, _ := val.Float64()
+ if f64 > 0 {
+ return int(f64)
+ }
+ return 0
+}
+
+func (fileInfo *FileInfo) GetThumbnailInfo() *FileInfo {
+ if fileInfo.ThumbnailInfo == nil {
+ fileInfo.ThumbnailInfo = &FileInfo{}
+ }
+ return fileInfo.ThumbnailInfo
+}
diff --git a/vendor/maunium.net/go/mautrix/event/powerlevels.go b/vendor/maunium.net/go/mautrix/event/powerlevels.go
new file mode 100644
index 00000000..cf623565
--- /dev/null
+++ b/vendor/maunium.net/go/mautrix/event/powerlevels.go
@@ -0,0 +1,149 @@
+// Copyright (c) 2020 Tulir Asokan
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package event
+
+import (
+ "sync"
+
+ "maunium.net/go/mautrix/id"
+)
+
+// PowerLevelsEventContent represents the content of a m.room.power_levels state event content.
+// https://spec.matrix.org/v1.5/client-server-api/#mroompower_levels
+type PowerLevelsEventContent struct {
+ usersLock sync.RWMutex
+ Users map[id.UserID]int `json:"users,omitempty"`
+ UsersDefault int `json:"users_default,omitempty"`
+
+ eventsLock sync.RWMutex
+ Events map[string]int `json:"events,omitempty"`
+ EventsDefault int `json:"events_default,omitempty"`
+
+ Notifications *NotificationPowerLevels `json:"notifications,omitempty"`
+
+ StateDefaultPtr *int `json:"state_default,omitempty"`
+
+ InvitePtr *int `json:"invite,omitempty"`
+ KickPtr *int `json:"kick,omitempty"`
+ BanPtr *int `json:"ban,omitempty"`
+ RedactPtr *int `json:"redact,omitempty"`
+ HistoricalPtr *int `json:"historical,omitempty"`
+}
+
+type NotificationPowerLevels struct {
+ RoomPtr *int `json:"room,omitempty"`
+}
+
+func (npl *NotificationPowerLevels) Room() int {
+ if npl != nil && npl.RoomPtr != nil {
+ return *npl.RoomPtr
+ }
+ return 50
+}
+
+func (pl *PowerLevelsEventContent) Invite() int {
+ if pl.InvitePtr != nil {
+ return *pl.InvitePtr
+ }
+ return 50
+}
+
+func (pl *PowerLevelsEventContent) Kick() int {
+ if pl.KickPtr != nil {
+ return *pl.KickPtr
+ }
+ return 50
+}
+
+func (pl *PowerLevelsEventContent) Ban() int {
+ if pl.BanPtr != nil {
+ return *pl.BanPtr
+ }
+ return 50
+}
+
+func (pl *PowerLevelsEventContent) Redact() int {
+ if pl.RedactPtr != nil {
+ return *pl.RedactPtr
+ }
+ return 50
+}
+
+func (pl *PowerLevelsEventContent) Historical() int {
+ if pl.HistoricalPtr != nil {
+ return *pl.HistoricalPtr
+ }
+ return 100
+}
+
+func (pl *PowerLevelsEventContent) StateDefault() int {
+ if pl.StateDefaultPtr != nil {
+ return *pl.StateDefaultPtr
+ }
+ return 50
+}
+
+func (pl *PowerLevelsEventContent) GetUserLevel(userID id.UserID) int {
+ pl.usersLock.RLock()
+ defer pl.usersLock.RUnlock()
+ level, ok := pl.Users[userID]
+ if !ok {
+ return pl.UsersDefault
+ }
+ return level
+}
+
+func (pl *PowerLevelsEventContent) SetUserLevel(userID id.UserID, level int) {
+ pl.usersLock.Lock()
+ defer pl.usersLock.Unlock()
+ if level == pl.UsersDefault {
+ delete(pl.Users, userID)
+ } else {
+ pl.Users[userID] = level
+ }
+}
+
+func (pl *PowerLevelsEventContent) EnsureUserLevel(userID id.UserID, level int) bool {
+ existingLevel := pl.GetUserLevel(userID)
+ if existingLevel != level {
+ pl.SetUserLevel(userID, level)
+ return true
+ }
+ return false
+}
+
+func (pl *PowerLevelsEventContent) GetEventLevel(eventType Type) int {
+ pl.eventsLock.RLock()
+ defer pl.eventsLock.RUnlock()
+ level, ok := pl.Events[eventType.String()]
+ if !ok {
+ if eventType.IsState() {
+ return pl.StateDefault()
+ }
+ return pl.EventsDefault
+ }
+ return level
+}
+
+func (pl *PowerLevelsEventContent) SetEventLevel(eventType Type, level int) {
+ pl.eventsLock.Lock()
+ defer pl.eventsLock.Unlock()
+ if (eventType.IsState() && level == pl.StateDefault()) || (!eventType.IsState() && level == pl.EventsDefault) {
+ delete(pl.Events, eventType.String())
+ } else {
+ pl.Events[eventType.String()] = level
+ }
+}
+
+func (pl *PowerLevelsEventContent) EnsureEventLevel(eventType Type, level int) bool {
+ existingLevel := pl.GetEventLevel(eventType)
+ if existingLevel != level {
+ pl.SetEventLevel(eventType, level)
+ return true
+ }
+ return false
+}
diff --git a/vendor/maunium.net/go/mautrix/event/relations.go b/vendor/maunium.net/go/mautrix/event/relations.go
new file mode 100644
index 00000000..ecd7a959
--- /dev/null
+++ b/vendor/maunium.net/go/mautrix/event/relations.go
@@ -0,0 +1,234 @@
+// Copyright (c) 2020 Tulir Asokan
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package event
+
+import (
+ "encoding/json"
+
+ "maunium.net/go/mautrix/id"
+)
+
+type RelationType string
+
+const (
+ RelReplace RelationType = "m.replace"
+ RelReference RelationType = "m.reference"
+ RelAnnotation RelationType = "m.annotation"
+ RelThread RelationType = "m.thread"
+)
+
+type RelatesTo struct {
+ Type RelationType `json:"rel_type,omitempty"`
+ EventID id.EventID `json:"event_id,omitempty"`
+ Key string `json:"key,omitempty"`
+
+ InReplyTo *InReplyTo `json:"m.in_reply_to,omitempty"`
+ IsFallingBack bool `json:"is_falling_back,omitempty"`
+}
+
+type InReplyTo struct {
+ EventID id.EventID `json:"event_id,omitempty"`
+
+ UnstableRoomID id.RoomID `json:"room_id,omitempty"`
+}
+
+func (rel *RelatesTo) Copy() *RelatesTo {
+ if rel == nil {
+ return nil
+ }
+ cp := *rel
+ return &cp
+}
+
+func (rel *RelatesTo) GetReplaceID() id.EventID {
+ if rel != nil && rel.Type == RelReplace {
+ return rel.EventID
+ }
+ return ""
+}
+
+func (rel *RelatesTo) GetReferenceID() id.EventID {
+ if rel != nil && rel.Type == RelReference {
+ return rel.EventID
+ }
+ return ""
+}
+
+func (rel *RelatesTo) GetThreadParent() id.EventID {
+ if rel != nil && rel.Type == RelThread {
+ return rel.EventID
+ }
+ return ""
+}
+
+func (rel *RelatesTo) GetReplyTo() id.EventID {
+ if rel != nil && rel.InReplyTo != nil {
+ return rel.InReplyTo.EventID
+ }
+ return ""
+}
+
+func (rel *RelatesTo) GetNonFallbackReplyTo() id.EventID {
+ if rel != nil && rel.InReplyTo != nil && !rel.IsFallingBack {
+ return rel.InReplyTo.EventID
+ }
+ return ""
+}
+
+func (rel *RelatesTo) GetAnnotationID() id.EventID {
+ if rel != nil && rel.Type == RelAnnotation {
+ return rel.EventID
+ }
+ return ""
+}
+
+func (rel *RelatesTo) GetAnnotationKey() string {
+ if rel != nil && rel.Type == RelAnnotation {
+ return rel.Key
+ }
+ return ""
+}
+
+func (rel *RelatesTo) SetReplace(mxid id.EventID) *RelatesTo {
+ rel.Type = RelReplace
+ rel.EventID = mxid
+ return rel
+}
+
+func (rel *RelatesTo) SetReplyTo(mxid id.EventID) *RelatesTo {
+ rel.InReplyTo = &InReplyTo{EventID: mxid}
+ rel.IsFallingBack = false
+ return rel
+}
+
+func (rel *RelatesTo) SetThread(mxid, fallback id.EventID) *RelatesTo {
+ rel.Type = RelThread
+ rel.EventID = mxid
+ if fallback != "" && rel.GetReplyTo() == "" {
+ rel.SetReplyTo(fallback)
+ rel.IsFallingBack = true
+ }
+ return rel
+}
+
+func (rel *RelatesTo) SetAnnotation(mxid id.EventID, key string) *RelatesTo {
+ rel.Type = RelAnnotation
+ rel.EventID = mxid
+ rel.Key = key
+ return rel
+}
+
+type RelationChunkItem struct {
+ Type RelationType `json:"type"`
+ EventID string `json:"event_id,omitempty"`
+ Key string `json:"key,omitempty"`
+ Count int `json:"count,omitempty"`
+}
+
+type RelationChunk struct {
+ Chunk []RelationChunkItem `json:"chunk"`
+
+ Limited bool `json:"limited"`
+ Count int `json:"count"`
+}
+
+type AnnotationChunk struct {
+ RelationChunk
+ Map map[string]int `json:"-"`
+}
+
+type serializableAnnotationChunk AnnotationChunk
+
+func (ac *AnnotationChunk) UnmarshalJSON(data []byte) error {
+ if err := json.Unmarshal(data, (*serializableAnnotationChunk)(ac)); err != nil {
+ return err
+ }
+ ac.Map = make(map[string]int)
+ for _, item := range ac.Chunk {
+ if item.Key != "" {
+ ac.Map[item.Key] += item.Count
+ }
+ }
+ return nil
+}
+
+func (ac *AnnotationChunk) Serialize() RelationChunk {
+ ac.Chunk = make([]RelationChunkItem, len(ac.Map))
+ i := 0
+ for key, count := range ac.Map {
+ ac.Chunk[i] = RelationChunkItem{
+ Type: RelAnnotation,
+ Key: key,
+ Count: count,
+ }
+ i++
+ }
+ return ac.RelationChunk
+}
+
+type EventIDChunk struct {
+ RelationChunk
+ List []string `json:"-"`
+}
+
+type serializableEventIDChunk EventIDChunk
+
+func (ec *EventIDChunk) UnmarshalJSON(data []byte) error {
+ if err := json.Unmarshal(data, (*serializableEventIDChunk)(ec)); err != nil {
+ return err
+ }
+ for _, item := range ec.Chunk {
+ ec.List = append(ec.List, item.EventID)
+ }
+ return nil
+}
+
+func (ec *EventIDChunk) Serialize(typ RelationType) RelationChunk {
+ ec.Chunk = make([]RelationChunkItem, len(ec.List))
+ for i, eventID := range ec.List {
+ ec.Chunk[i] = RelationChunkItem{
+ Type: typ,
+ EventID: eventID,
+ }
+ }
+ return ec.RelationChunk
+}
+
+type Relations struct {
+ Raw map[RelationType]RelationChunk `json:"-"`
+
+ Annotations AnnotationChunk `json:"m.annotation,omitempty"`
+ References EventIDChunk `json:"m.reference,omitempty"`
+ Replaces EventIDChunk `json:"m.replace,omitempty"`
+}
+
+type serializableRelations Relations
+
+func (relations *Relations) UnmarshalJSON(data []byte) error {
+ if err := json.Unmarshal(data, &relations.Raw); err != nil {
+ return err
+ }
+ return json.Unmarshal(data, (*serializableRelations)(relations))
+}
+
+func (relations *Relations) MarshalJSON() ([]byte, error) {
+ if relations.Raw == nil {
+ relations.Raw = make(map[RelationType]RelationChunk)
+ }
+ relations.Raw[RelAnnotation] = relations.Annotations.Serialize()
+ relations.Raw[RelReference] = relations.References.Serialize(RelReference)
+ relations.Raw[RelReplace] = relations.Replaces.Serialize(RelReplace)
+ for key, item := range relations.Raw {
+ if !item.Limited {
+ item.Count = len(item.Chunk)
+ }
+ if item.Count == 0 {
+ delete(relations.Raw, key)
+ }
+ }
+ return json.Marshal(relations.Raw)
+}
diff --git a/vendor/maunium.net/go/mautrix/event/reply.go b/vendor/maunium.net/go/mautrix/event/reply.go
new file mode 100644
index 00000000..e1844a4a
--- /dev/null
+++ b/vendor/maunium.net/go/mautrix/event/reply.go
@@ -0,0 +1,100 @@
+// Copyright (c) 2020 Tulir Asokan
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package event
+
+import (
+ "fmt"
+ "regexp"
+ "strings"
+
+ "golang.org/x/net/html"
+
+ "maunium.net/go/mautrix/id"
+)
+
+var HTMLReplyFallbackRegex = regexp.MustCompile(`^<mx-reply>[\s\S]+?</mx-reply>`)
+
+func TrimReplyFallbackHTML(html string) string {
+ return HTMLReplyFallbackRegex.ReplaceAllString(html, "")
+}
+
+func TrimReplyFallbackText(text string) string {
+ if !strings.HasPrefix(text, "> ") || !strings.Contains(text, "\n") {
+ return text
+ }
+
+ lines := strings.Split(text, "\n")
+ for len(lines) > 0 && strings.HasPrefix(lines[0], "> ") {
+ lines = lines[1:]
+ }
+ return strings.TrimSpace(strings.Join(lines, "\n"))
+}
+
+func (content *MessageEventContent) RemoveReplyFallback() {
+ if len(content.RelatesTo.GetReplyTo()) > 0 && !content.replyFallbackRemoved {
+ if content.Format == FormatHTML {
+ content.FormattedBody = TrimReplyFallbackHTML(content.FormattedBody)
+ }
+ content.Body = TrimReplyFallbackText(content.Body)
+ content.replyFallbackRemoved = true
+ }
+}
+
+// Deprecated: RelatesTo methods are nil-safe, so RelatesTo.GetReplyTo can be used directly
+func (content *MessageEventContent) GetReplyTo() id.EventID {
+ return content.RelatesTo.GetReplyTo()
+}
+
+const ReplyFormat = `<mx-reply><blockquote><a href="https://matrix.to/#/%s/%s">In reply to</a> <a href="https://matrix.to/#/%s">%s</a><br>%s</blockquote></mx-reply>`
+
+func (evt *Event) GenerateReplyFallbackHTML() string {
+ parsedContent, ok := evt.Content.Parsed.(*MessageEventContent)
+ if !ok {
+ return ""
+ }
+ parsedContent.RemoveReplyFallback()
+ body := parsedContent.FormattedBody
+ if len(body) == 0 {
+ body = strings.ReplaceAll(html.EscapeString(parsedContent.Body), "\n", "<br/>")
+ }
+
+ senderDisplayName := evt.Sender
+
+ return fmt.Sprintf(ReplyFormat, evt.RoomID, evt.ID, evt.Sender, senderDisplayName, body)
+}
+
+func (evt *Event) GenerateReplyFallbackText() string {
+ parsedContent, ok := evt.Content.Parsed.(*MessageEventContent)
+ if !ok {
+ return ""
+ }
+ parsedContent.RemoveReplyFallback()
+ body := parsedContent.Body
+ lines := strings.Split(strings.TrimSpace(body), "\n")
+ firstLine, lines := lines[0], lines[1:]
+
+ senderDisplayName := evt.Sender
+
+ var fallbackText strings.Builder
+ _, _ = fmt.Fprintf(&fallbackText, "> <%s> %s", senderDisplayName, firstLine)
+ for _, line := range lines {
+ _, _ = fmt.Fprintf(&fallbackText, "\n> %s", line)
+ }
+ fallbackText.WriteString("\n\n")
+ return fallbackText.String()
+}
+
+func (content *MessageEventContent) SetReply(inReplyTo *Event) {
+ content.RelatesTo = (&RelatesTo{}).SetReplyTo(inReplyTo.ID)
+
+ if content.MsgType == MsgText || content.MsgType == MsgNotice {
+ content.EnsureHasHTML()
+ content.FormattedBody = inReplyTo.GenerateReplyFallbackHTML() + content.FormattedBody
+ content.Body = inReplyTo.GenerateReplyFallbackText() + content.Body
+ content.replyFallbackRemoved = false
+ }
+}
diff --git a/vendor/maunium.net/go/mautrix/event/state.go b/vendor/maunium.net/go/mautrix/event/state.go
new file mode 100644
index 00000000..a387f015
--- /dev/null
+++ b/vendor/maunium.net/go/mautrix/event/state.go
@@ -0,0 +1,176 @@
+// Copyright (c) 2021 Tulir Asokan
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package event
+
+import (
+ "maunium.net/go/mautrix/id"
+)
+
+// CanonicalAliasEventContent represents the content of a m.room.canonical_alias state event.
+// https://spec.matrix.org/v1.2/client-server-api/#mroomcanonical_alias
+type CanonicalAliasEventContent struct {
+ Alias id.RoomAlias `json:"alias"`
+ AltAliases []id.RoomAlias `json:"alt_aliases,omitempty"`
+}
+
+// RoomNameEventContent represents the content of a m.room.name state event.
+// https://spec.matrix.org/v1.2/client-server-api/#mroomname
+type RoomNameEventContent struct {
+ Name string `json:"name"`
+}
+
+// RoomAvatarEventContent represents the content of a m.room.avatar state event.
+// https://spec.matrix.org/v1.2/client-server-api/#mroomavatar
+type RoomAvatarEventContent struct {
+ URL id.ContentURI `json:"url"`
+ Info *FileInfo `json:"info,omitempty"`
+}
+
+// ServerACLEventContent represents the content of a m.room.server_acl state event.
+// https://spec.matrix.org/v1.2/client-server-api/#server-access-control-lists-acls-for-rooms
+type ServerACLEventContent struct {
+ Allow []string `json:"allow,omitempty"`
+ AllowIPLiterals bool `json:"allow_ip_literals"`
+ Deny []string `json:"deny,omitempty"`
+}
+
+// TopicEventContent represents the content of a m.room.topic state event.
+// https://spec.matrix.org/v1.2/client-server-api/#mroomtopic
+type TopicEventContent struct {
+ Topic string `json:"topic"`
+}
+
+// TombstoneEventContent represents the content of a m.room.tombstone state event.
+// https://spec.matrix.org/v1.2/client-server-api/#mroomtombstone
+type TombstoneEventContent struct {
+ Body string `json:"body"`
+ ReplacementRoom id.RoomID `json:"replacement_room"`
+}
+
+type Predecessor struct {
+ RoomID id.RoomID `json:"room_id"`
+ EventID id.EventID `json:"event_id"`
+}
+
+// CreateEventContent represents the content of a m.room.create state event.
+// https://spec.matrix.org/v1.2/client-server-api/#mroomcreate
+type CreateEventContent struct {
+ Type RoomType `json:"type,omitempty"`
+ Creator id.UserID `json:"creator,omitempty"`
+ Federate bool `json:"m.federate,omitempty"`
+ RoomVersion string `json:"room_version,omitempty"`
+ Predecessor *Predecessor `json:"predecessor,omitempty"`
+}
+
+// JoinRule specifies how open a room is to new members.
+// https://spec.matrix.org/v1.2/client-server-api/#mroomjoin_rules
+type JoinRule string
+
+const (
+ JoinRulePublic JoinRule = "public"
+ JoinRuleKnock JoinRule = "knock"
+ JoinRuleInvite JoinRule = "invite"
+ JoinRuleRestricted JoinRule = "restricted"
+ JoinRulePrivate JoinRule = "private"
+)
+
+// JoinRulesEventContent represents the content of a m.room.join_rules state event.
+// https://spec.matrix.org/v1.2/client-server-api/#mroomjoin_rules
+type JoinRulesEventContent struct {
+ JoinRule JoinRule `json:"join_rule"`
+ Allow []JoinRuleAllow `json:"allow,omitempty"`
+}
+
+type JoinRuleAllowType string
+
+const (
+ JoinRuleAllowRoomMembership JoinRuleAllowType = "m.room_membership"
+)
+
+type JoinRuleAllow struct {
+ RoomID id.RoomID `json:"room_id"`
+ Type JoinRuleAllowType `json:"type"`
+}
+
+// PinnedEventsEventContent represents the content of a m.room.pinned_events state event.
+// https://spec.matrix.org/v1.2/client-server-api/#mroompinned_events
+type PinnedEventsEventContent struct {
+ Pinned []id.EventID `json:"pinned"`
+}
+
+// HistoryVisibility specifies who can see new messages.
+// https://spec.matrix.org/v1.2/client-server-api/#mroomhistory_visibility
+type HistoryVisibility string
+
+const (
+ HistoryVisibilityInvited HistoryVisibility = "invited"
+ HistoryVisibilityJoined HistoryVisibility = "joined"
+ HistoryVisibilityShared HistoryVisibility = "shared"
+ HistoryVisibilityWorldReadable HistoryVisibility = "world_readable"
+)
+
+// HistoryVisibilityEventContent represents the content of a m.room.history_visibility state event.
+// https://spec.matrix.org/v1.2/client-server-api/#mroomhistory_visibility
+type HistoryVisibilityEventContent struct {
+ HistoryVisibility HistoryVisibility `json:"history_visibility"`
+}
+
+// GuestAccess specifies whether or not guest accounts can join.
+// https://spec.matrix.org/v1.2/client-server-api/#mroomguest_access
+type GuestAccess string
+
+const (
+ GuestAccessCanJoin GuestAccess = "can_join"
+ GuestAccessForbidden GuestAccess = "forbidden"
+)
+
+// GuestAccessEventContent represents the content of a m.room.guest_access state event.
+// https://spec.matrix.org/v1.2/client-server-api/#mroomguest_access
+type GuestAccessEventContent struct {
+ GuestAccess GuestAccess `json:"guest_access"`
+}
+
+type BridgeInfoSection struct {
+ ID string `json:"id"`
+ DisplayName string `json:"displayname,omitempty"`
+ AvatarURL id.ContentURIString `json:"avatar_url,omitempty"`
+ ExternalURL string `json:"external_url,omitempty"`
+}
+
+// BridgeEventContent represents the content of a m.bridge state event.
+// https://github.com/matrix-org/matrix-doc/pull/2346
+type BridgeEventContent struct {
+ BridgeBot id.UserID `json:"bridgebot"`
+ Creator id.UserID `json:"creator,omitempty"`
+ Protocol BridgeInfoSection `json:"protocol"`
+ Network *BridgeInfoSection `json:"network,omitempty"`
+ Channel BridgeInfoSection `json:"channel"`
+}
+
+type SpaceChildEventContent struct {
+ Via []string `json:"via,omitempty"`
+ Order string `json:"order,omitempty"`
+ Suggested bool `json:"suggested,omitempty"`
+}
+
+type SpaceParentEventContent struct {
+ Via []string `json:"via,omitempty"`
+ Canonical bool `json:"canonical,omitempty"`
+}
+
+// ModPolicyContent represents the content of a m.room.rule.user, m.room.rule.room, and m.room.rule.server state event.
+// https://spec.matrix.org/v1.2/client-server-api/#moderation-policy-lists
+type ModPolicyContent struct {
+ Entity string `json:"entity"`
+ Reason string `json:"reason"`
+ Recommendation string `json:"recommendation"`
+}
+
+type InsertionMarkerContent struct {
+ InsertionID id.EventID `json:"org.matrix.msc2716.marker.insertion"`
+ Timestamp int64 `json:"com.beeper.timestamp,omitempty"`
+}
diff --git a/vendor/maunium.net/go/mautrix/event/type.go b/vendor/maunium.net/go/mautrix/event/type.go
new file mode 100644
index 00000000..050b17e9
--- /dev/null
+++ b/vendor/maunium.net/go/mautrix/event/type.go
@@ -0,0 +1,256 @@
+// Copyright (c) 2021 Tulir Asokan
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package event
+
+import (
+ "encoding/json"
+ "fmt"
+ "strings"
+)
+
+type RoomType string
+
+const (
+ RoomTypeDefault RoomType = ""
+ RoomTypeSpace RoomType = "m.space"
+)
+
+type TypeClass int
+
+func (tc TypeClass) Name() string {
+ switch tc {
+ case MessageEventType:
+ return "message"
+ case StateEventType:
+ return "state"
+ case EphemeralEventType:
+ return "ephemeral"
+ case AccountDataEventType:
+ return "account data"
+ case ToDeviceEventType:
+ return "to-device"
+ default:
+ return "unknown"
+ }
+}
+
+const (
+ // Unknown events
+ UnknownEventType TypeClass = iota
+ // Normal message events
+ MessageEventType
+ // State events
+ StateEventType
+ // Ephemeral events
+ EphemeralEventType
+ // Account data events
+ AccountDataEventType
+ // Device-to-device events
+ ToDeviceEventType
+)
+
+type Type struct {
+ Type string
+ Class TypeClass
+}
+
+func NewEventType(name string) Type {
+ evtType := Type{Type: name}
+ evtType.Class = evtType.GuessClass()
+ return evtType
+}
+
+func (et *Type) IsState() bool {
+ return et.Class == StateEventType
+}
+
+func (et *Type) IsEphemeral() bool {
+ return et.Class == EphemeralEventType
+}
+
+func (et *Type) IsAccountData() bool {
+ return et.Class == AccountDataEventType
+}
+
+func (et *Type) IsToDevice() bool {
+ return et.Class == ToDeviceEventType
+}
+
+func (et *Type) IsInRoomVerification() bool {
+ switch et.Type {
+ case InRoomVerificationStart.Type, InRoomVerificationReady.Type, InRoomVerificationAccept.Type,
+ InRoomVerificationKey.Type, InRoomVerificationMAC.Type, InRoomVerificationCancel.Type:
+ return true
+ default:
+ return false
+ }
+}
+
+func (et *Type) IsCall() bool {
+ switch et.Type {
+ case CallInvite.Type, CallCandidates.Type, CallAnswer.Type, CallReject.Type, CallSelectAnswer.Type,
+ CallNegotiate.Type, CallHangup.Type:
+ return true
+ default:
+ return false
+ }
+}
+
+func (et *Type) IsCustom() bool {
+ return !strings.HasPrefix(et.Type, "m.")
+}
+
+func (et *Type) GuessClass() TypeClass {
+ switch et.Type {
+ case StateAliases.Type, StateCanonicalAlias.Type, StateCreate.Type, StateJoinRules.Type, StateMember.Type,
+ StatePowerLevels.Type, StateRoomName.Type, StateRoomAvatar.Type, StateServerACL.Type, StateTopic.Type,
+ StatePinnedEvents.Type, StateTombstone.Type, StateEncryption.Type, StateBridge.Type, StateHalfShotBridge.Type,
+ StateSpaceParent.Type, StateSpaceChild.Type, StatePolicyRoom.Type, StatePolicyServer.Type, StatePolicyUser.Type,
+ StateInsertionMarker.Type:
+ return StateEventType
+ case EphemeralEventReceipt.Type, EphemeralEventTyping.Type, EphemeralEventPresence.Type:
+ return EphemeralEventType
+ case AccountDataDirectChats.Type, AccountDataPushRules.Type, AccountDataRoomTags.Type,
+ AccountDataSecretStorageKey.Type, AccountDataSecretStorageDefaultKey.Type,
+ AccountDataCrossSigningMaster.Type, AccountDataCrossSigningSelf.Type, AccountDataCrossSigningUser.Type:
+ return AccountDataEventType
+ case EventRedaction.Type, EventMessage.Type, EventEncrypted.Type, EventReaction.Type, EventSticker.Type,
+ InRoomVerificationStart.Type, InRoomVerificationReady.Type, InRoomVerificationAccept.Type,
+ InRoomVerificationKey.Type, InRoomVerificationMAC.Type, InRoomVerificationCancel.Type,
+ CallInvite.Type, CallCandidates.Type, CallAnswer.Type, CallReject.Type, CallSelectAnswer.Type,
+ CallNegotiate.Type, CallHangup.Type, BeeperMessageStatus.Type:
+ return MessageEventType
+ case ToDeviceRoomKey.Type, ToDeviceRoomKeyRequest.Type, ToDeviceForwardedRoomKey.Type, ToDeviceRoomKeyWithheld.Type:
+ return ToDeviceEventType
+ default:
+ return UnknownEventType
+ }
+}
+
+func (et *Type) UnmarshalJSON(data []byte) error {
+ err := json.Unmarshal(data, &et.Type)
+ if err != nil {
+ return err
+ }
+ et.Class = et.GuessClass()
+ return nil
+}
+
+func (et *Type) MarshalJSON() ([]byte, error) {
+ return json.Marshal(&et.Type)
+}
+
+func (et Type) UnmarshalText(data []byte) error {
+ et.Type = string(data)
+ et.Class = et.GuessClass()
+ return nil
+}
+
+func (et Type) MarshalText() ([]byte, error) {
+ return []byte(et.Type), nil
+}
+
+func (et *Type) String() string {
+ return et.Type
+}
+
+func (et *Type) Repr() string {
+ return fmt.Sprintf("%s (%s)", et.Type, et.Class.Name())
+}
+
+// State events
+var (
+ StateAliases = Type{"m.room.aliases", StateEventType}
+ StateCanonicalAlias = Type{"m.room.canonical_alias", StateEventType}
+ StateCreate = Type{"m.room.create", StateEventType}
+ StateJoinRules = Type{"m.room.join_rules", StateEventType}
+ StateHistoryVisibility = Type{"m.room.history_visibility", StateEventType}
+ StateGuestAccess = Type{"m.room.guest_access", StateEventType}
+ StateMember = Type{"m.room.member", StateEventType}
+ StatePowerLevels = Type{"m.room.power_levels", StateEventType}
+ StateRoomName = Type{"m.room.name", StateEventType}
+ StateTopic = Type{"m.room.topic", StateEventType}
+ StateRoomAvatar = Type{"m.room.avatar", StateEventType}
+ StatePinnedEvents = Type{"m.room.pinned_events", StateEventType}
+ StateServerACL = Type{"m.room.server_acl", StateEventType}
+ StateTombstone = Type{"m.room.tombstone", StateEventType}
+ StatePolicyRoom = Type{"m.policy.rule.room", StateEventType}
+ StatePolicyServer = Type{"m.policy.rule.server", StateEventType}
+ StatePolicyUser = Type{"m.policy.rule.user", StateEventType}
+ StateEncryption = Type{"m.room.encryption", StateEventType}
+ StateBridge = Type{"m.bridge", StateEventType}
+ StateHalfShotBridge = Type{"uk.half-shot.bridge", StateEventType}
+ StateSpaceChild = Type{"m.space.child", StateEventType}
+ StateSpaceParent = Type{"m.space.parent", StateEventType}
+ StateInsertionMarker = Type{"org.matrix.msc2716.marker", StateEventType}
+)
+
+// Message events
+var (
+ EventRedaction = Type{"m.room.redaction", MessageEventType}
+ EventMessage = Type{"m.room.message", MessageEventType}
+ EventEncrypted = Type{"m.room.encrypted", MessageEventType}
+ EventReaction = Type{"m.reaction", MessageEventType}
+ EventSticker = Type{"m.sticker", MessageEventType}
+
+ InRoomVerificationStart = Type{"m.key.verification.start", MessageEventType}
+ InRoomVerificationReady = Type{"m.key.verification.ready", MessageEventType}
+ InRoomVerificationAccept = Type{"m.key.verification.accept", MessageEventType}
+ InRoomVerificationKey = Type{"m.key.verification.key", MessageEventType}
+ InRoomVerificationMAC = Type{"m.key.verification.mac", MessageEventType}
+ InRoomVerificationCancel = Type{"m.key.verification.cancel", MessageEventType}
+
+ CallInvite = Type{"m.call.invite", MessageEventType}
+ CallCandidates = Type{"m.call.candidates", MessageEventType}
+ CallAnswer = Type{"m.call.answer", MessageEventType}
+ CallReject = Type{"m.call.reject", MessageEventType}
+ CallSelectAnswer = Type{"m.call.select_answer", MessageEventType}
+ CallNegotiate = Type{"m.call.negotiate", MessageEventType}
+ CallHangup = Type{"m.call.hangup", MessageEventType}
+
+ BeeperMessageStatus = Type{"com.beeper.message_send_status", MessageEventType}
+)
+
+// Ephemeral events
+var (
+ EphemeralEventReceipt = Type{"m.receipt", EphemeralEventType}
+ EphemeralEventTyping = Type{"m.typing", EphemeralEventType}
+ EphemeralEventPresence = Type{"m.presence", EphemeralEventType}
+)
+
+// Account data events
+var (
+ AccountDataDirectChats = Type{"m.direct", AccountDataEventType}
+ AccountDataPushRules = Type{"m.push_rules", AccountDataEventType}
+ AccountDataRoomTags = Type{"m.tag", AccountDataEventType}
+ AccountDataFullyRead = Type{"m.fully_read", AccountDataEventType}
+ AccountDataIgnoredUserList = Type{"m.ignored_user_list", AccountDataEventType}
+
+ AccountDataSecretStorageDefaultKey = Type{"m.secret_storage.default_key", AccountDataEventType}
+ AccountDataSecretStorageKey = Type{"m.secret_storage.key", AccountDataEventType}
+ AccountDataCrossSigningMaster = Type{"m.cross_signing.master", AccountDataEventType}
+ AccountDataCrossSigningUser = Type{"m.cross_signing.user_signing", AccountDataEventType}
+ AccountDataCrossSigningSelf = Type{"m.cross_signing.self_signing", AccountDataEventType}
+)
+
+// Device-to-device events
+var (
+ ToDeviceRoomKey = Type{"m.room_key", ToDeviceEventType}
+ ToDeviceRoomKeyRequest = Type{"m.room_key_request", ToDeviceEventType}
+ ToDeviceForwardedRoomKey = Type{"m.forwarded_room_key", ToDeviceEventType}
+ ToDeviceEncrypted = Type{"m.room.encrypted", ToDeviceEventType}
+ ToDeviceRoomKeyWithheld = Type{"m.room_key.withheld", ToDeviceEventType}
+ ToDeviceDummy = Type{"m.dummy", ToDeviceEventType}
+ ToDeviceVerificationRequest = Type{"m.key.verification.request", ToDeviceEventType}
+ ToDeviceVerificationStart = Type{"m.key.verification.start", ToDeviceEventType}
+ ToDeviceVerificationAccept = Type{"m.key.verification.accept", ToDeviceEventType}
+ ToDeviceVerificationKey = Type{"m.key.verification.key", ToDeviceEventType}
+ ToDeviceVerificationMAC = Type{"m.key.verification.mac", ToDeviceEventType}
+ ToDeviceVerificationCancel = Type{"m.key.verification.cancel", ToDeviceEventType}
+
+ ToDeviceOrgMatrixRoomKeyWithheld = Type{"org.matrix.room_key.withheld", ToDeviceEventType}
+)
diff --git a/vendor/maunium.net/go/mautrix/event/verification.go b/vendor/maunium.net/go/mautrix/event/verification.go
new file mode 100644
index 00000000..8410904d
--- /dev/null
+++ b/vendor/maunium.net/go/mautrix/event/verification.go
@@ -0,0 +1,307 @@
+// Copyright (c) 2020 Nikos Filippakis
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package event
+
+import (
+ "maunium.net/go/mautrix/id"
+)
+
+type VerificationMethod string
+
+const VerificationMethodSAS VerificationMethod = "m.sas.v1"
+
+// VerificationRequestEventContent represents the content of a m.key.verification.request to_device event.
+// https://spec.matrix.org/v1.2/client-server-api/#mkeyverificationrequest
+type VerificationRequestEventContent struct {
+ // The device ID which is initiating the request.
+ FromDevice id.DeviceID `json:"from_device"`
+ // An opaque identifier for the verification request. Must be unique with respect to the devices involved.
+ TransactionID string `json:"transaction_id,omitempty"`
+ // The verification methods supported by the sender.
+ Methods []VerificationMethod `json:"methods"`
+ // The POSIX timestamp in milliseconds for when the request was made.
+ Timestamp int64 `json:"timestamp,omitempty"`
+ // The user that the event is sent to for in-room verification.
+ To id.UserID `json:"to,omitempty"`
+ // Original event ID for in-room verification.
+ RelatesTo *RelatesTo `json:"m.relates_to,omitempty"`
+}
+
+func (vrec *VerificationRequestEventContent) SupportsVerificationMethod(meth VerificationMethod) bool {
+ for _, supportedMeth := range vrec.Methods {
+ if supportedMeth == meth {
+ return true
+ }
+ }
+ return false
+}
+
+type KeyAgreementProtocol string
+
+const (
+ KeyAgreementCurve25519 KeyAgreementProtocol = "curve25519"
+ KeyAgreementCurve25519HKDFSHA256 KeyAgreementProtocol = "curve25519-hkdf-sha256"
+)
+
+type VerificationHashMethod string
+
+const VerificationHashSHA256 VerificationHashMethod = "sha256"
+
+type MACMethod string
+
+const HKDFHMACSHA256 MACMethod = "hkdf-hmac-sha256"
+
+type SASMethod string
+
+const (
+ SASDecimal SASMethod = "decimal"
+ SASEmoji SASMethod = "emoji"
+)
+
+// VerificationStartEventContent represents the content of a m.key.verification.start to_device event.
+// https://spec.matrix.org/v1.2/client-server-api/#mkeyverificationstartmsasv1
+type VerificationStartEventContent struct {
+ // The device ID which is initiating the process.
+ FromDevice id.DeviceID `json:"from_device"`
+ // An opaque identifier for the verification process. Must be unique with respect to the devices involved.
+ TransactionID string `json:"transaction_id,omitempty"`
+ // The verification method to use.
+ Method VerificationMethod `json:"method"`
+ // The key agreement protocols the sending device understands.
+ KeyAgreementProtocols []KeyAgreementProtocol `json:"key_agreement_protocols"`
+ // The hash methods the sending device understands.
+ Hashes []VerificationHashMethod `json:"hashes"`
+ // The message authentication codes that the sending device understands.
+ MessageAuthenticationCodes []MACMethod `json:"message_authentication_codes"`
+ // The SAS methods the sending device (and the sending device's user) understands.
+ ShortAuthenticationString []SASMethod `json:"short_authentication_string"`
+ // The user that the event is sent to for in-room verification.
+ To id.UserID `json:"to,omitempty"`
+ // Original event ID for in-room verification.
+ RelatesTo *RelatesTo `json:"m.relates_to,omitempty"`
+}
+
+func (vsec *VerificationStartEventContent) SupportsKeyAgreementProtocol(proto KeyAgreementProtocol) bool {
+ for _, supportedProto := range vsec.KeyAgreementProtocols {
+ if supportedProto == proto {
+ return true
+ }
+ }
+ return false
+}
+
+func (vsec *VerificationStartEventContent) SupportsHashMethod(alg VerificationHashMethod) bool {
+ for _, supportedAlg := range vsec.Hashes {
+ if supportedAlg == alg {
+ return true
+ }
+ }
+ return false
+}
+
+func (vsec *VerificationStartEventContent) SupportsMACMethod(meth MACMethod) bool {
+ for _, supportedMeth := range vsec.MessageAuthenticationCodes {
+ if supportedMeth == meth {
+ return true
+ }
+ }
+ return false
+}
+
+func (vsec *VerificationStartEventContent) SupportsSASMethod(meth SASMethod) bool {
+ for _, supportedMeth := range vsec.ShortAuthenticationString {
+ if supportedMeth == meth {
+ return true
+ }
+ }
+ return false
+}
+
+func (vsec *VerificationStartEventContent) GetRelatesTo() *RelatesTo {
+ if vsec.RelatesTo == nil {
+ vsec.RelatesTo = &RelatesTo{}
+ }
+ return vsec.RelatesTo
+}
+
+func (vsec *VerificationStartEventContent) OptionalGetRelatesTo() *RelatesTo {
+ return vsec.RelatesTo
+}
+
+func (vsec *VerificationStartEventContent) SetRelatesTo(rel *RelatesTo) {
+ vsec.RelatesTo = rel
+}
+
+// VerificationReadyEventContent represents the content of a m.key.verification.ready event.
+// https://spec.matrix.org/v1.2/client-server-api/#mkeyverificationready
+type VerificationReadyEventContent struct {
+ // The device ID which accepted the process.
+ FromDevice id.DeviceID `json:"from_device"`
+ // The verification methods supported by the sender.
+ Methods []VerificationMethod `json:"methods"`
+ // Original event ID for in-room verification.
+ RelatesTo *RelatesTo `json:"m.relates_to,omitempty"`
+}
+
+var _ Relatable = (*VerificationReadyEventContent)(nil)
+
+func (vrec *VerificationReadyEventContent) GetRelatesTo() *RelatesTo {
+ if vrec.RelatesTo == nil {
+ vrec.RelatesTo = &RelatesTo{}
+ }
+ return vrec.RelatesTo
+}
+
+func (vrec *VerificationReadyEventContent) OptionalGetRelatesTo() *RelatesTo {
+ return vrec.RelatesTo
+}
+
+func (vrec *VerificationReadyEventContent) SetRelatesTo(rel *RelatesTo) {
+ vrec.RelatesTo = rel
+}
+
+// VerificationAcceptEventContent represents the content of a m.key.verification.accept to_device event.
+// https://spec.matrix.org/v1.2/client-server-api/#mkeyverificationaccept
+type VerificationAcceptEventContent struct {
+ // An opaque identifier for the verification process. Must be the same as the one used for the m.key.verification.start message.
+ TransactionID string `json:"transaction_id,omitempty"`
+ // The verification method to use.
+ Method VerificationMethod `json:"method"`
+ // The key agreement protocol the device is choosing to use, out of the options in the m.key.verification.start message.
+ KeyAgreementProtocol KeyAgreementProtocol `json:"key_agreement_protocol"`
+ // The hash method the device is choosing to use, out of the options in the m.key.verification.start message.
+ Hash VerificationHashMethod `json:"hash"`
+ // The message authentication code the device is choosing to use, out of the options in the m.key.verification.start message.
+ MessageAuthenticationCode MACMethod `json:"message_authentication_code"`
+ // The SAS methods both devices involved in the verification process understand. Must be a subset of the options in the m.key.verification.start message.
+ ShortAuthenticationString []SASMethod `json:"short_authentication_string"`
+ // The hash (encoded as unpadded base64) of the concatenation of the device's ephemeral public key (encoded as unpadded base64) and the canonical JSON representation of the m.key.verification.start message.
+ Commitment string `json:"commitment"`
+ // The user that the event is sent to for in-room verification.
+ To id.UserID `json:"to,omitempty"`
+ // Original event ID for in-room verification.
+ RelatesTo *RelatesTo `json:"m.relates_to,omitempty"`
+}
+
+func (vaec *VerificationAcceptEventContent) GetRelatesTo() *RelatesTo {
+ if vaec.RelatesTo == nil {
+ vaec.RelatesTo = &RelatesTo{}
+ }
+ return vaec.RelatesTo
+}
+
+func (vaec *VerificationAcceptEventContent) OptionalGetRelatesTo() *RelatesTo {
+ return vaec.RelatesTo
+}
+
+func (vaec *VerificationAcceptEventContent) SetRelatesTo(rel *RelatesTo) {
+ vaec.RelatesTo = rel
+}
+
+// VerificationKeyEventContent represents the content of a m.key.verification.key to_device event.
+// https://spec.matrix.org/v1.2/client-server-api/#mkeyverificationkey
+type VerificationKeyEventContent struct {
+ // An opaque identifier for the verification process. Must be the same as the one used for the m.key.verification.start message.
+ TransactionID string `json:"transaction_id,omitempty"`
+ // The device's ephemeral public key, encoded as unpadded base64.
+ Key string `json:"key"`
+ // The user that the event is sent to for in-room verification.
+ To id.UserID `json:"to,omitempty"`
+ // Original event ID for in-room verification.
+ RelatesTo *RelatesTo `json:"m.relates_to,omitempty"`
+}
+
+func (vkec *VerificationKeyEventContent) GetRelatesTo() *RelatesTo {
+ if vkec.RelatesTo == nil {
+ vkec.RelatesTo = &RelatesTo{}
+ }
+ return vkec.RelatesTo
+}
+
+func (vkec *VerificationKeyEventContent) OptionalGetRelatesTo() *RelatesTo {
+ return vkec.RelatesTo
+}
+
+func (vkec *VerificationKeyEventContent) SetRelatesTo(rel *RelatesTo) {
+ vkec.RelatesTo = rel
+}
+
+// VerificationMacEventContent represents the content of a m.key.verification.mac to_device event.
+// https://spec.matrix.org/v1.2/client-server-api/#mkeyverificationmac
+type VerificationMacEventContent struct {
+ // An opaque identifier for the verification process. Must be the same as the one used for the m.key.verification.start message.
+ TransactionID string `json:"transaction_id,omitempty"`
+ // A map of the key ID to the MAC of the key, using the algorithm in the verification process. The MAC is encoded as unpadded base64.
+ Mac map[id.KeyID]string `json:"mac"`
+ // The MAC of the comma-separated, sorted, list of key IDs given in the mac property, encoded as unpadded base64.
+ Keys string `json:"keys"`
+ // The user that the event is sent to for in-room verification.
+ To id.UserID `json:"to,omitempty"`
+ // Original event ID for in-room verification.
+ RelatesTo *RelatesTo `json:"m.relates_to,omitempty"`
+}
+
+func (vmec *VerificationMacEventContent) GetRelatesTo() *RelatesTo {
+ if vmec.RelatesTo == nil {
+ vmec.RelatesTo = &RelatesTo{}
+ }
+ return vmec.RelatesTo
+}
+
+func (vmec *VerificationMacEventContent) OptionalGetRelatesTo() *RelatesTo {
+ return vmec.RelatesTo
+}
+
+func (vmec *VerificationMacEventContent) SetRelatesTo(rel *RelatesTo) {
+ vmec.RelatesTo = rel
+}
+
+type VerificationCancelCode string
+
+const (
+ VerificationCancelByUser VerificationCancelCode = "m.user"
+ VerificationCancelByTimeout VerificationCancelCode = "m.timeout"
+ VerificationCancelUnknownTransaction VerificationCancelCode = "m.unknown_transaction"
+ VerificationCancelUnknownMethod VerificationCancelCode = "m.unknown_method"
+ VerificationCancelUnexpectedMessage VerificationCancelCode = "m.unexpected_message"
+ VerificationCancelKeyMismatch VerificationCancelCode = "m.key_mismatch"
+ VerificationCancelUserMismatch VerificationCancelCode = "m.user_mismatch"
+ VerificationCancelInvalidMessage VerificationCancelCode = "m.invalid_message"
+ VerificationCancelAccepted VerificationCancelCode = "m.accepted"
+ VerificationCancelSASMismatch VerificationCancelCode = "m.mismatched_sas"
+ VerificationCancelCommitmentMismatch VerificationCancelCode = "m.mismatched_commitment"
+)
+
+// VerificationCancelEventContent represents the content of a m.key.verification.cancel to_device event.
+// https://spec.matrix.org/v1.2/client-server-api/#mkeyverificationcancel
+type VerificationCancelEventContent struct {
+ // The opaque identifier for the verification process/request.
+ TransactionID string `json:"transaction_id,omitempty"`
+ // A human readable description of the code. The client should only rely on this string if it does not understand the code.
+ Reason string `json:"reason"`
+ // The error code for why the process/request was cancelled by the user.
+ Code VerificationCancelCode `json:"code"`
+ // The user that the event is sent to for in-room verification.
+ To id.UserID `json:"to,omitempty"`
+ // Original event ID for in-room verification.
+ RelatesTo *RelatesTo `json:"m.relates_to,omitempty"`
+}
+
+func (vcec *VerificationCancelEventContent) GetRelatesTo() *RelatesTo {
+ if vcec.RelatesTo == nil {
+ vcec.RelatesTo = &RelatesTo{}
+ }
+ return vcec.RelatesTo
+}
+
+func (vcec *VerificationCancelEventContent) OptionalGetRelatesTo() *RelatesTo {
+ return vcec.RelatesTo
+}
+
+func (vcec *VerificationCancelEventContent) SetRelatesTo(rel *RelatesTo) {
+ vcec.RelatesTo = rel
+}
diff --git a/vendor/maunium.net/go/mautrix/event/voip.go b/vendor/maunium.net/go/mautrix/event/voip.go
new file mode 100644
index 00000000..28f56c95
--- /dev/null
+++ b/vendor/maunium.net/go/mautrix/event/voip.go
@@ -0,0 +1,116 @@
+// Copyright (c) 2021 Tulir Asokan
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package event
+
+import (
+ "encoding/json"
+ "fmt"
+ "strconv"
+)
+
+type CallHangupReason string
+
+const (
+ CallHangupICEFailed CallHangupReason = "ice_failed"
+ CallHangupInviteTimeout CallHangupReason = "invite_timeout"
+ CallHangupUserHangup CallHangupReason = "user_hangup"
+ CallHangupUserMediaFailed CallHangupReason = "user_media_failed"
+ CallHangupUnknownError CallHangupReason = "unknown_error"
+)
+
+type CallDataType string
+
+const (
+ CallDataTypeOffer CallDataType = "offer"
+ CallDataTypeAnswer CallDataType = "answer"
+)
+
+type CallData struct {
+ SDP string `json:"sdp"`
+ Type CallDataType `json:"type"`
+}
+
+type CallCandidate struct {
+ Candidate string `json:"candidate"`
+ SDPMLineIndex int `json:"sdpMLineIndex"`
+ SDPMID string `json:"sdpMid"`
+}
+
+type CallVersion string
+
+func (cv *CallVersion) UnmarshalJSON(raw []byte) error {
+ var numberVersion int
+ err := json.Unmarshal(raw, &numberVersion)
+ if err != nil {
+ var stringVersion string
+ err = json.Unmarshal(raw, &stringVersion)
+ if err != nil {
+ return fmt.Errorf("failed to parse CallVersion: %w", err)
+ }
+ *cv = CallVersion(stringVersion)
+ } else {
+ *cv = CallVersion(strconv.Itoa(numberVersion))
+ }
+ return nil
+}
+
+func (cv *CallVersion) MarshalJSON() ([]byte, error) {
+ for _, char := range *cv {
+ if char < '0' || char > '9' {
+ // The version contains weird characters, return as string.
+ return json.Marshal(string(*cv))
+ }
+ }
+ // The version consists of only ASCII digits, return as an integer.
+ return []byte(*cv), nil
+}
+
+func (cv *CallVersion) Int() (int, error) {
+ return strconv.Atoi(string(*cv))
+}
+
+type BaseCallEventContent struct {
+ CallID string `json:"call_id"`
+ PartyID string `json:"party_id"`
+ Version CallVersion `json:"version"`
+}
+
+type CallInviteEventContent struct {
+ BaseCallEventContent
+ Lifetime int `json:"lifetime"`
+ Offer CallData `json:"offer"`
+}
+
+type CallCandidatesEventContent struct {
+ BaseCallEventContent
+ Candidates []CallCandidate `json:"candidates"`
+}
+
+type CallRejectEventContent struct {
+ BaseCallEventContent
+}
+
+type CallAnswerEventContent struct {
+ BaseCallEventContent
+ Answer CallData `json:"answer"`
+}
+
+type CallSelectAnswerEventContent struct {
+ BaseCallEventContent
+ SelectedPartyID string `json:"selected_party_id"`
+}
+
+type CallNegotiateEventContent struct {
+ BaseCallEventContent
+ Lifetime int `json:"lifetime"`
+ Description CallData `json:"description"`
+}
+
+type CallHangupEventContent struct {
+ BaseCallEventContent
+ Reason CallHangupReason `json:"reason"`
+}