diff --git a/packages/core/src/command.tsx b/packages/core/src/command.tsx new file mode 100644 index 000000000..ab9b5c1c4 --- /dev/null +++ b/packages/core/src/command.tsx @@ -0,0 +1,104 @@ +import { Context, Session } from "koishi" +import { Config, OutputType, SpoilerType } from "." + +export const inject = { + required: ['booru'], + optional: ['assets'], +} + +export function apply(ctx: Context, config: Config) { + + const count = (value: string, session: Session) => { + const count = parseInt(value) + if (count < 1 || count > config.maxCount) { + session.send('booru.count-invalid') + return 1 + } + return count + } + + ctx + .command('booru ') + .option('count', '-c ', { type: count, fallback: 1 }) + .option('label', '-l ') + .action(async ({ session, options }, query) => { + if (!ctx.booru.hasSource(options.label)) return session.text('.no-source') + + query = query?.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('.no-result') + + const output: Element[] = [] + + for (const image of filtered) { + if (config.asset && ctx.assets) { + image.url = await ctx.booru.imgUrlToAssetUrl(image) + if (!image.url) { + output.unshift() + continue + } + } + if (config.base64) { + image.url = await ctx.booru.imgUrlToBase64(image) + if (!image.url) { + output.unshift() + continue + } + } + switch (config.output) { + case OutputType.All: + if (image.tags) + output.unshift( +

{[source]}

+

{[image.tags.join(', ')]}

+
) + case OutputType.ImageAndLink: + if (image.pageUrl || image.authorUrl) + output.unshift( +

{[image.pageUrl]}

+

{[image.authorUrl]}

+
) + case OutputType.ImageAndInfo: + if (image.title && image.author && image.desc) + output.unshift( +

{image.title}

+

{[image.author]}

+

{[image.desc]}

+
) + case OutputType.ImageOnly: + output.unshift( + /** + * @TODO waiting for upstream to support spoiler tag + * but is only is attribute, so it's can work now. + */ + + { + switch (config.spoiler) { + case SpoilerType.Disabled: + return false + case SpoilerType.All: + return true + case SpoilerType.OnlyNSFW: + return Boolean(image.nsfw) + } + })()} url={image.url}> + ) + } + } + // the qq platform will can merge the all forward message with one element(forward message block). + // so can treat it as a spoiler message. + if (['qq', 'red', 'onebot'].includes(session.platform) && config.spoiler !== SpoilerType.Disabled) + return {output} + else + return output.length === 1 ? output[0] : {output} + }) +} diff --git a/packages/core/src/index.tsx b/packages/core/src/index.ts similarity index 61% rename from packages/core/src/index.tsx rename to packages/core/src/index.ts index 33d3ed411..8de3bf2c0 100644 --- a/packages/core/src/index.tsx +++ b/packages/core/src/index.ts @@ -1,6 +1,7 @@ import { Context, Element, Logger, Quester, Schema, Service, Session } from 'koishi' import LanguageDetect from 'languagedetect' import { ImageSource } from './source' +import * as Command from './command' import { } from '@koishijs/assets' export * from './source' @@ -169,107 +170,10 @@ export const Config = Schema.intersect([ }).description('输出设置'), ]) -export const inject = { - required: [], - optional: ['assets'], -} export function apply(ctx: Context, config: Config) { ctx.plugin(ImageService, config) + ctx.plugin(Command, config) ctx.i18n.define('zh', require('./locales/zh-CN')) - - const count = (value: string, session: Session) => { - const count = parseInt(value) - if (count < 1 || count > config.maxCount) { - session.send('booru.count-invalid') - return 1 - } - return count - } - - ctx - .command('booru ') - .option('count', '-c ', { type: count, fallback: 1 }) - .option('label', '-l ') - .action(async ({ session, options }, query) => { - if (!ctx.booru.hasSource(options.label)) return session.text('.no-source') - - query = query?.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('.no-result') - - const output: Element[] = [] - - for (const image of filtered) { - if (config.asset && ctx.assets) { - image.url = await ctx.booru.imgUrlToAssetUrl(image) - if (!image.url) { - output.unshift() - continue - } - } - if (config.base64) { - image.url = await ctx.booru.imgUrlToBase64(image) - if (!image.url) { - output.unshift() - continue - } - } - switch (config.output) { - case OutputType.All: - if (image.tags) - output.unshift( -

{[source]}

-

{[image.tags.join(', ')]}

-
) - case OutputType.ImageAndLink: - if (image.pageUrl || image.authorUrl) - output.unshift( -

{[image.pageUrl]}

-

{[image.authorUrl]}

-
) - case OutputType.ImageAndInfo: - if (image.title && image.author && image.desc) - output.unshift( -

{image.title}

-

{[image.author]}

-

{[image.desc]}

-
) - case OutputType.ImageOnly: - output.unshift( - /** - * @TODO waiting for upstream to support spoiler tag - * but is only is attribute, so it's can work now. - */ - - { - switch (config.spoiler) { - case SpoilerType.Disabled: - return false - case SpoilerType.All: - return true - case SpoilerType.OnlyNSFW: - return Boolean(image.nsfw) - } - })()} url={image.url}> - ) - } - } - // the qq platform will can merge the all forward message with one element(forward message block). - // so can treat it as a spoiler message. - if (['qq', 'red', 'onebot'].includes(session.platform) && config.spoiler !== SpoilerType.Disabled) - return {output} - else - return output.length === 1 ? output[0] : {output} - }) }