diff --git a/database/upgrades/00-latest-revision.sql b/database/upgrades/00-latest-revision.sql index da3d513..2ecea0e 100644 --- a/database/upgrades/00-latest-revision.sql +++ b/database/upgrades/00-latest-revision.sql @@ -1,4 +1,4 @@ --- v0 -> v4: Latest revision +-- v0 -> v5: Latest revision CREATE TABLE "user" ( -- only: postgres @@ -11,6 +11,7 @@ CREATE TABLE "user" ( session jsonb, self_participant_ids jsonb NOT NULL DEFAULT '[]', + sim_metadata jsonb NOT NULL DEFAULT '{}', management_room TEXT, space_room TEXT, diff --git a/database/upgrades/05-sim-metadata.sql b/database/upgrades/05-sim-metadata.sql new file mode 100644 index 0000000..a4fdd63 --- /dev/null +++ b/database/upgrades/05-sim-metadata.sql @@ -0,0 +1,2 @@ +-- v5: Store more SIM metadata for users +ALTER TABLE "user" ADD COLUMN sim_metadata jsonb NOT NULL DEFAULT '{}'; diff --git a/database/user.go b/database/user.go index 5251988..3000e7d 100644 --- a/database/user.go +++ b/database/user.go @@ -29,6 +29,7 @@ import ( "maunium.net/go/mautrix/id" "go.mau.fi/mautrix-gmessages/libgm" + "go.mau.fi/mautrix-gmessages/libgm/gmproto" ) type UserQuery struct { @@ -46,19 +47,19 @@ func (uq *UserQuery) getDB() *Database { } func (uq *UserQuery) GetAllWithSession(ctx context.Context) ([]*User, error) { - return getAll[*User](uq, ctx, `SELECT rowid, mxid, phone_id, session, self_participant_ids, 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, management_room, space_room, access_token FROM "user" WHERE session IS NOT NULL`) } func (uq *UserQuery) GetAllWithDoublePuppet(ctx context.Context) ([]*User, error) { - return getAll[*User](uq, ctx, `SELECT rowid, mxid, phone_id, session, self_participant_ids, 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, management_room, space_room, access_token FROM "user" WHERE access_token<>''`) } 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, 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, management_room, space_room, access_token FROM "user" WHERE rowid=$1`, rowID) } 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, 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, management_room, space_room, access_token FROM "user" WHERE mxid=$1`, userID) } type User struct { @@ -75,13 +76,16 @@ type User struct { SelfParticipantIDs []string selfParticipantIDsLock sync.RWMutex + simMetadata map[string]*gmproto.SIMCard + simMetadataLock sync.RWMutex + AccessToken string } func (user *User) Scan(row dbutil.Scannable) (*User, error) { var phoneID, session, managementRoom, spaceRoom, accessToken sql.NullString - var selfParticipantIDs string - err := row.Scan(&user.RowID, &user.MXID, &phoneID, &session, &selfParticipantIDs, &managementRoom, &spaceRoom, &accessToken) + var selfParticipantIDs, simMetadata string + err := row.Scan(&user.RowID, &user.MXID, &phoneID, &session, &selfParticipantIDs, &simMetadata, &managementRoom, &spaceRoom, &accessToken) if errors.Is(err, sql.ErrNoRows) { return nil, nil } else if err != nil { @@ -101,6 +105,12 @@ func (user *User) Scan(row dbutil.Scannable) (*User, error) { if err != nil { return nil, fmt.Errorf("failed to parse self participant IDs: %w", err) } + user.simMetadataLock.Lock() + err = json.Unmarshal([]byte(simMetadata), &user.simMetadata) + user.simMetadataLock.Unlock() + if err != nil { + return nil, fmt.Errorf("failed to parse SIM metadata: %w", err) + } user.PhoneID = phoneID.String user.AccessToken = accessToken.String user.ManagementRoom = id.RoomID(managementRoom.String) @@ -130,7 +140,13 @@ func (user *User) sqlVariables() []any { user.selfParticipantIDsLock.RLock() selfParticipantIDs, _ := json.Marshal(user.SelfParticipantIDs) user.selfParticipantIDsLock.RUnlock() - return []any{user.MXID, phoneID, session, string(selfParticipantIDs), managementRoom, spaceRoom, accessToken} + user.simMetadataLock.RLock() + simMetadata, err := json.Marshal(user.simMetadata) + if err != nil { + panic(err) + } + user.simMetadataLock.RUnlock() + return []any{user.MXID, phoneID, session, string(selfParticipantIDs), string(simMetadata), managementRoom, spaceRoom, accessToken} } func (user *User) IsSelfParticipantID(id string) bool { @@ -139,6 +155,70 @@ func (user *User) IsSelfParticipantID(id string) bool { return slices.Contains(user.SelfParticipantIDs, id) } +type bridgeStateSIMMeta struct { + CarrierName string `json:"carrier_name"` + ColorHex string `json:"color_hex"` + ParticipantID string `json:"participant_id"` + RCSEnabled bool `json:"rcs_enabled"` +} + +func (user *User) GetSIMsForBridgeState() []bridgeStateSIMMeta { + user.simMetadataLock.RLock() + data := make([]bridgeStateSIMMeta, 0, len(user.simMetadata)) + for _, sim := range user.simMetadata { + data = append(data, bridgeStateSIMMeta{ + CarrierName: sim.GetSIMData().GetCarrierName(), + ColorHex: sim.GetSIMData().GetHexHash(), + ParticipantID: sim.GetSIMParticipant().GetID(), + RCSEnabled: sim.GetRCSChats().GetEnabled(), + }) + } + user.simMetadataLock.RUnlock() + return data +} + +func (user *User) GetSIM(participantID string) *gmproto.SIMCard { + user.simMetadataLock.Lock() + defer user.simMetadataLock.Unlock() + return user.simMetadata[participantID] +} + +func simsAreEqualish(a, b *gmproto.SIMCard) bool { + return a.GetRCSChats().GetEnabled() != b.GetRCSChats().GetEnabled() || + a.GetSIMData().GetCarrierName() != b.GetSIMData().GetCarrierName() || + a.GetSIMData().GetSIMPayload().GetSIMNumber() != b.GetSIMData().GetSIMPayload().GetSIMNumber() || + a.GetSIMData().GetSIMPayload().GetTwo() != b.GetSIMData().GetSIMPayload().GetTwo() +} + +func (user *User) SetSIMs(sims []*gmproto.SIMCard) bool { + user.simMetadataLock.Lock() + defer user.simMetadataLock.Unlock() + user.selfParticipantIDsLock.Lock() + defer user.selfParticipantIDsLock.Unlock() + newMap := make(map[string]*gmproto.SIMCard) + participantIDsChanged := false + for _, sim := range sims { + participantID := sim.GetSIMParticipant().GetID() + newMap[sim.GetSIMParticipant().GetID()] = sim + if !slices.Contains(user.SelfParticipantIDs, participantID) { + user.SelfParticipantIDs = append(user.SelfParticipantIDs, participantID) + participantIDsChanged = true + } + } + oldMap := user.simMetadata + user.simMetadata = newMap + if participantIDsChanged || len(newMap) != len(oldMap) { + return true + } + for participantID, sim := range newMap { + existing, ok := oldMap[participantID] + if !ok || !simsAreEqualish(existing, sim) { + return true + } + } + return false +} + func (user *User) AddSelfParticipantID(ctx context.Context, id string) error { user.selfParticipantIDsLock.Lock() defer user.selfParticipantIDsLock.Unlock() @@ -153,12 +233,12 @@ func (user *User) AddSelfParticipantID(ctx context.Context, id string) error { func (user *User) Insert(ctx context.Context) error { err := user.db.Conn(ctx). - QueryRowContext(ctx, `INSERT INTO "user" (mxid, phone_id, session, self_participant_ids, management_room, space_room, access_token) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING rowid`, user.sqlVariables()...). + 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()...). Scan(&user.RowID) return err } 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, management_room=$5, space_room=$6, access_token=$7 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, management_room=$6, space_room=$7, access_token=$8 WHERE mxid=$1`, user.sqlVariables()...) return err } diff --git a/libgm/event_handler.go b/libgm/event_handler.go index 4b7c833..967864b 100644 --- a/libgm/event_handler.go +++ b/libgm/event_handler.go @@ -186,7 +186,9 @@ func (c *Client) handleUpdatesEvent(msg *IncomingRPCMessage) { c.triggerEvent(evt.UserAlertEvent) case *gmproto.UpdateEvents_SettingsEvent: - c.logContent(msg, "", nil) + c.Logger.Debug(). + Str("data", base64.StdEncoding.EncodeToString(msg.DecryptedData)). + Msg("Got settings event") c.triggerEvent(evt.SettingsEvent) case *gmproto.UpdateEvents_ConversationEvent: diff --git a/libgm/gmproto/client.pb.go b/libgm/gmproto/client.pb.go index 80963e8..e8f7cfa 100644 --- a/libgm/gmproto/client.pb.go +++ b/libgm/gmproto/client.pb.go @@ -2419,6 +2419,7 @@ type SendMessageRequest struct { ConversationID string `protobuf:"bytes,2,opt,name=conversationID,proto3" json:"conversationID,omitempty"` MessagePayload *MessagePayload `protobuf:"bytes,3,opt,name=messagePayload,proto3" json:"messagePayload,omitempty"` + SIMPayload *SIMPayload `protobuf:"bytes,4,opt,name=SIMPayload,proto3" json:"SIMPayload,omitempty"` TmpID string `protobuf:"bytes,5,opt,name=tmpID,proto3" json:"tmpID,omitempty"` IsReply bool `protobuf:"varint,6,opt,name=isReply,proto3" json:"isReply,omitempty"` // not sure Reply *ReplyPayload `protobuf:"bytes,8,opt,name=reply,proto3" json:"reply,omitempty"` @@ -2470,6 +2471,13 @@ func (x *SendMessageRequest) GetMessagePayload() *MessagePayload { return nil } +func (x *SendMessageRequest) GetSIMPayload() *SIMPayload { + if x != nil { + return x.SIMPayload + } + return nil +} + func (x *SendMessageRequest) GetTmpID() string { if x != nil { return x.TmpID @@ -3204,9 +3212,10 @@ var file_client_proto_goTypes = []interface{}{ (*Conversation)(nil), // 63: conversations.Conversation (*ContactNumber)(nil), // 64: conversations.ContactNumber (ConversationStatus)(0), // 65: conversations.ConversationStatus - (*MessageInfo)(nil), // 66: conversations.MessageInfo - (*MessageContent)(nil), // 67: conversations.MessageContent - (*ReactionData)(nil), // 68: conversations.ReactionData + (*SIMPayload)(nil), // 66: settings.SIMPayload + (*MessageInfo)(nil), // 67: conversations.MessageInfo + (*MessageContent)(nil), // 68: conversations.MessageContent + (*ReactionData)(nil), // 69: conversations.ReactionData } var file_client_proto_depIdxs = []int32{ 57, // 0: client.ReceiveMessagesRequest.auth:type_name -> authentication.AuthMessage @@ -3241,20 +3250,21 @@ var file_client_proto_depIdxs = []int32{ 1, // 29: client.UpdateConversationData.mute:type_name -> client.ConversationMuteStatus 63, // 30: client.GetConversationResponse.conversation:type_name -> conversations.Conversation 46, // 31: client.SendMessageRequest.messagePayload:type_name -> client.MessagePayload - 45, // 32: client.SendMessageRequest.reply:type_name -> client.ReplyPayload - 47, // 33: client.MessagePayload.messagePayloadContent:type_name -> client.MessagePayloadContent - 66, // 34: client.MessagePayload.messageInfo:type_name -> conversations.MessageInfo - 67, // 35: client.MessagePayloadContent.messageContent:type_name -> conversations.MessageContent - 68, // 36: client.SendReactionRequest.reactionData:type_name -> conversations.ReactionData - 4, // 37: client.SendReactionRequest.action:type_name -> client.SendReactionRequest.Action - 56, // 38: client.TypingUpdateRequest.data:type_name -> client.TypingUpdateRequest.Data - 53, // 39: client.ReceiveMessagesRequest.UnknownEmptyObject2.unknown:type_name -> client.ReceiveMessagesRequest.UnknownEmptyObject1 - 59, // 40: client.AckMessageRequest.Message.device:type_name -> authentication.Device - 41, // [41:41] is the sub-list for method output_type - 41, // [41:41] is the sub-list for method input_type - 41, // [41:41] is the sub-list for extension type_name - 41, // [41:41] is the sub-list for extension extendee - 0, // [0:41] is the sub-list for field type_name + 66, // 32: client.SendMessageRequest.SIMPayload:type_name -> settings.SIMPayload + 45, // 33: client.SendMessageRequest.reply:type_name -> client.ReplyPayload + 47, // 34: client.MessagePayload.messagePayloadContent:type_name -> client.MessagePayloadContent + 67, // 35: client.MessagePayload.messageInfo:type_name -> conversations.MessageInfo + 68, // 36: client.MessagePayloadContent.messageContent:type_name -> conversations.MessageContent + 69, // 37: client.SendReactionRequest.reactionData:type_name -> conversations.ReactionData + 4, // 38: client.SendReactionRequest.action:type_name -> client.SendReactionRequest.Action + 56, // 39: client.TypingUpdateRequest.data:type_name -> client.TypingUpdateRequest.Data + 53, // 40: client.ReceiveMessagesRequest.UnknownEmptyObject2.unknown:type_name -> client.ReceiveMessagesRequest.UnknownEmptyObject1 + 59, // 41: client.AckMessageRequest.Message.device:type_name -> authentication.Device + 42, // [42:42] is the sub-list for method output_type + 42, // [42:42] is the sub-list for method input_type + 42, // [42:42] is the sub-list for extension type_name + 42, // [42:42] is the sub-list for extension extendee + 0, // [0:42] is the sub-list for field type_name } func init() { file_client_proto_init() } @@ -3264,6 +3274,7 @@ func file_client_proto_init() { } file_conversations_proto_init() file_authentication_proto_init() + file_settings_proto_init() file_util_proto_init() if !protoimpl.UnsafeEnabled { file_client_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { diff --git a/libgm/gmproto/client.pb.raw b/libgm/gmproto/client.pb.raw index 19c4352..bcdb622 100644 Binary files a/libgm/gmproto/client.pb.raw and b/libgm/gmproto/client.pb.raw differ diff --git a/libgm/gmproto/client.proto b/libgm/gmproto/client.proto index 49ec0cf..6e13b0d 100644 --- a/libgm/gmproto/client.proto +++ b/libgm/gmproto/client.proto @@ -5,6 +5,7 @@ option go_package = "../gmproto"; import "conversations.proto"; import "authentication.proto"; +import "settings.proto"; import "util.proto"; message NotifyDittoActivityRequest { @@ -249,6 +250,7 @@ message IsBugleDefaultResponse { message SendMessageRequest { string conversationID = 2; MessagePayload messagePayload = 3; + settings.SIMPayload SIMPayload = 4; string tmpID = 5; bool isReply = 6; // not sure ReplyPayload reply = 8; diff --git a/libgm/gmproto/settings.pb.go b/libgm/gmproto/settings.pb.go index 4102efb..51a990b 100644 --- a/libgm/gmproto/settings.pb.go +++ b/libgm/gmproto/settings.pb.go @@ -27,9 +27,9 @@ type Settings struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Data *Data `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + SIMCards []*SIMCard `protobuf:"bytes,2,rep,name=SIMCards,proto3" json:"SIMCards,omitempty"` OpCodeData *SomeData `protobuf:"bytes,3,opt,name=opCodeData,proto3" json:"opCodeData,omitempty"` - RcsSettings *RCSSettings `protobuf:"bytes,4,opt,name=rcsSettings,proto3" json:"rcsSettings,omitempty"` + RCSSettings *RCSSettings `protobuf:"bytes,4,opt,name=RCSSettings,proto3" json:"RCSSettings,omitempty"` BugleVersion string `protobuf:"bytes,5,opt,name=bugleVersion,proto3" json:"bugleVersion,omitempty"` Bool1 bool `protobuf:"varint,7,opt,name=bool1,proto3" json:"bool1,omitempty"` BoolFields2 *BooleanFields2 `protobuf:"bytes,8,opt,name=boolFields2,proto3" json:"boolFields2,omitempty"` @@ -69,9 +69,9 @@ func (*Settings) Descriptor() ([]byte, []int) { return file_settings_proto_rawDescGZIP(), []int{0} } -func (x *Settings) GetData() *Data { +func (x *Settings) GetSIMCards() []*SIMCard { if x != nil { - return x.Data + return x.SIMCards } return nil } @@ -83,9 +83,9 @@ func (x *Settings) GetOpCodeData() *SomeData { return nil } -func (x *Settings) GetRcsSettings() *RCSSettings { +func (x *Settings) GetRCSSettings() *RCSSettings { if x != nil { - return x.RcsSettings + return x.RCSSettings } return nil } @@ -125,19 +125,19 @@ func (x *Settings) GetBoolFields3() *BooleanFields3 { return nil } -type Data struct { +type SIMCard struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - RcsChats *RCSChats `protobuf:"bytes,3,opt,name=rcsChats,proto3" json:"rcsChats,omitempty"` - SimData *SimData `protobuf:"bytes,5,opt,name=simData,proto3" json:"simData,omitempty"` - Bool1 bool `protobuf:"varint,6,opt,name=bool1,proto3" json:"bool1,omitempty"` - NoClue *NoClue `protobuf:"bytes,7,opt,name=noClue,proto3" json:"noClue,omitempty"` + RCSChats *RCSChats `protobuf:"bytes,3,opt,name=RCSChats,proto3,oneof" json:"RCSChats,omitempty"` + SIMData *SIMData `protobuf:"bytes,5,opt,name=SIMData,proto3" json:"SIMData,omitempty"` + Bool1 bool `protobuf:"varint,6,opt,name=bool1,proto3" json:"bool1,omitempty"` + SIMParticipant *SIMParticipant `protobuf:"bytes,7,opt,name=SIMParticipant,proto3" json:"SIMParticipant,omitempty"` } -func (x *Data) Reset() { - *x = Data{} +func (x *SIMCard) Reset() { + *x = SIMCard{} if protoimpl.UnsafeEnabled { mi := &file_settings_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -145,13 +145,13 @@ func (x *Data) Reset() { } } -func (x *Data) String() string { +func (x *SIMCard) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Data) ProtoMessage() {} +func (*SIMCard) ProtoMessage() {} -func (x *Data) ProtoReflect() protoreflect.Message { +func (x *SIMCard) ProtoReflect() protoreflect.Message { mi := &file_settings_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -163,35 +163,35 @@ func (x *Data) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Data.ProtoReflect.Descriptor instead. -func (*Data) Descriptor() ([]byte, []int) { +// Deprecated: Use SIMCard.ProtoReflect.Descriptor instead. +func (*SIMCard) Descriptor() ([]byte, []int) { return file_settings_proto_rawDescGZIP(), []int{1} } -func (x *Data) GetRcsChats() *RCSChats { +func (x *SIMCard) GetRCSChats() *RCSChats { if x != nil { - return x.RcsChats + return x.RCSChats } return nil } -func (x *Data) GetSimData() *SimData { +func (x *SIMCard) GetSIMData() *SIMData { if x != nil { - return x.SimData + return x.SIMData } return nil } -func (x *Data) GetBool1() bool { +func (x *SIMCard) GetBool1() bool { if x != nil { return x.Bool1 } return false } -func (x *Data) GetNoClue() *NoClue { +func (x *SIMCard) GetSIMParticipant() *SIMParticipant { if x != nil { - return x.NoClue + return x.SIMParticipant } return nil } @@ -290,20 +290,17 @@ func (x *BoolMsg) GetBool1() bool { return false } -type SimData struct { +type SIMPayload struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - UnknownMessage *UnknownMessage `protobuf:"bytes,1,opt,name=unknownMessage,proto3" json:"unknownMessage,omitempty"` - Bool1 bool `protobuf:"varint,2,opt,name=bool1,proto3" json:"bool1,omitempty"` - CarrierName string `protobuf:"bytes,3,opt,name=carrierName,proto3" json:"carrierName,omitempty"` - HexHash string `protobuf:"bytes,4,opt,name=hexHash,proto3" json:"hexHash,omitempty"` - Int1 int64 `protobuf:"varint,5,opt,name=int1,proto3" json:"int1,omitempty"` + Two int32 `protobuf:"varint,1,opt,name=two,proto3" json:"two,omitempty"` + SIMNumber int32 `protobuf:"varint,2,opt,name=SIMNumber,proto3" json:"SIMNumber,omitempty"` } -func (x *SimData) Reset() { - *x = SimData{} +func (x *SIMPayload) Reset() { + *x = SIMPayload{} if protoimpl.UnsafeEnabled { mi := &file_settings_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -311,13 +308,13 @@ func (x *SimData) Reset() { } } -func (x *SimData) String() string { +func (x *SIMPayload) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SimData) ProtoMessage() {} +func (*SIMPayload) ProtoMessage() {} -func (x *SimData) ProtoReflect() protoreflect.Message { +func (x *SIMPayload) ProtoReflect() protoreflect.Message { mi := &file_settings_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -329,40 +326,98 @@ func (x *SimData) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use SimData.ProtoReflect.Descriptor instead. -func (*SimData) Descriptor() ([]byte, []int) { +// Deprecated: Use SIMPayload.ProtoReflect.Descriptor instead. +func (*SIMPayload) Descriptor() ([]byte, []int) { return file_settings_proto_rawDescGZIP(), []int{4} } -func (x *SimData) GetUnknownMessage() *UnknownMessage { +func (x *SIMPayload) GetTwo() int32 { if x != nil { - return x.UnknownMessage + return x.Two + } + return 0 +} + +func (x *SIMPayload) GetSIMNumber() int32 { + if x != nil { + return x.SIMNumber + } + return 0 +} + +type SIMData struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SIMPayload *SIMPayload `protobuf:"bytes,1,opt,name=SIMPayload,proto3" json:"SIMPayload,omitempty"` + Bool1 bool `protobuf:"varint,2,opt,name=bool1,proto3" json:"bool1,omitempty"` + CarrierName string `protobuf:"bytes,3,opt,name=carrierName,proto3" json:"carrierName,omitempty"` + HexHash string `protobuf:"bytes,4,opt,name=hexHash,proto3" json:"hexHash,omitempty"` + Int1 int64 `protobuf:"varint,5,opt,name=int1,proto3" json:"int1,omitempty"` +} + +func (x *SIMData) Reset() { + *x = SIMData{} + if protoimpl.UnsafeEnabled { + mi := &file_settings_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SIMData) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SIMData) ProtoMessage() {} + +func (x *SIMData) ProtoReflect() protoreflect.Message { + mi := &file_settings_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SIMData.ProtoReflect.Descriptor instead. +func (*SIMData) Descriptor() ([]byte, []int) { + return file_settings_proto_rawDescGZIP(), []int{5} +} + +func (x *SIMData) GetSIMPayload() *SIMPayload { + if x != nil { + return x.SIMPayload } return nil } -func (x *SimData) GetBool1() bool { +func (x *SIMData) GetBool1() bool { if x != nil { return x.Bool1 } return false } -func (x *SimData) GetCarrierName() string { +func (x *SIMData) GetCarrierName() string { if x != nil { return x.CarrierName } return "" } -func (x *SimData) GetHexHash() string { +func (x *SIMData) GetHexHash() string { if x != nil { return x.HexHash } return "" } -func (x *SimData) GetInt1() int64 { +func (x *SIMData) GetInt1() int64 { if x != nil { return x.Int1 } @@ -381,7 +436,7 @@ type UnknownMessage struct { func (x *UnknownMessage) Reset() { *x = UnknownMessage{} if protoimpl.UnsafeEnabled { - mi := &file_settings_proto_msgTypes[5] + mi := &file_settings_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -394,7 +449,7 @@ func (x *UnknownMessage) String() string { func (*UnknownMessage) ProtoMessage() {} func (x *UnknownMessage) ProtoReflect() protoreflect.Message { - mi := &file_settings_proto_msgTypes[5] + mi := &file_settings_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -407,7 +462,7 @@ func (x *UnknownMessage) ProtoReflect() protoreflect.Message { // Deprecated: Use UnknownMessage.ProtoReflect.Descriptor instead. func (*UnknownMessage) Descriptor() ([]byte, []int) { - return file_settings_proto_rawDescGZIP(), []int{5} + return file_settings_proto_rawDescGZIP(), []int{6} } func (x *UnknownMessage) GetInt1() int64 { @@ -424,31 +479,31 @@ func (x *UnknownMessage) GetInt2() int64 { return 0 } -type NoClue struct { +type SIMParticipant struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Count string `protobuf:"bytes,1,opt,name=count,proto3" json:"count,omitempty"` + ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"` } -func (x *NoClue) Reset() { - *x = NoClue{} +func (x *SIMParticipant) Reset() { + *x = SIMParticipant{} if protoimpl.UnsafeEnabled { - mi := &file_settings_proto_msgTypes[6] + mi := &file_settings_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *NoClue) String() string { +func (x *SIMParticipant) String() string { return protoimpl.X.MessageStringOf(x) } -func (*NoClue) ProtoMessage() {} +func (*SIMParticipant) ProtoMessage() {} -func (x *NoClue) ProtoReflect() protoreflect.Message { - mi := &file_settings_proto_msgTypes[6] +func (x *SIMParticipant) ProtoReflect() protoreflect.Message { + mi := &file_settings_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -459,14 +514,14 @@ func (x *NoClue) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use NoClue.ProtoReflect.Descriptor instead. -func (*NoClue) Descriptor() ([]byte, []int) { - return file_settings_proto_rawDescGZIP(), []int{6} +// Deprecated: Use SIMParticipant.ProtoReflect.Descriptor instead. +func (*SIMParticipant) Descriptor() ([]byte, []int) { + return file_settings_proto_rawDescGZIP(), []int{7} } -func (x *NoClue) GetCount() string { +func (x *SIMParticipant) GetID() string { if x != nil { - return x.Count + return x.ID } return "" } @@ -486,7 +541,7 @@ type SomeData struct { func (x *SomeData) Reset() { *x = SomeData{} if protoimpl.UnsafeEnabled { - mi := &file_settings_proto_msgTypes[7] + mi := &file_settings_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -499,7 +554,7 @@ func (x *SomeData) String() string { func (*SomeData) ProtoMessage() {} func (x *SomeData) ProtoReflect() protoreflect.Message { - mi := &file_settings_proto_msgTypes[7] + mi := &file_settings_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -512,7 +567,7 @@ func (x *SomeData) ProtoReflect() protoreflect.Message { // Deprecated: Use SomeData.ProtoReflect.Descriptor instead. func (*SomeData) Descriptor() ([]byte, []int) { - return file_settings_proto_rawDescGZIP(), []int{7} + return file_settings_proto_rawDescGZIP(), []int{8} } func (x *SomeData) GetField7() bool { @@ -564,7 +619,7 @@ type RCSSettings struct { func (x *RCSSettings) Reset() { *x = RCSSettings{} if protoimpl.UnsafeEnabled { - mi := &file_settings_proto_msgTypes[8] + mi := &file_settings_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -577,7 +632,7 @@ func (x *RCSSettings) String() string { func (*RCSSettings) ProtoMessage() {} func (x *RCSSettings) ProtoReflect() protoreflect.Message { - mi := &file_settings_proto_msgTypes[8] + mi := &file_settings_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -590,7 +645,7 @@ func (x *RCSSettings) ProtoReflect() protoreflect.Message { // Deprecated: Use RCSSettings.ProtoReflect.Descriptor instead. func (*RCSSettings) Descriptor() ([]byte, []int) { - return file_settings_proto_rawDescGZIP(), []int{8} + return file_settings_proto_rawDescGZIP(), []int{9} } func (x *RCSSettings) GetIsEnabled() bool { @@ -636,7 +691,7 @@ type BooleanFields2 struct { func (x *BooleanFields2) Reset() { *x = BooleanFields2{} if protoimpl.UnsafeEnabled { - mi := &file_settings_proto_msgTypes[9] + mi := &file_settings_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -649,7 +704,7 @@ func (x *BooleanFields2) String() string { func (*BooleanFields2) ProtoMessage() {} func (x *BooleanFields2) ProtoReflect() protoreflect.Message { - mi := &file_settings_proto_msgTypes[9] + mi := &file_settings_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -662,7 +717,7 @@ func (x *BooleanFields2) ProtoReflect() protoreflect.Message { // Deprecated: Use BooleanFields2.ProtoReflect.Descriptor instead. func (*BooleanFields2) Descriptor() ([]byte, []int) { - return file_settings_proto_rawDescGZIP(), []int{9} + return file_settings_proto_rawDescGZIP(), []int{10} } func (x *BooleanFields2) GetBool1() bool { @@ -718,7 +773,7 @@ type BooleanFields3 struct { func (x *BooleanFields3) Reset() { *x = BooleanFields3{} if protoimpl.UnsafeEnabled { - mi := &file_settings_proto_msgTypes[10] + mi := &file_settings_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -731,7 +786,7 @@ func (x *BooleanFields3) String() string { func (*BooleanFields3) ProtoMessage() {} func (x *BooleanFields3) ProtoReflect() protoreflect.Message { - mi := &file_settings_proto_msgTypes[10] + mi := &file_settings_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -744,7 +799,7 @@ func (x *BooleanFields3) ProtoReflect() protoreflect.Message { // Deprecated: Use BooleanFields3.ProtoReflect.Descriptor instead. func (*BooleanFields3) Descriptor() ([]byte, []int) { - return file_settings_proto_rawDescGZIP(), []int{10} + return file_settings_proto_rawDescGZIP(), []int{11} } func (x *BooleanFields3) GetBool1() bool { @@ -820,30 +875,31 @@ func file_settings_proto_rawDescGZIP() []byte { return file_settings_proto_rawDescData } -var file_settings_proto_msgTypes = make([]protoimpl.MessageInfo, 11) +var file_settings_proto_msgTypes = make([]protoimpl.MessageInfo, 12) var file_settings_proto_goTypes = []interface{}{ (*Settings)(nil), // 0: settings.Settings - (*Data)(nil), // 1: settings.Data + (*SIMCard)(nil), // 1: settings.SIMCard (*RCSChats)(nil), // 2: settings.RCSChats (*BoolMsg)(nil), // 3: settings.BoolMsg - (*SimData)(nil), // 4: settings.SimData - (*UnknownMessage)(nil), // 5: settings.UnknownMessage - (*NoClue)(nil), // 6: settings.NoClue - (*SomeData)(nil), // 7: settings.SomeData - (*RCSSettings)(nil), // 8: settings.RCSSettings - (*BooleanFields2)(nil), // 9: settings.BooleanFields2 - (*BooleanFields3)(nil), // 10: settings.BooleanFields3 + (*SIMPayload)(nil), // 4: settings.SIMPayload + (*SIMData)(nil), // 5: settings.SIMData + (*UnknownMessage)(nil), // 6: settings.UnknownMessage + (*SIMParticipant)(nil), // 7: settings.SIMParticipant + (*SomeData)(nil), // 8: settings.SomeData + (*RCSSettings)(nil), // 9: settings.RCSSettings + (*BooleanFields2)(nil), // 10: settings.BooleanFields2 + (*BooleanFields3)(nil), // 11: settings.BooleanFields3 } var file_settings_proto_depIdxs = []int32{ - 1, // 0: settings.Settings.data:type_name -> settings.Data - 7, // 1: settings.Settings.opCodeData:type_name -> settings.SomeData - 8, // 2: settings.Settings.rcsSettings:type_name -> settings.RCSSettings - 9, // 3: settings.Settings.boolFields2:type_name -> settings.BooleanFields2 - 10, // 4: settings.Settings.boolFields3:type_name -> settings.BooleanFields3 - 2, // 5: settings.Data.rcsChats:type_name -> settings.RCSChats - 4, // 6: settings.Data.simData:type_name -> settings.SimData - 6, // 7: settings.Data.noClue:type_name -> settings.NoClue - 5, // 8: settings.SimData.unknownMessage:type_name -> settings.UnknownMessage + 1, // 0: settings.Settings.SIMCards:type_name -> settings.SIMCard + 8, // 1: settings.Settings.opCodeData:type_name -> settings.SomeData + 9, // 2: settings.Settings.RCSSettings:type_name -> settings.RCSSettings + 10, // 3: settings.Settings.boolFields2:type_name -> settings.BooleanFields2 + 11, // 4: settings.Settings.boolFields3:type_name -> settings.BooleanFields3 + 2, // 5: settings.SIMCard.RCSChats:type_name -> settings.RCSChats + 5, // 6: settings.SIMCard.SIMData:type_name -> settings.SIMData + 7, // 7: settings.SIMCard.SIMParticipant:type_name -> settings.SIMParticipant + 4, // 8: settings.SIMData.SIMPayload:type_name -> settings.SIMPayload 3, // 9: settings.BooleanFields2.boolMsg1:type_name -> settings.BoolMsg 3, // 10: settings.BooleanFields2.boolMsg2:type_name -> settings.BoolMsg 11, // [11:11] is the sub-list for method output_type @@ -872,7 +928,7 @@ func file_settings_proto_init() { } } file_settings_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Data); i { + switch v := v.(*SIMCard); i { case 0: return &v.state case 1: @@ -908,7 +964,7 @@ func file_settings_proto_init() { } } file_settings_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SimData); i { + switch v := v.(*SIMPayload); i { case 0: return &v.state case 1: @@ -920,7 +976,7 @@ func file_settings_proto_init() { } } file_settings_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UnknownMessage); i { + switch v := v.(*SIMData); i { case 0: return &v.state case 1: @@ -932,7 +988,7 @@ func file_settings_proto_init() { } } file_settings_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NoClue); i { + switch v := v.(*UnknownMessage); i { case 0: return &v.state case 1: @@ -944,7 +1000,7 @@ func file_settings_proto_init() { } } file_settings_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SomeData); i { + switch v := v.(*SIMParticipant); i { case 0: return &v.state case 1: @@ -956,7 +1012,7 @@ func file_settings_proto_init() { } } file_settings_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RCSSettings); i { + switch v := v.(*SomeData); i { case 0: return &v.state case 1: @@ -968,7 +1024,7 @@ func file_settings_proto_init() { } } file_settings_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BooleanFields2); i { + switch v := v.(*RCSSettings); i { case 0: return &v.state case 1: @@ -980,6 +1036,18 @@ func file_settings_proto_init() { } } file_settings_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BooleanFields2); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_settings_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BooleanFields3); i { case 0: return &v.state @@ -992,13 +1060,14 @@ func file_settings_proto_init() { } } } + file_settings_proto_msgTypes[1].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_settings_proto_rawDesc, NumEnums: 0, - NumMessages: 11, + NumMessages: 12, NumExtensions: 0, NumServices: 0, }, diff --git a/libgm/gmproto/settings.pb.raw b/libgm/gmproto/settings.pb.raw index 1da60c0..d0f4b66 100644 Binary files a/libgm/gmproto/settings.pb.raw and b/libgm/gmproto/settings.pb.raw differ diff --git a/libgm/gmproto/settings.proto b/libgm/gmproto/settings.proto index 9f263c1..e180b0b 100644 --- a/libgm/gmproto/settings.proto +++ b/libgm/gmproto/settings.proto @@ -5,9 +5,9 @@ option go_package = "../gmproto"; message Settings { - Data data = 2; + repeated SIMCard SIMCards = 2; SomeData opCodeData = 3; - RCSSettings rcsSettings = 4; + RCSSettings RCSSettings = 4; string bugleVersion = 5; bool bool1 = 7; BooleanFields2 boolFields2 = 8; @@ -15,11 +15,11 @@ message Settings { BooleanFields3 boolFields3 = 10; } -message Data { // i think its simdata? no clue - RCSChats rcsChats = 3; - SimData simData = 5; +message SIMCard { + optional RCSChats RCSChats = 3; + SIMData SIMData = 5; bool bool1 = 6; - NoClue noClue = 7; + SIMParticipant SIMParticipant = 7; } message RCSChats { @@ -30,8 +30,13 @@ message BoolMsg { bool bool1 = 1; } -message SimData { - UnknownMessage unknownMessage = 1; +message SIMPayload { + int32 two = 1; + int32 SIMNumber = 2; +} + +message SIMData { + SIMPayload SIMPayload = 1; bool bool1 = 2; string carrierName = 3; string hexHash = 4; @@ -43,8 +48,8 @@ message UnknownMessage { int64 int2 = 2; } -message NoClue { // just a guess lol - string count = 1; +message SIMParticipant { + string ID = 1; } message SomeData { diff --git a/portal.go b/portal.go index 7da3166..6486f11 100644 --- a/portal.go +++ b/portal.go @@ -1628,6 +1628,7 @@ func (portal *Portal) convertMatrixMessage(ctx context.Context, sender *User, co TmpID2: txnID, ParticipantID: portal.OutgoingID, }, + SIMPayload: sender.GetSIM(portal.OutgoingID).GetSIMData().GetSIMPayload(), } replyToMXID := content.RelatesTo.GetReplyTo() diff --git a/user.go b/user.go index 9c726ef..5c0eec7 100644 --- a/user.go +++ b/user.go @@ -617,6 +617,8 @@ func (user *User) syncHandleEvent(event any) { portal.messages <- PortalMessage{evt: v.Message, source: user, raw: v.Data} case *gmproto.UserAlertEvent: user.handleUserAlert(v) + case *gmproto.Settings: + user.handleSettings(v) default: user.zlog.Trace().Any("data", v).Type("data_type", v).Msg("Unknown event") } @@ -735,11 +737,26 @@ func (user *User) handleUserAlert(v *gmproto.UserAlertEvent) { user.BridgeState.Send(status.BridgeState{StateEvent: status.StateConnected}) } +func (user *User) handleSettings(settings *gmproto.Settings) { + if settings.SIMCards == nil { + return + } + ctx := context.TODO() + if user.SetSIMs(settings.SIMCards) { + err := user.Update(ctx) + if err != nil { + user.zlog.Err(err).Msg("Failed to save SIM details") + } + user.BridgeState.Send(status.BridgeState{StateEvent: status.StateConnected}) + } +} + func (user *User) FillBridgeState(state status.BridgeState) status.BridgeState { if state.Info == nil { state.Info = make(map[string]any) } if state.StateEvent == status.StateConnected { + state.Info["sims"] = user.GetSIMsForBridgeState() state.Info["battery_low"] = user.batteryLow state.Info["mobile_data"] = user.mobileData state.Info["browser_active"] = user.browserInactiveType == ""