UNPKG

koishi-plugin-booru

Version:
140 lines (139 loc) 6.92 kB
import { jsx as _jsx, jsxs as _jsxs } from "@satorijs/element/jsx-runtime"; /* eslint-disable no-fallthrough */ import { Random } from 'koishi'; import { OutputType, SpoilerType, preferSizes } from '.'; export const inject = { required: ['booru'], optional: ['assets'], }; export function apply(ctx, config) { const getTips = (session) => { for (const locale of ctx.i18n.fallback([ ...(session.user?.locales || []), ...(session.channel?.locales || []), ])) { if (ctx.i18n._data[locale]) { const tips = Object.keys(ctx.i18n._data[locale] || {}).filter((k) => k.startsWith('booru.tips')); if (tips.length) return tips; } } }; const count = (value, session) => { const count = parseInt(value); if (count < 1 || count > config.maxCount) { session.send('booru.count-invalid'); return 1; } return count; }; const command = ctx .command('booru <query:text>') .option('count', '-c <count:number>', { type: count, fallback: 1 }) .option('label', '-l <label:string>') .action(async ({ session, options }, query) => { if (!ctx.booru.hasSource(options.label)) return session.text('.no-source'); query = query?.trim() ?? ''; if (query) { // Since the type of query is text, when user append options after the query, the options // would not be parsed correctly. So we need to manually parse the query and options here. // https://github.com/koishijs/koishi-plugin-booru/issues/39 const countMatch = /(-c|--count)\s+(\d+)/g.exec(query); if (countMatch) { options.count = count(countMatch[2], session); query = query.replace(countMatch[0], '').trim(); } const labelMatch = /(-l|--label)\s+([^\s]+)/g.exec(query); if (labelMatch) { options.label = labelMatch[2]; query = query.replace(labelMatch[0], '').trim(); } } const images = await ctx.booru.get({ query, count: options.count, labels: options.label ?.split(',') ?.map((x) => x.trim()) ?.filter(Boolean) ?? [], }); const source = images?.source; const filtered = images?.filter((image) => config.nsfw || !image.nsfw); if (!filtered?.length) return session?.text('commands.booru.messages.no-result'); const output = []; for (const image of filtered) { const children = []; let url = ''; for (const size of preferSizes.slice(preferSizes.indexOf(config.preferSize))) { url = image.urls?.[size]; if (url) { break; } } url ||= image.url; if (config.asset && ctx.assets) { url = await ctx.booru.imgUrlToAssetUrl(url); if (!url) { children.unshift(_jsx("i18n", { path: 'commands.booru.messages.no-image' })); continue; } } else if (config.base64) { url = await ctx.booru.imgUrlToBase64(url); if (!url) { children.unshift(_jsx("i18n", { path: 'commands.booru.messages.no-image' })); continue; } } switch (config.output) { case OutputType.All: if (image.tags) { children.unshift(_jsx("p", { children: _jsx("i18n", { path: 'commands.booru.messages.output.source', children: [source] }) }), _jsx("p", { children: _jsx("i18n", { path: 'commands.booru.messages.output.tags', children: [image.tags.join(', ')] }) })); } case OutputType.ImageAndLink: case OutputType.ImageAndInfo: if (image.title || image.author || image.desc) { children.unshift(_jsx("p", { children: config.output >= OutputType.ImageAndLink && image.pageUrl ? (_jsx("a", { href: image.pageUrl, children: image.title })) : (image.title) }), _jsx("p", { children: config.output >= OutputType.ImageAndLink && image.authorUrl ? (_jsx("a", { href: image.authorUrl, children: _jsx("i18n", { path: 'commands.booru.messages.output.author', children: [image.author] }) })) : (_jsx("i18n", { path: 'commands.booru.messages.output.author', children: [image.author] })) }), _jsx("p", { children: _jsx("i18n", { path: 'commands.booru.messages.output.desc', children: [image.desc] }) })); } case OutputType.ImageOnly: children.unshift( /** * @TODO waiting for upstream to support spoiler tag * but is only is attribute, so it's can work now. */ _jsx("img", { spoiler: (() => { switch (config.spoiler) { case SpoilerType.Disabled: return false; case SpoilerType.All: return true; case SpoilerType.OnlyNSFW: return Boolean(image.nsfw); } })(), src: url })); } output.push(children); } if (config.showTips) { const tips = getTips(session); if (tips) { const tip = Random.pick(tips); output.push(_jsxs("p", { children: [_jsx("i18n", { path: 'commands.booru.messages.tips' }), _jsx("i18n", { path: tip, children: [command.displayName] })] })); } } switch (session.resolve(config.outputMethod)) { case 'one-by-one': return output.map((children) => _jsx("message", { children: children })); case 'merge-multiple': return _jsx("message", { children: output.map((children) => children) }); case 'forward-all': return (_jsxs("message", { forward: true, children: [_jsx("author", { id: session.userId, name: session.username }), output.map((children) => (_jsx("message", { children: children })))] })); case 'forward-multiple': if (output.length === 1) return _jsx("message", { children: output[0] }); return (_jsxs("message", { forward: true, children: [_jsx("author", { id: session.userId, name: session.username }), output.map((children) => (_jsx("message", { children: children })))] })); } }); }