2022-03-12 22:02:04 +00:00
|
|
|
// Copyright (c) 2022 Tulir Asokan
|
2022-01-30 23:27:37 +00:00
|
|
|
//
|
|
|
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
|
|
|
|
// Package store contains interfaces for storing data needed for WhatsApp multidevice.
|
|
|
|
package store
|
|
|
|
|
|
|
|
import (
|
2022-05-01 22:10:54 +00:00
|
|
|
"fmt"
|
2022-01-30 23:27:37 +00:00
|
|
|
"time"
|
|
|
|
|
2024-05-23 21:44:31 +00:00
|
|
|
"github.com/google/uuid"
|
|
|
|
|
2022-01-30 23:27:37 +00:00
|
|
|
waProto "go.mau.fi/whatsmeow/binary/proto"
|
|
|
|
"go.mau.fi/whatsmeow/types"
|
|
|
|
"go.mau.fi/whatsmeow/util/keys"
|
|
|
|
waLog "go.mau.fi/whatsmeow/util/log"
|
|
|
|
)
|
|
|
|
|
|
|
|
type IdentityStore interface {
|
|
|
|
PutIdentity(address string, key [32]byte) error
|
|
|
|
DeleteAllIdentities(phone string) error
|
|
|
|
DeleteIdentity(address string) error
|
|
|
|
IsTrustedIdentity(address string, key [32]byte) (bool, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
type SessionStore interface {
|
|
|
|
GetSession(address string) ([]byte, error)
|
|
|
|
HasSession(address string) (bool, error)
|
|
|
|
PutSession(address string, session []byte) error
|
|
|
|
DeleteAllSessions(phone string) error
|
|
|
|
DeleteSession(address string) error
|
|
|
|
}
|
|
|
|
|
|
|
|
type PreKeyStore interface {
|
|
|
|
GetOrGenPreKeys(count uint32) ([]*keys.PreKey, error)
|
|
|
|
GenOnePreKey() (*keys.PreKey, error)
|
|
|
|
GetPreKey(id uint32) (*keys.PreKey, error)
|
|
|
|
RemovePreKey(id uint32) error
|
|
|
|
MarkPreKeysAsUploaded(upToID uint32) error
|
|
|
|
UploadedPreKeyCount() (int, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
type SenderKeyStore interface {
|
|
|
|
PutSenderKey(group, user string, session []byte) error
|
|
|
|
GetSenderKey(group, user string) ([]byte, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
type AppStateSyncKey struct {
|
|
|
|
Data []byte
|
|
|
|
Fingerprint []byte
|
|
|
|
Timestamp int64
|
|
|
|
}
|
|
|
|
|
|
|
|
type AppStateSyncKeyStore interface {
|
|
|
|
PutAppStateSyncKey(id []byte, key AppStateSyncKey) error
|
|
|
|
GetAppStateSyncKey(id []byte) (*AppStateSyncKey, error)
|
2023-08-05 18:43:19 +00:00
|
|
|
GetLatestAppStateSyncKeyID() ([]byte, error)
|
2022-01-30 23:27:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type AppStateMutationMAC struct {
|
|
|
|
IndexMAC []byte
|
|
|
|
ValueMAC []byte
|
|
|
|
}
|
|
|
|
|
|
|
|
type AppStateStore interface {
|
|
|
|
PutAppStateVersion(name string, version uint64, hash [128]byte) error
|
|
|
|
GetAppStateVersion(name string) (uint64, [128]byte, error)
|
|
|
|
DeleteAppStateVersion(name string) error
|
|
|
|
|
|
|
|
PutAppStateMutationMACs(name string, version uint64, mutations []AppStateMutationMAC) error
|
|
|
|
DeleteAppStateMutationMACs(name string, indexMACs [][]byte) error
|
|
|
|
GetAppStateMutationMAC(name string, indexMAC []byte) (valueMAC []byte, err error)
|
|
|
|
}
|
|
|
|
|
2022-03-12 22:02:04 +00:00
|
|
|
type ContactEntry struct {
|
|
|
|
JID types.JID
|
|
|
|
FirstName string
|
|
|
|
FullName string
|
|
|
|
}
|
|
|
|
|
2022-01-30 23:27:37 +00:00
|
|
|
type ContactStore interface {
|
|
|
|
PutPushName(user types.JID, pushName string) (bool, string, error)
|
2022-06-24 22:36:16 +00:00
|
|
|
PutBusinessName(user types.JID, businessName string) (bool, string, error)
|
2022-01-30 23:27:37 +00:00
|
|
|
PutContactName(user types.JID, fullName, firstName string) error
|
2022-03-12 22:02:04 +00:00
|
|
|
PutAllContactNames(contacts []ContactEntry) error
|
2022-01-30 23:27:37 +00:00
|
|
|
GetContact(user types.JID) (types.ContactInfo, error)
|
|
|
|
GetAllContacts() (map[types.JID]types.ContactInfo, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
type ChatSettingsStore interface {
|
|
|
|
PutMutedUntil(chat types.JID, mutedUntil time.Time) error
|
|
|
|
PutPinned(chat types.JID, pinned bool) error
|
|
|
|
PutArchived(chat types.JID, archived bool) error
|
|
|
|
GetChatSettings(chat types.JID) (types.LocalChatSettings, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
type DeviceContainer interface {
|
|
|
|
PutDevice(store *Device) error
|
|
|
|
DeleteDevice(store *Device) error
|
|
|
|
}
|
|
|
|
|
2022-11-26 23:42:16 +00:00
|
|
|
type MessageSecretInsert struct {
|
|
|
|
Chat types.JID
|
|
|
|
Sender types.JID
|
|
|
|
ID types.MessageID
|
|
|
|
Secret []byte
|
|
|
|
}
|
|
|
|
|
|
|
|
type MsgSecretStore interface {
|
|
|
|
PutMessageSecrets([]MessageSecretInsert) error
|
|
|
|
PutMessageSecret(chat, sender types.JID, id types.MessageID, secret []byte) error
|
|
|
|
GetMessageSecret(chat, sender types.JID, id types.MessageID) ([]byte, error)
|
|
|
|
}
|
|
|
|
|
2023-01-28 21:57:53 +00:00
|
|
|
type PrivacyToken struct {
|
|
|
|
User types.JID
|
|
|
|
Token []byte
|
|
|
|
Timestamp time.Time
|
|
|
|
}
|
|
|
|
|
|
|
|
type PrivacyTokenStore interface {
|
|
|
|
PutPrivacyTokens(tokens ...PrivacyToken) error
|
|
|
|
GetPrivacyToken(user types.JID) (*PrivacyToken, error)
|
|
|
|
}
|
|
|
|
|
2022-01-30 23:27:37 +00:00
|
|
|
type Device struct {
|
|
|
|
Log waLog.Logger
|
|
|
|
|
|
|
|
NoiseKey *keys.KeyPair
|
|
|
|
IdentityKey *keys.KeyPair
|
|
|
|
SignedPreKey *keys.PreKey
|
|
|
|
RegistrationID uint32
|
|
|
|
AdvSecretKey []byte
|
|
|
|
|
|
|
|
ID *types.JID
|
|
|
|
Account *waProto.ADVSignedDeviceIdentity
|
|
|
|
Platform string
|
|
|
|
BusinessName string
|
|
|
|
PushName string
|
|
|
|
|
2024-05-23 21:44:31 +00:00
|
|
|
FacebookUUID uuid.UUID
|
|
|
|
|
2023-01-28 21:57:53 +00:00
|
|
|
Initialized bool
|
|
|
|
Identities IdentityStore
|
|
|
|
Sessions SessionStore
|
|
|
|
PreKeys PreKeyStore
|
|
|
|
SenderKeys SenderKeyStore
|
|
|
|
AppStateKeys AppStateSyncKeyStore
|
|
|
|
AppState AppStateStore
|
|
|
|
Contacts ContactStore
|
|
|
|
ChatSettings ChatSettingsStore
|
|
|
|
MsgSecrets MsgSecretStore
|
|
|
|
PrivacyTokens PrivacyTokenStore
|
|
|
|
Container DeviceContainer
|
2022-05-01 22:10:54 +00:00
|
|
|
|
|
|
|
DatabaseErrorHandler func(device *Device, action string, attemptIndex int, err error) (retry bool)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (device *Device) handleDatabaseError(attemptIndex int, err error, action string, args ...interface{}) bool {
|
|
|
|
if device.DatabaseErrorHandler != nil {
|
|
|
|
return device.DatabaseErrorHandler(device, fmt.Sprintf(action, args...), attemptIndex, err)
|
|
|
|
}
|
|
|
|
device.Log.Errorf("Failed to %s: %v", fmt.Sprintf(action, args...), err)
|
|
|
|
return false
|
2022-01-30 23:27:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (device *Device) Save() error {
|
|
|
|
return device.Container.PutDevice(device)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (device *Device) Delete() error {
|
|
|
|
err := device.Container.DeleteDevice(device)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
device.ID = nil
|
|
|
|
return nil
|
|
|
|
}
|