UNPKG

better-giveaways

Version:

A modern, feature-rich Discord giveaway manager with TypeScript support, flexible storage adapters, and comprehensive event system

188 lines (187 loc) 6.56 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.JSONAdapter = void 0; const fs_1 = __importDefault(require("fs")); /** * File-based storage adapter using JSON format. * * This adapter provides persistent storage for giveaway data using a local JSON file. * It's ideal for simple deployments, development environments, or small bots where * database setup might be overkill. * * Features: * - Automatic file creation if it doesn't exist * - In-memory caching for better performance * - Atomic write operations to prevent data corruption * - Human-readable JSON format for easy debugging * * @example * ```typescript * import { JSONAdapter } from 'better-giveaways'; * * // Use default file location (./giveaways.json) * const adapter = new JSONAdapter(); * * // Or specify a custom file path * const adapter = new JSONAdapter('./data/my-giveaways.json'); * * // Use with GiveawayManager * const giveawayManager = new GiveawayManager(client, adapter, options); * ``` */ class JSONAdapter { /** * Creates a new JSONAdapter instance. * * @param filePath - The path to the JSON file for storing giveaway data. * Defaults to './giveaways.json' in the current working directory. * The file will be created automatically if it doesn't exist. * * @example * ```typescript * // Use default location * const adapter = new JSONAdapter(); * * // Use custom location * const adapter = new JSONAdapter('./data/giveaways.json'); * * // Use absolute path * const adapter = new JSONAdapter('/var/lib/bot/giveaways.json'); * ``` */ constructor(filePath = "./giveaways.json") { this.cache = []; this.filePath = filePath; } /** * Loads giveaway data from the JSON file into memory cache. * * This method handles file creation if the file doesn't exist and provides * error handling for corrupted or inaccessible files. * * @private * @throws {Error} If the file exists but cannot be read or parsed */ load() { return __awaiter(this, void 0, void 0, function* () { try { const data = yield fs_1.default.readFileSync(this.filePath, "utf-8"); this.cache = JSON.parse(data); } catch (err) { if (err.code === "ENOENT") { this.cache = []; yield this.saveFile(); } else { throw err; } } }); } /** * Writes the current cache to the JSON file. * * The data is written with pretty formatting (2-space indentation) for * better readability when inspecting the file manually. * * @private * @throws {Error} If the file cannot be written (permissions, disk space, etc.) */ saveFile() { return __awaiter(this, void 0, void 0, function* () { yield fs_1.default.writeFileSync(this.filePath, JSON.stringify(this.cache, null, 2)); }); } /** * Saves or updates giveaway data. * * If a giveaway with the same ID already exists, it will be updated. * Otherwise, a new giveaway will be added to the storage. * * @param data - The giveaway data to save * @throws {Error} If the file cannot be written */ save(data) { return __awaiter(this, void 0, void 0, function* () { yield this.load(); const index = this.cache.findIndex((g) => g.giveawayId === data.giveawayId); if (index !== -1) { this.cache[index] = data; } else { this.cache.push(data); } yield this.saveFile(); }); } /** * Retrieves a specific giveaway by ID. * * @param id - The unique giveaway ID to retrieve * @returns The giveaway data or null if not found * @throws {Error} If the file cannot be read */ get(id) { return __awaiter(this, void 0, void 0, function* () { var _a; yield this.load(); return (_a = this.cache.find((g) => g.giveawayId === id)) !== null && _a !== void 0 ? _a : null; }); } /** * Deletes a giveaway from storage. * * @param id - The unique giveaway ID to delete * @throws {Error} If the file cannot be written */ delete(id) { return __awaiter(this, void 0, void 0, function* () { yield this.load(); this.cache = this.cache.filter((g) => g.giveawayId !== id); yield this.saveFile(); }); } /** * Retrieves all giveaways from storage. * * @returns A copy of all giveaway data (to prevent external modification of cache) * @throws {Error} If the file cannot be read */ getAll() { return __awaiter(this, void 0, void 0, function* () { yield this.load(); return [...this.cache]; }); } /** * Updates an existing giveaway with new data. * * This implementation deletes the old giveaway and saves the new data, * ensuring the giveaway ID can be changed if needed. * * @param id - The current giveaway ID to update * @param data - The new giveaway data * @throws {Error} If the file cannot be written */ edit(id, data) { return __awaiter(this, void 0, void 0, function* () { yield this.load(); yield this.delete(id); yield this.save(data); }); } } exports.JSONAdapter = JSONAdapter;