mirror of
https://mau.dev/mautrix/go.git
synced 2026-03-14 14:25:53 +01:00
bridgev2,event: add interface for message requests
This commit is contained in:
parent
e7a95b7f97
commit
31579be20a
13 changed files with 173 additions and 77 deletions
|
|
@ -56,30 +56,31 @@ type Portal struct {
|
|||
networkid.PortalKey
|
||||
MXID id.RoomID
|
||||
|
||||
ParentKey networkid.PortalKey
|
||||
RelayLoginID networkid.UserLoginID
|
||||
OtherUserID networkid.UserID
|
||||
Name string
|
||||
Topic string
|
||||
AvatarID networkid.AvatarID
|
||||
AvatarHash [32]byte
|
||||
AvatarMXC id.ContentURIString
|
||||
NameSet bool
|
||||
TopicSet bool
|
||||
AvatarSet bool
|
||||
NameIsCustom bool
|
||||
InSpace bool
|
||||
RoomType RoomType
|
||||
Disappear DisappearingSetting
|
||||
CapState CapabilityState
|
||||
Metadata any
|
||||
ParentKey networkid.PortalKey
|
||||
RelayLoginID networkid.UserLoginID
|
||||
OtherUserID networkid.UserID
|
||||
Name string
|
||||
Topic string
|
||||
AvatarID networkid.AvatarID
|
||||
AvatarHash [32]byte
|
||||
AvatarMXC id.ContentURIString
|
||||
NameSet bool
|
||||
TopicSet bool
|
||||
AvatarSet bool
|
||||
NameIsCustom bool
|
||||
InSpace bool
|
||||
MessageRequest bool
|
||||
RoomType RoomType
|
||||
Disappear DisappearingSetting
|
||||
CapState CapabilityState
|
||||
Metadata any
|
||||
}
|
||||
|
||||
const (
|
||||
getPortalBaseQuery = `
|
||||
SELECT bridge_id, id, receiver, mxid, parent_id, parent_receiver, relay_login_id, other_user_id,
|
||||
name, topic, avatar_id, avatar_hash, avatar_mxc,
|
||||
name_set, topic_set, avatar_set, name_is_custom, in_space,
|
||||
name_set, topic_set, avatar_set, name_is_custom, in_space, message_request,
|
||||
room_type, disappear_type, disappear_timer, cap_state,
|
||||
metadata
|
||||
FROM portal
|
||||
|
|
@ -101,11 +102,11 @@ const (
|
|||
bridge_id, id, receiver, mxid,
|
||||
parent_id, parent_receiver, relay_login_id, other_user_id,
|
||||
name, topic, avatar_id, avatar_hash, avatar_mxc,
|
||||
name_set, avatar_set, topic_set, name_is_custom, in_space,
|
||||
name_set, avatar_set, topic_set, name_is_custom, in_space, message_request,
|
||||
room_type, disappear_type, disappear_timer, cap_state,
|
||||
metadata, relay_bridge_id
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6, cast($7 AS TEXT), $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23,
|
||||
$1, $2, $3, $4, $5, $6, cast($7 AS TEXT), $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24,
|
||||
CASE WHEN cast($7 AS TEXT) IS NULL THEN NULL ELSE $1 END
|
||||
)
|
||||
`
|
||||
|
|
@ -114,8 +115,8 @@ const (
|
|||
SET mxid=$4, parent_id=$5, parent_receiver=$6,
|
||||
relay_login_id=cast($7 AS TEXT), relay_bridge_id=CASE WHEN cast($7 AS TEXT) IS NULL THEN NULL ELSE bridge_id END,
|
||||
other_user_id=$8, name=$9, topic=$10, avatar_id=$11, avatar_hash=$12, avatar_mxc=$13,
|
||||
name_set=$14, avatar_set=$15, topic_set=$16, name_is_custom=$17, in_space=$18,
|
||||
room_type=$19, disappear_type=$20, disappear_timer=$21, cap_state=$22, metadata=$23
|
||||
name_set=$14, avatar_set=$15, topic_set=$16, name_is_custom=$17, in_space=$18, message_request=$19,
|
||||
room_type=$20, disappear_type=$21, disappear_timer=$22, cap_state=$23, metadata=$24
|
||||
WHERE bridge_id=$1 AND id=$2 AND receiver=$3
|
||||
`
|
||||
deletePortalQuery = `
|
||||
|
|
@ -241,7 +242,7 @@ func (p *Portal) Scan(row dbutil.Scannable) (*Portal, error) {
|
|||
&p.BridgeID, &p.ID, &p.Receiver, &mxid,
|
||||
&parentID, &parentReceiver, &relayLoginID, &otherUserID,
|
||||
&p.Name, &p.Topic, &p.AvatarID, &avatarHash, &p.AvatarMXC,
|
||||
&p.NameSet, &p.TopicSet, &p.AvatarSet, &p.NameIsCustom, &p.InSpace,
|
||||
&p.NameSet, &p.TopicSet, &p.AvatarSet, &p.NameIsCustom, &p.InSpace, &p.MessageRequest,
|
||||
&p.RoomType, &disappearType, &disappearTimer,
|
||||
dbutil.JSON{Data: &p.CapState}, dbutil.JSON{Data: p.Metadata},
|
||||
)
|
||||
|
|
@ -288,7 +289,7 @@ func (p *Portal) sqlVariables() []any {
|
|||
p.BridgeID, p.ID, p.Receiver, dbutil.StrPtr(p.MXID),
|
||||
dbutil.StrPtr(p.ParentKey.ID), p.ParentKey.Receiver, dbutil.StrPtr(p.RelayLoginID), dbutil.StrPtr(p.OtherUserID),
|
||||
p.Name, p.Topic, p.AvatarID, avatarHash, p.AvatarMXC,
|
||||
p.NameSet, p.TopicSet, p.AvatarSet, p.NameIsCustom, p.InSpace,
|
||||
p.NameSet, p.TopicSet, p.AvatarSet, p.NameIsCustom, p.InSpace, p.MessageRequest,
|
||||
p.RoomType, dbutil.StrPtr(p.Disappear.Type), dbutil.NumPtr(p.Disappear.Timer),
|
||||
dbutil.JSON{Data: p.CapState}, dbutil.JSON{Data: p.Metadata},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
-- v0 -> v24 (compatible with v9+): Latest revision
|
||||
-- v0 -> v25 (compatible with v9+): Latest revision
|
||||
CREATE TABLE "user" (
|
||||
bridge_id TEXT NOT NULL,
|
||||
mxid TEXT NOT NULL,
|
||||
|
|
@ -48,6 +48,7 @@ CREATE TABLE portal (
|
|||
topic_set BOOLEAN NOT NULL,
|
||||
name_is_custom BOOLEAN NOT NULL DEFAULT false,
|
||||
in_space BOOLEAN NOT NULL,
|
||||
message_request BOOLEAN NOT NULL DEFAULT false,
|
||||
room_type TEXT NOT NULL,
|
||||
disappear_type TEXT,
|
||||
disappear_timer BIGINT,
|
||||
|
|
|
|||
2
bridgev2/database/upgrades/25-message-requests.sql
Normal file
2
bridgev2/database/upgrades/25-message-requests.sql
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
-- v25 (compatible with v9+): Flag for message request portals
|
||||
ALTER TABLE portal ADD COLUMN message_request BOOLEAN NOT NULL DEFAULT false;
|
||||
|
|
@ -40,40 +40,41 @@ var ErrDirectMediaNotEnabled = errors.New("direct media is not enabled")
|
|||
|
||||
// Common message status errors
|
||||
var (
|
||||
ErrPanicInEventHandler error = WrapErrorInStatus(errors.New("panic in event handler")).WithSendNotice(true).WithErrorAsMessage()
|
||||
ErrNoPortal error = WrapErrorInStatus(errors.New("room is not a portal")).WithIsCertain(true).WithSendNotice(false)
|
||||
ErrIgnoringReactionFromRelayedUser error = WrapErrorInStatus(errors.New("ignoring reaction event from relayed user")).WithIsCertain(true).WithSendNotice(false)
|
||||
ErrIgnoringPollFromRelayedUser error = WrapErrorInStatus(errors.New("ignoring poll event from relayed user")).WithIsCertain(true).WithSendNotice(false)
|
||||
ErrIgnoringDeleteChatRelayedUser error = WrapErrorInStatus(errors.New("ignoring delete chat event from relayed user")).WithIsCertain(true).WithSendNotice(false)
|
||||
ErrEditsNotSupported error = WrapErrorInStatus(errors.New("this bridge does not support edits")).WithIsCertain(true).WithErrorAsMessage().WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrEditsNotSupportedInPortal error = WrapErrorInStatus(errors.New("edits are not allowed in this chat")).WithIsCertain(true).WithErrorAsMessage().WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrCaptionsNotAllowed error = WrapErrorInStatus(errors.New("captions are not supported here")).WithIsCertain(true).WithErrorAsMessage().WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrLocationMessagesNotAllowed error = WrapErrorInStatus(errors.New("location messages are not supported here")).WithIsCertain(true).WithErrorAsMessage().WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrEditTargetTooOld error = WrapErrorInStatus(errors.New("the message is too old to be edited")).WithIsCertain(true).WithErrorAsMessage().WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrEditTargetTooManyEdits error = WrapErrorInStatus(errors.New("the message has been edited too many times")).WithIsCertain(true).WithErrorAsMessage().WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrReactionsNotSupported error = WrapErrorInStatus(errors.New("this bridge does not support reactions")).WithIsCertain(true).WithErrorAsMessage().WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrPollsNotSupported error = WrapErrorInStatus(errors.New("this bridge does not support polls")).WithIsCertain(true).WithErrorAsMessage().WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrRoomMetadataNotSupported error = WrapErrorInStatus(errors.New("this bridge does not support changing room metadata")).WithIsCertain(true).WithErrorAsMessage().WithSendNotice(false).WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrRoomMetadataNotAllowed error = WrapErrorInStatus(errors.New("changes are not allowed here")).WithIsCertain(true).WithErrorAsMessage().WithSendNotice(false).WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrRedactionsNotSupported error = WrapErrorInStatus(errors.New("this bridge does not support deleting messages")).WithIsCertain(true).WithErrorAsMessage().WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrUnexpectedParsedContentType error = WrapErrorInStatus(errors.New("unexpected parsed content type")).WithErrorAsMessage().WithIsCertain(true).WithSendNotice(true)
|
||||
ErrInvalidStateKey error = WrapErrorInStatus(errors.New("room metadata state key is unset or non-empty")).WithErrorAsMessage().WithIsCertain(true).WithSendNotice(false)
|
||||
ErrDatabaseError error = WrapErrorInStatus(errors.New("database error")).WithMessage("internal database error").WithIsCertain(true).WithSendNotice(true)
|
||||
ErrTargetMessageNotFound error = WrapErrorInStatus(errors.New("target message not found")).WithErrorAsMessage().WithIsCertain(true).WithSendNotice(false)
|
||||
ErrUnsupportedMessageType error = WrapErrorInStatus(errors.New("unsupported message type")).WithErrorAsMessage().WithIsCertain(true).WithSendNotice(true).WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrUnsupportedMediaType error = WrapErrorInStatus(errors.New("unsupported media type")).WithErrorAsMessage().WithIsCertain(true).WithSendNotice(true).WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrMediaDurationTooLong error = WrapErrorInStatus(errors.New("media duration too long")).WithErrorAsMessage().WithSendNotice(true).WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrVoiceMessageDurationTooLong error = WrapErrorInStatus(errors.New("voice message too long")).WithErrorAsMessage().WithSendNotice(true).WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrMediaTooLarge error = WrapErrorInStatus(errors.New("media too large")).WithErrorAsMessage().WithIsCertain(true).WithSendNotice(true).WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrIgnoringMNotice error = WrapErrorInStatus(errors.New("ignoring m.notice message")).WithIsCertain(true).WithErrorAsMessage().WithSendNotice(false)
|
||||
ErrMediaDownloadFailed error = WrapErrorInStatus(errors.New("failed to download media")).WithMessage("failed to download media").WithIsCertain(true).WithSendNotice(true)
|
||||
ErrMediaReuploadFailed error = WrapErrorInStatus(errors.New("failed to reupload media")).WithMessage("failed to reupload media").WithIsCertain(true).WithSendNotice(true)
|
||||
ErrMediaConvertFailed error = WrapErrorInStatus(errors.New("failed to convert media")).WithMessage("failed to convert media").WithIsCertain(true).WithSendNotice(true)
|
||||
ErrMembershipNotSupported error = WrapErrorInStatus(errors.New("this bridge does not support changing group membership")).WithIsCertain(true).WithErrorAsMessage().WithSendNotice(false).WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrDeleteChatNotSupported error = WrapErrorInStatus(errors.New("this bridge does not support deleting chats")).WithIsCertain(true).WithErrorAsMessage().WithSendNotice(false).WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrPowerLevelsNotSupported error = WrapErrorInStatus(errors.New("this bridge does not support changing group power levels")).WithIsCertain(true).WithErrorAsMessage().WithSendNotice(false).WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrRemoteEchoTimeout = WrapErrorInStatus(errors.New("remote echo timed out")).WithIsCertain(false).WithSendNotice(true).WithErrorReason(event.MessageStatusTooOld)
|
||||
ErrRemoteAckTimeout = WrapErrorInStatus(errors.New("remote ack timed out")).WithIsCertain(false).WithSendNotice(true).WithErrorReason(event.MessageStatusTooOld)
|
||||
ErrPanicInEventHandler error = WrapErrorInStatus(errors.New("panic in event handler")).WithSendNotice(true).WithErrorAsMessage()
|
||||
ErrNoPortal error = WrapErrorInStatus(errors.New("room is not a portal")).WithIsCertain(true).WithSendNotice(false)
|
||||
ErrIgnoringReactionFromRelayedUser error = WrapErrorInStatus(errors.New("ignoring reaction event from relayed user")).WithIsCertain(true).WithSendNotice(false)
|
||||
ErrIgnoringPollFromRelayedUser error = WrapErrorInStatus(errors.New("ignoring poll event from relayed user")).WithIsCertain(true).WithSendNotice(false)
|
||||
ErrIgnoringDeleteChatRelayedUser error = WrapErrorInStatus(errors.New("ignoring delete chat event from relayed user")).WithIsCertain(true).WithSendNotice(false)
|
||||
ErrIgnoringAcceptRequestRelayedUser error = WrapErrorInStatus(errors.New("ignoring accept message request event from relayed user")).WithIsCertain(true).WithSendNotice(false)
|
||||
ErrEditsNotSupported error = WrapErrorInStatus(errors.New("this bridge does not support edits")).WithIsCertain(true).WithErrorAsMessage().WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrEditsNotSupportedInPortal error = WrapErrorInStatus(errors.New("edits are not allowed in this chat")).WithIsCertain(true).WithErrorAsMessage().WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrCaptionsNotAllowed error = WrapErrorInStatus(errors.New("captions are not supported here")).WithIsCertain(true).WithErrorAsMessage().WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrLocationMessagesNotAllowed error = WrapErrorInStatus(errors.New("location messages are not supported here")).WithIsCertain(true).WithErrorAsMessage().WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrEditTargetTooOld error = WrapErrorInStatus(errors.New("the message is too old to be edited")).WithIsCertain(true).WithErrorAsMessage().WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrEditTargetTooManyEdits error = WrapErrorInStatus(errors.New("the message has been edited too many times")).WithIsCertain(true).WithErrorAsMessage().WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrReactionsNotSupported error = WrapErrorInStatus(errors.New("this bridge does not support reactions")).WithIsCertain(true).WithErrorAsMessage().WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrPollsNotSupported error = WrapErrorInStatus(errors.New("this bridge does not support polls")).WithIsCertain(true).WithErrorAsMessage().WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrRoomMetadataNotSupported error = WrapErrorInStatus(errors.New("this bridge does not support changing room metadata")).WithIsCertain(true).WithErrorAsMessage().WithSendNotice(false).WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrRoomMetadataNotAllowed error = WrapErrorInStatus(errors.New("changes are not allowed here")).WithIsCertain(true).WithErrorAsMessage().WithSendNotice(false).WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrRedactionsNotSupported error = WrapErrorInStatus(errors.New("this bridge does not support deleting messages")).WithIsCertain(true).WithErrorAsMessage().WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrUnexpectedParsedContentType error = WrapErrorInStatus(errors.New("unexpected parsed content type")).WithErrorAsMessage().WithIsCertain(true).WithSendNotice(true)
|
||||
ErrInvalidStateKey error = WrapErrorInStatus(errors.New("room metadata state key is unset or non-empty")).WithErrorAsMessage().WithIsCertain(true).WithSendNotice(false)
|
||||
ErrDatabaseError error = WrapErrorInStatus(errors.New("database error")).WithMessage("internal database error").WithIsCertain(true).WithSendNotice(true)
|
||||
ErrTargetMessageNotFound error = WrapErrorInStatus(errors.New("target message not found")).WithErrorAsMessage().WithIsCertain(true).WithSendNotice(false)
|
||||
ErrUnsupportedMessageType error = WrapErrorInStatus(errors.New("unsupported message type")).WithErrorAsMessage().WithIsCertain(true).WithSendNotice(true).WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrUnsupportedMediaType error = WrapErrorInStatus(errors.New("unsupported media type")).WithErrorAsMessage().WithIsCertain(true).WithSendNotice(true).WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrMediaDurationTooLong error = WrapErrorInStatus(errors.New("media duration too long")).WithErrorAsMessage().WithSendNotice(true).WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrVoiceMessageDurationTooLong error = WrapErrorInStatus(errors.New("voice message too long")).WithErrorAsMessage().WithSendNotice(true).WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrMediaTooLarge error = WrapErrorInStatus(errors.New("media too large")).WithErrorAsMessage().WithIsCertain(true).WithSendNotice(true).WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrIgnoringMNotice error = WrapErrorInStatus(errors.New("ignoring m.notice message")).WithIsCertain(true).WithErrorAsMessage().WithSendNotice(false)
|
||||
ErrMediaDownloadFailed error = WrapErrorInStatus(errors.New("failed to download media")).WithMessage("failed to download media").WithIsCertain(true).WithSendNotice(true)
|
||||
ErrMediaReuploadFailed error = WrapErrorInStatus(errors.New("failed to reupload media")).WithMessage("failed to reupload media").WithIsCertain(true).WithSendNotice(true)
|
||||
ErrMediaConvertFailed error = WrapErrorInStatus(errors.New("failed to convert media")).WithMessage("failed to convert media").WithIsCertain(true).WithSendNotice(true)
|
||||
ErrMembershipNotSupported error = WrapErrorInStatus(errors.New("this bridge does not support changing group membership")).WithIsCertain(true).WithErrorAsMessage().WithSendNotice(false).WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrDeleteChatNotSupported error = WrapErrorInStatus(errors.New("this bridge does not support deleting chats")).WithIsCertain(true).WithErrorAsMessage().WithSendNotice(false).WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrPowerLevelsNotSupported error = WrapErrorInStatus(errors.New("this bridge does not support changing group power levels")).WithIsCertain(true).WithErrorAsMessage().WithSendNotice(false).WithErrorReason(event.MessageStatusUnsupported)
|
||||
ErrRemoteEchoTimeout = WrapErrorInStatus(errors.New("remote echo timed out")).WithIsCertain(false).WithSendNotice(true).WithErrorReason(event.MessageStatusTooOld)
|
||||
ErrRemoteAckTimeout = WrapErrorInStatus(errors.New("remote ack timed out")).WithIsCertain(false).WithSendNotice(true).WithErrorReason(event.MessageStatusTooOld)
|
||||
|
||||
ErrPublicMediaDisabled = WrapErrorInStatus(errors.New("public media is not enabled in the bridge config")).WithIsCertain(true).WithErrorAsMessage().WithErrorReason(event.MessageStatusUnsupported).WithSendNotice(true)
|
||||
ErrPublicMediaDatabaseDisabled = WrapErrorInStatus(errors.New("public media database storage is disabled")).WithIsCertain(true).WithErrorAsMessage().WithErrorReason(event.MessageStatusUnsupported).WithSendNotice(true)
|
||||
|
|
|
|||
|
|
@ -151,6 +151,7 @@ func (br *Connector) Init(bridge *bridgev2.Bridge) {
|
|||
br.EventProcessor.On(event.StateTombstone, br.handleRoomEvent)
|
||||
br.EventProcessor.On(event.StateBeeperDisappearingTimer, br.handleRoomEvent)
|
||||
br.EventProcessor.On(event.BeeperDeleteChat, br.handleRoomEvent)
|
||||
br.EventProcessor.On(event.BeeperAcceptMessageRequest, br.handleRoomEvent)
|
||||
br.EventProcessor.On(event.EphemeralEventReceipt, br.handleEphemeralEvent)
|
||||
br.EventProcessor.On(event.EphemeralEventTyping, br.handleEphemeralEvent)
|
||||
br.Bot = br.AS.BotIntent()
|
||||
|
|
|
|||
|
|
@ -712,6 +712,14 @@ type DeleteChatHandlingNetworkAPI interface {
|
|||
HandleMatrixDeleteChat(ctx context.Context, msg *MatrixDeleteChat) error
|
||||
}
|
||||
|
||||
// MessageRequestAcceptingNetworkAPI is an optional interface that network connectors
|
||||
// can implement to accept message requests from the remote network.
|
||||
type MessageRequestAcceptingNetworkAPI interface {
|
||||
NetworkAPI
|
||||
// HandleMatrixAcceptMessageRequest is called when the user accepts a message request.
|
||||
HandleMatrixAcceptMessageRequest(ctx context.Context, msg *MatrixAcceptMessageRequest) error
|
||||
}
|
||||
|
||||
type ResolveIdentifierResponse struct {
|
||||
// Ghost is the ghost of the user that the identifier resolves to.
|
||||
// This field should be set whenever possible. However, it is not required,
|
||||
|
|
@ -1419,6 +1427,7 @@ type MatrixViewingChat struct {
|
|||
}
|
||||
|
||||
type MatrixDeleteChat = MatrixEventBase[*event.BeeperChatDeleteEventContent]
|
||||
type MatrixAcceptMessageRequest = MatrixEventBase[*event.BeeperAcceptMessageRequestEventContent]
|
||||
type MatrixMarkedUnread = MatrixRoomMeta[*event.MarkedUnreadEventContent]
|
||||
type MatrixMute = MatrixRoomMeta[*event.BeeperMuteEventContent]
|
||||
type MatrixRoomTag = MatrixRoomMeta[*event.TagEventContent]
|
||||
|
|
|
|||
|
|
@ -800,6 +800,8 @@ func (portal *Portal) handleMatrixEvent(ctx context.Context, sender *User, evt *
|
|||
return portal.handleMatrixPowerLevels(ctx, login, origSender, evt, isStateRequest)
|
||||
case event.BeeperDeleteChat:
|
||||
return portal.handleMatrixDeleteChat(ctx, login, origSender, evt)
|
||||
case event.BeeperAcceptMessageRequest:
|
||||
return portal.handleMatrixAcceptMessageRequest(ctx, login, origSender, evt)
|
||||
default:
|
||||
return EventHandlingResultIgnored
|
||||
}
|
||||
|
|
@ -1749,6 +1751,45 @@ func (portal *Portal) getTargetUser(ctx context.Context, userID id.UserID) (Ghos
|
|||
}
|
||||
}
|
||||
|
||||
func (portal *Portal) handleMatrixAcceptMessageRequest(
|
||||
ctx context.Context,
|
||||
sender *UserLogin,
|
||||
origSender *OrigSender,
|
||||
evt *event.Event,
|
||||
) EventHandlingResult {
|
||||
if origSender != nil {
|
||||
return EventHandlingResultFailed.WithMSSError(ErrIgnoringAcceptRequestRelayedUser)
|
||||
}
|
||||
log := zerolog.Ctx(ctx)
|
||||
content, ok := evt.Content.Parsed.(*event.BeeperAcceptMessageRequestEventContent)
|
||||
if !ok {
|
||||
log.Error().Type("content_type", evt.Content.Parsed).Msg("Unexpected parsed content type")
|
||||
return EventHandlingResultFailed.WithMSSError(fmt.Errorf("%w: %T", ErrUnexpectedParsedContentType, evt.Content.Parsed))
|
||||
}
|
||||
api, ok := sender.Client.(MessageRequestAcceptingNetworkAPI)
|
||||
if !ok {
|
||||
return EventHandlingResultIgnored.WithMSSError(ErrDeleteChatNotSupported)
|
||||
}
|
||||
err := api.HandleMatrixAcceptMessageRequest(ctx, &MatrixAcceptMessageRequest{
|
||||
Event: evt,
|
||||
Content: content,
|
||||
Portal: portal,
|
||||
})
|
||||
if err != nil {
|
||||
log.Err(err).Msg("Failed to handle Matrix accept message request")
|
||||
return EventHandlingResultFailed.WithMSSError(err)
|
||||
}
|
||||
if portal.MessageRequest {
|
||||
portal.MessageRequest = false
|
||||
portal.UpdateBridgeInfo(ctx)
|
||||
err = portal.Save(ctx)
|
||||
if err != nil {
|
||||
log.Err(err).Msg("Failed to save portal after accepting message request")
|
||||
}
|
||||
}
|
||||
return EventHandlingResultSuccess.WithMSS()
|
||||
}
|
||||
|
||||
func (portal *Portal) handleMatrixDeleteChat(
|
||||
ctx context.Context,
|
||||
sender *UserLogin,
|
||||
|
|
@ -3948,9 +3989,9 @@ type ChatInfo struct {
|
|||
Disappear *database.DisappearingSetting
|
||||
ParentID *networkid.PortalID
|
||||
|
||||
UserLocal *UserLocalPortalInfo
|
||||
|
||||
CanBackfill bool
|
||||
UserLocal *UserLocalPortalInfo
|
||||
MessageRequest *bool
|
||||
CanBackfill bool
|
||||
|
||||
ExcludeChangesFromTimeline bool
|
||||
|
||||
|
|
@ -4070,10 +4111,11 @@ func (portal *Portal) getBridgeInfo() (string, event.BridgeEventContent) {
|
|||
Creator: portal.Bridge.Bot.GetMXID(),
|
||||
Protocol: portal.Bridge.Network.GetName().AsBridgeInfoSection(),
|
||||
Channel: event.BridgeInfoSection{
|
||||
ID: string(portal.ID),
|
||||
DisplayName: portal.Name,
|
||||
AvatarURL: portal.AvatarMXC,
|
||||
Receiver: string(portal.Receiver),
|
||||
ID: string(portal.ID),
|
||||
DisplayName: portal.Name,
|
||||
AvatarURL: portal.AvatarMXC,
|
||||
Receiver: string(portal.Receiver),
|
||||
MessageRequest: portal.MessageRequest,
|
||||
// TODO external URL?
|
||||
},
|
||||
BeeperRoomTypeV2: string(portal.RoomType),
|
||||
|
|
@ -4815,6 +4857,10 @@ func (portal *Portal) UpdateInfo(ctx context.Context, info *ChatInfo, source *Us
|
|||
portal.RoomType = *info.Type
|
||||
}
|
||||
}
|
||||
if info.MessageRequest != nil && *info.MessageRequest != portal.MessageRequest {
|
||||
changed = true
|
||||
portal.MessageRequest = *info.MessageRequest
|
||||
}
|
||||
if info.Members != nil && portal.MXID != "" && source != nil {
|
||||
err := portal.syncParticipants(ctx, info.Members, source, nil, time.Time{})
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -89,7 +89,11 @@ type BeeperRoomKeyAckEventContent struct {
|
|||
}
|
||||
|
||||
type BeeperChatDeleteEventContent struct {
|
||||
DeleteForEveryone bool `json:"delete_for_everyone,omitempty"`
|
||||
DeleteForEveryone bool `json:"delete_for_everyone,omitempty"`
|
||||
FromMessageRequest bool `json:"from_message_request,omitempty"`
|
||||
}
|
||||
|
||||
type BeeperAcceptMessageRequestEventContent struct {
|
||||
}
|
||||
|
||||
type BeeperSendStateEventContent struct {
|
||||
|
|
|
|||
5
event/capabilities.d.ts
vendored
5
event/capabilities.d.ts
vendored
|
|
@ -77,6 +77,11 @@ export interface RoomFeatures {
|
|||
delete_chat?: boolean
|
||||
/** Whether deleting the chat for all participants is supported. */
|
||||
delete_chat_for_everyone?: boolean
|
||||
/** What can be done with message requests? */
|
||||
message_request?: {
|
||||
accept_with_message?: CapabilitySupportLevel
|
||||
accept_with_button?: CapabilitySupportLevel
|
||||
}
|
||||
}
|
||||
|
||||
declare type integer = number
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@ type RoomFeatures struct {
|
|||
DeleteChat bool `json:"delete_chat,omitempty"`
|
||||
DeleteChatForEveryone bool `json:"delete_chat_for_everyone,omitempty"`
|
||||
|
||||
MessageRequest *MessageRequestFeatures `json:"message_request,omitempty"`
|
||||
|
||||
PerMessageProfileRelay bool `json:"-"`
|
||||
}
|
||||
|
||||
|
|
@ -84,6 +86,7 @@ func (rf *RoomFeatures) Clone() *RoomFeatures {
|
|||
clone.DeleteMaxAge = ptr.Clone(clone.DeleteMaxAge)
|
||||
clone.DisappearingTimer = clone.DisappearingTimer.Clone()
|
||||
clone.AllowedReactions = slices.Clone(clone.AllowedReactions)
|
||||
clone.MessageRequest = clone.MessageRequest.Clone()
|
||||
return &clone
|
||||
}
|
||||
|
||||
|
|
@ -165,6 +168,25 @@ func (dtc *DisappearingTimerCapability) Supports(content *BeeperDisappearingTime
|
|||
return slices.Contains(dtc.Types, content.Type) && (dtc.Timers == nil || slices.Contains(dtc.Timers, content.Timer))
|
||||
}
|
||||
|
||||
type MessageRequestFeatures struct {
|
||||
AcceptWithMessage CapabilitySupportLevel `json:"accept_with_message,omitempty"`
|
||||
AcceptWithButton CapabilitySupportLevel `json:"accept_with_button,omitempty"`
|
||||
}
|
||||
|
||||
func (mrf *MessageRequestFeatures) Clone() *MessageRequestFeatures {
|
||||
return ptr.Clone(mrf)
|
||||
}
|
||||
|
||||
func (mrf *MessageRequestFeatures) Hash() []byte {
|
||||
if mrf == nil {
|
||||
return nil
|
||||
}
|
||||
hasher := sha256.New()
|
||||
hashValue(hasher, "accept_with_message", mrf.AcceptWithMessage)
|
||||
hashValue(hasher, "accept_with_button", mrf.AcceptWithButton)
|
||||
return hasher.Sum(nil)
|
||||
}
|
||||
|
||||
type CapabilityMsgType = MessageType
|
||||
|
||||
// Message types which are used for event capability signaling, but aren't real values for the msgtype field.
|
||||
|
|
@ -347,6 +369,7 @@ func (rf *RoomFeatures) Hash() []byte {
|
|||
hashBool(hasher, "mark_as_unread", rf.MarkAsUnread)
|
||||
hashBool(hasher, "delete_chat", rf.DeleteChat)
|
||||
hashBool(hasher, "delete_chat_for_everyone", rf.DeleteChatForEveryone)
|
||||
hashValue(hasher, "message_request", rf.MessageRequest)
|
||||
|
||||
return hasher.Sum(nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,10 +61,11 @@ var TypeMap = map[Type]reflect.Type{
|
|||
EventUnstablePollStart: reflect.TypeOf(PollStartEventContent{}),
|
||||
EventUnstablePollResponse: reflect.TypeOf(PollResponseEventContent{}),
|
||||
|
||||
BeeperMessageStatus: reflect.TypeOf(BeeperMessageStatusEventContent{}),
|
||||
BeeperTranscription: reflect.TypeOf(BeeperTranscriptionEventContent{}),
|
||||
BeeperDeleteChat: reflect.TypeOf(BeeperChatDeleteEventContent{}),
|
||||
BeeperSendState: reflect.TypeOf(BeeperSendStateEventContent{}),
|
||||
BeeperMessageStatus: reflect.TypeOf(BeeperMessageStatusEventContent{}),
|
||||
BeeperTranscription: reflect.TypeOf(BeeperTranscriptionEventContent{}),
|
||||
BeeperDeleteChat: reflect.TypeOf(BeeperChatDeleteEventContent{}),
|
||||
BeeperAcceptMessageRequest: reflect.TypeOf(BeeperAcceptMessageRequestEventContent{}),
|
||||
BeeperSendState: reflect.TypeOf(BeeperSendStateEventContent{}),
|
||||
|
||||
AccountDataRoomTags: reflect.TypeOf(TagEventContent{}),
|
||||
AccountDataDirectChats: reflect.TypeOf(DirectChatsEventContent{}),
|
||||
|
|
|
|||
|
|
@ -231,7 +231,8 @@ type BridgeInfoSection struct {
|
|||
AvatarURL id.ContentURIString `json:"avatar_url,omitempty"`
|
||||
ExternalURL string `json:"external_url,omitempty"`
|
||||
|
||||
Receiver string `json:"fi.mau.receiver,omitempty"`
|
||||
Receiver string `json:"fi.mau.receiver,omitempty"`
|
||||
MessageRequest bool `json:"com.beeper.message_request,omitempty"`
|
||||
}
|
||||
|
||||
// BridgeEventContent represents the content of a m.bridge state event.
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ func (et *Type) GuessClass() TypeClass {
|
|||
InRoomVerificationKey.Type, InRoomVerificationMAC.Type, InRoomVerificationCancel.Type,
|
||||
CallInvite.Type, CallCandidates.Type, CallAnswer.Type, CallReject.Type, CallSelectAnswer.Type,
|
||||
CallNegotiate.Type, CallHangup.Type, BeeperMessageStatus.Type, EventUnstablePollStart.Type, EventUnstablePollResponse.Type,
|
||||
EventUnstablePollEnd.Type, BeeperTranscription.Type, BeeperDeleteChat.Type:
|
||||
EventUnstablePollEnd.Type, BeeperTranscription.Type, BeeperDeleteChat.Type, BeeperAcceptMessageRequest.Type:
|
||||
return MessageEventType
|
||||
case ToDeviceRoomKey.Type, ToDeviceRoomKeyRequest.Type, ToDeviceForwardedRoomKey.Type, ToDeviceRoomKeyWithheld.Type,
|
||||
ToDeviceBeeperRoomKeyAck.Type:
|
||||
|
|
@ -234,10 +234,11 @@ var (
|
|||
CallNegotiate = Type{"m.call.negotiate", MessageEventType}
|
||||
CallHangup = Type{"m.call.hangup", MessageEventType}
|
||||
|
||||
BeeperMessageStatus = Type{"com.beeper.message_send_status", MessageEventType}
|
||||
BeeperTranscription = Type{"com.beeper.transcription", MessageEventType}
|
||||
BeeperDeleteChat = Type{"com.beeper.delete_chat", MessageEventType}
|
||||
BeeperSendState = Type{"com.beeper.send_state", MessageEventType}
|
||||
BeeperMessageStatus = Type{"com.beeper.message_send_status", MessageEventType}
|
||||
BeeperTranscription = Type{"com.beeper.transcription", MessageEventType}
|
||||
BeeperDeleteChat = Type{"com.beeper.delete_chat", MessageEventType}
|
||||
BeeperAcceptMessageRequest = Type{"com.beeper.accept_message_request", MessageEventType}
|
||||
BeeperSendState = Type{"com.beeper.send_state", MessageEventType}
|
||||
|
||||
EventUnstablePollStart = Type{Type: "org.matrix.msc3381.poll.start", Class: MessageEventType}
|
||||
EventUnstablePollResponse = Type{Type: "org.matrix.msc3381.poll.response", Class: MessageEventType}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue