Store phone settings for users
This commit is contained in:
parent
48d761a397
commit
1618051a12
7 changed files with 50 additions and 15 deletions
|
@ -1,4 +1,4 @@
|
||||||
-- v0 -> v5: Latest revision
|
-- v0 -> v6: Latest revision
|
||||||
|
|
||||||
CREATE TABLE "user" (
|
CREATE TABLE "user" (
|
||||||
-- only: postgres
|
-- only: postgres
|
||||||
|
@ -12,6 +12,7 @@ CREATE TABLE "user" (
|
||||||
|
|
||||||
self_participant_ids jsonb NOT NULL DEFAULT '[]',
|
self_participant_ids jsonb NOT NULL DEFAULT '[]',
|
||||||
sim_metadata jsonb NOT NULL DEFAULT '{}',
|
sim_metadata jsonb NOT NULL DEFAULT '{}',
|
||||||
|
settings jsonb NOT NULL DEFAULT '{}',
|
||||||
|
|
||||||
management_room TEXT,
|
management_room TEXT,
|
||||||
space_room TEXT,
|
space_room TEXT,
|
||||||
|
|
2
database/upgrades/06-phone-settings.sql
Normal file
2
database/upgrades/06-phone-settings.sql
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
-- v6: Store phone settings for users
|
||||||
|
ALTER TABLE "user" ADD COLUMN settings jsonb NOT NULL DEFAULT '{}';
|
|
@ -47,19 +47,26 @@ func (uq *UserQuery) getDB() *Database {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (uq *UserQuery) GetAllWithSession(ctx context.Context) ([]*User, error) {
|
func (uq *UserQuery) GetAllWithSession(ctx context.Context) ([]*User, error) {
|
||||||
return getAll[*User](uq, ctx, `SELECT rowid, mxid, phone_id, session, self_participant_ids, sim_metadata, management_room, space_room, access_token FROM "user" WHERE session IS NOT NULL`)
|
return getAll[*User](uq, ctx, `SELECT rowid, mxid, phone_id, session, self_participant_ids, sim_metadata, settings, management_room, space_room, access_token FROM "user" WHERE session IS NOT NULL`)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (uq *UserQuery) GetAllWithDoublePuppet(ctx context.Context) ([]*User, error) {
|
func (uq *UserQuery) GetAllWithDoublePuppet(ctx context.Context) ([]*User, error) {
|
||||||
return getAll[*User](uq, ctx, `SELECT rowid, mxid, phone_id, session, self_participant_ids, sim_metadata, management_room, space_room, access_token FROM "user" WHERE access_token<>''`)
|
return getAll[*User](uq, ctx, `SELECT rowid, mxid, phone_id, session, self_participant_ids, sim_metadata, settings, management_room, space_room, access_token FROM "user" WHERE access_token<>''`)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (uq *UserQuery) GetByRowID(ctx context.Context, rowID int) (*User, error) {
|
func (uq *UserQuery) GetByRowID(ctx context.Context, rowID int) (*User, error) {
|
||||||
return get[*User](uq, ctx, `SELECT rowid, mxid, phone_id, session, self_participant_ids, sim_metadata, management_room, space_room, access_token FROM "user" WHERE rowid=$1`, rowID)
|
return get[*User](uq, ctx, `SELECT rowid, mxid, phone_id, session, self_participant_ids, sim_metadata, settings, management_room, space_room, access_token FROM "user" WHERE rowid=$1`, rowID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (uq *UserQuery) GetByMXID(ctx context.Context, userID id.UserID) (*User, error) {
|
func (uq *UserQuery) GetByMXID(ctx context.Context, userID id.UserID) (*User, error) {
|
||||||
return get[*User](uq, ctx, `SELECT rowid, mxid, phone_id, session, self_participant_ids, sim_metadata, management_room, space_room, access_token FROM "user" WHERE mxid=$1`, userID)
|
return get[*User](uq, ctx, `SELECT rowid, mxid, phone_id, session, self_participant_ids, sim_metadata, settings, management_room, space_room, access_token FROM "user" WHERE mxid=$1`, userID)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Settings struct {
|
||||||
|
RCSEnabled bool `json:"rcs_enabled"`
|
||||||
|
ReadReceipts bool `json:"read_receipts"`
|
||||||
|
TypingNotifications bool `json:"typing_notifications"`
|
||||||
|
IsDefaultSMSApp bool `json:"is_default_sms_app"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
|
@ -79,13 +86,15 @@ type User struct {
|
||||||
simMetadata map[string]*gmproto.SIMCard
|
simMetadata map[string]*gmproto.SIMCard
|
||||||
simMetadataLock sync.RWMutex
|
simMetadataLock sync.RWMutex
|
||||||
|
|
||||||
|
Settings Settings
|
||||||
|
|
||||||
AccessToken string
|
AccessToken string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (user *User) Scan(row dbutil.Scannable) (*User, error) {
|
func (user *User) Scan(row dbutil.Scannable) (*User, error) {
|
||||||
var phoneID, session, managementRoom, spaceRoom, accessToken sql.NullString
|
var phoneID, session, managementRoom, spaceRoom, accessToken sql.NullString
|
||||||
var selfParticipantIDs, simMetadata string
|
var selfParticipantIDs, simMetadata, settings string
|
||||||
err := row.Scan(&user.RowID, &user.MXID, &phoneID, &session, &selfParticipantIDs, &simMetadata, &managementRoom, &spaceRoom, &accessToken)
|
err := row.Scan(&user.RowID, &user.MXID, &phoneID, &session, &selfParticipantIDs, &simMetadata, &settings, &managementRoom, &spaceRoom, &accessToken)
|
||||||
if errors.Is(err, sql.ErrNoRows) {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
|
@ -111,6 +120,10 @@ func (user *User) Scan(row dbutil.Scannable) (*User, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to parse SIM metadata: %w", err)
|
return nil, fmt.Errorf("failed to parse SIM metadata: %w", err)
|
||||||
}
|
}
|
||||||
|
err = json.Unmarshal([]byte(settings), &user.Settings)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to parse settings: %w", err)
|
||||||
|
}
|
||||||
user.PhoneID = phoneID.String
|
user.PhoneID = phoneID.String
|
||||||
user.AccessToken = accessToken.String
|
user.AccessToken = accessToken.String
|
||||||
user.ManagementRoom = id.RoomID(managementRoom.String)
|
user.ManagementRoom = id.RoomID(managementRoom.String)
|
||||||
|
@ -146,7 +159,11 @@ func (user *User) sqlVariables() []any {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
user.simMetadataLock.RUnlock()
|
user.simMetadataLock.RUnlock()
|
||||||
return []any{user.MXID, phoneID, session, string(selfParticipantIDs), string(simMetadata), managementRoom, spaceRoom, accessToken}
|
settings, err := json.Marshal(&user.Settings)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return []any{user.MXID, phoneID, session, string(selfParticipantIDs), string(simMetadata), string(settings), managementRoom, spaceRoom, accessToken}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (user *User) IsSelfParticipantID(id string) bool {
|
func (user *User) IsSelfParticipantID(id string) bool {
|
||||||
|
@ -233,12 +250,12 @@ func (user *User) AddSelfParticipantID(ctx context.Context, id string) error {
|
||||||
|
|
||||||
func (user *User) Insert(ctx context.Context) error {
|
func (user *User) Insert(ctx context.Context) error {
|
||||||
err := user.db.Conn(ctx).
|
err := user.db.Conn(ctx).
|
||||||
QueryRowContext(ctx, `INSERT INTO "user" (mxid, phone_id, session, self_participant_ids, sim_metadata, management_room, space_room, access_token) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING rowid`, user.sqlVariables()...).
|
QueryRowContext(ctx, `INSERT INTO "user" (mxid, phone_id, session, self_participant_ids, sim_metadata, settings, management_room, space_room, access_token) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING rowid`, user.sqlVariables()...).
|
||||||
Scan(&user.RowID)
|
Scan(&user.RowID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (user *User) Update(ctx context.Context) error {
|
func (user *User) Update(ctx context.Context) error {
|
||||||
_, err := user.db.Conn(ctx).ExecContext(ctx, `UPDATE "user" SET phone_id=$2, session=$3, self_participant_ids=$4, sim_metadata=$5, management_room=$6, space_room=$7, access_token=$8 WHERE mxid=$1`, user.sqlVariables()...)
|
_, err := user.db.Conn(ctx).ExecContext(ctx, `UPDATE "user" SET phone_id=$2, session=$3, self_participant_ids=$4, sim_metadata=$5, settings=$6, management_room=$7, space_room=$8, access_token=$9 WHERE mxid=$1`, user.sqlVariables()...)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -613,7 +613,7 @@ type RCSSettings struct {
|
||||||
IsEnabled bool `protobuf:"varint,1,opt,name=isEnabled,proto3" json:"isEnabled,omitempty"`
|
IsEnabled bool `protobuf:"varint,1,opt,name=isEnabled,proto3" json:"isEnabled,omitempty"`
|
||||||
SendReadReceipts bool `protobuf:"varint,2,opt,name=sendReadReceipts,proto3" json:"sendReadReceipts,omitempty"`
|
SendReadReceipts bool `protobuf:"varint,2,opt,name=sendReadReceipts,proto3" json:"sendReadReceipts,omitempty"`
|
||||||
ShowTypingIndicators bool `protobuf:"varint,3,opt,name=showTypingIndicators,proto3" json:"showTypingIndicators,omitempty"`
|
ShowTypingIndicators bool `protobuf:"varint,3,opt,name=showTypingIndicators,proto3" json:"showTypingIndicators,omitempty"`
|
||||||
Bool4 bool `protobuf:"varint,4,opt,name=bool4,proto3" json:"bool4,omitempty"`
|
IsDefaultSMSApp bool `protobuf:"varint,4,opt,name=isDefaultSMSApp,proto3" json:"isDefaultSMSApp,omitempty"` // uncertain, but this field seems to disappear when gmessages is un-defaulted
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RCSSettings) Reset() {
|
func (x *RCSSettings) Reset() {
|
||||||
|
@ -669,9 +669,9 @@ func (x *RCSSettings) GetShowTypingIndicators() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RCSSettings) GetBool4() bool {
|
func (x *RCSSettings) GetIsDefaultSMSApp() bool {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Bool4
|
return x.IsDefaultSMSApp
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
|
@ -64,7 +64,7 @@ message RCSSettings {
|
||||||
bool isEnabled = 1;
|
bool isEnabled = 1;
|
||||||
bool sendReadReceipts = 2;
|
bool sendReadReceipts = 2;
|
||||||
bool showTypingIndicators = 3;
|
bool showTypingIndicators = 3;
|
||||||
bool bool4 = 4;
|
bool isDefaultSMSApp = 4; // uncertain, but this field seems to disappear when gmessages is un-defaulted
|
||||||
}
|
}
|
||||||
|
|
||||||
message BooleanFields2 {
|
message BooleanFields2 {
|
||||||
|
|
17
user.go
17
user.go
|
@ -742,7 +742,21 @@ func (user *User) handleSettings(settings *gmproto.Settings) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
if user.SetSIMs(settings.SIMCards) {
|
changed := user.SetSIMs(settings.SIMCards)
|
||||||
|
newRCSSettings := settings.GetRCSSettings()
|
||||||
|
if user.Settings.RCSEnabled != newRCSSettings.GetIsEnabled() ||
|
||||||
|
user.Settings.ReadReceipts != newRCSSettings.GetSendReadReceipts() ||
|
||||||
|
user.Settings.TypingNotifications != newRCSSettings.GetShowTypingIndicators() ||
|
||||||
|
user.Settings.IsDefaultSMSApp != newRCSSettings.GetIsDefaultSMSApp() {
|
||||||
|
user.Settings = database.Settings{
|
||||||
|
RCSEnabled: newRCSSettings.GetIsEnabled(),
|
||||||
|
ReadReceipts: newRCSSettings.GetSendReadReceipts(),
|
||||||
|
TypingNotifications: newRCSSettings.GetShowTypingIndicators(),
|
||||||
|
IsDefaultSMSApp: newRCSSettings.GetIsDefaultSMSApp(),
|
||||||
|
}
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
if changed {
|
||||||
err := user.Update(ctx)
|
err := user.Update(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
user.zlog.Err(err).Msg("Failed to save SIM details")
|
user.zlog.Err(err).Msg("Failed to save SIM details")
|
||||||
|
@ -757,6 +771,7 @@ func (user *User) FillBridgeState(state status.BridgeState) status.BridgeState {
|
||||||
}
|
}
|
||||||
if state.StateEvent == status.StateConnected {
|
if state.StateEvent == status.StateConnected {
|
||||||
state.Info["sims"] = user.GetSIMsForBridgeState()
|
state.Info["sims"] = user.GetSIMsForBridgeState()
|
||||||
|
state.Info["settings"] = user.Settings
|
||||||
state.Info["battery_low"] = user.batteryLow
|
state.Info["battery_low"] = user.batteryLow
|
||||||
state.Info["mobile_data"] = user.mobileData
|
state.Info["mobile_data"] = user.mobileData
|
||||||
state.Info["browser_active"] = user.browserInactiveType == ""
|
state.Info["browser_active"] = user.browserInactiveType == ""
|
||||||
|
|
Loading…
Reference in a new issue