From 8e5044f7ce5401a87d697545ed584f4ea3d682f4 Mon Sep 17 00:00:00 2001 From: Bob <115008575+bobslavtriev@users.noreply.github.com> Date: Thu, 6 Jun 2024 01:10:50 -0300 Subject: [PATCH 01/22] Update index.ts --- src/Utils/index.ts | 62 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/src/Utils/index.ts b/src/Utils/index.ts index f705bf9..087241f 100644 --- a/src/Utils/index.ts +++ b/src/Utils/index.ts @@ -1,7 +1,6 @@ import { curve } from 'libsignal' -import { randomBytes } from 'crypto' -import { v4 } from 'uuid' -import { KeyPair, valueReplacer, valueReviver } from '../Types' +import { randomBytes, randomUUID } from 'crypto' +import { KeyPair, valueReplacer, valueReviver, AppDataSync, Bits } from '../Types' const generateKeyPair = () => { const { pubKey, privKey } = curve.generateKeyPair() @@ -26,6 +25,56 @@ const signedKeyPair = (identityKeyPair: KeyPair, keyId: number) => { return { keyPair: preKey, signature, keyId } } +const allocate = (str: string) => { + let p = str.length + + if (!p){ + return new Uint8Array(1) + } + + let n = 0 + + while (--p % 4 > 1 && str.charAt(p) === "="){ + ++n + } + + return new Uint8Array(Math.ceil(str.length * 3) / 4 - n).fill(0) +} + +const parseTimestamp = (timestamp: Bits | number) => { + if (typeof timestamp === 'string') { + return parseInt(timestamp, 10) + } + + if (typeof timestamp === "number") { + return timestamp + } + + return { + low: 0, + high: 0, + unsigned: false + } +} + +export const fromObject = (args: AppDataSync) => { + const message = { + keyData: Array.isArray(args.keyData) ? args.keyData : new Uint8Array(), + fingerprint: { + rawId: args.fingerprint.rawId, + currentIndex: args.fingerprint.rawId, + deviceIndexes: Array.isArray(args.fingerprint.deviceIndexes) ? args.fingerprint.deviceIndexes : [] + }, + timestamp: parseTimestamp(args.timestamp) + } + + if (typeof args.keyData === "string") { + message.keyData = allocate(args.keyData) + } + + return message +} + export const BufferJSON = { replacer: (_: string, value: valueReplacer) => { if(value?.type === 'Buffer' && Array.isArray(value?.data)) { @@ -60,13 +109,14 @@ export const initAuthCreds = () => { accountSettings: { unarchiveChats: false }, - deviceId: Buffer.from(v4().replace(/-/g, ''), 'hex').toString('base64url'), - phoneId: v4(), + deviceId: Buffer.from(randomUUID().replace(/-/g, ''), 'hex').toString('base64url'), + phoneId: randomUUID(), identityId: randomBytes(20), backupToken: randomBytes(20), registered: false, registration: {}, pairingCode: undefined, - lastPropHash: undefined + lastPropHash: undefined, + routingInfo: undefined } } From aa835b58c69f53c37fca3a310e5bcc392266c276 Mon Sep 17 00:00:00 2001 From: Bob <115008575+bobslavtriev@users.noreply.github.com> Date: Thu, 6 Jun 2024 01:11:40 -0300 Subject: [PATCH 02/22] Update index.ts --- src/Mysql/index.ts | 125 +++++++++++++++++++++------------------------ 1 file changed, 57 insertions(+), 68 deletions(-) diff --git a/src/Mysql/index.ts b/src/Mysql/index.ts index f4ff96c..b2e739f 100644 --- a/src/Mysql/index.ts +++ b/src/Mysql/index.ts @@ -1,49 +1,58 @@ import { createConnection } from 'mysql2/promise' -import { proto } from '@whiskeysockets/baileys' -import { BufferJSON, initAuthCreds } from '../Utils' -import { MySQLConfig, sqlData, sqlConnection, AuthenticationCreds, AuthenticationState } from '../Types' +import { BufferJSON, initAuthCreds, fromObject } from '../Utils' +import { MySQLConfig, sqlData, sqlConnection, AuthenticationCreds, AuthenticationState, SignalDataTypeMap } from '../Types' /** * Stores the full authentication state in mysql * Far more efficient than file - * @param {string} host - MySql host, by default localhost - * @param {string} port - MySql port, by default 3306 - * @param {string} user - MySql user, by default root - * @param {string} password - MySql password - * @param {string} database - MySql database name - * @param {string} tableName - MySql table name, by default auth - * @param {string} keepAliveIntervalMs - Always keep active, by default 30s - * @param {string} retryRequestDelayMs - Retry the query at each interval if it fails, by default 200ms - * @param {string} maxtRetries - Maximum attempts if the query fails, by default 10 - * @param {string} session - Session name to identify the connection, allowing multisessions with mysql + * @param {string} host - The hostname of the database you are connecting to. (Default: localhost) + * @param {string} port - The port number to connect to. (Default: 3306) + * @param {string} user - The MySQL user to authenticate as. (Default: root) + * @param {string} password - The password of that MySQL user + * @param {string} password1 - Alias for the MySQL user password. Makes a bit more sense in a multifactor authentication setup (see "password2" and "password3") + * @param {string} password2 - 2nd factor authentication password. Mandatory when the authentication policy for the MySQL user account requires an additional authentication method that needs a password. + * @param {string} password3 - 3rd factor authentication password. Mandatory when the authentication policy for the MySQL user account requires two additional authentication methods and the last one needs a password. + * @param {string} database - Name of the database to use for this connection. (Default: auth) + * @param {string} tableName - MySql table name, by default auth. + * @param {string} retryRequestDelayMs - Retry the query at each interval if it fails. (Default: 200ms) + * @param {string} maxtRetries - Maximum attempts if the query fails. (Default: 10) + * @param {string} session - Session name to identify the connection, allowing multisessions with mysql. + * @param {string} localAddress - The source IP address to use for TCP connection. + * @param {string} socketPath - The path to a unix domain socket to connect to. When used host and port are ignored. + * @param {string} insecureAuth - Allow connecting to MySQL instances that ask for the old (insecure) authentication method. (Default: false) + * @param {string} isServer - If your connection is a server. (Default: false) */ let conn: sqlConnection -let pending: boolean | undefined -let taskKeepAlive: NodeJS.Timeout | undefined -const DEFAULT_TABLE_NAME = 'auth'; +let pending: boolean = false -async function connection(config: MySQLConfig, force: true | false = false){ +async function connection(config: MySQLConfig, force: boolean = false){ const ended = !!conn?.connection?._closing const newConnection = conn === undefined - const tableName = config?.tableName || DEFAULT_TABLE_NAME if (newConnection || ended || force){ pending = true conn = await createConnection({ - host: config?.host || 'localhost', - port: config?.port || 3306, - user: config?.user || 'root', - password: config.password || 'Password123#', database: config.database || 'base', - ssl: config?.ssl - }).catch((e) => { - throw e + host: config.host || 'localhost', + port: config.port || 3306, + user: config.user || 'root', + password: config.password, + password1: config.password1, + password2: config.password2, + password3: config.password3, + enableKeepAlive: true, + keepAliveInitialDelay: 5000, + ssl: config.ssl, + localAddress: config.localAddress, + socketPath: config.socketPath, + insecureAuth: config.insecureAuth || false, + isServer: config.isServer || false }) if (newConnection) { - await conn.execute('CREATE TABLE IF NOT EXISTS `' + tableName + '` (`session` varchar(50) NOT NULL, `id` varchar(70) NOT NULL, `value` json DEFAULT NULL, UNIQUE KEY `idxunique` (`session`,`id`), KEY `idxsession` (`session`), KEY `idxid` (`id`)) ENGINE=MyISAM;') + await conn.execute('CREATE TABLE IF NOT EXISTS `' + config.tableName + '` (`session` varchar(50) NOT NULL, `id` varchar(80) NOT NULL, `value` json DEFAULT NULL, UNIQUE KEY `idxunique` (`session`,`id`), KEY `idxsession` (`session`), KEY `idxid` (`id`)) ENGINE=MyISAM;') } pending = false @@ -53,38 +62,13 @@ async function connection(config: MySQLConfig, force: true | false = false){ } export const useMySQLAuthState = async(config: MySQLConfig): Promise<{ state: AuthenticationState, saveCreds: () => Promise, clear: () => Promise, removeCreds: () => Promise }> => { - if (typeof config?.session !== 'string'){ - throw new Error('session name must be a string') - } - - let sqlConn = await connection(config) + const sqlConn = await connection(config) - const keepAliveIntervalMs = config?.keepAliveIntervalMs || 30_000 - const retryRequestDelayMs = config?.retryRequestDelayMs || 200 - const maxtRetries = config?.maxtRetries || 10 - - const reconnect = async () => { - if (!pending){ - sqlConn = await connection(config, true) - } - } - - if (taskKeepAlive){ - clearInterval(taskKeepAlive) - } + const tableName = config.tableName || 'auth' + const retryRequestDelayMs = config.retryRequestDelayMs || 200 + const maxtRetries = config.maxtRetries || 10 - taskKeepAlive = setInterval(async () => { - await conn.ping().catch(async () => await reconnect()) - if (conn?.connection?._closing){ - await reconnect() - } - }, keepAliveIntervalMs) - - const session = config.session - - const tableName = config?.tableName || DEFAULT_TABLE_NAME - - const query = async (sql: string, values: Array) => { + const query = async (sql: string, values: string[]) => { for (let x = 0; x < maxtRetries; x++){ try { const [rows] = await sqlConn.query(sql, values) @@ -93,11 +77,11 @@ export const useMySQLAuthState = async(config: MySQLConfig): Promise<{ state: Au await new Promise(r => setTimeout(r, retryRequestDelayMs)) } } - return [] as sqlData + return [] as sqlData } const readData = async (id: string) => { - const data = await query(`SELECT value FROM ${tableName} WHERE id = ? AND session = ?`, [id, session]) + const data = await query(`SELECT value FROM ${tableName} WHERE id = ? AND session = ?`, [id, config.session]) if(!data[0]?.value){ return null } @@ -108,33 +92,38 @@ export const useMySQLAuthState = async(config: MySQLConfig): Promise<{ state: Au const writeData = async (id: string, value: object) => { const valueFixed = JSON.stringify(value, BufferJSON.replacer) - await query(`INSERT INTO ${tableName} (value, id, session) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE value = ?`, [valueFixed, id, session, valueFixed]) + await query(`INSERT INTO ${tableName} (session, id, value) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE value = ?`, [id, config.session, valueFixed, valueFixed]) } const removeData = async (id: string) => { - await query(`DELETE FROM ${tableName} WHERE id = ? AND session = ?`, [id, session]) + await query(`DELETE FROM ${tableName} WHERE id = ? AND session = ?`, [id, config.session]) } const clearAll = async () => { - await query(`DELETE FROM ${tableName} WHERE id != 'creds' AND session = ?`, [session]) + await query(`DELETE FROM ${tableName} WHERE id != 'creds' AND session = ?`, [config.session]) } const removeAll = async () => { - await query(`DELETE FROM ${tableName} WHERE session = ?`, [session]) + await query(`DELETE FROM ${tableName} WHERE session = ?`, [config.session]) } - const creds: AuthenticationCreds = await readData('creds') || initAuthCreds() + let creds: AuthenticationCreds = await readData('creds') || initAuthCreds() + + if (!creds?.registered){ + creds = initAuthCreds() + await writeData('creds', creds) + } return { state: { - creds, + creds: creds, keys: { get: async (type, ids) => { - const data = { } + const data: { [id: string]: SignalDataTypeMap[typeof type] } = { } for(const id of ids){ let value = await readData(`${type}-${id}`) - if(type === 'app-state-sync-key' && value) { - value = proto.Message.AppStateSyncKeyData.fromObject(value) + if (type === 'app-state-sync-key' && value){ + value = fromObject(value) } data[id] = value } @@ -143,7 +132,7 @@ export const useMySQLAuthState = async(config: MySQLConfig): Promise<{ state: Au set: async (data) => { for(const category in data) { for(const id in data[category]) { - const value = data[category][id]; + const value = data[category][id] const name = `${category}-${id}` if (value){ await writeData(name, value) From 24510408619383921266438e80650025036c6c83 Mon Sep 17 00:00:00 2001 From: Bob <115008575+bobslavtriev@users.noreply.github.com> Date: Thu, 6 Jun 2024 01:12:42 -0300 Subject: [PATCH 03/22] Update index.ts --- src/Types/index.ts | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/Types/index.ts b/src/Types/index.ts index 90d48a3..d9ccd95 100644 --- a/src/Types/index.ts +++ b/src/Types/index.ts @@ -65,10 +65,10 @@ type SignalKeyStore = { interface RegistrationOptions { phoneNumber?: string - phoneNumberCountryCode: string - phoneNumberNationalNumber: string - phoneNumberMobileCountryCode: string - phoneNumberMobileNetworkCode: string + phoneNumberCountryCode?: string + phoneNumberNationalNumber?: string + phoneNumberMobileCountryCode?: string + phoneNumberMobileNetworkCode?: string method?: 'sms' | 'voice' | 'captcha' captcha?: string } @@ -106,12 +106,12 @@ export type AppDataSync = { } export type SignalDataTypeMap = { - session: Uint8Array - 'pre-key': KeyPair - 'sender-key': Uint8Array - 'app-state-sync-key': AppDataSync - 'app-state-sync-version': LTHashState - 'sender-key-memory': { + session: Uint8Array + 'pre-key': KeyPair + 'sender-key': Uint8Array + 'app-state-sync-key': AppDataSync + 'app-state-sync-version': LTHashState + 'sender-key-memory': { [jid: string]: boolean } } @@ -143,15 +143,21 @@ export interface sqlConnection extends Connection { export type MySQLConfig = { session: string host: string - user?: string port?: number - password: string database: string tableName?: string - keepAliveIntervalMs?: number + user?: string + password?: string + password1?: string + password2?: string + password3?: string retryRequestDelayMs?: number maxtRetries?: number ssl?: string | SslOptions + localAddress?: string; + socketPath?: string; + insecureAuth?: boolean + isServer?: boolean } export type valueReplacer = { From 7e83c933708892f0dec5408b008cb67c1ccc19e2 Mon Sep 17 00:00:00 2001 From: Bob <115008575+bobslavtriev@users.noreply.github.com> Date: Thu, 6 Jun 2024 01:14:52 -0300 Subject: [PATCH 04/22] Update index.ts --- src/Mysql/index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Mysql/index.ts b/src/Mysql/index.ts index b2e739f..514b1e6 100644 --- a/src/Mysql/index.ts +++ b/src/Mysql/index.ts @@ -12,8 +12,8 @@ import { MySQLConfig, sqlData, sqlConnection, AuthenticationCreds, Authenticatio * @param {string} password1 - Alias for the MySQL user password. Makes a bit more sense in a multifactor authentication setup (see "password2" and "password3") * @param {string} password2 - 2nd factor authentication password. Mandatory when the authentication policy for the MySQL user account requires an additional authentication method that needs a password. * @param {string} password3 - 3rd factor authentication password. Mandatory when the authentication policy for the MySQL user account requires two additional authentication methods and the last one needs a password. - * @param {string} database - Name of the database to use for this connection. (Default: auth) - * @param {string} tableName - MySql table name, by default auth. + * @param {string} database - Name of the database to use for this connection. (Default: base) + * @param {string} tableName - MySql table name. (Default: auth) * @param {string} retryRequestDelayMs - Retry the query at each interval if it fails. (Default: 200ms) * @param {string} maxtRetries - Maximum attempts if the query fails. (Default: 10) * @param {string} session - Session name to identify the connection, allowing multisessions with mysql. @@ -52,7 +52,7 @@ async function connection(config: MySQLConfig, force: boolean = false){ }) if (newConnection) { - await conn.execute('CREATE TABLE IF NOT EXISTS `' + config.tableName + '` (`session` varchar(50) NOT NULL, `id` varchar(80) NOT NULL, `value` json DEFAULT NULL, UNIQUE KEY `idxunique` (`session`,`id`), KEY `idxsession` (`session`), KEY `idxid` (`id`)) ENGINE=MyISAM;') + await conn.execute('CREATE TABLE IF NOT EXISTS `' + config.tableName || 'auth' + '` (`session` varchar(50) NOT NULL, `id` varchar(80) NOT NULL, `value` json DEFAULT NULL, UNIQUE KEY `idxunique` (`session`,`id`), KEY `idxsession` (`session`), KEY `idxid` (`id`)) ENGINE=MyISAM') } pending = false From 6e57481fe04dbaa83aa6cf32418a30ef510b7f42 Mon Sep 17 00:00:00 2001 From: Bob <115008575+bobslavtriev@users.noreply.github.com> Date: Thu, 6 Jun 2024 01:17:49 -0300 Subject: [PATCH 05/22] Update index.ts --- src/Mysql/index.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Mysql/index.ts b/src/Mysql/index.ts index 514b1e6..f3c07c8 100644 --- a/src/Mysql/index.ts +++ b/src/Mysql/index.ts @@ -1,6 +1,6 @@ import { createConnection } from 'mysql2/promise' -import { BufferJSON, initAuthCreds, fromObject } from '../Utils' -import { MySQLConfig, sqlData, sqlConnection, AuthenticationCreds, AuthenticationState, SignalDataTypeMap } from '../Types' +import { BufferJSON, initAuthCreds, fromObject } from '../Utils/utils_beta' +import { MySQLConfig, sqlData, sqlConnection, AuthenticationCreds, AuthenticationState, SignalDataTypeMap } from '../Types/types_beta' /** * Stores the full authentication state in mysql @@ -12,8 +12,8 @@ import { MySQLConfig, sqlData, sqlConnection, AuthenticationCreds, Authenticatio * @param {string} password1 - Alias for the MySQL user password. Makes a bit more sense in a multifactor authentication setup (see "password2" and "password3") * @param {string} password2 - 2nd factor authentication password. Mandatory when the authentication policy for the MySQL user account requires an additional authentication method that needs a password. * @param {string} password3 - 3rd factor authentication password. Mandatory when the authentication policy for the MySQL user account requires two additional authentication methods and the last one needs a password. - * @param {string} database - Name of the database to use for this connection. (Default: base) - * @param {string} tableName - MySql table name. (Default: auth) + * @param {string} database - Name of the database to use for this connection. (Default: auth) + * @param {string} tableName - MySql table name, by default auth. * @param {string} retryRequestDelayMs - Retry the query at each interval if it fails. (Default: 200ms) * @param {string} maxtRetries - Maximum attempts if the query fails. (Default: 10) * @param {string} session - Session name to identify the connection, allowing multisessions with mysql. @@ -52,7 +52,7 @@ async function connection(config: MySQLConfig, force: boolean = false){ }) if (newConnection) { - await conn.execute('CREATE TABLE IF NOT EXISTS `' + config.tableName || 'auth' + '` (`session` varchar(50) NOT NULL, `id` varchar(80) NOT NULL, `value` json DEFAULT NULL, UNIQUE KEY `idxunique` (`session`,`id`), KEY `idxsession` (`session`), KEY `idxid` (`id`)) ENGINE=MyISAM') + await conn.execute('CREATE TABLE IF NOT EXISTS `' + config.tableName + '` (`session` varchar(50) NOT NULL, `id` varchar(80) NOT NULL, `value` json DEFAULT NULL, UNIQUE KEY `idxunique` (`session`,`id`), KEY `idxsession` (`session`), KEY `idxid` (`id`)) ENGINE=MyISAM;') } pending = false @@ -107,9 +107,9 @@ export const useMySQLAuthState = async(config: MySQLConfig): Promise<{ state: Au await query(`DELETE FROM ${tableName} WHERE session = ?`, [config.session]) } - let creds: AuthenticationCreds = await readData('creds') || initAuthCreds() + let creds: AuthenticationCreds = await readData('creds') - if (!creds?.registered){ + if (!creds){ creds = initAuthCreds() await writeData('creds', creds) } From 2aa33447ac12948ca71e981d93f47631ed2ffb30 Mon Sep 17 00:00:00 2001 From: Bob <115008575+bobslavtriev@users.noreply.github.com> Date: Thu, 6 Jun 2024 01:18:13 -0300 Subject: [PATCH 06/22] Update index.ts --- src/Mysql/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mysql/index.ts b/src/Mysql/index.ts index f3c07c8..88f436c 100644 --- a/src/Mysql/index.ts +++ b/src/Mysql/index.ts @@ -1,6 +1,6 @@ import { createConnection } from 'mysql2/promise' -import { BufferJSON, initAuthCreds, fromObject } from '../Utils/utils_beta' -import { MySQLConfig, sqlData, sqlConnection, AuthenticationCreds, AuthenticationState, SignalDataTypeMap } from '../Types/types_beta' +import { BufferJSON, initAuthCreds, fromObject } from '../Utils' +import { MySQLConfig, sqlData, sqlConnection, AuthenticationCreds, AuthenticationState, SignalDataTypeMap } from '../Types' /** * Stores the full authentication state in mysql From c6d5e30681467e0090b3de0ae6b2b456d395285f Mon Sep 17 00:00:00 2001 From: Bob <115008575+bobslavtriev@users.noreply.github.com> Date: Thu, 6 Jun 2024 01:19:17 -0300 Subject: [PATCH 07/22] Update index.ts --- src/Types/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Types/index.ts b/src/Types/index.ts index d9ccd95..dd8fa90 100644 --- a/src/Types/index.ts +++ b/src/Types/index.ts @@ -142,7 +142,7 @@ export interface sqlConnection extends Connection { export type MySQLConfig = { session: string - host: string + host?: string port?: number database: string tableName?: string From 7d45f82c94527faa00bd8b98c4aa7ab250373a92 Mon Sep 17 00:00:00 2001 From: Bob <115008575+bobslavtriev@users.noreply.github.com> Date: Thu, 6 Jun 2024 01:51:40 -0300 Subject: [PATCH 08/22] Update index.ts --- src/Types/index.ts | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/Types/index.ts b/src/Types/index.ts index dd8fa90..ea8983f 100644 --- a/src/Types/index.ts +++ b/src/Types/index.ts @@ -65,10 +65,10 @@ type SignalKeyStore = { interface RegistrationOptions { phoneNumber?: string - phoneNumberCountryCode?: string - phoneNumberNationalNumber?: string - phoneNumberMobileCountryCode?: string - phoneNumberMobileNetworkCode?: string + phoneNumberCountryCode: string + phoneNumberNationalNumber: string + phoneNumberMobileCountryCode: string + phoneNumberMobileNetworkCode: string method?: 'sms' | 'voice' | 'captcha' captcha?: string } @@ -102,16 +102,16 @@ export type Bits = { export type AppDataSync = { keyData: Uint8Array fingerprint: Fingerprint - timestamp: Bits | number + timestamp: Long | number } export type SignalDataTypeMap = { - session: Uint8Array - 'pre-key': KeyPair - 'sender-key': Uint8Array - 'app-state-sync-key': AppDataSync - 'app-state-sync-version': LTHashState - 'sender-key-memory': { + session: Uint8Array + 'pre-key': KeyPair + 'sender-key': Uint8Array + 'app-state-sync-key': AppDataSync + 'app-state-sync-version': LTHashState + 'sender-key-memory': { [jid: string]: boolean } } @@ -148,16 +148,16 @@ export type MySQLConfig = { tableName?: string user?: string password?: string - password1?: string - password2?: string - password3?: string + password1?: string + password2?: string + password3?: string retryRequestDelayMs?: number maxtRetries?: number ssl?: string | SslOptions - localAddress?: string; - socketPath?: string; - insecureAuth?: boolean - isServer?: boolean + localAddress?: string; + socketPath?: string; + insecureAuth?: boolean + isServer?: boolean } export type valueReplacer = { From fe49f56705c38bd182d90dcdb8ed9f32722624c7 Mon Sep 17 00:00:00 2001 From: Bob <115008575+bobslavtriev@users.noreply.github.com> Date: Thu, 6 Jun 2024 01:52:46 -0300 Subject: [PATCH 09/22] Update index.ts --- src/Utils/index.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/Utils/index.ts b/src/Utils/index.ts index 087241f..98bdf39 100644 --- a/src/Utils/index.ts +++ b/src/Utils/index.ts @@ -1,6 +1,6 @@ import { curve } from 'libsignal' import { randomBytes, randomUUID } from 'crypto' -import { KeyPair, valueReplacer, valueReviver, AppDataSync, Bits } from '../Types' +import { KeyPair, valueReplacer, valueReviver, AppDataSync, Fingerprint, Bits } from '../Types' const generateKeyPair = () => { const { pubKey, privKey } = curve.generateKeyPair() @@ -58,12 +58,17 @@ const parseTimestamp = (timestamp: Bits | number) => { } export const fromObject = (args: AppDataSync) => { + const f: Fingerprint = { + ...args.fingerprint, + deviceIndexes: Array.isArray(args.fingerprint.deviceIndexes) ? args.fingerprint.deviceIndexes : [] + } + const message = { keyData: Array.isArray(args.keyData) ? args.keyData : new Uint8Array(), fingerprint: { - rawId: args.fingerprint.rawId, - currentIndex: args.fingerprint.rawId, - deviceIndexes: Array.isArray(args.fingerprint.deviceIndexes) ? args.fingerprint.deviceIndexes : [] + rawId: f.rawId || 0, + currentIndex: f.rawId || 0, + deviceIndexes: f.deviceIndexes }, timestamp: parseTimestamp(args.timestamp) } @@ -114,9 +119,9 @@ export const initAuthCreds = () => { identityId: randomBytes(20), backupToken: randomBytes(20), registered: false, - registration: {}, + registration: {} as never, pairingCode: undefined, lastPropHash: undefined, - routingInfo: undefined + routingInfo: undefined } } From a35f7fc9ccd532ac5d6c980c3bcde144d49e6ffe Mon Sep 17 00:00:00 2001 From: Bob <115008575+bobslavtriev@users.noreply.github.com> Date: Thu, 6 Jun 2024 01:55:32 -0300 Subject: [PATCH 10/22] Update index.ts --- src/Mysql/index.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Mysql/index.ts b/src/Mysql/index.ts index 88f436c..bb74553 100644 --- a/src/Mysql/index.ts +++ b/src/Mysql/index.ts @@ -107,12 +107,7 @@ export const useMySQLAuthState = async(config: MySQLConfig): Promise<{ state: Au await query(`DELETE FROM ${tableName} WHERE session = ?`, [config.session]) } - let creds: AuthenticationCreds = await readData('creds') - - if (!creds){ - creds = initAuthCreds() - await writeData('creds', creds) - } + const creds: AuthenticationCreds = await readData('creds') || initAuthCreds() return { state: { From cca141e29184e8d08260ac53875da4968a1091f1 Mon Sep 17 00:00:00 2001 From: Bob <115008575+bobslavtriev@users.noreply.github.com> Date: Thu, 6 Jun 2024 01:58:06 -0300 Subject: [PATCH 11/22] Update index.ts --- src/Types/index.ts | 54 +++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/Types/index.ts b/src/Types/index.ts index ea8983f..9a1d5bf 100644 --- a/src/Types/index.ts +++ b/src/Types/index.ts @@ -74,17 +74,17 @@ interface RegistrationOptions { } export type SslOptions = { - pfx?: string; - key?: string | string[] | Buffer | Buffer[]; - passphrase?: string; - cert?: string | string[] | Buffer | Buffer[]; - ca?: string | string[] | Buffer | Buffer[]; - crl?: string | string[]; - ciphers?: string; - rejectUnauthorized?: boolean; - minVersion?: string; - maxVersion?: string; - verifyIdentity?: boolean; + pfx?: string + key?: string | string[] | Buffer | Buffer[] + passphrase?: string + cert?: string | string[] | Buffer | Buffer[] + ca?: string | string[] | Buffer | Buffer[] + crl?: string | string[] + ciphers?: string + rejectUnauthorized?: boolean + minVersion?: string + maxVersion?: string + verifyIdentity?: boolean } export type Fingerprint = { @@ -102,16 +102,16 @@ export type Bits = { export type AppDataSync = { keyData: Uint8Array fingerprint: Fingerprint - timestamp: Long | number + timestamp: Bits | number } export type SignalDataTypeMap = { - session: Uint8Array - 'pre-key': KeyPair - 'sender-key': Uint8Array - 'app-state-sync-key': AppDataSync - 'app-state-sync-version': LTHashState - 'sender-key-memory': { + session: Uint8Array + 'pre-key': KeyPair + 'sender-key': Uint8Array + 'app-state-sync-key': AppDataSync + 'app-state-sync-version': LTHashState + 'sender-key-memory': { [jid: string]: boolean } } @@ -129,8 +129,8 @@ export type KeyPair = { export type sqlData = { constructor: { - name: 'RowDataPacket'; - }; + name: 'RowDataPacket' + } value?: object[] } @@ -148,16 +148,16 @@ export type MySQLConfig = { tableName?: string user?: string password?: string - password1?: string - password2?: string - password3?: string + password1?: string + password2?: string + password3?: string retryRequestDelayMs?: number maxtRetries?: number ssl?: string | SslOptions - localAddress?: string; - socketPath?: string; - insecureAuth?: boolean - isServer?: boolean + localAddress?: string + socketPath?: string + insecureAuth?: boolean + isServer?: boolean } export type valueReplacer = { From 0af918f95cf8cc0120f1bc1ac11914cf44d80a3a Mon Sep 17 00:00:00 2001 From: Bob <115008575+bobslavtriev@users.noreply.github.com> Date: Thu, 6 Jun 2024 02:09:32 -0300 Subject: [PATCH 12/22] Update index.ts --- src/Types/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Types/index.ts b/src/Types/index.ts index 9a1d5bf..fe22095 100644 --- a/src/Types/index.ts +++ b/src/Types/index.ts @@ -102,7 +102,7 @@ export type Bits = { export type AppDataSync = { keyData: Uint8Array fingerprint: Fingerprint - timestamp: Bits | number + timestamp: Long | number } export type SignalDataTypeMap = { From 3588968784c63c287ab5d59fedb74c31dcda405e Mon Sep 17 00:00:00 2001 From: Bob <115008575+bobslavtriev@users.noreply.github.com> Date: Thu, 6 Jun 2024 02:20:48 -0300 Subject: [PATCH 13/22] Update index.ts --- src/Mysql/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mysql/index.ts b/src/Mysql/index.ts index bb74553..01b9b16 100644 --- a/src/Mysql/index.ts +++ b/src/Mysql/index.ts @@ -92,7 +92,7 @@ export const useMySQLAuthState = async(config: MySQLConfig): Promise<{ state: Au const writeData = async (id: string, value: object) => { const valueFixed = JSON.stringify(value, BufferJSON.replacer) - await query(`INSERT INTO ${tableName} (session, id, value) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE value = ?`, [id, config.session, valueFixed, valueFixed]) + await query(`INSERT INTO ${tableName} (session, id, value) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE value = ?`, [config.session, id, valueFixed, valueFixed]) } const removeData = async (id: string) => { From d7f5945e7a5e5beaaa1e70e92e9fcd449ed84e23 Mon Sep 17 00:00:00 2001 From: Bob <115008575+bobslavtriev@users.noreply.github.com> Date: Thu, 6 Jun 2024 02:25:04 -0300 Subject: [PATCH 14/22] Update package.json --- package.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index e3c2560..9a9a9c7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "author": "bobslavtriev", "name": "mysql-baileys", - "version": "1.4.0", + "version": "1.5.0", "main": "lib/index.js", "types": "lib/index.d.ts", "description": "Implementation of MySQL in Baileys.", @@ -29,8 +29,7 @@ }, "dependencies": { "libsignal": "github:adiwajshing/libsignal-node", - "mysql2": "^3.3.5", - "uuid": "^9.0.0" + "mysql2": "^3.3.5" }, "devDependencies": { "@adiwajshing/eslint-config": "github:adiwajshing/eslint-config", From 0c519683d20d32ba5b22439a1e8cd12053778a01 Mon Sep 17 00:00:00 2001 From: Bob <115008575+bobslavtriev@users.noreply.github.com> Date: Thu, 6 Jun 2024 02:26:52 -0300 Subject: [PATCH 15/22] Update index.ts --- src/Mysql/index.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Mysql/index.ts b/src/Mysql/index.ts index 01b9b16..db2a6d3 100644 --- a/src/Mysql/index.ts +++ b/src/Mysql/index.ts @@ -24,15 +24,12 @@ import { MySQLConfig, sqlData, sqlConnection, AuthenticationCreds, Authenticatio */ let conn: sqlConnection -let pending: boolean = false async function connection(config: MySQLConfig, force: boolean = false){ const ended = !!conn?.connection?._closing const newConnection = conn === undefined if (newConnection || ended || force){ - pending = true - conn = await createConnection({ database: config.database || 'base', host: config.host || 'localhost', @@ -54,8 +51,6 @@ async function connection(config: MySQLConfig, force: boolean = false){ if (newConnection) { await conn.execute('CREATE TABLE IF NOT EXISTS `' + config.tableName + '` (`session` varchar(50) NOT NULL, `id` varchar(80) NOT NULL, `value` json DEFAULT NULL, UNIQUE KEY `idxunique` (`session`,`id`), KEY `idxsession` (`session`), KEY `idxid` (`id`)) ENGINE=MyISAM;') } - - pending = false } return conn From 6509d31d3985de2fbb32b4681cd9ee79ea811190 Mon Sep 17 00:00:00 2001 From: Bob <115008575+bobslavtriev@users.noreply.github.com> Date: Thu, 6 Jun 2024 02:32:00 -0300 Subject: [PATCH 16/22] Update index.ts --- src/Mysql/index.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Mysql/index.ts b/src/Mysql/index.ts index db2a6d3..3a64bd6 100644 --- a/src/Mysql/index.ts +++ b/src/Mysql/index.ts @@ -6,21 +6,21 @@ import { MySQLConfig, sqlData, sqlConnection, AuthenticationCreds, Authenticatio * Stores the full authentication state in mysql * Far more efficient than file * @param {string} host - The hostname of the database you are connecting to. (Default: localhost) - * @param {string} port - The port number to connect to. (Default: 3306) + * @param {number} port - The port number to connect to. (Default: 3306) * @param {string} user - The MySQL user to authenticate as. (Default: root) * @param {string} password - The password of that MySQL user * @param {string} password1 - Alias for the MySQL user password. Makes a bit more sense in a multifactor authentication setup (see "password2" and "password3") * @param {string} password2 - 2nd factor authentication password. Mandatory when the authentication policy for the MySQL user account requires an additional authentication method that needs a password. * @param {string} password3 - 3rd factor authentication password. Mandatory when the authentication policy for the MySQL user account requires two additional authentication methods and the last one needs a password. - * @param {string} database - Name of the database to use for this connection. (Default: auth) - * @param {string} tableName - MySql table name, by default auth. - * @param {string} retryRequestDelayMs - Retry the query at each interval if it fails. (Default: 200ms) - * @param {string} maxtRetries - Maximum attempts if the query fails. (Default: 10) + * @param {string} database - Name of the database to use for this connection. (Default: base) + * @param {string} tableName - MySql table name. (Default: auth) + * @param {number} retryRequestDelayMs - Retry the query at each interval if it fails. (Default: 200ms) + * @param {number} maxtRetries - Maximum attempts if the query fails. (Default: 10) * @param {string} session - Session name to identify the connection, allowing multisessions with mysql. * @param {string} localAddress - The source IP address to use for TCP connection. * @param {string} socketPath - The path to a unix domain socket to connect to. When used host and port are ignored. - * @param {string} insecureAuth - Allow connecting to MySQL instances that ask for the old (insecure) authentication method. (Default: false) - * @param {string} isServer - If your connection is a server. (Default: false) + * @param {boolean} insecureAuth - Allow connecting to MySQL instances that ask for the old (insecure) authentication method. (Default: false) + * @param {boolean} isServer - If your connection is a server. (Default: false) */ let conn: sqlConnection From 0290ef8cd2bb3ae2483c4502b52c892224ac0a64 Mon Sep 17 00:00:00 2001 From: Bob <115008575+bobslavtriev@users.noreply.github.com> Date: Thu, 6 Jun 2024 02:37:51 -0300 Subject: [PATCH 17/22] Update index.ts --- src/Types/index.ts | 49 +++++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/src/Types/index.ts b/src/Types/index.ts index fe22095..0956bdd 100644 --- a/src/Types/index.ts +++ b/src/Types/index.ts @@ -141,23 +141,40 @@ export interface sqlConnection extends Connection { } export type MySQLConfig = { - session: string - host?: string - port?: number - database: string - tableName?: string - user?: string - password?: string - password1?: string - password2?: string - password3?: string - retryRequestDelayMs?: number - maxtRetries?: number + /* The hostname of the database you are connecting to. (Default: localhost) */ + host?: string, + /* The port number to connect to. (Default: 3306) */ + port?: number, + /* The MySQL user to authenticate as. (Default: root) */ + user?: string, + /* The password of that MySQL user */ + password: string, + /* Alias for the MySQL user password. Makes a bit more sense in a multifactor authentication setup (see "password2" and "password3") */ + password1?: string, + /* 2nd factor authentication password. Mandatory when the authentication policy for the MySQL user account requires an additional authentication method that needs a password. */ + password2?: string, + /* 3rd factor authentication password. Mandatory when the authentication policy for the MySQL user account requires two additional authentication methods and the last one needs a password. */ + password3?: string, + /* Name of the database to use for this connection. (Default: base) */ + database: string, + /* MySql table name. (Default: auth) */ + tableName?: string, + /* Retry the query at each interval if it fails. (Default: 200ms) */ + retryRequestDelayMs: number, + /* Maximum attempts if the query fails. (Default: 10) */ + maxtRetries?: number, + /* Session name to identify the connection, allowing multisessions with mysql. */ + session: string, + /* The source IP address to use for TCP connection. */ + localAddress?: string, + /* The path to a unix domain socket to connect to. When used host and port are ignored. */ + socketPath?: string, + /* Allow connecting to MySQL instances that ask for the old (insecure) authentication method. (Default: false) */ + insecureAuth?: boolean, + /* If your connection is a server. (Default: false) */ + isServer?: boolean, + /* Use the config SSL. (Default: disabled) */ ssl?: string | SslOptions - localAddress?: string - socketPath?: string - insecureAuth?: boolean - isServer?: boolean } export type valueReplacer = { From 39b123a0ecfc7bba57b803b84b3bd79e3c2bb9ac Mon Sep 17 00:00:00 2001 From: Bob <115008575+bobslavtriev@users.noreply.github.com> Date: Thu, 6 Jun 2024 02:39:56 -0300 Subject: [PATCH 18/22] Update README.md --- README.md | 74 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 59b1a54..96c5178 100644 --- a/README.md +++ b/README.md @@ -39,40 +39,48 @@ const { useMySQLAuthState } = require('mysql-baileys') ```ts const { state, saveCreds, removeCreds } = await useMySQLAuthState({ session: sessionName, // required - host: 'localhost', // optional - port: 3306, // optional - user: 'root', // optional password: 'Password123#', // required database: 'baileys', // required - tableName: 'auth' // optional }) ``` ### 5. All parameters for useMySQLAuthState() ```ts type MySQLConfig = { - /* Session name to identify the connection, allowing multisessions with mysql */ - session: string - /* MySql host, by default localhost */ - host: string - /* MySql port, by default 3306 */ - port: number | undefined - /* MySql user, by default root */ - user: string - /* MySql password */ - password: string - /* MySql database name */ - database: string - /* MySql table name, by default auth */ - tableName: string | undefined - /* Always keep active, by default 30s */ - keepAliveIntervalMs: number | undefined - /* Retry the query at each interval if it fails, by default 200ms */ - retryRequestDelayMs: number | undefined - /* Maximum attempts if the query fails, by default 10 */ - maxtRetries: number | undefined - /* MySql SSL config */ - ssl?: string | SslOptions | undefined + /* The hostname of the database you are connecting to. (Default: localhost) */ + host?: string, + /* The port number to connect to. (Default: 3306) */ + port?: number, + /* The MySQL user to authenticate as. (Default: root) */ + user?: string, + /* The password of that MySQL user */ + password: string, + /* Alias for the MySQL user password. Makes a bit more sense in a multifactor authentication setup (see "password2" and "password3") */ + password1?: string, + /* 2nd factor authentication password. Mandatory when the authentication policy for the MySQL user account requires an additional authentication method that needs a password. */ + password2?: string, + /* 3rd factor authentication password. Mandatory when the authentication policy for the MySQL user account requires two additional authentication methods and the last one needs a password. */ + password3?: string, + /* Name of the database to use for this connection. (Default: base) */ + database: string, + /* MySql table name. (Default: auth) */ + tableName?: string, + /* Retry the query at each interval if it fails. (Default: 200ms) */ + retryRequestDelayMs: number, + /* Maximum attempts if the query fails. (Default: 10) */ + maxtRetries?: number, + /* Session name to identify the connection, allowing multisessions with mysql. */ + session: string, + /* The source IP address to use for TCP connection. */ + localAddress?: string, + /* The path to a unix domain socket to connect to. When used host and port are ignored. */ + socketPath?: string, + /* Allow connecting to MySQL instances that ask for the old (insecure) authentication method. (Default: false) */ + insecureAuth?: boolean, + /* If your connection is a server. (Default: false) */ + isServer?: boolean, + /* Use the config SSL. (Default: disabled) */ + ssl?: string | SslOptions } ``` @@ -90,13 +98,13 @@ async function startSock(sessionName){ } const { state, saveCreds, removeCreds } = await useMySQLAuthState({ - session: sessionName, // required - host: 'localhost', // optional - port: 3306, // optional - user: 'root', // optional - password: 'Password123#', // required - database: 'baileys', // required - tableName: 'auth' // optional + session: sessionName, + host: 'localhost', + port: 3306, + user: 'bob', + password: 'Password123#', + database: 'baileys', + tableName: 'auth' }) const sock = makeWASocket({ From 06b4e359125b1ecb57eb6ca64f316362eb6cdf48 Mon Sep 17 00:00:00 2001 From: Bob <115008575+bobslavtriev@users.noreply.github.com> Date: Thu, 6 Jun 2024 03:16:35 -0300 Subject: [PATCH 19/22] Update index.ts --- src/Utils/index.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Utils/index.ts b/src/Utils/index.ts index 98bdf39..aa43c94 100644 --- a/src/Utils/index.ts +++ b/src/Utils/index.ts @@ -41,7 +41,7 @@ const allocate = (str: string) => { return new Uint8Array(Math.ceil(str.length * 3) / 4 - n).fill(0) } -const parseTimestamp = (timestamp: Bits | number) => { +const parseTimestamp = (timestamp: string | number | Long) => { if (typeof timestamp === 'string') { return parseInt(timestamp, 10) } @@ -50,11 +50,7 @@ const parseTimestamp = (timestamp: Bits | number) => { return timestamp } - return { - low: 0, - high: 0, - unsigned: false - } + return timestamp } export const fromObject = (args: AppDataSync) => { From 764f4ace642cc7a1d84781c81c95aab7148d9e50 Mon Sep 17 00:00:00 2001 From: Bob <115008575+bobslavtriev@users.noreply.github.com> Date: Thu, 6 Jun 2024 03:17:51 -0300 Subject: [PATCH 20/22] Update index.ts --- src/Types/index.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Types/index.ts b/src/Types/index.ts index 0956bdd..f1aa59f 100644 --- a/src/Types/index.ts +++ b/src/Types/index.ts @@ -93,12 +93,6 @@ export type Fingerprint = { deviceIndexes: number[] } -export type Bits = { - low: number - high: number - unsigned: boolean -} - export type AppDataSync = { keyData: Uint8Array fingerprint: Fingerprint From 70aa1a277e16a61fe616a0f557935d970774164f Mon Sep 17 00:00:00 2001 From: Bob <115008575+bobslavtriev@users.noreply.github.com> Date: Thu, 6 Jun 2024 03:19:21 -0300 Subject: [PATCH 21/22] Update index.ts --- src/Utils/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Utils/index.ts b/src/Utils/index.ts index aa43c94..7b59f15 100644 --- a/src/Utils/index.ts +++ b/src/Utils/index.ts @@ -1,6 +1,6 @@ import { curve } from 'libsignal' import { randomBytes, randomUUID } from 'crypto' -import { KeyPair, valueReplacer, valueReviver, AppDataSync, Fingerprint, Bits } from '../Types' +import { KeyPair, valueReplacer, valueReviver, AppDataSync, Fingerprint } from '../Types' const generateKeyPair = () => { const { pubKey, privKey } = curve.generateKeyPair() From c18b7d7e68fe2d6ae2c065087953c830e014678c Mon Sep 17 00:00:00 2001 From: Bob <115008575+bobslavtriev@users.noreply.github.com> Date: Thu, 6 Jun 2024 03:22:22 -0300 Subject: [PATCH 22/22] Update index.ts --- src/Types/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Types/index.ts b/src/Types/index.ts index f1aa59f..b8b1ee4 100644 --- a/src/Types/index.ts +++ b/src/Types/index.ts @@ -154,7 +154,7 @@ export type MySQLConfig = { /* MySql table name. (Default: auth) */ tableName?: string, /* Retry the query at each interval if it fails. (Default: 200ms) */ - retryRequestDelayMs: number, + retryRequestDelayMs?: number, /* Maximum attempts if the query fails. (Default: 10) */ maxtRetries?: number, /* Session name to identify the connection, allowing multisessions with mysql. */