/* Copyright 2023 0xf8.dev@proton.me This file is part of Galerie Galerie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Galerie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Galerie. If not, see . */ import { createHash } from "crypto"; import { Request, Response } from "express"; import { readdirSync, existsSync, mkdirSync, statSync, readFileSync, watch } from "fs"; import path from "path"; class Sync { constructor() { this.root = path.join(process.cwd(), "public"); if (!existsSync(this.root)) { mkdirSync(this.root); } this.update(); } async update() { return new Promise((res, rej) => { this.files = readdirSync(this.root).filter(async (v) => { let f = path.join(this.root, v); if (existsSync(f)) { let s = statSync(f); return s.isFile() && s.size > 1; } else { await this.update(); res(); } }); let c = createHash("sha1"); this.files.forEach(async (v) => { let f = path.join(this.root, v); if (existsSync(f)) c.update(readFileSync(f)) else { await this.update(); res(); } }); this.checksum = c.digest("hex"); res(); }); } root: string; files: string[]; checksum: string; pastchecksum: string[]; } const state: Sync = new Sync(); let lastUpdate = Date.now(); watch(state.root, {}, (e, f) => { let now = Date.now(); // If lastUpdate occured within 1 second if (now - lastUpdate < 1000) { lastUpdate = now; return; } lastUpdate = now; state.update(); }); let sync = async (req: Request, res: Response) => { try { switch (req.method) { case "GET": { // "Update me" res.status(405); break; } case "POST": { await state.update(); let reqd: { action: string; checksum: string; }; try { reqd = JSON.parse(req.body); } catch { res.status(400); break; } let action = reqd.action; switch (action) { case "validateChecksum": { res.write(JSON.stringify({ valid: (reqd.checksum == state.checksum) })) break; } case "fullUpdate": { if (reqd.checksum != state.checksum) res.write(JSON.stringify({ valid: false, checksum: state.checksum, files: state.files })); else res.write(JSON.stringify({ valid: true })); break; } default: { res.status(501); res.write("{}"); break; } } break; } } } catch (e) { console.error(e); res.status(500); } res.end(); } export default sync;