UNPKG

mangakonekuto

Version:

Your CLI for reading manga from the terminal

224 lines (223 loc) • 10.2 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 }); const inquirer_1 = __importDefault(require("inquirer")); const ora_1 = __importDefault(require("ora")); const open_1 = __importDefault(require("open")); const fs_extra_1 = __importDefault(require("fs-extra")); const path_1 = __importDefault(require("path")); const SettingsConfig_1 = __importDefault(require("../SettingsConfig")); // modular loaders const Loader_1 = __importDefault(require("../../modules/mangakakalot/Loader")); class MangaEventHandler { constructor() { this.lastDownloadedFolder = null; this.currentServer = null; } parseChapterNumber(title) { const match = title.match(/chapter\s*(\d+(\.\d+)?)/i); if (match && match[1]) return parseFloat(match[1]); return Number.MAX_SAFE_INTEGER; } cleanupPreviousDownload() { return __awaiter(this, void 0, void 0, function* () { const shouldDelete = SettingsConfig_1.default.get("Settings.DeletePrevious") || false; if (shouldDelete && this.lastDownloadedFolder) { try { yield fs_extra_1.default.remove(this.lastDownloadedFolder); } catch (_a) { // ignore } } }); } setupServer() { const enabledServers = SettingsConfig_1.default.get("Settings.Server") || []; if (enabledServers.includes("MangaKakalot")) { this.currentServer = Loader_1.default; return true; } // future: // if (enabledServers.includes("MangaDex")) { // this.currentServer = MangaDex; // return true; // } console.log('\nāš ļø No supported servers enabled in your settings.'); console.log('Please enable a server in Settings -> Enable Server.'); return false; } manage() { return __awaiter(this, void 0, void 0, function* () { var _a; if (!this.setupServer()) return; console.log(`\n🌐 Using ${(_a = this.currentServer) === null || _a === void 0 ? void 0 : _a.name} as your manga source.`); const searchAnswer = yield inquirer_1.default.prompt([ { type: 'input', name: 'query', message: 'Enter the manga title to search for:', }, ]); const searchSpinner = (0, ora_1.default)('Searching...').start(); const searchResults = yield this.currentServer.searchManga(searchAnswer.query); searchSpinner.stop(); if (searchResults.length === 0) { console.log('No results found.'); return; } const mangaChoices = searchResults.map((manga) => ({ name: `${manga.title} - Author: ${manga.author}`, value: manga, })); const selectAnswer = yield inquirer_1.default.prompt([ { type: 'rawlist', name: 'selectedManga', message: 'Select a manga:', choices: mangaChoices, }, ]); const selectedManga = selectAnswer.selectedManga; const infoSpinner = (0, ora_1.default)('Loading manga info...').start(); const mangaInfo = yield this.currentServer.getMangaDetail(selectedManga.id); infoSpinner.stop(); if (!mangaInfo) { console.log('Failed to load manga details.'); return; } console.log(`\n=== Manga Information ===`); console.log(`Title: ${mangaInfo.title}`); console.log(`Image URL: ${mangaInfo.imageUrl}`); console.log(`Summary:\n${mangaInfo.summary}\n`); const actionAnswer = yield inquirer_1.default.prompt([ { type: 'list', name: 'action', message: `What would you like to do?`, choices: [ { name: 'Select Chapter To Read', value: 'read' }, { name: 'Back to Search', value: 'back' }, ], }, ]); if (actionAnswer.action === 'read') { yield this.readChapters(selectedManga.id, mangaInfo.title); } else { yield this.manage(); } }); } readChapters(mangaId, mangaTitle) { return __awaiter(this, void 0, void 0, function* () { const chapterSpinner = (0, ora_1.default)(`Loading chapters for "${mangaTitle}"...`).start(); let chapters = yield this.currentServer.getChapterList(mangaId); chapterSpinner.stop(); if (chapters.length === 0) { console.log('No chapters found.'); return; } chapters.sort((a, b) => this.parseChapterNumber(a.title) - this.parseChapterNumber(b.title)); let currentIndex; while (true) { if (typeof currentIndex !== 'number') { const chapterChoices = chapters.map((ch, idx) => ({ name: `${ch.title} (${ch.date})`, value: idx, })); const chapterAnswer = yield inquirer_1.default.prompt([ { type: 'list', name: 'chapterIndex', message: `Select a chapter to read:`, choices: chapterChoices, }, ]); currentIndex = chapterAnswer.chapterIndex; } if (typeof currentIndex === 'number' && currentIndex < chapters.length) { const selectedChapter = chapters[currentIndex]; console.log(`\nšŸ“– Now reading: ${selectedChapter.title} (${selectedChapter.date}) [${currentIndex + 1} / ${chapters.length}]`); const safeMangaTitle = mangaTitle.replace(/[^a-z0-9]/gi, '_').toLowerCase(); const safeChapterTitle = selectedChapter.title.replace(/[^a-z0-9]/gi, '_').toLowerCase(); yield this.cleanupPreviousDownload(); const pdfPath = yield this.currentServer.getImagesAndCreatePDF(selectedChapter.url, safeMangaTitle, safeChapterTitle); this.lastDownloadedFolder = path_1.default.dirname(pdfPath); yield (0, open_1.default)(pdfPath); const nextAction = yield inquirer_1.default.prompt([ { type: 'list', name: 'action', message: `What do you want to do now?`, choices: [ { name: 'Read Next Chapter', value: 'next' }, { name: 'Back to Chapter List', value: 'back' }, { name: 'Back to Manga Search', value: 'search' }, ], }, ]); if (nextAction.action === 'next') { currentIndex++; if (currentIndex >= chapters.length) { console.log('\nšŸš€ No more chapters available.'); const backAnswer = yield inquirer_1.default.prompt([ { type: 'confirm', name: 'goBack', message: 'Would you like to go back to the chapter list?', default: true, }, ]); if (backAnswer.goBack) { currentIndex = undefined; continue; } else { break; } } } else if (nextAction.action === 'back') { currentIndex = undefined; } else { break; } } else { console.log('\nšŸš€ No more chapters available.'); const backAnswer = yield inquirer_1.default.prompt([ { type: 'confirm', name: 'goBack', message: 'Would you like to go back to the chapter list?', default: true, }, ]); if (backAnswer.goBack) { currentIndex = undefined; continue; } else { break; } } } }); } } exports.default = MangaEventHandler;