Add bots files handling logic
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
import BunSQLite from "@moduletrace/bun-sqlite";
|
||||
import { existsSync, mkdirSync, renameSync, rmSync, copyFileSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
import AppError from "@/src/utils/app-error";
|
||||
import grabDirNames from "@/src/utils/grab-dir-names";
|
||||
import resolveBotPath from "@/src/utils/resolve-bot-path";
|
||||
import type { StorageScope } from "@/src/utils/storage-access";
|
||||
import { canReachScope } from "@/src/utils/storage-access";
|
||||
import grabBotFile from "./grab-bot-file";
|
||||
import grabStorageDir from "./grab-storage-dir";
|
||||
import { grabBotFileRow } from "./record-bot-file";
|
||||
|
||||
type Params = {
|
||||
scopes: StorageScope[];
|
||||
file_id: number | string;
|
||||
/**
|
||||
* The new path, in the file's own directory.
|
||||
*/
|
||||
path: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Renames a file or moves it into another folder, inside its own
|
||||
* directory. The bytes move on disk and the row follows; an existing file
|
||||
* at the target is refused, never overwritten by a rename.
|
||||
*/
|
||||
export default async function moveBotFile({ scopes, file_id, path: target }: Params) {
|
||||
const file = await grabBotFile({ scopes, file_id });
|
||||
|
||||
if (!file?.id) {
|
||||
throw new AppError(`That file isn't in your files.`);
|
||||
}
|
||||
|
||||
if (!canReachScope({ scopes, scope: file.scope as any, owner_id: file.owner_id! })) {
|
||||
throw new AppError(`That file isn't in your files.`);
|
||||
}
|
||||
|
||||
const root = grabStorageDir({ scope: file.scope as any, owner_id: file.owner_id! });
|
||||
const resolved = resolveBotPath({ root, path: target });
|
||||
|
||||
if (resolved.relative == file.path) return file;
|
||||
|
||||
const taken = await grabBotFileRow({
|
||||
scope: file.scope as any,
|
||||
owner_id: file.owner_id!,
|
||||
path: resolved.relative,
|
||||
});
|
||||
|
||||
if (taken?.id) {
|
||||
throw new AppError(`There's already a file at ${resolved.relative}.`);
|
||||
}
|
||||
|
||||
const { DATA_DIR } = grabDirNames();
|
||||
const from = path.join(root, file.path || "");
|
||||
|
||||
mkdirSync(path.dirname(resolved.absolute), { recursive: true });
|
||||
|
||||
if (existsSync(from)) {
|
||||
try {
|
||||
renameSync(from, resolved.absolute);
|
||||
} catch {
|
||||
copyFileSync(from, resolved.absolute);
|
||||
rmSync(from, { force: true });
|
||||
}
|
||||
}
|
||||
|
||||
await BunSQLite.sql({
|
||||
sql: `UPDATE bot_files SET path = ?, name = ?, folder = ?, updated_at = ? WHERE id = ?`,
|
||||
values: [resolved.relative, resolved.name, resolved.folder, Date.now(), file.id],
|
||||
});
|
||||
|
||||
if (file.media_id) {
|
||||
const write_path = resolved.absolute.startsWith(DATA_DIR)
|
||||
? resolved.absolute.slice(DATA_DIR.length).replace(/^[\\/]/, "").split("\\").join("/")
|
||||
: resolved.relative;
|
||||
|
||||
await BunSQLite.sql({
|
||||
sql: `UPDATE media SET media_write_path = ?, updated_at = ? WHERE id = ?`,
|
||||
values: [write_path, Date.now(), file.media_id],
|
||||
});
|
||||
}
|
||||
|
||||
return { ...file, path: resolved.relative, name: resolved.name, folder: resolved.folder };
|
||||
}
|
||||
Reference in New Issue
Block a user