Spaces:
Paused
Paused
| /** | |
| * Storage handling for offline PMs. | |
| * By Mia. | |
| * @author mia-pi-git | |
| */ | |
| import { type SQL, FS } from '../../lib'; | |
| import { MAX_PENDING } from '.'; | |
| export const statements = { | |
| send: 'INSERT INTO offline_pms (sender, receiver, message, time) VALUES (?, ?, ?, ?)', | |
| clear: 'DELETE FROM offline_pms WHERE receiver = ?', | |
| fetch: 'SELECT * FROM offline_pms WHERE receiver = ?', | |
| fetchNew: 'SELECT * FROM offline_pms WHERE receiver = ? AND seen IS NULL', | |
| clearDated: 'DELETE FROM offline_pms WHERE ? - time >= ?', | |
| checkSentCount: 'SELECT count(*) as count FROM offline_pms WHERE sender = ? AND receiver = ?', | |
| setSeen: 'UPDATE offline_pms SET seen = ? WHERE receiver = ? AND seen IS NULL', | |
| clearSeen: 'DELETE FROM offline_pms WHERE ? - seen >= ?', | |
| getSettings: 'SELECT * FROM pm_settings WHERE userid = ?', | |
| setBlock: 'REPLACE INTO pm_settings (userid, view_only) VALUES (?, ?)', | |
| deleteSettings: 'DELETE FROM pm_settings WHERE userid = ?', | |
| } as const; | |
| type Statement = keyof typeof statements; | |
| class StatementMap { | |
| env: SQL.TransactionEnvironment; | |
| constructor(env: SQL.TransactionEnvironment) { | |
| this.env = env; | |
| } | |
| run(name: Statement, args: any[] | AnyObject) { | |
| return this.getStatement(name).run(args); | |
| } | |
| all(name: Statement, args: any[] | AnyObject) { | |
| return this.getStatement(name).all(args); | |
| } | |
| get(name: Statement, args: any[] | AnyObject) { | |
| return this.getStatement(name).get(args); | |
| } | |
| getStatement(name: Statement) { | |
| const source = statements[name]; | |
| return this.env.statements.get(source)!; | |
| } | |
| } | |
| export const transactions: { | |
| [k: string]: (args: any[], env: SQL.TransactionEnvironment) => any, | |
| } = { | |
| send: (args, env) => { | |
| const statementList = new StatementMap(env); | |
| const [sender, receiver, message] = args; | |
| const count = statementList.get('checkSentCount', [sender, receiver])?.count; | |
| if (count && count > MAX_PENDING) { | |
| return { error: `You have already sent the maximum ${MAX_PENDING} offline PMs to that user.` }; | |
| } | |
| return statementList.run('send', [sender, receiver, message, Date.now()]); | |
| }, | |
| listNew: (args, env) => { | |
| const list = new StatementMap(env); | |
| const [receiver] = args; | |
| const pms = list.all('fetchNew', [receiver]); | |
| list.run('setSeen', [Date.now(), receiver]); | |
| return pms; | |
| }, | |
| }; | |
| export function onDatabaseStart(database: import('better-sqlite3').Database) { | |
| let version; | |
| try { | |
| version = database.prepare('SELECT * FROM db_info').get().version; | |
| } catch { | |
| const schemaContent = FS('databases/schemas/pms.sql').readSync(); | |
| database.exec(schemaContent); | |
| } | |
| const migrations = FS('databases/migrations/pms').readdirIfExistsSync(); | |
| if (version !== migrations.length) { | |
| for (const migration of migrations) { | |
| const num = /(\d+)\.sql$/.exec(migration)?.[1]; | |
| if (!num || version >= num) continue; | |
| database.exec('BEGIN TRANSACTION'); | |
| try { | |
| database.exec(FS(`databases/migrations/pms/${migration}`).readSync()); | |
| } catch (e: any) { | |
| console.log(`Error in PM migration ${migration} - ${e.message}`); | |
| console.log(e.stack); | |
| database.exec('ROLLBACK'); | |
| continue; | |
| } | |
| database.exec('COMMIT'); | |
| } | |
| } | |
| } | |