diff --git a/config/config.schema.yaml b/config/config.schema.yaml index 40b50ca147af8ef9cc445d8d7b3124b397063115..96cc1abae3f025bc906806d31ceed6f4c7fa58ca 100644 --- a/config/config.schema.yaml +++ b/config/config.schema.yaml @@ -68,8 +68,10 @@ properties: type: "string" database: type: "object" - required: ["filename"] + required: [] properties: + connString: + type: "string" filename: type: "string" userStorePath: diff --git a/src/config.ts b/src/config.ts index f8be3e41843271fa177fcef2c51b4a2bcc0c7f43..cfa5727b746f21dd4d3091327af04e52d7331f01 100644 --- a/src/config.ts +++ b/src/config.ts @@ -37,7 +37,8 @@ class DiscordBridgeConfigBridge { public disableHereMention: boolean = false; } -class DiscordBridgeConfigDatabase { +export class DiscordBridgeConfigDatabase { + public connString: string; public filename: string; public userStorePath: string; public roomStorePath: string; diff --git a/src/db/dbdataevent.ts b/src/db/dbdataevent.ts index d4af4bbf3f3d5ec29aff9fe1cea202e27956c904..8756b9ec431a2b4ad5dbe9ae1fc9c7030fda57fb 100644 --- a/src/db/dbdataevent.ts +++ b/src/db/dbdataevent.ts @@ -81,7 +81,7 @@ export class DbEvent implements IDbDataMany { FROM discord_msg_store WHERE msg_id = $id`, { id: this.DiscordId, - }) !== undefined; + }) != null; if (msgExists) { return; } diff --git a/src/db/sqlite3.ts b/src/db/sqlite3.ts index 61c4f80600789a579fcbc7bc87e7a22ac8a11664..57ac65762e00d2bcde9d80f2529cf132acab6d45 100644 --- a/src/db/sqlite3.ts +++ b/src/db/sqlite3.ts @@ -1,8 +1,9 @@ import * as Database from "better-sqlite3"; import { Log } from "../log"; +import { DatabaseConnector } from "./connector"; const log = new Log("SQLite3"); -export class SQLite3 { +export class SQLite3 implements DatabaseConnector { private db: Database; constructor (private filename: string) { diff --git a/src/discordas.ts b/src/discordas.ts index 4aa4597114981446e1873e51cde6811df17da690..33b70b2b3404766b314538ebbad82e7693a0aa74 100644 --- a/src/discordas.ts +++ b/src/discordas.ts @@ -57,7 +57,8 @@ function run (port: number, fileConfig: DiscordBridgeConfig) { url: config.bridge.homeserverUrl, }); const provisioner = new Provisioner(); - const discordstore = new DiscordStore(config.database ? config.database.filename : "discord.db"); + // Warn and deprecate old config options. + const discordstore = new DiscordStore(config.database); const discordbot = new DiscordBot(config, discordstore, provisioner); const roomhandler = new MatrixRoomHandler(discordbot, config, botUserId, provisioner); diff --git a/src/store.ts b/src/store.ts index dec11df3e4413af02df75f92a900ed2070e11d3c..ad6b48fcfcfd6c922a7159a1fbf88cc672826a92 100644 --- a/src/store.ts +++ b/src/store.ts @@ -5,6 +5,9 @@ import { SQLite3 } from "./db/sqlite3"; export const CURRENT_SCHEMA = 7; import { Log } from "./log"; +import { DiscordBridgeConfigDatabase } from "./config"; +import { Postgres } from "./db/postgres"; +import { DatabaseConnector } from "./db/connector"; const log = new Log("DiscordStore"); /** * Stores data for specific users and data not specific to rooms. @@ -13,20 +16,29 @@ export class DiscordStore { /** * @param {string} filepath Location of the SQLite database file. */ - public db: SQLite3; + public db: DatabaseConnector; private version: number; - private filepath: string; - constructor (filepath: string) { + private config: DiscordBridgeConfigDatabase; + constructor (private configOrFile: DiscordBridgeConfigDatabase|string) { + if (typeof(configOrFile) === "string"){ + this.config = new DiscordBridgeConfigDatabase(); + this.config.filename = configOrFile; + } else { + this.config = configOrFile; + } this.version = null; - this.filepath = filepath; } public backup_database(): Promise<void|{}> { - if (this.filepath === ":memory:") { + if (this.config.filename == null) { + log.warn("Backups not supported on non-sqlite connector"); + return; + } + if (this.config.filename === ":memory:") { log.info("Can't backup a :memory: database."); return Promise.resolve(); } - const BACKUP_NAME = this.filepath + ".backup"; + const BACKUP_NAME = this.config.filename + ".backup"; return new Promise((resolve, reject) => { // Check to see if a backup file already exists. @@ -39,7 +51,7 @@ export class DiscordStore { log.warn("NOT backing up database while a file already exists"); resolve(true); } - const rd = fs.createReadStream(this.filepath); + const rd = fs.createReadStream(this.config.filename); rd.on("error", reject); const wr = fs.createWriteStream(BACKUP_NAME); wr.on("error", reject); @@ -146,7 +158,7 @@ export class DiscordStore { userId, }, ).then( (rows) => { - if (rows !== undefined) { + if (rows != null) { return rows.map((row) => row.discord_id); } else { return []; @@ -168,7 +180,7 @@ export class DiscordStore { discordId, }, ).then( (row) => { - return row !== undefined ? row.token : null; + return row != null ? row.token : null; }).catch( (err) => { log.error("Error getting discord ids ", err.Error); throw err; @@ -188,7 +200,7 @@ export class DiscordStore { discordId, discordChannel, }).then( (row) => { - return row !== undefined ? row.room_id : null; + return row != null ? row.room_id : null; }).catch( (err) => { log.error("Error getting room_id ", err.Error); throw err; @@ -276,8 +288,13 @@ export class DiscordStore { } private async open_database(): Promise<void|Error> { - log.info("Opening database ", this.filepath); - this.db = new SQLite3(this.filepath); + if (this.config.filename) { + log.info("Filename present in config, using sqlite"); + this.db = new SQLite3(this.config.filename); + } else if (this.config.connString) { + log.info("connString present in config, using postgres"); + this.db = new Postgres(this.config.connString); + } try { await this.db.Open(); } catch (ex) {