bridgev2: add remote profile field in bridge states

This commit is contained in:
Tulir Asokan 2024-08-04 20:52:52 +03:00
commit 0e048db4f7
6 changed files with 67 additions and 44 deletions

View file

@ -52,6 +52,18 @@ const (
StateLoggedOut BridgeStateEvent = "LOGGED_OUT"
)
type RemoteProfile struct {
Phone string `json:"phone,omitempty"`
Email string `json:"email,omitempty"`
Username string `json:"username,omitempty"`
Name string `json:"name,omitempty"`
Avatar id.ContentURIString `json:"avatar,omitempty"`
}
func (rp *RemoteProfile) IsEmpty() bool {
return rp == nil || (rp.Phone == "" && rp.Email == "" && rp.Username == "" && rp.Name == "" && rp.Avatar == "")
}
type BridgeState struct {
StateEvent BridgeStateEvent `json:"state_event"`
Timestamp jsontime.Unix `json:"timestamp"`
@ -61,9 +73,10 @@ type BridgeState struct {
Error BridgeStateErrorCode `json:"error,omitempty"`
Message string `json:"message,omitempty"`
UserID id.UserID `json:"user_id,omitempty"`
RemoteID string `json:"remote_id,omitempty"`
RemoteName string `json:"remote_name,omitempty"`
UserID id.UserID `json:"user_id,omitempty"`
RemoteID string `json:"remote_id,omitempty"`
RemoteName string `json:"remote_name,omitempty"`
RemoteProfile RemoteProfile `json:"remote_profile,omitempty"`
Reason string `json:"reason,omitempty"`
Info map[string]interface{} `json:"info,omitempty"`
@ -89,13 +102,15 @@ type CustomBridgeStateFiller interface {
StandaloneCustomBridgeStateFiller
}
func (pong BridgeState) Fill(user BridgeStateFiller) BridgeState {
func (pong BridgeState) Fill(user any) BridgeState {
if user != nil {
pong.UserID = user.GetMXID()
pong.RemoteID = user.GetRemoteID()
pong.RemoteName = user.GetRemoteName()
if std, ok := user.(BridgeStateFiller); ok {
pong.UserID = std.GetMXID()
pong.RemoteID = std.GetRemoteID()
pong.RemoteName = std.GetRemoteName()
}
if custom, ok := user.(CustomBridgeStateFiller); ok {
if custom, ok := user.(StandaloneCustomBridgeStateFiller); ok {
pong = custom.FillBridgeState(pong)
}
}

View file

@ -21,7 +21,7 @@ type BridgeStateQueue struct {
prevSent *status.BridgeState
ch chan status.BridgeState
bridge *Bridge
user status.BridgeStateFiller
user status.StandaloneCustomBridgeStateFiller
}
func (br *Bridge) SendGlobalBridgeState(state status.BridgeState) {
@ -41,7 +41,7 @@ func (br *Bridge) SendGlobalBridgeState(state status.BridgeState) {
}
}
func (br *Bridge) NewBridgeStateQueue(user status.BridgeStateFiller) *BridgeStateQueue {
func (br *Bridge) NewBridgeStateQueue(user status.StandaloneCustomBridgeStateFiller) *BridgeStateQueue {
bsq := &BridgeStateQueue{
ch: make(chan status.BridgeState, 10),
bridge: br,

View file

@ -1,4 +1,4 @@
-- v0 -> v15 (compatible with v9+): Latest revision
-- v0 -> v16 (compatible with v9+): Latest revision
CREATE TABLE "user" (
bridge_id TEXT NOT NULL,
mxid TEXT NOT NULL,
@ -10,12 +10,13 @@ CREATE TABLE "user" (
);
CREATE TABLE user_login (
bridge_id TEXT NOT NULL,
user_mxid TEXT NOT NULL,
id TEXT NOT NULL,
remote_name TEXT NOT NULL,
space_room TEXT,
metadata jsonb NOT NULL,
bridge_id TEXT NOT NULL,
user_mxid TEXT NOT NULL,
id TEXT NOT NULL,
remote_name TEXT NOT NULL,
remote_profile jsonb,
space_room TEXT,
metadata jsonb NOT NULL,
PRIMARY KEY (bridge_id, id),
CONSTRAINT user_login_user_fkey FOREIGN KEY (bridge_id, user_mxid)

View file

@ -0,0 +1,2 @@
-- v16 (compatible with v9+): Save remote profile in user logins
ALTER TABLE user_login ADD COLUMN remote_profile jsonb;

View file

@ -12,6 +12,7 @@ import (
"go.mau.fi/util/dbutil"
"maunium.net/go/mautrix/bridge/status"
"maunium.net/go/mautrix/bridgev2/networkid"
"maunium.net/go/mautrix/id"
)
@ -23,32 +24,33 @@ type UserLoginQuery struct {
}
type UserLogin struct {
BridgeID networkid.BridgeID
UserMXID id.UserID
ID networkid.UserLoginID
RemoteName string
SpaceRoom id.RoomID
Metadata any
BridgeID networkid.BridgeID
UserMXID id.UserID
ID networkid.UserLoginID
RemoteName string
RemoteProfile status.RemoteProfile
SpaceRoom id.RoomID
Metadata any
}
const (
getUserLoginBaseQuery = `
SELECT bridge_id, user_mxid, id, remote_name, space_room, metadata FROM user_login
SELECT bridge_id, user_mxid, id, remote_name, remote_profile, space_room, metadata FROM user_login
`
getLoginByIDQuery = getUserLoginBaseQuery + `WHERE bridge_id=$1 AND id=$2`
getAllUsersWithLoginsQuery = `SELECT DISTINCT user_mxid FROM user_login WHERE bridge_id=$1`
getAllLoginsForUserQuery = getUserLoginBaseQuery + `WHERE bridge_id=$1 AND user_mxid=$2`
getAllLoginsInPortalQuery = `
SELECT ul.bridge_id, ul.user_mxid, ul.id, ul.remote_name, ul.space_room, ul.metadata FROM user_portal
SELECT ul.bridge_id, ul.user_mxid, ul.id, ul.remote_name, ul.remote_profile, ul.space_room, ul.metadata FROM user_portal
LEFT JOIN user_login ul ON user_portal.bridge_id=ul.bridge_id AND user_portal.user_mxid=ul.user_mxid AND user_portal.login_id=ul.id
WHERE user_portal.bridge_id=$1 AND user_portal.portal_id=$2 AND user_portal.portal_receiver=$3
`
insertUserLoginQuery = `
INSERT INTO user_login (bridge_id, user_mxid, id, remote_name, space_room, metadata)
VALUES ($1, $2, $3, $4, $5, $6)
INSERT INTO user_login (bridge_id, user_mxid, id, remote_name, remote_profile, space_room, metadata)
VALUES ($1, $2, $3, $4, $5, $6, $7)
`
updateUserLoginQuery = `
UPDATE user_login SET remote_name=$4, space_room=$5, metadata=$6
UPDATE user_login SET remote_name=$4, remote_profile=$5, space_room=$6, metadata=$7
WHERE bridge_id=$1 AND user_mxid=$2 AND id=$3
`
deleteUserLoginQuery = `
@ -89,7 +91,15 @@ func (uq *UserLoginQuery) Delete(ctx context.Context, loginID networkid.UserLogi
func (u *UserLogin) Scan(row dbutil.Scannable) (*UserLogin, error) {
var spaceRoom sql.NullString
err := row.Scan(&u.BridgeID, &u.UserMXID, &u.ID, &u.RemoteName, &spaceRoom, dbutil.JSON{Data: u.Metadata})
err := row.Scan(
&u.BridgeID,
&u.UserMXID,
&u.ID,
&u.RemoteName,
dbutil.JSON{Data: &u.RemoteProfile},
&spaceRoom,
dbutil.JSON{Data: u.Metadata},
)
if err != nil {
return nil, err
}
@ -105,5 +115,9 @@ func (u *UserLogin) ensureHasMetadata(metaType MetaTypeCreator) *UserLogin {
}
func (u *UserLogin) sqlVariables() []any {
return []any{u.BridgeID, u.UserMXID, u.ID, u.RemoteName, dbutil.StrPtr(u.SpaceRoom), dbutil.JSON{Data: u.Metadata}}
var remoteProfile dbutil.JSON
if !u.RemoteProfile.IsEmpty() {
remoteProfile.Data = &u.RemoteProfile
}
return []any{u.BridgeID, u.UserMXID, u.ID, u.RemoteName, remoteProfile, dbutil.StrPtr(u.SpaceRoom), dbutil.JSON{Data: u.Metadata}}
}

View file

@ -22,7 +22,6 @@ import (
"maunium.net/go/mautrix/bridgev2/database"
"maunium.net/go/mautrix/bridgev2/networkid"
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/id"
)
type UserLogin struct {
@ -460,21 +459,13 @@ func (ul *UserLogin) MarkAsPreferredIn(ctx context.Context, portal *Portal) erro
return ul.Bridge.DB.UserPortal.MarkAsPreferred(ctx, ul.UserLogin, portal.PortalKey)
}
var _ status.CustomBridgeStateFiller = (*UserLogin)(nil)
func (ul *UserLogin) GetMXID() id.UserID {
return ul.UserMXID
}
func (ul *UserLogin) GetRemoteID() string {
return string(ul.ID)
}
func (ul *UserLogin) GetRemoteName() string {
return ul.RemoteName
}
var _ status.StandaloneCustomBridgeStateFiller = (*UserLogin)(nil)
func (ul *UserLogin) FillBridgeState(state status.BridgeState) status.BridgeState {
state.UserID = ul.UserMXID
state.RemoteID = string(ul.ID)
state.RemoteName = ul.RemoteName
state.RemoteProfile = ul.RemoteProfile
filler, ok := ul.Client.(status.StandaloneCustomBridgeStateFiller)
if ok {
return filler.FillBridgeState(state)