1/2
This commit is contained in:
@@ -12,12 +12,14 @@ import (
|
||||
"fmt"
|
||||
mathRand "math/rand"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"go.mau.fi/util/random"
|
||||
|
||||
waProto "go.mau.fi/whatsmeow/binary/proto"
|
||||
"go.mau.fi/whatsmeow/store"
|
||||
"go.mau.fi/whatsmeow/types"
|
||||
"go.mau.fi/whatsmeow/util/keys"
|
||||
waLog "go.mau.fi/whatsmeow/util/log"
|
||||
"go.mau.fi/whatsmeow/util/randbytes"
|
||||
)
|
||||
|
||||
// Container is a wrapper for a SQL database that can contain multiple whatsmeow sessions.
|
||||
@@ -86,7 +88,7 @@ const getAllDevicesQuery = `
|
||||
SELECT jid, registration_id, noise_key, identity_key,
|
||||
signed_pre_key, signed_pre_key_id, signed_pre_key_sig,
|
||||
adv_key, adv_details, adv_account_sig, adv_account_sig_key, adv_device_sig,
|
||||
platform, business_name, push_name
|
||||
platform, business_name, push_name, facebook_uuid
|
||||
FROM whatsmeow_device
|
||||
`
|
||||
|
||||
@@ -103,12 +105,13 @@ func (c *Container) scanDevice(row scannable) (*store.Device, error) {
|
||||
device.SignedPreKey = &keys.PreKey{}
|
||||
var noisePriv, identityPriv, preKeyPriv, preKeySig []byte
|
||||
var account waProto.ADVSignedDeviceIdentity
|
||||
var fbUUID uuid.NullUUID
|
||||
|
||||
err := row.Scan(
|
||||
&device.ID, &device.RegistrationID, &noisePriv, &identityPriv,
|
||||
&preKeyPriv, &device.SignedPreKey.KeyID, &preKeySig,
|
||||
&device.AdvSecretKey, &account.Details, &account.AccountSignature, &account.AccountSignatureKey, &account.DeviceSignature,
|
||||
&device.Platform, &device.BusinessName, &device.PushName)
|
||||
&device.Platform, &device.BusinessName, &device.PushName, &fbUUID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to scan session: %w", err)
|
||||
} else if len(noisePriv) != 32 || len(identityPriv) != 32 || len(preKeyPriv) != 32 || len(preKeySig) != 64 {
|
||||
@@ -120,6 +123,7 @@ func (c *Container) scanDevice(row scannable) (*store.Device, error) {
|
||||
device.SignedPreKey.KeyPair = *keys.NewKeyPairFromPrivateKey(*(*[32]byte)(preKeyPriv))
|
||||
device.SignedPreKey.Signature = (*[64]byte)(preKeySig)
|
||||
device.Account = &account
|
||||
device.FacebookUUID = fbUUID.UUID
|
||||
|
||||
innerStore := NewSQLStore(c, *device.ID)
|
||||
device.Identities = innerStore
|
||||
@@ -188,8 +192,8 @@ const (
|
||||
INSERT INTO whatsmeow_device (jid, registration_id, noise_key, identity_key,
|
||||
signed_pre_key, signed_pre_key_id, signed_pre_key_sig,
|
||||
adv_key, adv_details, adv_account_sig, adv_account_sig_key, adv_device_sig,
|
||||
platform, business_name, push_name)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15)
|
||||
platform, business_name, push_name, facebook_uuid)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)
|
||||
ON CONFLICT (jid) DO UPDATE
|
||||
SET platform=excluded.platform, business_name=excluded.business_name, push_name=excluded.push_name
|
||||
`
|
||||
@@ -210,7 +214,7 @@ func (c *Container) NewDevice() *store.Device {
|
||||
NoiseKey: keys.NewKeyPair(),
|
||||
IdentityKey: keys.NewKeyPair(),
|
||||
RegistrationID: mathRand.Uint32(),
|
||||
AdvSecretKey: randbytes.Make(32),
|
||||
AdvSecretKey: random.Bytes(32),
|
||||
}
|
||||
device.SignedPreKey = device.IdentityKey.CreateSignedPreKey(1)
|
||||
return device
|
||||
@@ -219,6 +223,14 @@ func (c *Container) NewDevice() *store.Device {
|
||||
// ErrDeviceIDMustBeSet is the error returned by PutDevice if you try to save a device before knowing its JID.
|
||||
var ErrDeviceIDMustBeSet = errors.New("device JID must be known before accessing database")
|
||||
|
||||
// Close will close the container's database
|
||||
func (c *Container) Close() error {
|
||||
if c != nil && c.db != nil {
|
||||
return c.db.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// PutDevice stores the given device in this database. This should be called through Device.Save()
|
||||
// (which usually doesn't need to be called manually, as the library does that automatically when relevant).
|
||||
func (c *Container) PutDevice(device *store.Device) error {
|
||||
@@ -229,7 +241,7 @@ func (c *Container) PutDevice(device *store.Device) error {
|
||||
device.ID.String(), device.RegistrationID, device.NoiseKey.Priv[:], device.IdentityKey.Priv[:],
|
||||
device.SignedPreKey.Priv[:], device.SignedPreKey.KeyID, device.SignedPreKey.Signature[:],
|
||||
device.AdvSecretKey, device.Account.Details, device.Account.AccountSignature, device.Account.AccountSignatureKey, device.Account.DeviceSignature,
|
||||
device.Platform, device.BusinessName, device.PushName)
|
||||
device.Platform, device.BusinessName, device.PushName, uuid.NullUUID{UUID: device.FacebookUUID, Valid: device.FacebookUUID != uuid.Nil})
|
||||
|
||||
if !device.Initialized {
|
||||
innerStore := NewSQLStore(c, *device.ID)
|
||||
|
||||
@@ -8,6 +8,7 @@ package sqlstore
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type upgradeFunc func(*sql.Tx, *Container) error
|
||||
@@ -16,7 +17,7 @@ type upgradeFunc func(*sql.Tx, *Container) error
|
||||
//
|
||||
// This may be of use if you want to manage the database fully manually, but in most cases you
|
||||
// should just call Container.Upgrade to let the library handle everything.
|
||||
var Upgrades = [...]upgradeFunc{upgradeV1, upgradeV2, upgradeV3, upgradeV4}
|
||||
var Upgrades = [...]upgradeFunc{upgradeV1, upgradeV2, upgradeV3, upgradeV4, upgradeV5, upgradeV6}
|
||||
|
||||
func (c *Container) getVersion() (int, error) {
|
||||
_, err := c.db.Exec("CREATE TABLE IF NOT EXISTS whatsmeow_version (version INTEGER)")
|
||||
@@ -43,6 +44,16 @@ func (c *Container) setVersion(tx *sql.Tx, version int) error {
|
||||
|
||||
// Upgrade upgrades the database from the current to the latest version available.
|
||||
func (c *Container) Upgrade() error {
|
||||
if c.dialect == "sqlite" {
|
||||
var foreignKeysEnabled bool
|
||||
err := c.db.QueryRow("PRAGMA foreign_keys").Scan(&foreignKeysEnabled)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to check if foreign keys are enabled: %w", err)
|
||||
} else if !foreignKeysEnabled {
|
||||
return fmt.Errorf("foreign keys are not enabled")
|
||||
}
|
||||
}
|
||||
|
||||
version, err := c.getVersion()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -271,3 +282,13 @@ func upgradeV4(tx *sql.Tx, container *Container) error {
|
||||
)`)
|
||||
return err
|
||||
}
|
||||
|
||||
func upgradeV5(tx *sql.Tx, container *Container) error {
|
||||
_, err := tx.Exec("UPDATE whatsmeow_device SET jid=REPLACE(jid, '.0', '')")
|
||||
return err
|
||||
}
|
||||
|
||||
func upgradeV6(tx *sql.Tx, container *Container) error {
|
||||
_, err := tx.Exec("ALTER TABLE whatsmeow_device ADD COLUMN facebook_uuid uuid")
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user