This commit is contained in:
tzagim
2024-05-21 20:08:12 +03:00
committed by GitHub
parent ff6d9f23e3
commit 0cf7c09ed5
85 changed files with 31569 additions and 479 deletions

View File

@@ -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)

View File

@@ -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
}