UNPKG

imessage-ts

Version:

TypeScript library for interacting with iMessage on macOS - send messages, monitor chats, and automate responses

160 lines 5.64 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Database = void 0; const path_1 = __importDefault(require("path")); const os_1 = __importDefault(require("os")); const fs_extra_1 = __importDefault(require("fs-extra")); const sqlite3_1 = __importDefault(require("sqlite3")); const util_1 = require("util"); /** * Default paths to the iMessage database and attachments */ const DEFAULT_DB_PATH = path_1.default.join(os_1.default.homedir(), 'Library/Messages/chat.db'); const DEFAULT_ATTACHMENTS_PATH = path_1.default.join(os_1.default.homedir(), 'Library/Messages/Attachments'); /** * Class to handle access to the iMessage database */ class Database { constructor(options = {}) { this.sqliteDb = null; this.options = { databasePath: options.databasePath || DEFAULT_DB_PATH, attachmentsPath: options.attachmentsPath || DEFAULT_ATTACHMENTS_PATH, pollInterval: options.pollInterval || 1000, catchUpOnStart: options.catchUpOnStart ?? false, }; } /** * Initialize the database connection */ async initialize() { if (this.sqliteDb) { return; } try { // Check if the database exists if (!(await fs_extra_1.default.pathExists(this.options.databasePath))) { throw new Error(`iMessage database not found at ${this.options.databasePath}`); } // Open a direct connection to the database in read-only mode // No need to copy the file, just connect directly console.log(`Connecting directly to database at: ${this.options.databasePath}`); this.sqliteDb = new sqlite3_1.default.Database(this.options.databasePath, sqlite3_1.default.OPEN_READONLY); // Wait for the database to open await new Promise((resolve, reject) => { this.sqliteDb.on('open', () => { console.log('Database connection opened successfully'); resolve(); }); this.sqliteDb.on('error', (err) => { console.error('Database connection error:', err); reject(err); }); }); } catch (error) { throw new Error(`Failed to initialize iMessage database: ${error.message}`); } } /** * Close the database connection */ close() { if (this.sqliteDb) { this.sqliteDb.close(); this.sqliteDb = null; } } /** * Execute a SQL query and return the results */ async query(sql, params = {}) { if (!this.sqliteDb) { await this.initialize(); } try { // Convert named parameters to positional parameters const formattedSql = this.formatSqlForSqlite3(sql); const formattedParams = this.formatParamsForSqlite3(formattedSql, params); // Promisify the all method const all = (0, util_1.promisify)((sql, params, callback) => { this.sqliteDb.all(sql, params, callback); }); return await all(formattedSql, formattedParams); } catch (error) { throw new Error(`Database query failed: ${error.message}`); } } /** * Execute a SQL query and return a single result */ async queryOne(sql, params = {}) { if (!this.sqliteDb) { await this.initialize(); } try { // Convert named parameters to positional parameters const formattedSql = this.formatSqlForSqlite3(sql); const formattedParams = this.formatParamsForSqlite3(formattedSql, params); // Promisify the get method const get = (0, util_1.promisify)((sql, params, callback) => { this.sqliteDb.get(sql, params, callback); }); return await get(formattedSql, formattedParams) || null; } catch (error) { throw new Error(`Database query failed: ${error.message}`); } } /** * Format SQL for sqlite3 (replacing $ params with ?) */ formatSqlForSqlite3(sql) { return sql.replace(/\$(\w+)/g, '?'); } /** * Format params for sqlite3 (turns named params into positional params) */ formatParamsForSqlite3(sql, params) { const paramNames = sql.match(/\?/g); if (!paramNames) return []; const paramValues = []; // Extract original param names from the original query const originalParamNames = Object.keys(params); // For each ? in the query, find the corresponding parameter value for (let i = 0; i < paramNames.length; i++) { if (i < originalParamNames.length) { paramValues.push(params[originalParamNames[i]]); } else { paramValues.push(null); } } return paramValues; } /** * Get the database path */ getDatabasePath() { return this.options.databasePath; } /** * Get the attachments path */ getAttachmentsPath() { return this.options.attachmentsPath; } /** * Get the poll interval */ getPollInterval() { return this.options.pollInterval; } } exports.Database = Database; //# sourceMappingURL=database.js.map