bridgev2

package
v0.20.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 16, 2024 License: MPL-2.0 Imports: 35 Imported by: 21

Documentation

Index

Constants

View Source
const BackfillMinBackoffAfterRoomCreate = 1 * time.Minute
View Source
const BackfillQueueErrorBackoff = 1 * time.Minute
View Source
const BackfillQueueMaxEmptyBackoff = 10 * time.Minute
View Source
const DisappearCheckInterval = 1 * time.Hour
View Source
const PortalEventBuffer = 64

Variables

View Source
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)
	ErrEditsNotSupported               error = WrapErrorInStatus(errors.New("this bridge does not support edits")).WithIsCertain(true).WithErrorAsMessage()
	ErrEditsNotSupportedInPortal       error = WrapErrorInStatus(errors.New("edits are not allowed in this chat")).WithIsCertain(true).WithErrorAsMessage()
	ErrCaptionsNotAllowed              error = WrapErrorInStatus(errors.New("captions are not supported here")).WithIsCertain(true).WithErrorAsMessage()
	ErrLocationMessagesNotAllowed      error = WrapErrorInStatus(errors.New("location messages are not supported here")).WithIsCertain(true).WithErrorAsMessage()
	ErrEditTargetTooOld                error = WrapErrorInStatus(errors.New("the message is too old to be edited")).WithIsCertain(true).WithErrorAsMessage()
	ErrEditTargetTooManyEdits          error = WrapErrorInStatus(errors.New("the message has been edited too many times")).WithIsCertain(true).WithErrorAsMessage()
	ErrReactionsNotSupported           error = WrapErrorInStatus(errors.New("this bridge does not support reactions")).WithIsCertain(true).WithErrorAsMessage()
	ErrRoomMetadataNotSupported        error = WrapErrorInStatus(errors.New("this bridge does not support changing room metadata")).WithIsCertain(true).WithErrorAsMessage().WithSendNotice(false)
	ErrRedactionsNotSupported          error = WrapErrorInStatus(errors.New("this bridge does not support deleting messages")).WithIsCertain(true).WithErrorAsMessage()
	ErrUnexpectedParsedContentType     error = WrapErrorInStatus(errors.New("unexpected parsed content type")).WithErrorAsMessage().WithIsCertain(true).WithSendNotice(true)
	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)
	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)
	ErrPowerLevelsNotSupported         error = WrapErrorInStatus(errors.New("this bridge does not support changing group power levels")).WithIsCertain(true).WithErrorAsMessage().WithSendNotice(false)
)

Common message status errors

View Source
var (
	AcceptInvite  = MembershipChangeType{From: event.MembershipInvite, To: event.MembershipJoin, IsSelf: true}
	RevokeInvite  = MembershipChangeType{From: event.MembershipInvite, To: event.MembershipLeave}
	RejectInvite  = MembershipChangeType{From: event.MembershipInvite, To: event.MembershipLeave, IsSelf: true}
	BanInvited    = MembershipChangeType{From: event.MembershipInvite, To: event.MembershipBan}
	ProfileChange = MembershipChangeType{From: event.MembershipJoin, To: event.MembershipJoin, IsSelf: true}
	Leave         = MembershipChangeType{From: event.MembershipJoin, To: event.MembershipLeave, IsSelf: true}
	Kick          = MembershipChangeType{From: event.MembershipJoin, To: event.MembershipLeave}
	BanJoined     = MembershipChangeType{From: event.MembershipJoin, To: event.MembershipBan}
	Invite        = MembershipChangeType{From: event.MembershipLeave, To: event.MembershipInvite}
	Join          = MembershipChangeType{From: event.MembershipLeave, To: event.MembershipJoin}
	BanLeft       = MembershipChangeType{From: event.MembershipLeave, To: event.MembershipBan}
	Knock         = MembershipChangeType{From: event.MembershipLeave, To: event.MembershipKnock, IsSelf: true}
	AcceptKnock   = MembershipChangeType{From: event.MembershipKnock, To: event.MembershipInvite}
	RejectKnock   = MembershipChangeType{From: event.MembershipKnock, To: event.MembershipLeave}
	RetractKnock  = MembershipChangeType{From: event.MembershipKnock, To: event.MembershipLeave, IsSelf: true}
	BanKnocked    = MembershipChangeType{From: event.MembershipKnock, To: event.MembershipBan}
	Unban         = MembershipChangeType{From: event.MembershipBan, To: event.MembershipLeave}
)
View Source
var ErrDirectMediaNotEnabled = errors.New("direct media is not enabled")

ErrDirectMediaNotEnabled may be returned by Matrix connectors if [MatrixConnector.GenerateContentURI] is called, but direct media is not enabled.

View Source
var ErrIgnoringRemoteEvent = errors.New("ignoring remote event")

ErrIgnoringRemoteEvent can be returned by [RemoteMessage.ConvertMessage] or [RemoteEdit.ConvertEdit] to indicate that the event should be ignored after all. Handling the event will be cancelled immediately.

View Source
var ErrNoStatus = errors.New("omit message status")

ErrNoStatus can be returned by [MatrixMessageResponse.HandleEcho] to indicate that the message is still in-flight and a status should not be sent yet. The message will still be saved into the database.

View Source
var ErrNotLoggedIn = errors.New("not logged in")
View Source
var ErrResolveIdentifierTryNext = errors.New("that identifier is not available via this login")

ErrResolveIdentifierTryNext can be returned by ResolveIdentifier to signal that the identifier is valid, but can't be reached by the current login, and the caller should try the next login if there are more.

This should generally only be returned when resolving internal IDs (which happens when initiating chats via Matrix). For example, Google Messages would return this when trying to resolve another login's user ID, and Telegram would return this when the access hash isn't available.

View Source
var Unmuted = time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)

Functions

func CleanNonInternationalPhoneNumber added in v0.20.0

func CleanNonInternationalPhoneNumber(phone string) (string, error)

func CleanPhoneNumber

func CleanPhoneNumber(phone string) (string, error)

func DeleteManyPortals added in v0.20.0

func DeleteManyPortals(ctx context.Context, portals []*Portal, errorCallback func(portal *Portal, delete bool, err error))

Types

type APNsPushConfig

type APNsPushConfig struct {
	BundleID string `json:"bundle_id"`
}

type Avatar

type Avatar struct {
	ID     networkid.AvatarID
	Get    func(ctx context.Context) ([]byte, error)
	Remove bool

	// For pre-uploaded avatars, the MXC URI and hash can be provided directly
	MXC  id.ContentURIString
	Hash [32]byte
}

func (*Avatar) Reupload

func (a *Avatar) Reupload(ctx context.Context, intent MatrixAPI, currentHash [32]byte, currentMXC id.ContentURIString) (id.ContentURIString, [32]byte, error)

type BackfillMessage

type BackfillMessage struct {
	*ConvertedMessage
	Sender      EventSender
	ID          networkid.MessageID
	TxnID       networkid.TransactionID
	Timestamp   time.Time
	StreamOrder int64
	Reactions   []*BackfillReaction

	ShouldBackfillThread bool
	LastThreadMessage    networkid.MessageID
}

BackfillMessage is an individual message in a history pagination request.

type BackfillReaction

type BackfillReaction struct {
	// Optional part of the message that the reaction targets.
	// If nil, the reaction targets the first part of the message.
	TargetPart *networkid.PartID
	// Optional timestamp for the reaction.
	// If unset, the reaction will have a fake timestamp that is slightly after the message timestamp.
	Timestamp time.Time

	Sender       EventSender
	EmojiID      networkid.EmojiID
	Emoji        string
	ExtraContent map[string]any
	DBMetadata   any
}

BackfillReaction is an individual reaction to a message in a history pagination request.

The target message is always the BackfillMessage that contains this item. Optionally, the reaction can target a specific part by specifying TargetPart. If not specified, the first part (sorted lexicographically) is targeted.

type BackfillingNetworkAPI

type BackfillingNetworkAPI interface {
	NetworkAPI
	FetchMessages(ctx context.Context, fetchParams FetchMessagesParams) (*FetchMessagesResponse, error)
}

BackfillingNetworkAPI is an optional interface that network connectors can implement to support backfilling message history.

type BackfillingNetworkAPIWithLimits added in v0.20.0

type BackfillingNetworkAPIWithLimits interface {
	BackfillingNetworkAPI
	GetBackfillMaxBatchCount(ctx context.Context, portal *Portal, task *database.BackfillTask) int
}

type Bridge

type Bridge struct {
	ID  networkid.BridgeID
	DB  *database.Database
	Log zerolog.Logger

	Matrix   MatrixConnector
	Bot      MatrixAPI
	Network  NetworkConnector
	Commands CommandProcessor
	Config   *bridgeconfig.BridgeConfig

	DisappearLoop *DisappearLoop
	// contains filtered or unexported fields
}

func NewBridge

func NewBridge(
	bridgeID networkid.BridgeID,
	db *dbutil.Database,
	log zerolog.Logger,
	cfg *bridgeconfig.BridgeConfig,
	matrix MatrixConnector,
	network NetworkConnector,
	newCommandProcessor func(*Bridge) CommandProcessor,
) *Bridge

func (*Bridge) FindCachedPortalReceiver

func (br *Bridge) FindCachedPortalReceiver(id networkid.PortalID, maybeReceiver networkid.UserLoginID) networkid.PortalKey

func (*Bridge) FindPortalReceiver

func (br *Bridge) FindPortalReceiver(ctx context.Context, id networkid.PortalID, maybeReceiver networkid.UserLoginID) (networkid.PortalKey, error)

func (*Bridge) GetAllPortals added in v0.20.0

func (br *Bridge) GetAllPortals(ctx context.Context) ([]*Portal, error)

func (*Bridge) GetAllPortalsWithMXID

func (br *Bridge) GetAllPortalsWithMXID(ctx context.Context) ([]*Portal, error)

func (*Bridge) GetCachedUserLoginByID

func (br *Bridge) GetCachedUserLoginByID(id networkid.UserLoginID) *UserLogin

func (*Bridge) GetCurrentBridgeStates

func (br *Bridge) GetCurrentBridgeStates() (states []status.BridgeState)

func (*Bridge) GetDMPortalsWith added in v0.20.0

func (br *Bridge) GetDMPortalsWith(ctx context.Context, otherUserID networkid.UserID) ([]*Portal, error)

func (*Bridge) GetExistingGhostByID added in v0.20.0

func (br *Bridge) GetExistingGhostByID(ctx context.Context, id networkid.UserID) (*Ghost, error)

func (*Bridge) GetExistingPortalByKey

func (br *Bridge) GetExistingPortalByKey(ctx context.Context, key networkid.PortalKey) (*Portal, error)

func (*Bridge) GetExistingUserByMXID

func (br *Bridge) GetExistingUserByMXID(ctx context.Context, userID id.UserID) (*User, error)

func (*Bridge) GetExistingUserLoginByID

func (br *Bridge) GetExistingUserLoginByID(ctx context.Context, id networkid.UserLoginID) (*UserLogin, error)

func (*Bridge) GetGhostByID

func (br *Bridge) GetGhostByID(ctx context.Context, id networkid.UserID) (*Ghost, error)

func (*Bridge) GetGhostByMXID

func (br *Bridge) GetGhostByMXID(ctx context.Context, mxid id.UserID) (*Ghost, error)

func (*Bridge) GetPortalByKey

func (br *Bridge) GetPortalByKey(ctx context.Context, key networkid.PortalKey) (*Portal, error)

func (*Bridge) GetPortalByMXID

func (br *Bridge) GetPortalByMXID(ctx context.Context, mxid id.RoomID) (*Portal, error)

func (*Bridge) GetUserByMXID

func (br *Bridge) GetUserByMXID(ctx context.Context, userID id.UserID) (*User, error)

func (*Bridge) GetUserLoginsInPortal

func (br *Bridge) GetUserLoginsInPortal(ctx context.Context, portal networkid.PortalKey) ([]*UserLogin, error)

func (*Bridge) IsGhostMXID added in v0.20.0

func (br *Bridge) IsGhostMXID(userID id.UserID) bool

func (*Bridge) NewBridgeStateQueue

func (br *Bridge) NewBridgeStateQueue(user status.StandaloneCustomBridgeStateFiller) *BridgeStateQueue

func (*Bridge) QueueMatrixEvent

func (br *Bridge) QueueMatrixEvent(ctx context.Context, evt *event.Event)

func (*Bridge) QueueRemoteEvent

func (br *Bridge) QueueRemoteEvent(login *UserLogin, evt RemoteEvent)

func (*Bridge) ReIDPortal

func (br *Bridge) ReIDPortal(ctx context.Context, source, target networkid.PortalKey) (ReIDResult, *Portal, error)

func (*Bridge) RunBackfillQueue added in v0.20.0

func (br *Bridge) RunBackfillQueue()

func (*Bridge) SendGlobalBridgeState

func (br *Bridge) SendGlobalBridgeState(state status.BridgeState)

func (*Bridge) Start

func (br *Bridge) Start() error

func (*Bridge) StartConnectors added in v0.20.0

func (br *Bridge) StartConnectors() error

func (*Bridge) StartLogins added in v0.20.0

func (br *Bridge) StartLogins() error

func (*Bridge) Stop

func (br *Bridge) Stop()

func (*Bridge) UnlockedGetPortalByKey

func (br *Bridge) UnlockedGetPortalByKey(ctx context.Context, key networkid.PortalKey, onlyIfExists bool) (*Portal, error)

func (*Bridge) WakeupBackfillQueue added in v0.20.0

func (br *Bridge) WakeupBackfillQueue()

type BridgeName

type BridgeName struct {
	// The displayname of the network, e.g. `Discord`
	DisplayName string `json:"displayname"`
	// The URL to the website of the network, e.g. `https://discord.com`
	NetworkURL string `json:"network_url"`
	// The icon of the network as a mxc:// URI
	NetworkIcon id.ContentURIString `json:"network_icon"`
	// An identifier uniquely identifying the network, e.g. `discord`
	NetworkID string `json:"network_id"`
	// An identifier uniquely identifying the bridge software.
	// The Go import path is a good choice here (e.g. github.com/octocat/discordbridge)
	BeeperBridgeType string `json:"beeper_bridge_type"`
	// The default appservice port to use in the example config, defaults to 8080 if unset
	// Official mautrix bridges will use ports defined in https://mau.fi/ports
	DefaultPort uint16 `json:"default_port,omitempty"`
	// The default command prefix to use in the example config, defaults to NetworkID if unset. Must include the ! prefix.
	DefaultCommandPrefix string `json:"default_command_prefix,omitempty"`
}

BridgeName contains information about the network that a connector bridges to.

func (BridgeName) AsBridgeInfoSection

func (bn BridgeName) AsBridgeInfoSection() event.BridgeInfoSection

type BridgeStateQueue

type BridgeStateQueue struct {
	// contains filtered or unexported fields
}

func (*BridgeStateQueue) Destroy

func (bsq *BridgeStateQueue) Destroy()

func (*BridgeStateQueue) GetPrev

func (bsq *BridgeStateQueue) GetPrev() status.BridgeState

func (*BridgeStateQueue) GetPrevUnsent added in v0.20.0

func (bsq *BridgeStateQueue) GetPrevUnsent() status.BridgeState

func (*BridgeStateQueue) Send

func (bsq *BridgeStateQueue) Send(state status.BridgeState)

func (*BridgeStateQueue) SetPrev

func (bsq *BridgeStateQueue) SetPrev(prev status.BridgeState)

type ChatInfo

type ChatInfo struct {
	Name   *string
	Topic  *string
	Avatar *Avatar

	Members  *ChatMemberList
	JoinRule *event.JoinRulesEventContent

	Type      *database.RoomType
	Disappear *database.DisappearingSetting
	ParentID  *networkid.PortalID

	UserLocal *UserLocalPortalInfo

	CanBackfill bool

	ExtraUpdates ExtraUpdater[*Portal]
}

type ChatInfoChange

type ChatInfoChange struct {
	// The chat info that changed. Any fields that did not change can be left as nil.
	ChatInfo *ChatInfo
	// A list of member changes.
	// This list should only include changes, not the whole member list.
	// To resync the whole list, use the field inside ChatInfo.
	MemberChanges *ChatMemberList
}

type ChatMember

type ChatMember struct {
	EventSender
	Membership event.Membership
	Nickname   *string
	PowerLevel *int
	UserInfo   *UserInfo

	PrevMembership event.Membership
}

type ChatMemberList

type ChatMemberList struct {
	// Whether this is the full member list.
	// If true, any extra members not listed here will be removed from the portal.
	IsFull bool
	// Should the bridge call IsThisUser for every member in the list?
	// This should be used when SenderLogin can't be filled accurately.
	CheckAllLogins bool

	// The total number of members in the chat, regardless of how many of those members are included in Members.
	TotalMemberCount int

	// For DM portals, the ID of the recipient user.
	// This field is optional and will be automatically filled from Members if there are only 2 entries in the list.
	OtherUserID networkid.UserID

	Members     []ChatMember
	PowerLevels *PowerLevelOverrides
}

type CommandProcessor

type CommandProcessor interface {
	Handle(ctx context.Context, roomID id.RoomID, eventID id.EventID, user *User, message string, replyTo id.EventID)
}

type ConfigValidatingNetwork

type ConfigValidatingNetwork interface {
	NetworkConnector
	ValidateConfig() error
}

ConfigValidatingNetwork is an optional interface that network connectors can implement to validate config fields before the bridge is started.

When the ValidateConfig method is called, the config data will already be unmarshaled into the object returned by [NetworkConnector.GetConfig].

This mechanism is usually used to refuse bridge startup if a mandatory field has an invalid value.

type ContactListingNetworkAPI

type ContactListingNetworkAPI interface {
	NetworkAPI
	GetContactList(ctx context.Context) ([]*ResolveIdentifierResponse, error)
}

ContactListingNetworkAPI is an optional interface that network connectors can implement to provide the user's contact list.

type ConvertedEdit

type ConvertedEdit struct {
	ModifiedParts []*ConvertedEditPart
	DeletedParts  []*database.Message
	// Warning: added parts will be sent at the end of the room.
	// If other messages have been sent after the message being edited,
	// these new parts will not be next to the existing parts.
	AddedParts *ConvertedMessage
}

type ConvertedEditPart

type ConvertedEditPart struct {
	Part *database.Message

	Type event.Type
	// The Content and Extra fields will be put inside `m.new_content` automatically.
	// SetEdit must NOT be called by the network connector.
	Content *event.MessageEventContent
	Extra   map[string]any
	// TopLevelExtra can be used to specify custom fields at the top level of the content rather than inside `m.new_content`.
	TopLevelExtra map[string]any
	// NewMentions can be used to specify new mentions that should ping the users again.
	// Mentions inside the edited content will not ping.
	NewMentions *event.Mentions

	DontBridge bool
}

type ConvertedMessage

type ConvertedMessage struct {
	ReplyTo    *networkid.MessageOptionalPartID
	ThreadRoot *networkid.MessageID
	Parts      []*ConvertedMessagePart
	Disappear  database.DisappearingSetting
}

func (*ConvertedMessage) MergeCaption

func (cm *ConvertedMessage) MergeCaption() bool

type ConvertedMessagePart

type ConvertedMessagePart struct {
	ID         networkid.PartID
	Type       event.Type
	Content    *event.MessageEventContent
	Extra      map[string]any
	DBMetadata any
	DontBridge bool
}

func MergeCaption

func MergeCaption(textPart, mediaPart *ConvertedMessagePart) *ConvertedMessagePart

func (*ConvertedMessagePart) ToEditPart

func (cmp *ConvertedMessagePart) ToEditPart(part *database.Message) *ConvertedEditPart

type CreateChatResponse

type CreateChatResponse struct {
	PortalKey networkid.PortalKey
	// Portal and PortalInfo are not required, the caller will fetch them automatically based on PortalKey if necessary.
	Portal     *Portal
	PortalInfo *ChatInfo
}

type DBUpgradeError

type DBUpgradeError struct {
	Err     error
	Section string
}

func (DBUpgradeError) Error

func (e DBUpgradeError) Error() string

func (DBUpgradeError) Unwrap

func (e DBUpgradeError) Unwrap() error

type DeleteOpts added in v0.20.0

type DeleteOpts struct {
	LogoutRemote     bool
	DontCleanupRooms bool
	// contains filtered or unexported fields
}

type DirectMediableNetwork

type DirectMediableNetwork interface {
	NetworkConnector
	SetUseDirectMedia()
	Download(ctx context.Context, mediaID networkid.MediaID) (mediaproxy.GetMediaResponse, error)
}

DirectMediableNetwork is an optional interface that network connectors can implement to support direct media access.

If the Matrix connector has direct media enabled, SetUseDirectMedia will be called before the Start method of the network connector. Download will then be called whenever someone wants to download a direct media `mxc://` URI which was generated by calling GenerateContentURI on the Matrix connector.

type DisappearLoop

type DisappearLoop struct {
	NextCheck time.Time
	// contains filtered or unexported fields
}

func (*DisappearLoop) Add

func (*DisappearLoop) Start

func (dl *DisappearLoop) Start()

func (*DisappearLoop) StartAll

func (dl *DisappearLoop) StartAll(ctx context.Context, roomID id.RoomID)

func (*DisappearLoop) Stop

func (dl *DisappearLoop) Stop()

type EditHandlingNetworkAPI

type EditHandlingNetworkAPI interface {
	NetworkAPI
	// HandleMatrixEdit is called when a previously bridged message is edited in a portal room.
	// The central bridge module will save the [*database.Message] after this function returns,
	// so the network connector is allowed to mutate the provided object.
	HandleMatrixEdit(ctx context.Context, msg *MatrixEdit) error
}

EditHandlingNetworkAPI is an optional interface that network connectors can implement to handle message edits.

type EventSender

type EventSender struct {
	// If IsFromMe is true, the UserLogin who the event was received through is used as the sender.
	// Double puppeting will be used if available.
	IsFromMe bool
	// SenderLogin is the ID of the UserLogin who sent the event. This may be different from the
	// login the event was received through. It is used to ensure double puppeting can still be
	// used even if the event is received through another login.
	SenderLogin networkid.UserLoginID
	// Sender is the remote user ID of the user who sent the event.
	// For new events, this will not be used for double puppeting.
	//
	// However, in the member list, [ChatMemberList.CheckAllLogins] can be specified to go through every login
	// and call [NetworkAPI.IsThisUser] to check if this ID belongs to that login. This method is not recommended,
	// it is better to fill the IsFromMe and SenderLogin fields appropriately.
	Sender networkid.UserID

	// ForceDMUser can be set if the event should be sent as the DM user even if the Sender is different.
	// This only applies in DM rooms where [database.Portal.OtherUserID] is set and is ignored if IsFromMe is true.
	// A warning will be logged if the sender is overridden due to this flag.
	ForceDMUser bool
}

EventSender represents a specific user in a chat.

type ExtraUpdater added in v0.20.0

type ExtraUpdater[T any] func(context.Context, T) bool

func MergeExtraUpdaters added in v0.20.0

func MergeExtraUpdaters[T any](funcs ...ExtraUpdater[T]) ExtraUpdater[T]

type FCMPushConfig

type FCMPushConfig struct {
	SenderID string `json:"sender_id"`
}

type FetchMessagesParams

type FetchMessagesParams struct {
	// The portal to fetch messages in. Always present.
	Portal *Portal
	// When fetching messages inside a thread, the ID of the thread.
	ThreadRoot networkid.MessageID
	// Whether to fetch new messages instead of old ones.
	Forward bool
	// The oldest known message in the thread or the portal. If Forward is true, this is the newest known message instead.
	// If the portal doesn't have any bridged messages, this will be nil.
	AnchorMessage *database.Message
	// The cursor returned by the previous call to FetchMessages with the same portal and thread root.
	// This will not be present in Forward calls.
	Cursor networkid.PaginationCursor
	// The preferred number of messages to return. The returned batch can be bigger or smaller
	// without any side effects, but the network connector should aim for this number.
	Count int

	// When a forward backfill is triggered by a [RemoteChatResyncBackfillBundle], this will contain
	// the bundled data returned by the event. It can be used as an optimization to avoid fetching
	// messages that were already provided by the remote network, while still supporting fetching
	// more messages if the limit is higher.
	BundledData any

	// When the messages are being fetched for a queued backfill, this is the task object.
	Task *database.BackfillTask
}

FetchMessagesParams contains the parameters for a message history pagination request.

type FetchMessagesResponse

type FetchMessagesResponse struct {
	// The messages to backfill. Messages should always be sorted in chronological order (oldest to newest).
	Messages []*BackfillMessage
	// The next cursor to use for fetching more messages.
	Cursor networkid.PaginationCursor
	// Whether there are more messages that can be backfilled.
	// This field is required. If it is false, FetchMessages will not be called again.
	HasMore bool
	// Whether the batch contains new messages rather than old ones.
	// Cursor, HasMore and the progress fields will be ignored when this is present.
	Forward bool
	// When sending forward backfill (or the first batch in a room), this field can be set
	// to mark the messages as read immediately after backfilling.
	MarkRead bool

	// Approximate backfill progress as a number between 0 and 1.
	ApproxProgress float64
	// Approximate number of messages remaining that can be backfilled.
	ApproxRemainingCount int
	// Approximate total number of messages in the chat.
	ApproxTotalCount int
}

FetchMessagesResponse contains the response for a message history pagination request.

type FileRestriction

type FileRestriction struct {
	MaxSize   int64
	MimeTypes []string
}

type Ghost

type Ghost struct {
	*database.Ghost
	Bridge *Bridge
	Log    zerolog.Logger
	Intent MatrixAPI
}

func (*Ghost) UpdateAvatar

func (ghost *Ghost) UpdateAvatar(ctx context.Context, avatar *Avatar) bool

func (*Ghost) UpdateContactInfo

func (ghost *Ghost) UpdateContactInfo(ctx context.Context, identifiers []string, isBot *bool) bool

func (*Ghost) UpdateInfo

func (ghost *Ghost) UpdateInfo(ctx context.Context, info *UserInfo)

func (*Ghost) UpdateInfoIfNecessary

func (ghost *Ghost) UpdateInfoIfNecessary(ctx context.Context, source *UserLogin, evtType RemoteEventType)

func (*Ghost) UpdateName

func (ghost *Ghost) UpdateName(ctx context.Context, name string) bool

type GhostOrUserLogin added in v0.20.0

type GhostOrUserLogin interface {
	// contains filtered or unexported methods
}

type GroupCreatingNetworkAPI

type GroupCreatingNetworkAPI interface {
	IdentifierResolvingNetworkAPI
	CreateGroup(ctx context.Context, name string, users ...networkid.UserID) (*CreateChatResponse, error)
}

type IdentifierResolvingNetworkAPI

type IdentifierResolvingNetworkAPI interface {
	NetworkAPI
	// ResolveIdentifier is called when the user wants to start a new chat.
	// This can happen via the `resolve-identifier` or `start-chat` bridge bot commands,
	// or the corresponding provisioning API endpoints.
	ResolveIdentifier(ctx context.Context, identifier string, createChat bool) (*ResolveIdentifierResponse, error)
}

IdentifierResolvingNetworkAPI is an optional interface that network connectors can implement to support starting new direct chats.

type IdentifierValidatingNetwork added in v0.20.0

type IdentifierValidatingNetwork interface {
	NetworkConnector
	ValidateUserID(id networkid.UserID) bool
}

type LoginCompleteParams

type LoginCompleteParams struct {
	UserLoginID networkid.UserLoginID `json:"user_login_id"`
	UserLogin   *UserLogin            `json:"-"`
}

type LoginCookieField added in v0.20.0

type LoginCookieField struct {
	// The key in the map that is submitted to the connector.
	ID       string `json:"id"`
	Required bool   `json:"required"`
	// The sources that can be used to acquire the field value. Only one of these needs to be used.
	Sources []LoginCookieFieldSource `json:"sources"`
	// A regex pattern that the client can use to validate value client-side.
	Pattern string `json:"pattern,omitempty"`
}

type LoginCookieFieldSource added in v0.20.0

type LoginCookieFieldSource struct {
	// The type of source.
	Type LoginCookieFieldSourceType `json:"type"`
	// The name of the field. The exact meaning depends on the type of source.
	// Cookie:         cookie name
	// Local storage:  key in local storage
	// Request header: header name
	// Request body:   field name inside body after it's parsed (as JSON or multipart form data)
	// Special:        a namespaced identifier that clients can implement special handling for
	Name string `json:"name"`

	// For request header & body types, a regex matching request URLs where the value can be extracted from.
	RequestURLRegex string `json:"request_url_regex,omitempty"`
	// For cookie types, the domain the cookie is present on.
	CookieDomain string `json:"cookie_domain,omitempty"`
}

type LoginCookieFieldSourceType added in v0.20.0

type LoginCookieFieldSourceType string
const (
	LoginCookieTypeCookie        LoginCookieFieldSourceType = "cookie"
	LoginCookieTypeLocalStorage  LoginCookieFieldSourceType = "local_storage"
	LoginCookieTypeRequestHeader LoginCookieFieldSourceType = "request_header"
	LoginCookieTypeRequestBody   LoginCookieFieldSourceType = "request_body"
	LoginCookieTypeSpecial       LoginCookieFieldSourceType = "special"
)

type LoginCookiesParams

type LoginCookiesParams struct {
	URL       string `json:"url"`
	UserAgent string `json:"user_agent,omitempty"`

	// The fields that are needed for this cookie login.
	Fields []LoginCookieField `json:"fields"`
	// A JavaScript snippet that can extract some or all of the fields.
	// The snippet will evaluate to a promise that resolves when the relevant fields are found.
	// Fields that are not present in the promise result must be extracted another way.
	ExtractJS string `json:"extract_js,omitempty"`
}

type LoginDisplayAndWaitParams

type LoginDisplayAndWaitParams struct {
	// The type of thing to display (QR, emoji or text code)
	Type LoginDisplayType `json:"type"`
	// The thing to display (raw data for QR, unicode emoji for emoji, plain string for code, omitted for nothing)
	Data string `json:"data,omitempty"`
	// An image containing the thing to display. If present, this is recommended over using data directly.
	// For emojis, the URL to the canonical image representation of the emoji
	ImageURL string `json:"image_url,omitempty"`
}

type LoginDisplayType

type LoginDisplayType string
const (
	LoginDisplayTypeQR      LoginDisplayType = "qr"
	LoginDisplayTypeEmoji   LoginDisplayType = "emoji"
	LoginDisplayTypeCode    LoginDisplayType = "code"
	LoginDisplayTypeNothing LoginDisplayType = "nothing"
)

type LoginFlow

type LoginFlow struct {
	Name        string `json:"name"`
	Description string `json:"description"`
	ID          string `json:"id"`
}

type LoginInputDataField

type LoginInputDataField struct {
	// The type of input field as a hint for the client.
	Type LoginInputFieldType `json:"type"`
	// The ID of the field to be used as the key in the map that is submitted to the connector.
	ID string `json:"id"`
	// The name of the field shown to the user.
	Name string `json:"name"`
	// The description of the field shown to the user.
	Description string `json:"description"`
	// A regex pattern that the client can use to validate input client-side.
	Pattern string `json:"pattern,omitempty"`
	// A function that validates the input and optionally cleans it up before it's submitted to the connector.
	Validate func(string) (string, error) `json:"-"`
}

func (*LoginInputDataField) FillDefaultValidate

func (f *LoginInputDataField) FillDefaultValidate()

type LoginInputFieldType

type LoginInputFieldType string
const (
	LoginInputFieldTypeUsername    LoginInputFieldType = "username"
	LoginInputFieldTypePassword    LoginInputFieldType = "password"
	LoginInputFieldTypePhoneNumber LoginInputFieldType = "phone_number"
	LoginInputFieldTypeEmail       LoginInputFieldType = "email"
	LoginInputFieldType2FACode     LoginInputFieldType = "2fa_code"
	LoginInputFieldTypeToken       LoginInputFieldType = "token"
)

type LoginProcess

type LoginProcess interface {
	// Start starts the process and returns the first step.
	//
	// For example, a network using QR login may connect to the network, fetch a QR code,
	// and return a DisplayAndWait-type step.
	//
	// This will only ever be called once.
	Start(ctx context.Context) (*LoginStep, error)
	// Cancel stops the login process and cleans up any resources.
	// No other methods will be called after cancel.
	//
	// Cancel will not be called if any other method returned an error:
	// errors are always treated as fatal and the process is assumed to be automatically cancelled.
	Cancel()
}

LoginProcess represents a single occurrence of a user logging into the remote network.

type LoginProcessCookies

type LoginProcessCookies interface {
	LoginProcess
	SubmitCookies(ctx context.Context, cookies map[string]string) (*LoginStep, error)
}

type LoginProcessDisplayAndWait

type LoginProcessDisplayAndWait interface {
	LoginProcess
	Wait(ctx context.Context) (*LoginStep, error)
}

type LoginProcessUserInput

type LoginProcessUserInput interface {
	LoginProcess
	SubmitUserInput(ctx context.Context, input map[string]string) (*LoginStep, error)
}

type LoginStep

type LoginStep struct {
	// The type of login step
	Type LoginStepType `json:"type"`
	// A unique ID for this step. The ID should be same for every login using the same flow,
	// but it should be different for different bridges and step types.
	//
	// For example, Telegram's QR scan followed by a 2-factor password
	// might use the IDs `fi.mau.telegram.qr` and `fi.mau.telegram.2fa_password`.
	StepID string `json:"step_id"`
	// Instructions contains human-readable instructions for completing the login step.
	Instructions string `json:"instructions"`

	DisplayAndWaitParams *LoginDisplayAndWaitParams `json:"display_and_wait,omitempty"`
	CookiesParams        *LoginCookiesParams        `json:"cookies,omitempty"`
	UserInputParams      *LoginUserInputParams      `json:"user_input,omitempty"`
	CompleteParams       *LoginCompleteParams       `json:"complete,omitempty"`
}

type LoginStepType

type LoginStepType string
const (
	LoginStepTypeUserInput      LoginStepType = "user_input"
	LoginStepTypeCookies        LoginStepType = "cookies"
	LoginStepTypeDisplayAndWait LoginStepType = "display_and_wait"
	LoginStepTypeComplete       LoginStepType = "complete"
)

type LoginSubmit

type LoginSubmit struct {
}

type LoginUserInputParams

type LoginUserInputParams struct {
	// The fields that the user needs to fill in.
	Fields []LoginInputDataField `json:"fields"`
}

type MarkAsDMMatrixAPI added in v0.20.0

type MarkAsDMMatrixAPI interface {
	MarkAsDM(ctx context.Context, roomID id.RoomID, otherUser id.UserID) error
}

type MarkedUnreadHandlingNetworkAPI added in v0.20.0

type MarkedUnreadHandlingNetworkAPI interface {
	NetworkAPI
	HandleMarkedUnread(ctx context.Context, msg *MatrixMarkedUnread) error
}

type MatrixAPI

type MatrixAPI interface {
	GetMXID() id.UserID

	SendMessage(ctx context.Context, roomID id.RoomID, eventType event.Type, content *event.Content, extra *MatrixSendExtra) (*mautrix.RespSendEvent, error)
	SendState(ctx context.Context, roomID id.RoomID, eventType event.Type, stateKey string, content *event.Content, ts time.Time) (*mautrix.RespSendEvent, error)
	MarkRead(ctx context.Context, roomID id.RoomID, eventID id.EventID, ts time.Time) error
	MarkUnread(ctx context.Context, roomID id.RoomID, unread bool) error
	MarkTyping(ctx context.Context, roomID id.RoomID, typingType TypingType, timeout time.Duration) error
	DownloadMedia(ctx context.Context, uri id.ContentURIString, file *event.EncryptedFileInfo) ([]byte, error)
	UploadMedia(ctx context.Context, roomID id.RoomID, data []byte, fileName, mimeType string) (url id.ContentURIString, file *event.EncryptedFileInfo, err error)

	SetDisplayName(ctx context.Context, name string) error
	SetAvatarURL(ctx context.Context, avatarURL id.ContentURIString) error
	SetExtraProfileMeta(ctx context.Context, data any) error

	CreateRoom(ctx context.Context, req *mautrix.ReqCreateRoom) (id.RoomID, error)
	DeleteRoom(ctx context.Context, roomID id.RoomID, puppetsOnly bool) error
	InviteUser(ctx context.Context, roomID id.RoomID, userID id.UserID) error
	EnsureJoined(ctx context.Context, roomID id.RoomID) error
	EnsureInvited(ctx context.Context, roomID id.RoomID, userID id.UserID) error

	TagRoom(ctx context.Context, roomID id.RoomID, tag event.RoomTag, isTagged bool) error
	MuteRoom(ctx context.Context, roomID id.RoomID, until time.Time) error
}

type MatrixCapabilities

type MatrixCapabilities struct {
	AutoJoinInvites bool
	BatchSending    bool
}

type MatrixConnector

type MatrixConnector interface {
	Init(*Bridge)
	Start(ctx context.Context) error
	Stop()

	GetCapabilities() *MatrixCapabilities

	ParseGhostMXID(userID id.UserID) (networkid.UserID, bool)
	GhostIntent(userID networkid.UserID) MatrixAPI
	NewUserIntent(ctx context.Context, userID id.UserID, accessToken string) (MatrixAPI, string, error)
	BotIntent() MatrixAPI

	SendBridgeStatus(ctx context.Context, state *status.BridgeState) error
	SendMessageStatus(ctx context.Context, status *MessageStatus, evt *MessageStatusEventInfo)

	GenerateContentURI(ctx context.Context, mediaID networkid.MediaID) (id.ContentURIString, error)

	GetPowerLevels(ctx context.Context, roomID id.RoomID) (*event.PowerLevelsEventContent, error)
	GetMembers(ctx context.Context, roomID id.RoomID) (map[id.UserID]*event.MemberEventContent, error)
	GetMemberInfo(ctx context.Context, roomID id.RoomID, userID id.UserID) (*event.MemberEventContent, error)

	BatchSend(ctx context.Context, roomID id.RoomID, req *mautrix.ReqBeeperBatchSend, extras []*MatrixSendExtra) (*mautrix.RespBeeperBatchSend, error)
	GenerateDeterministicEventID(roomID id.RoomID, portalKey networkid.PortalKey, messageID networkid.MessageID, partID networkid.PartID) id.EventID
	GenerateReactionEventID(roomID id.RoomID, targetMessage *database.Message, sender networkid.UserID, emojiID networkid.EmojiID) id.EventID

	ServerName() string
}

type MatrixConnectorWithNameDisambiguation added in v0.20.0

type MatrixConnectorWithNameDisambiguation interface {
	IsConfusableName(ctx context.Context, roomID id.RoomID, userID id.UserID, name string) ([]id.UserID, error)
}

type MatrixConnectorWithPostRoomBridgeHandling added in v0.20.0

type MatrixConnectorWithPostRoomBridgeHandling interface {
	HandleNewlyBridgedRoom(ctx context.Context, roomID id.RoomID) error
}

type MatrixConnectorWithPublicMedia added in v0.20.0

type MatrixConnectorWithPublicMedia interface {
	GetPublicMediaAddress(contentURI id.ContentURIString) string
}

type MatrixConnectorWithServer

type MatrixConnectorWithServer interface {
	GetPublicAddress() string
	GetRouter() *mux.Router
}

type MatrixEdit

type MatrixEdit struct {
	MatrixEventBase[*event.MessageEventContent]
	EditTarget *database.Message
}

type MatrixEventBase

type MatrixEventBase[ContentType any] struct {
	// The raw event being bridged.
	Event *event.Event
	// The parsed content struct of the event. Custom fields can be found in Event.Content.Raw.
	Content ContentType
	// The room where the event happened.
	Portal *Portal

	// The original sender user ID. Only present in case the event is being relayed (and Sender is not the same user).
	OrigSender *OrigSender
}

type MatrixMarkedUnread added in v0.20.0

type MatrixMarkedUnread = MatrixRoomMeta[*event.MarkedUnreadEventContent]

type MatrixMembershipChange added in v0.20.0

type MatrixMembershipChange struct {
	MatrixRoomMeta[*event.MemberEventContent]
	Target GhostOrUserLogin
	Type   MembershipChangeType

	// Deprecated: Use Target instead
	TargetGhost *Ghost
	// Deprecated: Use Target instead
	TargetUserLogin *UserLogin
}

type MatrixMessage

type MatrixMessage struct {
	MatrixEventBase[*event.MessageEventContent]
	ThreadRoot *database.Message
	ReplyTo    *database.Message
}

type MatrixMessageRemove

type MatrixMessageRemove struct {
	MatrixEventBase[*event.RedactionEventContent]
	TargetMessage *database.Message
}

type MatrixMessageResponse

type MatrixMessageResponse struct {
	DB *database.Message

	Pending    networkid.TransactionID
	HandleEcho func(RemoteMessage, *database.Message) (bool, error)
}

type MatrixMute added in v0.20.0

type MatrixReaction

type MatrixReaction struct {
	MatrixEventBase[*event.ReactionEventContent]
	TargetMessage *database.Message
	PreHandleResp *MatrixReactionPreResponse

	// When EmojiID is blank and there's already an existing reaction, this is the old reaction that is being overridden.
	ReactionToOverride *database.Reaction
	// When MaxReactions is >0 in the pre-response, this is the list of previous reactions that should be preserved.
	ExistingReactionsToKeep []*database.Reaction
}

type MatrixReactionPreResponse

type MatrixReactionPreResponse struct {
	SenderID     networkid.UserID
	EmojiID      networkid.EmojiID
	Emoji        string
	MaxReactions int
}

type MatrixReactionRemove

type MatrixReactionRemove struct {
	MatrixEventBase[*event.RedactionEventContent]
	TargetReaction *database.Reaction
}

type MatrixReadReceipt

type MatrixReadReceipt struct {
	Portal *Portal
	// The event ID that the receipt is targeting
	EventID id.EventID
	// The exact message that was read. This may be nil if the event ID isn't a message.
	ExactMessage *database.Message
	// The timestamp that the user has read up to. This is either the timestamp of the message
	// (if one is present) or the timestamp of the receipt.
	ReadUpTo time.Time
	// The ReadUpTo timestamp of the previous message
	LastRead time.Time
	// The receipt metadata.
	Receipt event.ReadReceipt
}

type MatrixRoomMeta

type MatrixRoomMeta[ContentType any] struct {
	MatrixEventBase[ContentType]
	PrevContent ContentType
}

type MatrixRoomTag added in v0.20.0

type MatrixRoomTag = MatrixRoomMeta[*event.TagEventContent]

type MatrixRoomTopic

type MatrixRoomTopic = MatrixRoomMeta[*event.TopicEventContent]

type MatrixSendExtra added in v0.20.0

type MatrixSendExtra struct {
	Timestamp    time.Time
	MessageMeta  *database.Message
	ReactionMeta *database.Reaction
	StreamOrder  int64
	PartIndex    int
}

type MatrixTyping

type MatrixTyping struct {
	Portal   *Portal
	IsTyping bool
	Type     TypingType
}

type MaxFileSizeingNetwork

type MaxFileSizeingNetwork interface {
	NetworkConnector
	SetMaxFileSize(maxSize int64)
}

MaxFileSizeingNetwork is an optional interface that network connectors can implement to find out the maximum file size that can be uploaded to Matrix.

The SetMaxFileSize will be called asynchronously soon after startup. Before the function is called, the connector may assume a default limit of 50 MiB.

type MembershipChangeType added in v0.20.0

type MembershipChangeType struct {
	From   event.Membership
	To     event.Membership
	IsSelf bool
}

type MembershipHandlingNetworkAPI added in v0.20.0

type MembershipHandlingNetworkAPI interface {
	NetworkAPI
	HandleMatrixMembership(ctx context.Context, msg *MatrixMembershipChange) (bool, error)
}

type MessageStatus

type MessageStatus struct {
	Step     status.MessageCheckpointStep
	RetryNum int

	Status        event.MessageStatus
	ErrorReason   event.MessageStatusReason
	DeliveredTo   []id.UserID
	InternalError error  // Internal error to be tracked in message checkpoints
	Message       string // Human-readable message shown to users

	ErrorAsMessage bool
	IsCertain      bool
	SendNotice     bool
	DisableMSS     bool
}

MessageStatus represents the status of a message. It also implements the error interface to allow network connectors to return errors which get translated into user-friendly error messages and/or status events.

func WrapErrorInStatus

func WrapErrorInStatus(err error) MessageStatus

func (MessageStatus) Error

func (ms MessageStatus) Error() string

func (*MessageStatus) ToCheckpoint

func (*MessageStatus) ToMSSEvent

func (*MessageStatus) ToNoticeEvent

func (MessageStatus) Unwrap

func (ms MessageStatus) Unwrap() error

func (MessageStatus) WithErrorAsMessage

func (ms MessageStatus) WithErrorAsMessage() MessageStatus

func (MessageStatus) WithErrorReason

func (ms MessageStatus) WithErrorReason(reason event.MessageStatusReason) MessageStatus

func (MessageStatus) WithIsCertain

func (ms MessageStatus) WithIsCertain(certain bool) MessageStatus

func (MessageStatus) WithMessage

func (ms MessageStatus) WithMessage(msg string) MessageStatus

func (MessageStatus) WithSendNotice

func (ms MessageStatus) WithSendNotice(send bool) MessageStatus

func (MessageStatus) WithStatus

func (ms MessageStatus) WithStatus(status event.MessageStatus) MessageStatus

func (MessageStatus) WithStep

type MessageStatusEventInfo

type MessageStatusEventInfo struct {
	RoomID      id.RoomID
	EventID     id.EventID
	EventType   event.Type
	MessageType event.MessageType
	Sender      id.UserID
	ThreadRoot  id.EventID
}

func StatusEventInfoFromEvent

func StatusEventInfoFromEvent(evt *event.Event) *MessageStatusEventInfo

type MuteHandlingNetworkAPI added in v0.20.0

type MuteHandlingNetworkAPI interface {
	NetworkAPI
	HandleMute(ctx context.Context, msg *MatrixMute) error
}

type NetworkAPI

type NetworkAPI interface {
	// Connect is called to actually connect to the remote network.
	// If there's no persistent connection, this may just check access token validity, or even do nothing at all.
	Connect(ctx context.Context) error
	// Disconnect should disconnect from the remote network.
	// A clean disconnection is preferred, but it should not take too long.
	Disconnect()
	// IsLoggedIn should return whether the access tokens in this NetworkAPI are valid.
	// This should not do any IO operations, it should only return cached data which is updated elsewhere.
	IsLoggedIn() bool
	// LogoutRemote should invalidate the access tokens in this NetworkAPI if possible
	// and disconnect from the remote network.
	LogoutRemote(ctx context.Context)

	// IsThisUser should return whether the given remote network user ID is the same as this login.
	// This is used when the bridge wants to convert a user login ID to a user ID.
	IsThisUser(ctx context.Context, userID networkid.UserID) bool
	// GetChatInfo returns info for a given chat. Any fields that are nil will be ignored and not processed at all,
	// while empty strings will change the relevant value in the room to be an empty string.
	// For example, a nil name will mean the room name is not changed, while an empty string name will remove the name.
	GetChatInfo(ctx context.Context, portal *Portal) (*ChatInfo, error)
	// GetUserInfo returns info for a given user. Like chat info, fields can be nil to skip them.
	GetUserInfo(ctx context.Context, ghost *Ghost) (*UserInfo, error)
	// GetCapabilities returns the bridging capabilities in a given room.
	// This can simply return a static list if the remote network has no per-chat capability differences,
	// but all calls will include the portal, because some networks do have per-chat differences.
	GetCapabilities(ctx context.Context, portal *Portal) *NetworkRoomCapabilities

	// HandleMatrixMessage is called when a message is sent from Matrix in an existing portal room.
	// This function should convert the message as appropriate, send it over to the remote network,
	// and return the info so the central bridge can store it in the database.
	//
	// This is only called for normal non-edit messages. For other types of events, see the optional extra interfaces (`XHandlingNetworkAPI`).
	HandleMatrixMessage(ctx context.Context, msg *MatrixMessage) (message *MatrixMessageResponse, err error)
}

NetworkAPI is an interface representing a remote network client for a single user login.

Implementations of this interface are stored in [UserLogin.Client]. The [NetworkConnector.LoadUserLogin] method is responsible for filling the Client field with a NetworkAPI.

type NetworkConnector

type NetworkConnector interface {
	// Init is called when the bridge is initialized. The connector should store the bridge instance for later use.
	// This should not do any network calls or other blocking operations.
	Init(*Bridge)
	// Start is called when the bridge is starting.
	// The connector should do any non-user-specific startup actions necessary.
	// User logins will be loaded separately, so the connector should not load them here.
	Start(context.Context) error

	// GetName returns the name of the bridge and some additional metadata,
	// which is used to fill `m.bridge` events among other things.
	//
	// The first call happens *before* the config is loaded, because the data here is also used to
	// fill parts of the example config (like the default username template and bot localpart).
	// The output can still be adjusted based on config variables, but the function must have
	// default values when called without a config.
	GetName() BridgeName
	// GetDBMetaTypes returns struct types that are used to store connector-specific metadata in various tables.
	// All fields are optional. If a field isn't provided, then the corresponding table will have no custom metadata.
	// This will be called before Init, it should have a hardcoded response.
	GetDBMetaTypes() database.MetaTypes
	// GetCapabilities returns the general capabilities of the network connector.
	// Note that most capabilities are scoped to rooms and are returned by [NetworkAPI.GetCapabilities] instead.
	GetCapabilities() *NetworkGeneralCapabilities
	// GetConfig returns all the parts of the network connector's config file. Specifically:
	// - example: a string containing an example config file
	// - data: an interface to unmarshal the actual config into
	// - upgrader: a config upgrader to ensure all fields are present and to do any migrations from old configs
	GetConfig() (example string, data any, upgrader configupgrade.Upgrader)

	// LoadUserLogin is called when a UserLogin is loaded from the database in order to fill the [UserLogin.Client] field.
	//
	// This is called within the bridge's global cache lock, so it must not do any slow operations,
	// such as connecting to the network. Instead, connecting should happen when [NetworkAPI.Connect] is called later.
	LoadUserLogin(ctx context.Context, login *UserLogin) error

	// GetLoginFlows returns a list of login flows that the network supports.
	GetLoginFlows() []LoginFlow
	// CreateLogin is called when a user wants to log in to the network.
	//
	// This should generally not do any work, it should just return a LoginProcess that remembers
	// the user and will execute the requested flow. The actual work should start when [LoginProcess.Start] is called.
	CreateLogin(ctx context.Context, user *User, flowID string) (LoginProcess, error)
}

NetworkConnector is the main interface that a network connector must implement.

type NetworkGeneralCapabilities

type NetworkGeneralCapabilities struct {
	// Does the network connector support disappearing messages?
	// This flag enables the message disappearing loop in the bridge.
	DisappearingMessages bool
	// Should the bridge re-request user info on incoming messages even if the ghost already has info?
	// By default, info is only requested for ghosts with no name, and other updating is left to events.
	AggressiveUpdateInfo bool
}

type NetworkRoomCapabilities

type NetworkRoomCapabilities struct {
	FormattedText bool
	UserMentions  bool
	RoomMentions  bool

	LocationMessages bool
	Captions         bool
	MaxTextLength    int
	MaxCaptionLength int

	Threads      bool
	Replies      bool
	Edits        bool
	EditMaxCount int
	EditMaxAge   time.Duration
	Deletes      bool
	DeleteMaxAge time.Duration

	DefaultFileRestriction *FileRestriction
	Files                  map[event.MessageType]FileRestriction

	ReadReceipts bool

	Reactions        bool
	ReactionCount    int
	AllowedReactions []string
}

type NewLoginParams

type NewLoginParams struct {
	LoadUserLogin     func(context.Context, *UserLogin) error
	DeleteOnConflict  bool
	DontReuseExisting bool
}

type OrigSender

type OrigSender struct {
	User   *User
	UserID id.UserID

	RequiresDisambiguation bool
	DisambiguatedName      string
	FormattedName          string

	event.MemberEventContent
}

type Portal

type Portal struct {
	*database.Portal
	Bridge *Bridge
	Log    zerolog.Logger
	Parent *Portal
	Relay  *UserLogin
	// contains filtered or unexported fields
}

func (*Portal) CreateMatrixRoom

func (portal *Portal) CreateMatrixRoom(ctx context.Context, source *UserLogin, info *ChatInfo) (retErr error)

func (*Portal) Delete

func (portal *Portal) Delete(ctx context.Context) error

func (*Portal) DoBackwardsBackfill

func (portal *Portal) DoBackwardsBackfill(ctx context.Context, source *UserLogin, task *database.BackfillTask) error

func (*Portal) FindPreferredLogin

func (portal *Portal) FindPreferredLogin(ctx context.Context, user *User, allowRelay bool) (*UserLogin, *database.UserPortal, error)

func (*Portal) GetIntentFor

func (portal *Portal) GetIntentFor(ctx context.Context, sender EventSender, source *UserLogin, evtType RemoteEventType) MatrixAPI

func (*Portal) GetTopLevelParent

func (portal *Portal) GetTopLevelParent() *Portal

func (*Portal) Internal deprecated added in v0.20.0

func (portal *Portal) Internal() *PortalInternals

Deprecated: portal internals should be used carefully and only when necessary.

func (*Portal) ProcessChatInfoChange

func (portal *Portal) ProcessChatInfoChange(ctx context.Context, sender EventSender, source *UserLogin, change *ChatInfoChange, ts time.Time)

func (*Portal) RemoveMXID added in v0.20.0

func (portal *Portal) RemoveMXID(ctx context.Context) error

func (*Portal) Save

func (portal *Portal) Save(ctx context.Context) error

func (*Portal) SetRelay

func (portal *Portal) SetRelay(ctx context.Context, relay *UserLogin) error

func (*Portal) UpdateBridgeInfo

func (portal *Portal) UpdateBridgeInfo(ctx context.Context)

func (*Portal) UpdateDisappearingSetting

func (portal *Portal) UpdateDisappearingSetting(ctx context.Context, setting database.DisappearingSetting, sender MatrixAPI, ts time.Time, implicit, save bool) bool

func (*Portal) UpdateInfo

func (portal *Portal) UpdateInfo(ctx context.Context, info *ChatInfo, source *UserLogin, sender MatrixAPI, ts time.Time)

func (*Portal) UpdateInfoFromGhost added in v0.20.0

func (portal *Portal) UpdateInfoFromGhost(ctx context.Context, ghost *Ghost) (changed bool)

type PortalBridgeInfoFillingNetwork added in v0.20.0

type PortalBridgeInfoFillingNetwork interface {
	NetworkConnector
	FillPortalBridgeInfo(portal *Portal, content *event.BridgeEventContent)
}

type PortalInfo deprecated

type PortalInfo = ChatInfo

Deprecated: Renamed to ChatInfo

type PortalInternals added in v0.20.0

type PortalInternals Portal

func (*PortalInternals) AddToParentSpaceAndSave added in v0.20.0

func (portal *PortalInternals) AddToParentSpaceAndSave(ctx context.Context, save bool)

func (*PortalInternals) ApplyRelationMeta added in v0.20.0

func (portal *PortalInternals) ApplyRelationMeta(content *event.MessageEventContent, replyTo, threadRoot, prevThreadEvent *database.Message)

func (*PortalInternals) CheckConfusableName added in v0.20.0

func (portal *PortalInternals) CheckConfusableName(ctx context.Context, userID id.UserID, name string) bool

func (*PortalInternals) CheckMessageContentCaps added in v0.20.0

func (portal *PortalInternals) CheckMessageContentCaps(ctx context.Context, caps *NetworkRoomCapabilities, content *event.MessageEventContent, evt *event.Event) bool

func (*PortalInternals) CheckPendingMessage added in v0.20.0

func (portal *PortalInternals) CheckPendingMessage(ctx context.Context, evt RemoteMessage) (bool, *database.Message)

func (*PortalInternals) CompileBatchMessage added in v0.20.0

func (portal *PortalInternals) CompileBatchMessage(ctx context.Context, source *UserLogin, msg *BackfillMessage, out *compileBatchOutput, inThread bool)

func (*PortalInternals) CreateMatrixRoomInLoop added in v0.20.0

func (portal *PortalInternals) CreateMatrixRoomInLoop(ctx context.Context, source *UserLogin, info *ChatInfo, backfillBundle any) error

func (*PortalInternals) CreateParentAndAddToSpace added in v0.20.0

func (portal *PortalInternals) CreateParentAndAddToSpace(ctx context.Context, source *UserLogin)

func (*PortalInternals) DoForwardBackfill added in v0.20.0

func (portal *PortalInternals) DoForwardBackfill(ctx context.Context, source *UserLogin, lastMessage *database.Message, bundledData any)

func (*PortalInternals) DoThreadBackfill added in v0.20.0

func (portal *PortalInternals) DoThreadBackfill(ctx context.Context, source *UserLogin, threadID networkid.MessageID)

func (*PortalInternals) EventLoop added in v0.20.0

func (portal *PortalInternals) EventLoop()

func (*PortalInternals) FetchThreadBackfill added in v0.20.0

func (portal *PortalInternals) FetchThreadBackfill(ctx context.Context, source *UserLogin, anchor *database.Message) *FetchMessagesResponse

func (*PortalInternals) FetchThreadInsideBatch added in v0.20.0

func (portal *PortalInternals) FetchThreadInsideBatch(ctx context.Context, source *UserLogin, dbMsg *database.Message, out *compileBatchOutput)

func (*PortalInternals) GetBridgeInfo added in v0.20.0

func (portal *PortalInternals) GetBridgeInfo() (string, event.BridgeEventContent)

func (*PortalInternals) GetInitialMemberList added in v0.20.0

func (portal *PortalInternals) GetInitialMemberList(ctx context.Context, members *ChatMemberList, source *UserLogin, pl *event.PowerLevelsEventContent) (invite, functional []id.UserID, err error)

func (*PortalInternals) GetIntentAndUserMXIDFor added in v0.20.0

func (portal *PortalInternals) GetIntentAndUserMXIDFor(ctx context.Context, sender EventSender, source *UserLogin, otherLogins []*UserLogin, evtType RemoteEventType) (intent MatrixAPI, extraUserID id.UserID)

func (*PortalInternals) GetIntentForMXID added in v0.20.0

func (portal *PortalInternals) GetIntentForMXID(ctx context.Context, userID id.UserID) (MatrixAPI, error)

func (*PortalInternals) GetRelationMeta added in v0.20.0

func (portal *PortalInternals) GetRelationMeta(ctx context.Context, currentMsg networkid.MessageID, replyToPtr *networkid.MessageOptionalPartID, threadRootPtr *networkid.MessageID, isBatchSend bool) (replyTo, threadRoot, prevThreadEvent *database.Message)

func (*PortalInternals) GetTargetMessagePart added in v0.20.0

func (portal *PortalInternals) GetTargetMessagePart(ctx context.Context, evt RemoteEventWithTargetMessage) (*database.Message, error)

func (*PortalInternals) GetTargetReaction added in v0.20.0

func (portal *PortalInternals) GetTargetReaction(ctx context.Context, evt RemoteReactionRemove) (*database.Reaction, error)

func (*PortalInternals) GetTargetUser added in v0.20.0

func (portal *PortalInternals) GetTargetUser(ctx context.Context, userID id.UserID) (GhostOrUserLogin, error)

func (*PortalInternals) HandleCreateEvent added in v0.20.0

func (portal *PortalInternals) HandleCreateEvent(evt *portalCreateEvent)

func (*PortalInternals) HandleMatrixEdit added in v0.20.0

func (portal *PortalInternals) HandleMatrixEdit(ctx context.Context, sender *UserLogin, origSender *OrigSender, evt *event.Event, content *event.MessageEventContent, caps *NetworkRoomCapabilities)

func (*PortalInternals) HandleMatrixEvent added in v0.20.0

func (portal *PortalInternals) HandleMatrixEvent(sender *User, evt *event.Event)

func (*PortalInternals) HandleMatrixMembership added in v0.20.0

func (portal *PortalInternals) HandleMatrixMembership(ctx context.Context, sender *UserLogin, origSender *OrigSender, evt *event.Event)

func (*PortalInternals) HandleMatrixMessage added in v0.20.0

func (portal *PortalInternals) HandleMatrixMessage(ctx context.Context, sender *UserLogin, origSender *OrigSender, evt *event.Event)

func (*PortalInternals) HandleMatrixPowerLevels added in v0.20.0

func (portal *PortalInternals) HandleMatrixPowerLevels(ctx context.Context, sender *UserLogin, origSender *OrigSender, evt *event.Event)

func (*PortalInternals) HandleMatrixReaction added in v0.20.0

func (portal *PortalInternals) HandleMatrixReaction(ctx context.Context, sender *UserLogin, evt *event.Event)

func (*PortalInternals) HandleMatrixReadReceipt added in v0.20.0

func (portal *PortalInternals) HandleMatrixReadReceipt(ctx context.Context, user *User, eventID id.EventID, receipt event.ReadReceipt)

func (*PortalInternals) HandleMatrixReceipts added in v0.20.0

func (portal *PortalInternals) HandleMatrixReceipts(ctx context.Context, evt *event.Event)

func (*PortalInternals) HandleMatrixRedaction added in v0.20.0

func (portal *PortalInternals) HandleMatrixRedaction(ctx context.Context, sender *UserLogin, origSender *OrigSender, evt *event.Event)

func (*PortalInternals) HandleMatrixTyping added in v0.20.0

func (portal *PortalInternals) HandleMatrixTyping(ctx context.Context, evt *event.Event)

func (*PortalInternals) HandleRemoteBackfill added in v0.20.0

func (portal *PortalInternals) HandleRemoteBackfill(ctx context.Context, source *UserLogin, backfill RemoteBackfill)

func (*PortalInternals) HandleRemoteChatDelete added in v0.20.0

func (portal *PortalInternals) HandleRemoteChatDelete(ctx context.Context, source *UserLogin, evt RemoteChatDelete)

func (*PortalInternals) HandleRemoteChatInfoChange added in v0.20.0

func (portal *PortalInternals) HandleRemoteChatInfoChange(ctx context.Context, source *UserLogin, evt RemoteChatInfoChange)

func (*PortalInternals) HandleRemoteChatResync added in v0.20.0

func (portal *PortalInternals) HandleRemoteChatResync(ctx context.Context, source *UserLogin, evt RemoteChatResync)

func (*PortalInternals) HandleRemoteDeliveryReceipt added in v0.20.0

func (portal *PortalInternals) HandleRemoteDeliveryReceipt(ctx context.Context, source *UserLogin, evt RemoteDeliveryReceipt)

func (*PortalInternals) HandleRemoteEdit added in v0.20.0

func (portal *PortalInternals) HandleRemoteEdit(ctx context.Context, source *UserLogin, evt RemoteEdit)

func (*PortalInternals) HandleRemoteEvent added in v0.20.0

func (portal *PortalInternals) HandleRemoteEvent(source *UserLogin, evt RemoteEvent)

func (*PortalInternals) HandleRemoteMarkUnread added in v0.20.0

func (portal *PortalInternals) HandleRemoteMarkUnread(ctx context.Context, source *UserLogin, evt RemoteMarkUnread)

func (*PortalInternals) HandleRemoteMessage added in v0.20.0

func (portal *PortalInternals) HandleRemoteMessage(ctx context.Context, source *UserLogin, evt RemoteMessage)

func (*PortalInternals) HandleRemoteMessageRemove added in v0.20.0

func (portal *PortalInternals) HandleRemoteMessageRemove(ctx context.Context, source *UserLogin, evt RemoteMessageRemove)

func (*PortalInternals) HandleRemoteReaction added in v0.20.0

func (portal *PortalInternals) HandleRemoteReaction(ctx context.Context, source *UserLogin, evt RemoteReaction)

func (*PortalInternals) HandleRemoteReactionRemove added in v0.20.0

func (portal *PortalInternals) HandleRemoteReactionRemove(ctx context.Context, source *UserLogin, evt RemoteReactionRemove)

func (*PortalInternals) HandleRemoteReactionSync added in v0.20.0

func (portal *PortalInternals) HandleRemoteReactionSync(ctx context.Context, source *UserLogin, evt RemoteReactionSync)

func (*PortalInternals) HandleRemoteReadReceipt added in v0.20.0

func (portal *PortalInternals) HandleRemoteReadReceipt(ctx context.Context, source *UserLogin, evt RemoteReadReceipt)

func (*PortalInternals) HandleRemoteTyping added in v0.20.0

func (portal *PortalInternals) HandleRemoteTyping(ctx context.Context, source *UserLogin, evt RemoteTyping)

func (*PortalInternals) HandleRemoteUpsert added in v0.20.0

func (portal *PortalInternals) HandleRemoteUpsert(ctx context.Context, source *UserLogin, evt RemoteMessageUpsert, existing []*database.Message) bool

func (*PortalInternals) LockedUpdateInfoFromGhost added in v0.20.0

func (portal *PortalInternals) LockedUpdateInfoFromGhost(ctx context.Context, ghost *Ghost)

func (*PortalInternals) PeriodicTypingUpdater added in v0.20.0

func (portal *PortalInternals) PeriodicTypingUpdater()

func (*PortalInternals) QueueEvent added in v0.20.0

func (portal *PortalInternals) QueueEvent(ctx context.Context, evt portalEvent)

func (*PortalInternals) RedactMessageParts added in v0.20.0

func (portal *PortalInternals) RedactMessageParts(ctx context.Context, parts []*database.Message, intent MatrixAPI, ts time.Time)

func (*PortalInternals) RemoveInPortalCache added in v0.20.0

func (portal *PortalInternals) RemoveInPortalCache(ctx context.Context)

func (*PortalInternals) SendBackfill added in v0.20.0

func (portal *PortalInternals) SendBackfill(ctx context.Context, source *UserLogin, messages []*BackfillMessage, forceForward, markRead, inThread bool)

func (*PortalInternals) SendBatch added in v0.20.0

func (portal *PortalInternals) SendBatch(ctx context.Context, source *UserLogin, messages []*BackfillMessage, forceForward, markRead, inThread bool)

func (*PortalInternals) SendConvertedEdit added in v0.20.0

func (portal *PortalInternals) SendConvertedEdit(ctx context.Context, targetID networkid.MessageID, senderID networkid.UserID, converted *ConvertedEdit, intent MatrixAPI, ts time.Time, streamOrder int64)

func (*PortalInternals) SendConvertedMessage added in v0.20.0

func (portal *PortalInternals) SendConvertedMessage(ctx context.Context, id networkid.MessageID, intent MatrixAPI, senderID networkid.UserID, converted *ConvertedMessage, ts time.Time, streamOrder int64, logContext func(*zerolog.Event) *zerolog.Event) []*database.Message

func (*PortalInternals) SendConvertedReaction added in v0.20.0

func (portal *PortalInternals) SendConvertedReaction(ctx context.Context, senderID networkid.UserID, intent MatrixAPI, targetMessage *database.Message, emojiID networkid.EmojiID, emoji string, ts time.Time, dbMetadata any, extraContent map[string]any, logContext func(*zerolog.Event) *zerolog.Event)

func (*PortalInternals) SendErrorStatus added in v0.20.0

func (portal *PortalInternals) SendErrorStatus(ctx context.Context, evt *event.Event, err error)

func (*PortalInternals) SendLegacyBackfill added in v0.20.0

func (portal *PortalInternals) SendLegacyBackfill(ctx context.Context, source *UserLogin, messages []*BackfillMessage, markRead bool)

func (*PortalInternals) SendRemoteErrorNotice added in v0.20.0

func (portal *PortalInternals) SendRemoteErrorNotice(ctx context.Context, intent MatrixAPI, err error, ts time.Time, evtTypeName string)

func (*PortalInternals) SendRoomMeta added in v0.20.0

func (portal *PortalInternals) SendRoomMeta(ctx context.Context, sender MatrixAPI, ts time.Time, eventType event.Type, stateKey string, content any) bool

func (*PortalInternals) SendStateWithIntentOrBot added in v0.20.0

func (portal *PortalInternals) SendStateWithIntentOrBot(ctx context.Context, sender MatrixAPI, eventType event.Type, stateKey string, content *event.Content, ts time.Time) (resp *mautrix.RespSendEvent, err error)

func (*PortalInternals) SendSuccessStatus added in v0.20.0

func (portal *PortalInternals) SendSuccessStatus(ctx context.Context, evt *event.Event)

func (*PortalInternals) SendTypings added in v0.20.0

func (portal *PortalInternals) SendTypings(ctx context.Context, userIDs []id.UserID, typing bool)

func (*PortalInternals) SetMXIDToExistingRoom added in v0.20.0

func (portal *PortalInternals) SetMXIDToExistingRoom(roomID id.RoomID) bool

func (*PortalInternals) SyncParticipants added in v0.20.0

func (portal *PortalInternals) SyncParticipants(ctx context.Context, members *ChatMemberList, source *UserLogin, sender MatrixAPI, ts time.Time) error

func (*PortalInternals) ToggleSpace added in v0.20.0

func (portal *PortalInternals) ToggleSpace(ctx context.Context, spaceID id.RoomID, canonical, remove bool) error

func (*PortalInternals) UnlockedDelete added in v0.20.0

func (portal *PortalInternals) UnlockedDelete(ctx context.Context) error

func (*PortalInternals) UnlockedDeleteCache added in v0.20.0

func (portal *PortalInternals) UnlockedDeleteCache()

func (*PortalInternals) UnlockedReID added in v0.20.0

func (portal *PortalInternals) UnlockedReID(ctx context.Context, target networkid.PortalKey) error

func (*PortalInternals) UpdateAvatar added in v0.20.0

func (portal *PortalInternals) UpdateAvatar(ctx context.Context, avatar *Avatar, sender MatrixAPI, ts time.Time) bool

func (*PortalInternals) UpdateLogger added in v0.20.0

func (portal *PortalInternals) UpdateLogger()

func (*PortalInternals) UpdateName added in v0.20.0

func (portal *PortalInternals) UpdateName(ctx context.Context, name string, sender MatrixAPI, ts time.Time) bool

func (*PortalInternals) UpdateOtherUser added in v0.20.0

func (portal *PortalInternals) UpdateOtherUser(ctx context.Context, members *ChatMemberList) (changed bool)

func (*PortalInternals) UpdateParent added in v0.20.0

func (portal *PortalInternals) UpdateParent(ctx context.Context, newParent networkid.PortalID, source *UserLogin) bool

func (*PortalInternals) UpdateTopic added in v0.20.0

func (portal *PortalInternals) UpdateTopic(ctx context.Context, topic string, sender MatrixAPI, ts time.Time) bool

func (*PortalInternals) UpdateUserLocalInfo added in v0.20.0

func (portal *PortalInternals) UpdateUserLocalInfo(ctx context.Context, info *UserLocalPortalInfo, source *UserLogin, didJustCreate bool)

type PowerLevelChanges deprecated

type PowerLevelChanges = PowerLevelOverrides

Deprecated: renamed to PowerLevelOverrides

type PowerLevelHandlingNetworkAPI added in v0.20.0

type PowerLevelHandlingNetworkAPI interface {
	NetworkAPI
	HandleMatrixPowerLevels(ctx context.Context, msg *MatrixPowerLevelChange) (bool, error)
}

type PowerLevelOverrides added in v0.20.0

type PowerLevelOverrides struct {
	Events        map[event.Type]int
	UsersDefault  *int
	EventsDefault *int
	StateDefault  *int
	Invite        *int
	Kick          *int
	Ban           *int
	Redact        *int

	Custom func(*event.PowerLevelsEventContent) bool
}

func (*PowerLevelOverrides) Apply added in v0.20.0

func (plc *PowerLevelOverrides) Apply(actor id.UserID, content *event.PowerLevelsEventContent) (changed bool)

type PushConfig

type PushConfig struct {
	Web  *WebPushConfig  `json:"web,omitempty"`
	FCM  *FCMPushConfig  `json:"fcm,omitempty"`
	APNs *APNsPushConfig `json:"apns,omitempty"`
}

type PushType

type PushType int
const (
	PushTypeUnknown PushType = iota
	PushTypeWeb
	PushTypeAPNs
	PushTypeFCM
)

func PushTypeFromString

func PushTypeFromString(str string) PushType

func (PushType) GoString

func (pt PushType) GoString() string

func (PushType) String

func (pt PushType) String() string

type PushableNetworkAPI

type PushableNetworkAPI interface {
	RegisterPushNotifications(ctx context.Context, pushType PushType, token string) error
	GetPushConfigs() *PushConfig
}

type ReIDResult

type ReIDResult int
const (
	ReIDResultError ReIDResult = iota
	ReIDResultNoOp
	ReIDResultSourceDeleted
	ReIDResultSourceReIDd
	ReIDResultTargetDeletedAndSourceReIDd
	ReIDResultSourceTombstonedIntoTarget
)

type ReactionHandlingNetworkAPI

type ReactionHandlingNetworkAPI interface {
	NetworkAPI
	// PreHandleMatrixReaction is called as the first step of handling a reaction. It returns the emoji ID,
	// sender user ID and max reaction count to allow the central bridge module to de-duplicate the reaction
	// if appropriate.
	PreHandleMatrixReaction(ctx context.Context, msg *MatrixReaction) (MatrixReactionPreResponse, error)
	// HandleMatrixReaction is called after confirming that the reaction is not a duplicate.
	// This is the method that should actually send the reaction to the remote network.
	// The returned [database.Reaction] object may be empty: the central bridge module already has
	// all the required fields and will fill them automatically if they're empty. However, network
	// connectors are allowed to set fields themselves if any extra fields are necessary.
	HandleMatrixReaction(ctx context.Context, msg *MatrixReaction) (reaction *database.Reaction, err error)
	// HandleMatrixReactionRemove is called when a redaction event is received pointing at a previously
	// bridged reaction. The network connector should remove the reaction from the remote network.
	HandleMatrixReactionRemove(ctx context.Context, msg *MatrixReactionRemove) error
}

ReactionHandlingNetworkAPI is an optional interface that network connectors can implement to handle message reactions.

type ReactionSyncData added in v0.20.0

type ReactionSyncData struct {
	Users map[networkid.UserID]*ReactionSyncUser
	// Whether the map contains all users who have reacted to the message
	HasAllUsers bool
}

func (*ReactionSyncData) ToBackfill added in v0.20.0

func (rsd *ReactionSyncData) ToBackfill() []*BackfillReaction

type ReactionSyncUser added in v0.20.0

type ReactionSyncUser struct {
	Reactions []*BackfillReaction
	// Whether the list contains all reactions the user has sent
	HasAllReactions bool
	// If the list doesn't contain all reactions from the user,
	// then this field can be set to remove old reactions if there are more than a certain number.
	MaxCount int
}

type ReadReceiptHandlingNetworkAPI

type ReadReceiptHandlingNetworkAPI interface {
	NetworkAPI
	// HandleMatrixReadReceipt is called when a read receipt is sent in a portal room.
	// This will be called even if the target message is not a bridged message.
	// Network connectors must gracefully handle [MatrixReadReceipt.ExactMessage] being nil.
	// The exact handling is up to the network connector.
	HandleMatrixReadReceipt(ctx context.Context, msg *MatrixReadReceipt) error
}

ReadReceiptHandlingNetworkAPI is an optional interface that network connectors can implement to handle read receipts.

type RedactionHandlingNetworkAPI

type RedactionHandlingNetworkAPI interface {
	NetworkAPI
	// HandleMatrixMessageRemove is called when a previously bridged message is deleted in a portal room.
	HandleMatrixMessageRemove(ctx context.Context, msg *MatrixMessageRemove) error
}

RedactionHandlingNetworkAPI is an optional interface that network connectors can implement to handle message deletions.

type RemoteBackfill

type RemoteBackfill interface {
	RemoteEvent
	GetBackfillData(ctx context.Context, portal *Portal) (*FetchMessagesResponse, error)
}

type RemoteChatDelete added in v0.20.0

type RemoteChatDelete interface {
	RemoteEvent
	DeleteOnlyForMe() bool
}

type RemoteChatInfoChange

type RemoteChatInfoChange interface {
	RemoteEvent
	GetChatInfoChange(ctx context.Context) (*ChatInfoChange, error)
}

type RemoteChatResync

type RemoteChatResync interface {
	RemoteEvent
}

type RemoteChatResyncBackfill

type RemoteChatResyncBackfill interface {
	RemoteChatResync
	CheckNeedsBackfill(ctx context.Context, latestMessage *database.Message) (bool, error)
}

type RemoteChatResyncBackfillBundle added in v0.20.0

type RemoteChatResyncBackfillBundle interface {
	RemoteChatResyncBackfill
	GetBundledBackfillData() any
}

type RemoteChatResyncWithInfo

type RemoteChatResyncWithInfo interface {
	RemoteChatResync
	GetChatInfo(ctx context.Context, portal *Portal) (*ChatInfo, error)
}

type RemoteDeliveryReceipt added in v0.20.0

type RemoteDeliveryReceipt interface {
	RemoteEvent
	GetReceiptTargets() []networkid.MessageID
}

type RemoteEdit

type RemoteEdit interface {
	RemoteEventWithTargetMessage
	ConvertEdit(ctx context.Context, portal *Portal, intent MatrixAPI, existing []*database.Message) (*ConvertedEdit, error)
}

type RemoteEvent

type RemoteEvent interface {
	GetType() RemoteEventType
	GetPortalKey() networkid.PortalKey
	AddLogContext(c zerolog.Context) zerolog.Context
	GetSender() EventSender
}

RemoteEvent represents a single event from the remote network, such as a message or a reaction.

When a NetworkAPI receives an event from the remote network, it should convert it into a RemoteEvent and pass it to the bridge for processing using Bridge.QueueRemoteEvent.

type RemoteEventThatMayCreatePortal

type RemoteEventThatMayCreatePortal interface {
	RemoteEvent
	ShouldCreatePortal() bool
}

type RemoteEventType

type RemoteEventType int
const (
	RemoteEventUnknown RemoteEventType = iota
	RemoteEventMessage
	RemoteEventMessageUpsert
	RemoteEventEdit
	RemoteEventReaction
	RemoteEventReactionRemove
	RemoteEventReactionSync
	RemoteEventMessageRemove
	RemoteEventReadReceipt
	RemoteEventDeliveryReceipt
	RemoteEventMarkUnread
	RemoteEventTyping
	RemoteEventChatInfoChange
	RemoteEventChatResync
	RemoteEventChatDelete
	RemoteEventBackfill
)

func (RemoteEventType) String

func (ret RemoteEventType) String() string

type RemoteEventWithBundledParts added in v0.20.0

type RemoteEventWithBundledParts interface {
	RemoteEventWithTargetMessage
	GetTargetDBMessage() []*database.Message
}

type RemoteEventWithStreamOrder added in v0.20.0

type RemoteEventWithStreamOrder interface {
	RemoteEvent
	GetStreamOrder() int64
}

type RemoteEventWithTargetMessage

type RemoteEventWithTargetMessage interface {
	RemoteEvent
	GetTargetMessage() networkid.MessageID
}

type RemoteEventWithTargetPart

type RemoteEventWithTargetPart interface {
	RemoteEventWithTargetMessage
	GetTargetMessagePart() networkid.PartID
}

type RemoteEventWithTimestamp

type RemoteEventWithTimestamp interface {
	RemoteEvent
	GetTimestamp() time.Time
}

type RemoteEventWithUncertainPortalReceiver added in v0.20.0

type RemoteEventWithUncertainPortalReceiver interface {
	RemoteEvent
	PortalReceiverIsUncertain() bool
}

type RemoteMarkUnread

type RemoteMarkUnread interface {
	RemoteEvent
	GetUnread() bool
}

type RemoteMessage

type RemoteMessage interface {
	RemoteEvent
	GetID() networkid.MessageID
	ConvertMessage(ctx context.Context, portal *Portal, intent MatrixAPI) (*ConvertedMessage, error)
}

type RemoteMessageRemove

type RemoteMessageRemove interface {
	RemoteEventWithTargetMessage
}

type RemoteMessageUpsert added in v0.20.0

type RemoteMessageUpsert interface {
	RemoteMessage
	HandleExisting(ctx context.Context, portal *Portal, intent MatrixAPI, existing []*database.Message) (UpsertResult, error)
}

type RemoteMessageWithTransactionID added in v0.20.0

type RemoteMessageWithTransactionID interface {
	RemoteMessage
	GetTransactionID() networkid.TransactionID
}

type RemotePreHandler

type RemotePreHandler interface {
	RemoteEvent
	PreHandle(ctx context.Context, portal *Portal)
}

type RemoteReaction

type RemoteReaction interface {
	RemoteEventWithTargetMessage
	GetReactionEmoji() (string, networkid.EmojiID)
}

type RemoteReactionRemove

type RemoteReactionRemove interface {
	RemoteEventWithTargetMessage
	GetRemovedEmojiID() networkid.EmojiID
}

type RemoteReactionSync added in v0.20.0

type RemoteReactionSync interface {
	RemoteEventWithTargetMessage
	GetReactions() *ReactionSyncData
}

type RemoteReactionWithExtraContent

type RemoteReactionWithExtraContent interface {
	RemoteReaction
	GetReactionExtraContent() map[string]any
}

type RemoteReactionWithMeta

type RemoteReactionWithMeta interface {
	RemoteReaction
	GetReactionDBMetadata() any
}

type RemoteReadReceipt added in v0.20.0

type RemoteReadReceipt interface {
	RemoteEvent
	GetLastReceiptTarget() networkid.MessageID
	GetReceiptTargets() []networkid.MessageID
	GetReadUpTo() time.Time
}

type RemoteReceipt deprecated

type RemoteReceipt = RemoteReadReceipt

Deprecated: Renamed to RemoteReadReceipt.

type RemoteTyping

type RemoteTyping interface {
	RemoteEvent
	GetTimeout() time.Duration
}

type RemoteTypingWithType

type RemoteTypingWithType interface {
	RemoteTyping
	GetTypingType() TypingType
}

type ResolveIdentifierResponse

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,
	// and the central bridge module will not try to create a ghost if it is not set.
	Ghost *Ghost

	// UserID is the user ID of the user that the identifier resolves to.
	UserID networkid.UserID
	// UserInfo contains the info of the user that the identifier resolves to.
	// If both this and the Ghost field are set, the central bridge module will
	// automatically update the ghost's info with the data here.
	UserInfo *UserInfo

	// Chat contains info about the direct chat with the resolved user.
	// This field is required when createChat is true in the ResolveIdentifier call,
	// and optional otherwise.
	Chat *CreateChatResponse
}

type RespError added in v0.20.0

type RespError mautrix.RespError

RespError is a class of error that certain network interface methods can return to ensure that the error is properly translated into an HTTP error when the method is called via the provisioning API.

However, unlike mautrix.RespError, this does not include the error code in the message shown to users when used outside HTTP contexts.

func WrapRespErr added in v0.20.0

func WrapRespErr(err error, target mautrix.RespError) RespError

func WrapRespErrManual added in v0.20.0

func WrapRespErrManual(err error, code string, status int) RespError

func (RespError) AppendMessage added in v0.20.0

func (re RespError) AppendMessage(append string, args ...any) RespError

func (RespError) Error added in v0.20.0

func (re RespError) Error() string

func (RespError) Is added in v0.20.0

func (re RespError) Is(err error) bool

type RoomAvatarHandlingNetworkAPI

type RoomAvatarHandlingNetworkAPI interface {
	NetworkAPI
	// HandleMatrixRoomAvatar is called when the avatar of a portal room is changed.
	// This method should update the AvatarID, AvatarHash and AvatarMXC fields
	// with the new avatar details and return true if the change was successful.
	// If the change is not successful, then the fields should not be updated.
	HandleMatrixRoomAvatar(ctx context.Context, msg *MatrixRoomAvatar) (bool, error)
}

RoomAvatarHandlingNetworkAPI is an optional interface that network connectors can implement to handle room avatar changes.

type RoomNameHandlingNetworkAPI

type RoomNameHandlingNetworkAPI interface {
	NetworkAPI
	// HandleMatrixRoomName is called when the name of a portal room is changed.
	// This method should update the Name and NameSet fields of the Portal with
	// the new name and return true if the change was successful.
	// If the change is not successful, then the fields should not be updated.
	HandleMatrixRoomName(ctx context.Context, msg *MatrixRoomName) (bool, error)
}

RoomNameHandlingNetworkAPI is an optional interface that network connectors can implement to handle room name changes.

type RoomTopicHandlingNetworkAPI

type RoomTopicHandlingNetworkAPI interface {
	NetworkAPI
	// HandleMatrixRoomTopic is called when the topic of a portal room is changed.
	// This method should update the Topic and TopicSet fields of the Portal with
	// the new topic and return true if the change was successful.
	// If the change is not successful, then the fields should not be updated.
	HandleMatrixRoomTopic(ctx context.Context, msg *MatrixRoomTopic) (bool, error)
}

RoomTopicHandlingNetworkAPI is an optional interface that network connectors can implement to handle room topic changes.

type SimpleRemoteEvent deprecated

type SimpleRemoteEvent[T any] struct {
	Type         RemoteEventType
	LogContext   func(c zerolog.Context) zerolog.Context
	PortalKey    networkid.PortalKey
	Data         T
	CreatePortal bool

	ID             networkid.MessageID
	Sender         EventSender
	TargetMessage  networkid.MessageID
	EmojiID        networkid.EmojiID
	Emoji          string
	ReactionDBMeta any
	Timestamp      time.Time
	ChatInfoChange *ChatInfoChange

	ResyncChatInfo       *ChatInfo
	ResyncBackfillNeeded bool

	BackfillData *FetchMessagesResponse

	ConvertMessageFunc func(ctx context.Context, portal *Portal, intent MatrixAPI, data T) (*ConvertedMessage, error)
	ConvertEditFunc    func(ctx context.Context, portal *Portal, intent MatrixAPI, existing []*database.Message, data T) (*ConvertedEdit, error)
}

SimpleRemoteEvent is a simple implementation of RemoteEvent that can be used with struct fields and some callbacks.

Using this type is only recommended for simple bridges. More advanced ones should implement the remote event interfaces themselves by wrapping the remote network library event types.

Deprecated: use the types in the simplevent package instead.

func (*SimpleRemoteEvent[T]) AddLogContext

func (sre *SimpleRemoteEvent[T]) AddLogContext(c zerolog.Context) zerolog.Context

func (*SimpleRemoteEvent[T]) CheckNeedsBackfill added in v0.20.0

func (sre *SimpleRemoteEvent[T]) CheckNeedsBackfill(ctx context.Context, latestMessage *database.Message) (bool, error)

func (*SimpleRemoteEvent[T]) ConvertEdit

func (sre *SimpleRemoteEvent[T]) ConvertEdit(ctx context.Context, portal *Portal, intent MatrixAPI, existing []*database.Message) (*ConvertedEdit, error)

func (*SimpleRemoteEvent[T]) ConvertMessage

func (sre *SimpleRemoteEvent[T]) ConvertMessage(ctx context.Context, portal *Portal, intent MatrixAPI) (*ConvertedMessage, error)

func (*SimpleRemoteEvent[T]) GetBackfillData added in v0.20.0

func (sre *SimpleRemoteEvent[T]) GetBackfillData(ctx context.Context, portal *Portal) (*FetchMessagesResponse, error)

func (*SimpleRemoteEvent[T]) GetChatInfo added in v0.20.0

func (sre *SimpleRemoteEvent[T]) GetChatInfo(ctx context.Context, portal *Portal) (*ChatInfo, error)

func (*SimpleRemoteEvent[T]) GetChatInfoChange

func (sre *SimpleRemoteEvent[T]) GetChatInfoChange(ctx context.Context) (*ChatInfoChange, error)

func (*SimpleRemoteEvent[T]) GetID

func (sre *SimpleRemoteEvent[T]) GetID() networkid.MessageID

func (*SimpleRemoteEvent[T]) GetPortalKey

func (sre *SimpleRemoteEvent[T]) GetPortalKey() networkid.PortalKey

func (*SimpleRemoteEvent[T]) GetReactionDBMetadata

func (sre *SimpleRemoteEvent[T]) GetReactionDBMetadata() any

func (*SimpleRemoteEvent[T]) GetReactionEmoji

func (sre *SimpleRemoteEvent[T]) GetReactionEmoji() (string, networkid.EmojiID)

func (*SimpleRemoteEvent[T]) GetRemovedEmojiID

func (sre *SimpleRemoteEvent[T]) GetRemovedEmojiID() networkid.EmojiID

func (*SimpleRemoteEvent[T]) GetSender

func (sre *SimpleRemoteEvent[T]) GetSender() EventSender

func (*SimpleRemoteEvent[T]) GetTargetMessage

func (sre *SimpleRemoteEvent[T]) GetTargetMessage() networkid.MessageID

func (*SimpleRemoteEvent[T]) GetTimestamp

func (sre *SimpleRemoteEvent[T]) GetTimestamp() time.Time

func (*SimpleRemoteEvent[T]) GetType

func (sre *SimpleRemoteEvent[T]) GetType() RemoteEventType

func (*SimpleRemoteEvent[T]) ShouldCreatePortal

func (sre *SimpleRemoteEvent[T]) ShouldCreatePortal() bool

type SinglePowerLevelChange added in v0.20.0

type SinglePowerLevelChange struct {
	OrigLevel int
	NewLevel  int
	NewIsSet  bool
}

type TagHandlingNetworkAPI added in v0.20.0

type TagHandlingNetworkAPI interface {
	NetworkAPI
	HandleRoomTag(ctx context.Context, msg *MatrixRoomTag) error
}

type TypingHandlingNetworkAPI

type TypingHandlingNetworkAPI interface {
	NetworkAPI
	// HandleMatrixTyping is called when a user starts typing in a portal room.
	// In the future, the central bridge module will likely get a loop to automatically repeat
	// calls to this function until the user stops typing.
	HandleMatrixTyping(ctx context.Context, msg *MatrixTyping) error
}

TypingHandlingNetworkAPI is an optional interface that network connectors can implement to handle typing events.

type TypingType

type TypingType int
const (
	TypingTypeText TypingType = iota
	TypingTypeUploadingMedia
	TypingTypeRecordingMedia
)

type UpsertResult added in v0.20.0

type UpsertResult struct {
	SubEvents               []RemoteEvent
	SaveParts               bool
	ContinueMessageHandling bool
}

type User

type User struct {
	*database.User
	Bridge *Bridge
	Log    zerolog.Logger

	CommandState unsafe.Pointer
	Permissions  bridgeconfig.Permissions
	// contains filtered or unexported fields
}

func (*User) DoublePuppet

func (user *User) DoublePuppet(ctx context.Context) MatrixAPI

func (*User) GetCachedUserLogins

func (user *User) GetCachedUserLogins() []*UserLogin

func (*User) GetDefaultLogin

func (user *User) GetDefaultLogin() *UserLogin

func (*User) GetFormattedUserLogins

func (user *User) GetFormattedUserLogins() string

func (*User) GetManagementRoom

func (user *User) GetManagementRoom(ctx context.Context) (id.RoomID, error)

func (*User) GetUserLoginIDs

func (user *User) GetUserLoginIDs() []networkid.UserLoginID

func (*User) LoginDoublePuppet

func (user *User) LoginDoublePuppet(ctx context.Context, token string) error

func (*User) LogoutDoublePuppet

func (user *User) LogoutDoublePuppet(ctx context.Context)

func (*User) NewLogin

func (user *User) NewLogin(ctx context.Context, data *database.UserLogin, params *NewLoginParams) (*UserLogin, error)

NewLogin creates a UserLogin object for this user with the given parameters.

If a login already exists with the same ID, it is reused after updating the remote name and metadata from the provided data, unless DontReuseExisting is set in params.

If the existing login belongs to another user, this returns an error, unless DeleteOnConflict is set in the params, in which case the existing login is deleted.

This will automatically call LoadUserLogin after creating the UserLogin object. The load method defaults to the network connector's LoadUserLogin method, but it can be overridden in params.

func (*User) Save

func (user *User) Save(ctx context.Context) error

type UserInfo

type UserInfo struct {
	Identifiers []string
	Name        *string
	Avatar      *Avatar
	IsBot       *bool

	ExtraUpdates ExtraUpdater[*Ghost]
}

type UserLocalPortalInfo

type UserLocalPortalInfo struct {
	// To signal an indefinite mute, use [event.MutedForever] as the value here.
	// To unmute, set any time before now, e.g. [bridgev2.Unmuted].
	MutedUntil *time.Time
	Tag        *event.RoomTag
}

type UserLogin

type UserLogin struct {
	*database.UserLogin
	Bridge *Bridge
	User   *User
	Log    zerolog.Logger

	Client      NetworkAPI
	BridgeState *BridgeStateQueue
	// contains filtered or unexported fields
}

func (*UserLogin) AddPortalToSpace

func (ul *UserLogin) AddPortalToSpace(ctx context.Context, portal *Portal, userPortal *database.UserPortal) error

func (*UserLogin) Delete

func (ul *UserLogin) Delete(ctx context.Context, state status.BridgeState, opts DeleteOpts)

func (*UserLogin) Disconnect

func (ul *UserLogin) Disconnect(done func())

func (*UserLogin) FillBridgeState added in v0.20.0

func (ul *UserLogin) FillBridgeState(state status.BridgeState) status.BridgeState

func (*UserLogin) GetSpaceRoom

func (ul *UserLogin) GetSpaceRoom(ctx context.Context) (id.RoomID, error)

func (*UserLogin) KickUserFromPortalsForBadCredentials added in v0.20.0

func (ul *UserLogin) KickUserFromPortalsForBadCredentials(ctx context.Context)

KickUserFromPortalsForBadCredentials can be called to kick the user from portals without deleting the entire UserLogin object.

func (*UserLogin) Logout

func (ul *UserLogin) Logout(ctx context.Context)

func (*UserLogin) MarkAsPreferredIn

func (ul *UserLogin) MarkAsPreferredIn(ctx context.Context, portal *Portal) error

func (*UserLogin) MarkInPortal

func (ul *UserLogin) MarkInPortal(ctx context.Context, portal *Portal)

func (*UserLogin) Save

func (ul *UserLogin) Save(ctx context.Context) error

type UserPowerLevelChange added in v0.20.0

type UserPowerLevelChange struct {
	Target GhostOrUserLogin
	SinglePowerLevelChange
}

type UserSearchingNetworkAPI

type UserSearchingNetworkAPI interface {
	IdentifierResolvingNetworkAPI
	SearchUsers(ctx context.Context, query string) ([]*ResolveIdentifierResponse, error)
}

type WebPushConfig

type WebPushConfig struct {
	VapidKey string `json:"vapid_key"`
}

Directories

Path Synopsis
mxmain
Package mxmain contains initialization code for a single-network Matrix bridge using the bridgev2 package.
Package mxmain contains initialization code for a single-network Matrix bridge using the bridgev2 package.
Package networkid contains string types used to represent different kinds of identifiers on remote networks.
Package networkid contains string types used to represent different kinds of identifiers on remote networks.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL