Files
2026-05-03 11:13:06 -04:00

242 lines
6.2 KiB
JavaScript

'use strict';
const path = require('path');
const sqlite3 = require('sqlite3').verbose();
const { open } = require('sqlite');
const target = process.argv[2];
const dbPath = path.resolve(__dirname, '..', 'storage', 'storage.db');
const GROUPS = {
all: {
tables: ['shulker_items', 'chest_loose_items', 'shulkers', 'chests',
'item_index', 'trades', 'invite_permissions', 'invite_sites',
'maps', 'permissions'],
label: 'ALL tables'
},
storage: {
tables: ['shulker_items', 'chest_loose_items', 'shulkers', 'chests', 'item_index'],
label: 'storage tables (chests, shulkers, items, index)'
},
permissions: {
tables: ['permissions'],
label: 'permissions table'
},
maps: {
tables: ['maps'],
label: 'maps table'
},
invites: {
tables: ['invite_permissions', 'invite_sites'],
label: 'invite tables'
},
trades: {
tables: ['trades'],
label: 'trades table'
}
};
function usage() {
console.log('Usage: node scripts/db-reset.js <target>');
console.log('Targets:');
for (const [name, group] of Object.entries(GROUPS)) {
console.log(` ${name.padEnd(14)} ${group.label}`);
}
process.exit(1);
}
if (!target || !GROUPS[target]) {
usage();
}
const group = GROUPS[target];
async function main() {
console.log(`Database: ${dbPath}`);
console.log(`Resetting ${group.label}...`);
const db = await open({
filename: dbPath,
driver: sqlite3.Database
});
try {
await db.run('PRAGMA foreign_keys = OFF');
for (const table of group.tables) {
console.log(` DROP TABLE IF EXISTS ${table}`);
await db.run(`DROP TABLE IF EXISTS ${table}`);
}
await db.run('PRAGMA foreign_keys = ON');
// Recreate tables and re-insert defaults
await recreateTables(db, group);
console.log('Done.');
} finally {
await db.close();
}
}
async function recreateTables(db, group) {
const tables = group.tables;
const recreate = (t) => tables.includes(t);
if (recreate('permissions')) {
await db.exec(`CREATE TABLE permissions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
player_name TEXT UNIQUE NOT NULL,
role TEXT DEFAULT 'team' NOT NULL CHECK(role IN ('owner', 'team', 'readonly')),
joined_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)`);
console.log(' Recreated permissions');
await insertDefaultPermissions(db);
}
if (recreate('chests')) {
await db.exec(`CREATE TABLE chests (
id INTEGER PRIMARY KEY AUTOINCREMENT,
pos_x INTEGER NOT NULL,
pos_y INTEGER NOT NULL,
pos_z INTEGER NOT NULL,
chest_type TEXT NOT NULL CHECK(chest_type IN ('single', 'double')),
row INTEGER NOT NULL,
column INTEGER NOT NULL,
category TEXT,
last_scan TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(pos_x, pos_y, pos_z)
)`);
console.log(' Recreated chests');
}
if (recreate('shulkers')) {
await db.exec(`CREATE TABLE shulkers (
id INTEGER PRIMARY KEY AUTOINCREMENT,
chest_id INTEGER NOT NULL,
slot INTEGER NOT NULL,
shulker_type TEXT DEFAULT 'shulker_box',
category TEXT,
item_focus TEXT,
slot_count INTEGER DEFAULT 0,
total_items INTEGER DEFAULT 0,
last_scan TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (chest_id) REFERENCES chests(id) ON DELETE CASCADE,
UNIQUE(chest_id, slot)
)`);
console.log(' Recreated shulkers');
}
if (recreate('shulker_items')) {
await db.exec(`CREATE TABLE shulker_items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
shulker_id INTEGER NOT NULL,
item_name TEXT NOT NULL,
item_id INTEGER NOT NULL,
slot INTEGER NOT NULL,
count INTEGER NOT NULL,
nbt_data TEXT,
FOREIGN KEY (shulker_id) REFERENCES shulkers(id) ON DELETE CASCADE,
UNIQUE(shulker_id, slot),
CHECK(slot >= 0 AND slot <= 26),
CHECK(count > 0 AND count <= 64)
)`);
console.log(' Recreated shulker_items');
}
if (recreate('trades')) {
await db.exec(`CREATE TABLE trades (
id INTEGER PRIMARY KEY AUTOINCREMENT,
player_name TEXT NOT NULL,
action TEXT NOT NULL CHECK(action IN ('deposit', 'withdraw')),
items TEXT NOT NULL,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)`);
console.log(' Recreated trades');
}
if (recreate('chest_loose_items')) {
await db.exec(`CREATE TABLE chest_loose_items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
chest_id INTEGER NOT NULL,
slot INTEGER NOT NULL,
item_name TEXT NOT NULL,
item_id INTEGER NOT NULL,
count INTEGER NOT NULL,
FOREIGN KEY (chest_id) REFERENCES chests(id) ON DELETE CASCADE,
UNIQUE(chest_id, slot)
)`);
console.log(' Recreated chest_loose_items');
}
if (recreate('item_index')) {
await db.exec(`CREATE TABLE item_index (
id INTEGER PRIMARY KEY AUTOINCREMENT,
item_id INTEGER UNIQUE NOT NULL,
item_name TEXT NOT NULL,
total_count INTEGER DEFAULT 0,
shulker_ids TEXT,
last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)`);
console.log(' Recreated item_index');
}
if (recreate('maps')) {
await db.exec(`CREATE TABLE maps (
id INTEGER PRIMARY KEY AUTOINCREMENT,
map_id INTEGER UNIQUE NOT NULL,
image_data TEXT,
pixel_data TEXT,
captured_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)`);
console.log(' Recreated maps');
}
if (recreate('invite_sites')) {
await db.exec(`CREATE TABLE invite_sites (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT UNIQUE NOT NULL,
label TEXT NOT NULL,
bot_name TEXT NOT NULL,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)`);
console.log(' Recreated invite_sites');
}
if (recreate('invite_permissions')) {
await db.exec(`CREATE TABLE invite_permissions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
site_id INTEGER NOT NULL,
player_name TEXT NOT NULL,
FOREIGN KEY (site_id) REFERENCES invite_sites(id) ON DELETE CASCADE,
UNIQUE(site_id, player_name)
)`);
console.log(' Recreated invite_permissions');
}
}
async function insertDefaultPermissions(db) {
const conf = require('../conf/base');
const defaultPlayers = conf.storage?.defaultPlayers || [];
for (const player of defaultPlayers) {
try {
await db.run(
'INSERT OR IGNORE INTO permissions (player_name, role) VALUES (?, ?)',
[player.name, player.role]
);
} catch (e) {
console.error(` Error inserting ${player.name}:`, e.message);
}
}
if (defaultPlayers.length > 0) {
console.log(` Inserted ${defaultPlayers.length} default players`);
}
}
main().catch(err => {
console.error('Fatal:', err);
process.exit(1);
});