store.go 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. // Copyright (c) 2025 Tulir Asokan
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this
  5. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. // Package store contains interfaces for storing data needed for WhatsApp multidevice.
  7. package store
  8. import (
  9. "context"
  10. waProto "git.bobomao.top/joey/testwh/binary/proto"
  11. "time"
  12. "github.com/google/uuid"
  13. "git.bobomao.top/joey/testwh/proto/waAdv"
  14. "git.bobomao.top/joey/testwh/types"
  15. "git.bobomao.top/joey/testwh/util/keys"
  16. waLog "git.bobomao.top/joey/testwh/util/log"
  17. )
  18. type IdentityStore interface {
  19. PutIdentity(ctx context.Context, address string, key [32]byte) error
  20. DeleteAllIdentities(ctx context.Context, phone string) error
  21. DeleteIdentity(ctx context.Context, address string) error
  22. IsTrustedIdentity(ctx context.Context, address string, key [32]byte) (bool, error)
  23. }
  24. type SessionStore interface {
  25. GetSession(ctx context.Context, address string) ([]byte, error)
  26. HasSession(ctx context.Context, address string) (bool, error)
  27. GetManySessions(ctx context.Context, addresses []string) (map[string][]byte, error)
  28. PutSession(ctx context.Context, address string, session []byte) error
  29. PutManySessions(ctx context.Context, sessions map[string][]byte) error
  30. DeleteAllSessions(ctx context.Context, phone string) error
  31. DeleteSession(ctx context.Context, address string) error
  32. MigratePNToLID(ctx context.Context, pn, lid types.JID) error
  33. }
  34. type PreKeyStore interface {
  35. GetOrGenPreKeys(ctx context.Context, count uint32) ([]*keys.PreKey, error)
  36. GenOnePreKey(ctx context.Context) (*keys.PreKey, error)
  37. GetPreKey(ctx context.Context, id uint32) (*keys.PreKey, error)
  38. RemovePreKey(ctx context.Context, id uint32) error
  39. MarkPreKeysAsUploaded(ctx context.Context, upToID uint32) error
  40. UploadedPreKeyCount(ctx context.Context) (int, error)
  41. }
  42. type SenderKeyStore interface {
  43. PutSenderKey(ctx context.Context, group, user string, session []byte) error
  44. GetSenderKey(ctx context.Context, group, user string) ([]byte, error)
  45. }
  46. type AppStateSyncKey struct {
  47. Data []byte
  48. Fingerprint []byte
  49. Timestamp int64
  50. }
  51. type AppStateSyncKeyStore interface {
  52. PutAppStateSyncKey(ctx context.Context, id []byte, key AppStateSyncKey) error
  53. GetAppStateSyncKey(ctx context.Context, id []byte) (*AppStateSyncKey, error)
  54. GetLatestAppStateSyncKeyID(ctx context.Context) ([]byte, error)
  55. }
  56. type AppStateMutationMAC struct {
  57. IndexMAC []byte
  58. ValueMAC []byte
  59. }
  60. type AppStateStore interface {
  61. PutAppStateVersion(ctx context.Context, name string, version uint64, hash [128]byte) error
  62. GetAppStateVersion(ctx context.Context, name string) (uint64, [128]byte, error)
  63. DeleteAppStateVersion(ctx context.Context, name string) error
  64. PutAppStateMutationMACs(ctx context.Context, name string, version uint64, mutations []AppStateMutationMAC) error
  65. DeleteAppStateMutationMACs(ctx context.Context, name string, indexMACs [][]byte) error
  66. GetAppStateMutationMAC(ctx context.Context, name string, indexMAC []byte) (valueMAC []byte, err error)
  67. }
  68. type ContactEntry struct {
  69. JID types.JID
  70. FirstName string
  71. FullName string
  72. }
  73. func (ce ContactEntry) GetMassInsertValues() [3]any {
  74. return [...]any{ce.JID.String(), ce.FirstName, ce.FullName}
  75. }
  76. type RedactedPhoneEntry struct {
  77. JID types.JID
  78. RedactedPhone string
  79. }
  80. func (rpe RedactedPhoneEntry) GetMassInsertValues() [2]any {
  81. return [...]any{rpe.JID.String(), rpe.RedactedPhone}
  82. }
  83. type ContactStore interface {
  84. PutPushName(ctx context.Context, user types.JID, pushName string) (bool, string, error)
  85. PutBusinessName(ctx context.Context, user types.JID, businessName string) (bool, string, error)
  86. PutContactName(ctx context.Context, user types.JID, fullName, firstName string) error
  87. PutAllContactNames(ctx context.Context, contacts []ContactEntry) error
  88. PutManyRedactedPhones(ctx context.Context, entries []RedactedPhoneEntry) error
  89. GetContact(ctx context.Context, user types.JID) (types.ContactInfo, error)
  90. GetAllContacts(ctx context.Context) (map[types.JID]types.ContactInfo, error)
  91. }
  92. var MutedForever = time.Date(9999, 12, 31, 23, 59, 59, 999999999, time.UTC)
  93. type ChatSettingsStore interface {
  94. PutMutedUntil(ctx context.Context, chat types.JID, mutedUntil time.Time) error
  95. PutPinned(ctx context.Context, chat types.JID, pinned bool) error
  96. PutArchived(ctx context.Context, chat types.JID, archived bool) error
  97. GetChatSettings(ctx context.Context, chat types.JID) (types.LocalChatSettings, error)
  98. }
  99. type DeviceContainer interface {
  100. PutDevice(ctx context.Context, store *Device) error
  101. DeleteDevice(ctx context.Context, store *Device) error
  102. }
  103. type MessageSecretInsert struct {
  104. Chat types.JID
  105. Sender types.JID
  106. ID types.MessageID
  107. Secret []byte
  108. }
  109. type MsgSecretStore interface {
  110. PutMessageSecrets(ctx context.Context, inserts []MessageSecretInsert) error
  111. PutMessageSecret(ctx context.Context, chat, sender types.JID, id types.MessageID, secret []byte) error
  112. GetMessageSecret(ctx context.Context, chat, sender types.JID, id types.MessageID) ([]byte, types.JID, error)
  113. }
  114. type PrivacyToken struct {
  115. User types.JID
  116. Token []byte
  117. Timestamp time.Time
  118. }
  119. type PrivacyTokenStore interface {
  120. PutPrivacyTokens(ctx context.Context, tokens ...PrivacyToken) error
  121. GetPrivacyToken(ctx context.Context, user types.JID) (*PrivacyToken, error)
  122. }
  123. type BufferedEvent struct {
  124. Plaintext []byte
  125. InsertTime time.Time
  126. ServerTime time.Time
  127. }
  128. type EventBuffer interface {
  129. GetBufferedEvent(ctx context.Context, ciphertextHash [32]byte) (*BufferedEvent, error)
  130. PutBufferedEvent(ctx context.Context, ciphertextHash [32]byte, plaintext []byte, serverTimestamp time.Time) error
  131. DoDecryptionTxn(ctx context.Context, fn func(context.Context) error) error
  132. ClearBufferedEventPlaintext(ctx context.Context, ciphertextHash [32]byte) error
  133. DeleteOldBufferedHashes(ctx context.Context) error
  134. }
  135. type LIDMapping struct {
  136. LID types.JID
  137. PN types.JID
  138. }
  139. func (lm LIDMapping) GetMassInsertValues() [2]any {
  140. return [...]any{lm.LID.User, lm.PN.User}
  141. }
  142. type LIDStore interface {
  143. PutManyLIDMappings(ctx context.Context, mappings []LIDMapping) error
  144. PutLIDMapping(ctx context.Context, lid, jid types.JID) error
  145. GetPNForLID(ctx context.Context, lid types.JID) (types.JID, error)
  146. GetLIDForPN(ctx context.Context, pn types.JID) (types.JID, error)
  147. GetManyLIDsForPNs(ctx context.Context, pns []types.JID) (map[types.JID]types.JID, error)
  148. }
  149. type AllSessionSpecificStores interface {
  150. IdentityStore
  151. SessionStore
  152. PreKeyStore
  153. SenderKeyStore
  154. AppStateSyncKeyStore
  155. AppStateStore
  156. ContactStore
  157. ChatSettingsStore
  158. MsgSecretStore
  159. PrivacyTokenStore
  160. EventBuffer
  161. }
  162. type AllGlobalStores interface {
  163. LIDStore
  164. }
  165. type AllStores interface {
  166. AllSessionSpecificStores
  167. AllGlobalStores
  168. }
  169. type Device struct {
  170. Log waLog.Logger
  171. NoiseKey *keys.KeyPair
  172. IdentityKey *keys.KeyPair
  173. SignedPreKey *keys.PreKey
  174. RegistrationID uint32
  175. AdvSecretKey []byte
  176. ID *types.JID
  177. LID types.JID
  178. Account *waAdv.ADVSignedDeviceIdentity
  179. Platform string
  180. BusinessName string
  181. PushName string
  182. LIDMigrationTimestamp int64
  183. FacebookUUID uuid.UUID
  184. Initialized bool
  185. Identities IdentityStore
  186. Sessions SessionStore
  187. PreKeys PreKeyStore
  188. SenderKeys SenderKeyStore
  189. AppStateKeys AppStateSyncKeyStore
  190. AppState AppStateStore
  191. Contacts ContactStore
  192. ChatSettings ChatSettingsStore
  193. MsgSecrets MsgSecretStore
  194. PrivacyTokens PrivacyTokenStore
  195. EventBuffer EventBuffer
  196. LIDs LIDStore
  197. Container DeviceContainer
  198. Uuid string
  199. Mobile bool
  200. MobileInfo []byte
  201. LoggedOut string
  202. ClientPayload *waProto.ClientPayload
  203. }
  204. func (device *Device) GetJID() types.JID {
  205. if device == nil {
  206. return types.EmptyJID
  207. }
  208. id := device.ID
  209. if id == nil {
  210. return types.EmptyJID
  211. }
  212. return *id
  213. }
  214. func (device *Device) GetLID() types.JID {
  215. if device == nil {
  216. return types.EmptyJID
  217. }
  218. return device.LID
  219. }
  220. func (device *Device) Save(ctx context.Context) error {
  221. return device.Container.PutDevice(ctx, device)
  222. }
  223. func (device *Device) Delete(ctx context.Context) error {
  224. err := device.Container.DeleteDevice(ctx, device)
  225. if err != nil {
  226. return err
  227. }
  228. device.ID = nil
  229. device.LID = types.EmptyJID
  230. return nil
  231. }
  232. func (device *Device) GetAltJID(ctx context.Context, jid types.JID) (types.JID, error) {
  233. if device == nil {
  234. return types.EmptyJID, nil
  235. } else if jid.Server == types.DefaultUserServer {
  236. return device.LIDs.GetLIDForPN(ctx, jid)
  237. } else if jid.Server == types.HiddenUserServer {
  238. return device.LIDs.GetPNForLID(ctx, jid)
  239. } else {
  240. return types.EmptyJID, nil
  241. }
  242. }