Skip to content

Commit

Permalink
Merge branch 'main' into l10n
Browse files Browse the repository at this point in the history
  • Loading branch information
MaikoTan authored Oct 30, 2023
2 parents a723e8f + f6d94be commit 6a63bf9
Show file tree
Hide file tree
Showing 27 changed files with 794 additions and 17 deletions.
3 changes: 3 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ko_fi: maikotan
custom:
- https://afdian.net/a/ff14_hamster
2 changes: 2 additions & 0 deletions docs/.vitepress/config/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@
"text": "插件",
"items": [
{ "text": "Danbooru", "link": "/plugins/danbooru" },
{ "text": "e621", "link": "/plugins/e621" },
{ "text": "Gelbooru", "link": "/plugins/gelbooru" },
{ "text": "Konachan", "link": "/plugins/konachan" },
{ "text": "Lolibooru", "link": "/plugins/lolibooru" },
{ "text": "Lolicon", "link": "/plugins/lolicon" },
{ "text": "Local", "link": "/plugins/local" },
{ "text": "Pixiv", "link": "/plugins/pixiv" },
{ "text": "Safebooru", "link": "/plugins/safebooru" },
{ "text": "Sankaku", "link": "/plugins/sankaku" },
Expand Down
3 changes: 3 additions & 0 deletions docs/zh-CN/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ Booru 插件支持多个图源站点,每个图源站点都有一个对应的
| 图源 | 插件 |
| --- | --- |
| [Danbooru](https://danbooru.donmai.us/) | [`koishi-plugin-booru-danbooru`](./plugins/danbooru.md) |
| [e621](https://e621.net/) | [`koishi-plugin-booru-e621`](./plugins/e621.md) |
| [e926](https://e926.net/) | [`koishi-plugin-booru-e621`](./plugins/e621.md) |
| [Gelbooru](https://gelbooru.com/) | [`koishi-plugin-booru-gelbooru`](./plugins/gelbooru.md) |
| [Konachan](https://konachan.com/) | [`koishi-plugin-booru-konachan`](./plugins/konachan.md) |
| [Konachan.net](https://konachan.net/) | [`koishi-plugin-booru-konachan`](./plugins/konachan.md) |
Expand All @@ -31,3 +33,4 @@ Booru 插件支持多个图源站点,每个图源站点都有一个对应的
| [Safebooru](https://safebooru.org/) | [`koishi-plugin-booru-safebooru`](./plugins/safebooru.md) |
| [SankakuComplex](https://chan.sankakucomplex.com/) | [`koishi-plugin-booru-sankaku`](./plugins/sankaku.md) |
| [Yande.re](https://yande.re/) | [`koishi-plugin-booru-yande`](./plugins/yande.md) |
| 本地文件夹 | [`koishi-plugin-booru-local`](./plugins/local.md) |
31 changes: 31 additions & 0 deletions docs/zh-CN/plugins/e621.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# koishi-plugin-booru-e621

## 安装

1. 在 Koishi 中下载并安装本插件,若你还未安装 [Booru 插件](../index.md),请先安装。

## 配置项

### 全局设置

:::tip
此处的配置项可参考[图源全局设置](../config#图源全局设置)
:::

### 搜索设置

<br>

#### userAgent

- 类型:`string`
- 默认值:`Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.37`

请求时所使用的 User-Agent

#### endpoint

- 类型:`string`
- 默认值:`https://e621.net`

e621/e926 的 API 地址。
100 changes: 100 additions & 0 deletions docs/zh-CN/plugins/local.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# koishi-plugin-booru-local

超快的本地图源支持

## 安装

1. 在 Koishi 中下载并安装本插件,若你还未安装 [Booru 插件](../index.md),请先安装。

## 配置项

### 全局设置

:::tip
此处的配置项可参考[图源全局设置](../config#图源全局设置)
:::

### 图源设置

<br>

#### endpoint

- 类型: `string[]`

图源文件夹,支持多个不同的文件夹

#### languages

- 类型: `string[]`
- 默认值: `['zh-CN', 'en']`

图源支持的语言

#### extension

- 类型: `string[]`
- 默认值: `['.jpg', '.png', '.jpeg', '.gif']`

支持的图片扩展名

#### scraper

- 类型: `string`
- 默认值: `{filename}-{tag}`

文件元信息刮削器格式,详见 [刮削器](#刮削器)

## 刮削器

:::tip
该方式需要图片文件名是特定的格式,且为减少边界情况,仅支持使用 `-` 分割
:::

这是一个在文件名中指定该图片元信息的方式,以便于插件能够正确的搜索符合需求的图片。

### 使用

插件设置中 `scraper` 默认值可得出大致的使用方式

### 标签

#### `#...#`

- 类型: `string`
- 默认值: `name`
- 示例: `#name#{fliename}-{tag}`

(仅在开头有效)指定刮削器的工作方式,目前支持以下几种方式:

1. `name`: 文件名模式
2. `meta`(WIP): 文件元信息模式(开发中)

#### `{filename}`

- 类型: `string`

> `{filename}` 被放置在最后时,`+` 将失效(即 `{foo}-{filename}+`
文件名

#### `{tag}`

- 类型: `string[]`

图片拥有的 tag

#### `{nsfw}`(WIP)

- 类型: `boolean | 'furry' | 'guro' | 'shota' | 'bl'`
- 默认值: `nsfw=false`

限制级图片

#### `+`

忽略后续的内容不作为元信息处理

#### `.`

匹配 `.` 开头的隐藏文件,不设置的情况下将忽略隐藏文件
2 changes: 1 addition & 1 deletion docs/zh-CN/plugins/pixiv.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

1. 在 Koishi 中下载并安装本插件,若你还未安装 [Booru 插件](../index.md),请先安装。
2.[Pixiv](https://www.pixiv.net/) 注册账号并登录。
3. 使用 [Pixiv OAuth Script] 脚本获取 `Refresh Token`
3. 使用 [Pixiv OAuth Script](https://gist.github.com/ZipFile/c9ebedb224406f4f11845ab700124362) 脚本获取 `Refresh Token`
4.`Refresh Token` 填入配置项中的 `token` 项。

## 配置项
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"mocha": "^9.2.2",
"sass": "^1.62.1",
"shx": "^0.3.4",
"typescript": "^4.9.5",
"typescript": "^5.1.6",
"vitepress": "1.0.0-alpha.73",
"yakumo": "^0.3.10",
"yakumo-esbuild": "^0.3.22",
Expand Down
4 changes: 4 additions & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,17 @@
"service": {
"implements": [
"booru"
],
"optional": [
"assets"
]
}
},
"peerDependencies": {
"koishi": "^4.10.0"
},
"devDependencies": {
"@koishijs/assets": "^1.0.2",
"koishi": "^4.12.4"
},
"dependencies": {
Expand Down
2 changes: 2 additions & 0 deletions packages/core/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
## 图源插件

- [koishi-plugin-booru-danbooru](https://booru.koishi.chat/plugins/danbooru.html)
- [koishi-plugin-booru-e621](https://booru.koishi.chat/plugins/e621.html)
- [koishi-plugin-booru-gelbooru](https://booru.koishi.chat/plugins/gelbooru.html)
- [koishi-plugin-booru-konachan](https://booru.koishi.chat/plugins/konachan.html)
- [koishi-plugin-booru-lolibooru](https://booru.koishi.chat/plugins/lolibooru.html)
- [koishi-plugin-booru-lolicon](https://booru.koishi.chat/plugins/lolicon.html)
- [koishi-plugin-booru-local](https://booru.koishi.chat/plugins/local.html)
- [koishi-plugin-booru-pixiv](https://booru.koishi.chat/plugins/pixiv.html)
- [koishi-plugin-booru-safebooru](https://booru.koishi.chat/plugins/safebooru.html)
- [koishi-plugin-booru-sankaku](https://booru.koishi.chat/plugins/sankaku.html)
Expand Down
65 changes: 51 additions & 14 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Context, Dict, Element, Logger, Quester, Schema, Service, Session } from 'koishi'
import { Context, Element, Logger, Quester, Schema, Service, Session } from 'koishi'
import LanguageDetect from 'languagedetect'
import { ImageSource } from './source'
import { } from '@koishijs/assets'

export * from './source'

Expand All @@ -13,32 +14,29 @@ declare module 'koishi' {
}

class ImageService extends Service {
private config: Config
private sources: Dict<ImageSource> = {}
private counter = 0

private sources: ImageSource[] = []
private languageDetect = new LanguageDetect()

constructor(ctx: Context, config: Config) {
constructor(ctx: Context, private config: Config) {
super(ctx, 'booru', true)
this.config = config
}

register(source: ImageSource) {
const id = ++this.counter
this.sources[id] = source
return this.caller.collect('booru', () => delete this.sources[id])
const index = this.sources.length
this.sources.push(source)
return this.caller.collect('booru', () => delete this.sources[index])
}

hasSource(name?: string): boolean {
if (name) {
return Object.values(this.sources).some((source) => source.config.label === name)
return this.sources.some((source) => source.config.label === name)
}
return Object.keys(this.sources).length > 0
return this.sources.some(Boolean)
}

async get(query: ImageService.Query): Promise<ImageArray> {
const sources = Object.values(this.sources)
const sources = this.sources
.filter((source) => {
if (query.labels.length && !query.labels.includes(source.config.label)) return false
if (this.config.detectLanguage) {
Expand All @@ -59,7 +57,7 @@ class ImageService extends Service {
// return the first non-empty result
for (const source of sources) {
const tags = source.tokenize(query.query)
const images = await source.get({ ...query, tags, raw: query.query }).catch((err) => {
const images = await source.get({ count: query.count, tags, raw: query.query }).catch((err) => {
if (Quester.isAxiosError(err)) {
logger.warn(`source ${source.config.label} request failed with code ${err.status} ${JSON.stringify(err.response?.data)}`)
} else {
Expand All @@ -74,6 +72,26 @@ class ImageService extends Service {

return undefined
}

async imgUrlToAssetUrl(image: ImageSource.Result): Promise<string> {
return await this.ctx.assets.upload(image.url, Date.now().toString()).catch(() => {
logger.warn('Request failed when trying to store image with assets service.')
return null
})
}

async imgUrlToBase64(image: ImageSource.Result): Promise<string> {
return this.ctx.http.axios(image.url, { method: 'GET', responseType: 'arraybuffer' }).then(resp => {
return `data:${resp.headers['content-type']};base64,${Buffer.from(resp.data, 'binary').toString('base64')}`
}).catch(err => {
if (Quester.isAxiosError(err)) {
logger.warn(`Request images failed with HTTP status ${err.status}: ${JSON.stringify(err.response?.data)}.`)
} else {
logger.error(`Request images failed with unknown error: ${err.message}.`)
}
return null
})
}
}

namespace ImageService {
Expand All @@ -97,6 +115,8 @@ export interface Config {
maxCount: number
output: OutputType
nsfw: boolean
asset: boolean
base64: boolean
}

interface ImageArray extends Array<ImageSource.Result> {
Expand Down Expand Up @@ -126,6 +146,8 @@ export const Config = Schema.intersect([
Schema.const(2).description('发送图片、相关信息和链接'),
Schema.const(3).description('发送全部信息'),
]).description('输出方式。').default(1),
asset: Schema.boolean().default(false).description('优先使用 [assets服务](https://assets.koishi.chat/) 转存图片。'),
base64: Schema.boolean().default(false).description('使用 base64 发送图片。')
}).description('输出设置'),
])

Expand All @@ -148,7 +170,7 @@ export function apply(ctx: Context, config: Config) {
.option('count', '-c <count:number>', { type: count, fallback: 1 })
.option('label', '-l <label:string>')
.action(async ({ session, options }, query) => {
if (!ctx.booru.hasSource()) return session.text('.no-source')
if (!ctx.booru.hasSource(options.label)) return session.text('.no-source')

query = query?.trim() ?? ''

Expand All @@ -164,7 +186,22 @@ export function apply(ctx: Context, config: Config) {
if (!filtered?.length) return session?.text('.no-result')

const output: (string | Element)[] = []

for (const image of filtered) {
if (config.asset && ctx.assets) {
image.url = await ctx.booru.imgUrlToAssetUrl(image)
if (!image.url) {
output.unshift(session.text('.no-image'))
continue
}
}
if (config.base64) {
image.url = await ctx.booru.imgUrlToBase64(image)
if (!image.url) {
output.unshift(session.text('.no-image'))
continue
}
}
switch (config.output) {
case OutputType.All:
if (image.tags)
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/locales/zh-CN.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ commands:
messages:
no-source: 当前未找到可用图源。请从插件市场添加 booru 系图源插件并启用 (插件名通常以 booru- 开头)。
no-result: 没有找到符合条件的图片
no-image: 获取图片失败
output:
image: <message><image url={url}></image></message>
info: |
Expand Down
Loading

0 comments on commit 6a63bf9

Please sign in to comment.