galerie/srv/src/sync.ts

136 lines
3.2 KiB
TypeScript
Raw Normal View History

/*
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 <https://www.gnu.org/licenses/>.
*/
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<void>((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;