Release Healer Man 0.1.43
This commit is contained in:
1 parent
c7e8163790
commit
ccc01396cd
86 files changed
+2951
-198
No files matched your search
@@ -19,11 +19,22 @@ export function createDungeonReportRepository(database, { isGameMaster, ErrorTyp
|
||||
revision INTEGER NOT NULL DEFAULT 0
|
||||
) STRICT;
|
||||
CREATE INDEX IF NOT EXISTS dungeon_reports_dungeon_status_idx ON dungeon_reports(dungeon_id, status);
|
||||
CREATE TABLE IF NOT EXISTS boss_testing_reviews (
|
||||
boss_key TEXT PRIMARY KEY,
|
||||
dungeon_id TEXT NOT NULL,
|
||||
boss_name TEXT NOT NULL,
|
||||
status TEXT NOT NULL CHECK (status IN ('ready', 'needs-testing', 'not-ready')),
|
||||
reviewed_by TEXT NOT NULL,
|
||||
reviewed_at INTEGER NOT NULL
|
||||
) STRICT;
|
||||
`);
|
||||
const columns = new Set(database.prepare("PRAGMA table_info(dungeon_reports)").all().map((column) => column.name));
|
||||
if (!columns.has("boss_key")) database.exec("ALTER TABLE dungeon_reports ADD COLUMN boss_key TEXT");
|
||||
if (!columns.has("boss_name")) database.exec("ALTER TABLE dungeon_reports ADD COLUMN boss_name TEXT");
|
||||
const insert = database.prepare(`
|
||||
INSERT INTO dungeon_reports (
|
||||
id, dungeon_id, comment, status, submitted_by_account_id, submitted_by_username, created_at, updated_at
|
||||
) VALUES (?, ?, ?, 'Submitted', ?, ?, ?, ?)
|
||||
id, dungeon_id, comment, status, submitted_by_account_id, submitted_by_username, created_at, updated_at, boss_key, boss_name
|
||||
) VALUES (?, ?, ?, 'Submitted', ?, ?, ?, ?, ?, ?)
|
||||
`);
|
||||
const byId = database.prepare("SELECT * FROM dungeon_reports WHERE id = ?");
|
||||
const list = database.prepare(`
|
||||
@@ -45,6 +56,14 @@ export function createDungeonReportRepository(database, { isGameMaster, ErrorTyp
|
||||
function validateStatus(status) {
|
||||
if (!policy.statuses.includes(status)) throw new ErrorType("Choose a valid report status.", 400, "invalid_report_status");
|
||||
}
|
||||
function validateBoss(input) {
|
||||
validateDungeon(input?.dungeonId);
|
||||
if (typeof input.bossKey !== "string" || !input.bossKey.startsWith(`${input.dungeonId}/`)
|
||||
|| input.bossKey.length <= input.dungeonId.length + 1 || input.bossKey.length > 256
|
||||
|| typeof input.bossName !== "string" || !input.bossName.trim() || input.bossName.length > 128) {
|
||||
throw new ErrorType("Choose a valid boss.", 400, "invalid_boss");
|
||||
}
|
||||
}
|
||||
function publicReport(row) {
|
||||
return {
|
||||
id: row.id,
|
||||
@@ -56,10 +75,30 @@ export function createDungeonReportRepository(database, { isGameMaster, ErrorTyp
|
||||
updatedAt: Number(row.updated_at),
|
||||
updatedBy: row.updated_by_username,
|
||||
revision: Number(row.revision),
|
||||
...(row.boss_key ? { bossKey: row.boss_key, bossName: row.boss_name } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
listBossTestingReviews() {
|
||||
return { reviews: database.prepare("SELECT * FROM boss_testing_reviews ORDER BY boss_key").all().map((row) => ({
|
||||
bossKey: row.boss_key, dungeonId: row.dungeon_id, bossName: row.boss_name,
|
||||
status: row.status, reviewedBy: row.reviewed_by, reviewedAt: Number(row.reviewed_at),
|
||||
})) };
|
||||
},
|
||||
saveBossTestingReview(account, input) {
|
||||
validateBoss(input);
|
||||
if (!["ready", "needs-testing", "not-ready"].includes(input.status)) {
|
||||
throw new ErrorType("Choose a valid boss readiness status.", 400, "invalid_boss_status");
|
||||
}
|
||||
const review = { bossKey: input.bossKey, dungeonId: input.dungeonId, bossName: input.bossName.trim(),
|
||||
status: input.status, reviewedBy: account?.username ?? "Guest player", reviewedAt: Date.now() };
|
||||
database.prepare(`INSERT INTO boss_testing_reviews VALUES (?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(boss_key) DO UPDATE SET boss_name = excluded.boss_name, status = excluded.status,
|
||||
reviewed_by = excluded.reviewed_by, reviewed_at = excluded.reviewed_at`).run(
|
||||
review.bossKey, review.dungeonId, review.bossName, review.status, review.reviewedBy, review.reviewedAt);
|
||||
return review;
|
||||
},
|
||||
listDungeonReports({ status = null, dungeonId = null } = {}) {
|
||||
if (status !== null) validateStatus(status);
|
||||
if (dungeonId !== null) validateDungeon(dungeonId);
|
||||
@@ -70,13 +109,14 @@ export function createDungeonReportRepository(database, { isGameMaster, ErrorTyp
|
||||
},
|
||||
submitDungeonReport(account, input) {
|
||||
validateDungeon(input?.dungeonId);
|
||||
if (input?.bossKey !== undefined || input?.bossName !== undefined) validateBoss(input);
|
||||
if (typeof input?.comment !== "string" || !input.comment.trim() || input.comment.length > policy.commentMaxLength) {
|
||||
throw new ErrorType("Describe the issue in 1-500 characters.", 400, "invalid_report_comment");
|
||||
}
|
||||
const id = randomUUID();
|
||||
const now = Date.now();
|
||||
insert.run(id, input.dungeonId, input.comment.replace(/\r\n?/g, "\n").trim(), account?.id ?? null,
|
||||
account?.username ?? "Guest player", now, now);
|
||||
account?.username ?? "Guest player", now, now, input.bossKey ?? null, input.bossName?.trim() ?? null);
|
||||
return publicReport(byId.get(id));
|
||||
},
|
||||
updateDungeonReport(account, id, input) {
|
||||
|
||||
Reference in new issue
Block a user