UNPKG

koishi-plugin-jmcomic-api

Version:
187 lines (186 loc) 7.28 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.logger = exports.usage = exports.inject = exports.Config = exports.name = void 0; exports.apply = apply; const koishi_1 = require("koishi"); exports.name = 'jmcomic-api'; exports.Config = koishi_1.Schema.intersect([ koishi_1.Schema.object({ apiUrl: koishi_1.Schema.string().description('API 地址(注意末尾不要带 / )').required(), defaultPassword: koishi_1.Schema.string().description('默认加密密码').default(''), }).description('基础设置'), koishi_1.Schema.object({ getDataMethod: koishi_1.Schema.union([ koishi_1.Schema.const('base64').description('base64'), koishi_1.Schema.const('form-data').description('form-data'), koishi_1.Schema.const('url').description('url'), ]).default('url').description('获取文件的方式'), }).description('进阶设置'), ]); exports.inject = { required: ['http'], optional: ['jmcomic'], }; exports.usage = ` # 安装 <br> 1.后端安装前需要Python <br> 2.在终端执行以下指令 <br> \`\`\` pip install jmcomic_api python -m jmcomic_api \`\`\` <br> 把API填入配置即可 <br> `; function apply(ctx, config) { exports.logger = new koishi_1.Logger(exports.name); ctx.on('ready', async () => { exports.logger.info('JMComic API 服务初始化中...'); ctx.plugin(JMComicService, config); exports.logger.info('JMComic API 服务已启动'); setupCommands(ctx, config); }); ctx.on('dispose', () => { exports.logger.info('JMComic API 服务已卸载'); }); } class JMComicService extends koishi_1.Service { config; constructor(ctx, config) { super(ctx, 'jmcomic', true); this.config = config; } async fetchAPI(endpoint) { try { const response = await this.ctx.http.get(`${this.config.apiUrl}${endpoint}`); return response.data; } catch (error) { if (koishi_1.HTTP.Error.is(error)) { const response = error.response; if (response?.status === 400) { const data = response.data?.data || {}; throw new Error(data.log || 'API 请求错误'); } } throw error; } } async getRanking(type = 'day', page = 1) { const data = await this.fetchAPI(`/get/raw/ranking?page=${page}&types=${type}`); return data.raw_results[type].content; } async search(keyword, type = 'site', page = 1) { const data = await this.fetchAPI(`/get/raw/search?page=${page}&text=${encodeURIComponent(keyword)}&types=${type}`); return data.raw_results[type].content; } async getComicInfo(jm_id) { const data = await this.fetchAPI(`/get/raw?jm_id=${jm_id}&types=info`); return data.raw_info; } async prepareDownload(jm_id, noCache = false) { await this.fetchAPI(`/download/image?jm_id=${jm_id}&no_cache=${noCache}`); } async getFileData(jm_id, fileType, password) { const url = `/get/file?jm_id=${jm_id}` + `&file_type=${fileType}&return_method=${this.config.getDataMethod}` + (password ? `&file_pwd=${password}` : ''); if (this.config.getDataMethod === 'form-data') { return this.config.apiUrl + url; } const response = await this.fetchAPI(url); return response.file; } } function setupCommands(ctx, config) { ctx.command('jm.ranking [type:string] [page:number]', '本子排名') .alias('jm.排名') .option('page', '-p <page:number> 页数', { fallback: 1 }) .option('type', '-t <type:string> 排名类型', { type: ['day', 'week', 'month'], fallback: 'day', }) .action(async ({ options }, type, page) => { type = type || options.type; const results = await ctx.jmcomic.getRanking(type, page || options.page); return formatResults('ranking', type || options.type, results); }); ctx.command('jm.search <keyword:string>', '搜索本子') .alias('jm.搜索') .option('page', '-p <page:number> 页数', { fallback: 1 }) .option('type', '-t <type:string> 搜索类型', { type: ['site', 'author', 'tags', 'work'], fallback: 'site' }) .action(async ({ options }, keyword) => { if (!keyword) return '请输入搜索关键词'; const results = await ctx.jmcomic.search(keyword, options.type, options.page); return formatResults('search', options.type, results); }); ctx.command('jm.info <jm_id:number>', '获取本子信息') .alias('jm.信息') .action(async (_, jm_id) => { if (!jm_id) return '请输入有效本子ID'; const info = await ctx.jmcomic.getComicInfo(jm_id); return formatComicInfo(jm_id, info); }); ctx.command('jm.get <jm_id:number>', '获取本子文件') .alias('jm.获取') .option('type', '-t <type:string> 文件类型', { type: ['pdf', 'zip'], fallback: 'pdf' }) .option('password', '-p <password:string> 解压密码') .option('noCache', '-c 禁用缓存') .action(async ({ options }, jm_id) => { try { await ctx.jmcomic.prepareDownload(jm_id, options.noCache); const data = await ctx.jmcomic.getFileData(jm_id, options.type, options.password || config.defaultPassword); switch (ctx.jmcomic.config.getDataMethod) { case 'base64': return koishi_1.h.file(Buffer.from(data, 'base64'), options.type, { title: `${jm_id}.${options.type}` }); case 'url': return koishi_1.h.file(data, { title: `${jm_id}.${options.type}` }); case 'form-data': return koishi_1.h.file(data, { title: `${jm_id}.${options.type}` }); default: return '不支持的返回方式'; } } catch (error) { return error.message; } }); } function formatResults(type, subType, results) { if (!results?.length) return '未找到相关内容'; const titles = { ranking: { day: '📅 今日排行榜', week: '📆 本周排行榜', month: '🗓️ 本月排行榜' }, search: { site: '🔍 全站搜索结果', tags: '🏷️ 标签搜索结果', author: '👤 作者作品', work: '📚 系列作品' } }; const header = titles[type][subType] + '\n\n'; return header + results.map(([id, details]) => `🚗 车牌号: ${id} 📖 名称: ${details.name} 🏷️ 标签: ${details.tags?.join(', ') || '无'} ━━━━━━━━━━━━━━━━━━━`).join('\n\n'); } function formatComicInfo(jm_id, info) { return `🚗 车牌号: ${jm_id} 📛 名称: ${info.idoname} 👤 作者: ${info.author} 💬 评论数: ${info.comment_count} ❤️ 点赞量: ${info.likes} 👀 浏览量: ${info.views} 🏷️ 标签: ${info.tags?.join(', ') || '无'}`; }