UNPKG

@tomisakae/syosetu-api

Version:

Enterprise-grade Fastify TypeScript API for Syosetu.com data extraction using official API and web scraping. Run instantly with 'npx @tomisakae/syosetu-api'

204 lines 9.25 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.syosetuController = exports.SyosetuController = void 0; const utils_1 = require("@/utils"); const services_1 = require("@/services"); const logger = (0, utils_1.createChildLogger)('SyosetuController'); class SyosetuController { async getNovelDetails(request, reply) { try { const { ncode } = request.params; if (!(0, utils_1.validateNcode)(ncode)) { (0, utils_1.sendError)(reply, 'Ncode không hợp lệ (chỉ chấp nhận chữ và số)', 400); return; } logger.info(`Getting novel details for ncode: ${ncode}`); const result = await services_1.syosetuService.getNovelMetadata(ncode); if (result.success) { (0, utils_1.sendSuccess)(reply, result.data, 'Lấy thông tin tiểu thuyết thành công'); } else { (0, utils_1.sendNotFound)(reply, 'Tiểu thuyết'); } } catch (error) { logger.error('Error in getNovelDetails:', error); (0, utils_1.sendInternalError)(reply, 'Lỗi server khi lấy thông tin tiểu thuyết'); } } async getChapterContent(request, reply) { try { const { ncode, chapter } = request.params; if (!(0, utils_1.validateNcode)(ncode)) { (0, utils_1.sendError)(reply, 'Ncode không hợp lệ', 400); return; } const chapterNumber = (0, utils_1.validateChapterNumber)(chapter); if (chapterNumber === null) { (0, utils_1.sendError)(reply, 'Chapter phải là số nguyên dương', 400); return; } logger.info(`Getting chapter content for ncode: ${ncode}, chapter: ${chapterNumber}`); const result = await services_1.syosetuService.getChapterContent(ncode, chapterNumber); if (result.success) { (0, utils_1.sendSuccess)(reply, result.data, 'Lấy nội dung chapter thành công'); } else { (0, utils_1.sendNotFound)(reply, 'Chapter'); } } catch (error) { logger.error('Error in getChapterContent:', error); (0, utils_1.sendInternalError)(reply, 'Lỗi server khi lấy nội dung chapter'); } } async getMultipleChapters(request, reply) { try { const { ncode } = request.params; const { chapters } = request.body; if (!(0, utils_1.validateNcode)(ncode)) { (0, utils_1.sendError)(reply, 'Ncode không hợp lệ', 400); return; } if (!chapters || !Array.isArray(chapters) || chapters.length === 0) { (0, utils_1.sendError)(reply, 'Chapters phải là array không rỗng', 400); return; } if (chapters.length > 10) { (0, utils_1.sendError)(reply, 'Tối đa 10 chapters mỗi lần', 400); return; } for (const chapter of chapters) { if (typeof chapter !== 'number' || chapter < 1) { (0, utils_1.sendError)(reply, `Chapter ${chapter} không hợp lệ`, 400); return; } } logger.info(`Getting multiple chapters for ncode: ${ncode}, chapters: ${chapters.join(', ')}`); const results = await Promise.all(chapters.map(chapter => services_1.syosetuService.getChapterContent(ncode, chapter))); const successfulResults = results.filter(result => result.success); const failedResults = results.filter(result => !result.success); (0, utils_1.sendSuccess)(reply, { ncode, totalRequested: chapters.length, successful: successfulResults.length, failed: failedResults.length, chapters: successfulResults.map(result => result.data), errors: failedResults.map(result => result.error), }, 'Lấy nhiều chapter hoàn tất'); } catch (error) { logger.error('Error in getMultipleChapters:', error); (0, utils_1.sendInternalError)(reply, 'Lỗi server khi lấy nhiều chapter'); } } async searchNovels(request, reply) { try { const { keyword, order = 'new', limit = '20', start, gzip, ...otherOptions } = request.query; if (!keyword) { (0, utils_1.sendError)(reply, 'Keyword là bắt buộc', 400); return; } if (!(0, utils_1.validateSearchOrder)(order)) { (0, utils_1.sendError)(reply, 'Order không hợp lệ', 400, { validOrders: { new: 'Mới nhất', favnovelcnt: 'Bookmark nhiều nhất', reviewcnt: 'Review nhiều nhất', hyoka: 'Điểm cao nhất', weeklypoint: 'Điểm tuần', monthlypoint: 'Điểm tháng', yearlypoint: 'Điểm năm', weekly: 'Weekly unique users', }, }); return; } const limitNum = parseInt(limit, 10); if (!(0, utils_1.validateLimit)(limitNum, 500)) { (0, utils_1.sendError)(reply, 'Limit phải từ 1 đến 500', 400); return; } if (start) { const startNum = parseInt(start, 10); if (!(0, utils_1.validateStartPosition)(startNum)) { (0, utils_1.sendError)(reply, 'Start position phải từ 1 đến 2000', 400); return; } } if (gzip) { const gzipNum = parseInt(gzip, 10); if (!(0, utils_1.validateGzipLevel)(gzipNum)) { (0, utils_1.sendError)(reply, 'Gzip level phải từ 1 đến 5', 400); return; } } const options = { order, limit: limitNum, ...(start && { start: parseInt(start, 10) }), ...(gzip && { gzip: parseInt(gzip, 10) }), ...Object.fromEntries(Object.entries(otherOptions).map(([key, value]) => [ key, typeof value === 'string' && /^\d+$/.test(value) ? parseInt(value, 10) : value, ])), }; logger.info(`Searching novels with keyword: ${keyword}`); const result = await services_1.syosetuService.searchNovels(keyword, options); if (result.success) { (0, utils_1.sendSuccess)(reply, result.data, 'Tìm kiếm thành công'); } else { (0, utils_1.sendError)(reply, result.error || 'Lỗi khi tìm kiếm', 500); } } catch (error) { logger.error('Error in searchNovels:', error); (0, utils_1.sendInternalError)(reply, 'Lỗi server khi tìm kiếm tiểu thuyết'); } } async getRanking(request, reply) { try { const { order = 'hyoka', biggenre, genre, limit = '50' } = request.query; if (!(0, utils_1.validateRankingOrder)(order)) { (0, utils_1.sendError)(reply, 'Order không hợp lệ cho ranking', 400, { validOrders: { hyoka: 'Điểm đánh giá cao nhất', favnovelcnt: 'Bookmark nhiều nhất', weeklypoint: 'Điểm tuần cao nhất', monthlypoint: 'Điểm tháng cao nhất', }, }); return; } const limitNum = parseInt(limit, 10); if (!(0, utils_1.validateLimit)(limitNum, 100)) { (0, utils_1.sendError)(reply, 'Limit phải từ 1 đến 100', 400); return; } const options = { order, limit: limitNum, ...(biggenre && { biggenre }), ...(genre && { genre }), }; logger.info('Getting ranking'); const result = await services_1.syosetuService.getRanking(options); if (result.success) { (0, utils_1.sendSuccess)(reply, result.data, 'Lấy ranking thành công'); } else { (0, utils_1.sendError)(reply, result.error || 'Lỗi khi lấy ranking', 500); } } catch (error) { logger.error('Error in getRanking:', error); (0, utils_1.sendInternalError)(reply, 'Lỗi server khi lấy ranking'); } } } exports.SyosetuController = SyosetuController; exports.syosetuController = new SyosetuController(); //# sourceMappingURL=syosetu.controller.js.map