kokkoro-plugin-saucenao 2.0.2 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,11 +17,11 @@ bun add kokkoro-plugin-saucenao
17
17
  /搜图
18
18
  ```
19
19
 
20
- 发送「/搜图」时附带图片,插件会搜索消息中的第一张图片,并以 Markdown 返回搜索结果,默认显示相似度最高的 3 条。
20
+ 发送「/搜图」指令时附带图片,或引用包含图片的消息回复该指令。插件搜索首张图片的来源,并通过 QQ Markdown 返回结果,默认显示相似度最高的 3 条。
21
21
 
22
22
  ## 快捷方式
23
23
 
24
- 发送「搜图」时附带图片,也会返回搜索结果。要让普通群消息触发快捷方式,需要开启「获取群内全部消息」权限。
24
+ 「搜图」与「/搜图」的用法相同。在普通群消息中使用快捷方式,需要开启「获取群内全部消息」权限。
25
25
 
26
26
  ```text
27
27
  搜图
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kokkoro-plugin-saucenao",
3
- "version": "2.0.2",
3
+ "version": "2.0.3",
4
4
  "description": "SauceNAO 图片搜索,查找动漫、漫画、插画等图片的来源。",
5
5
  "keywords": [
6
6
  "bot",
package/src/index.ts CHANGED
@@ -7,20 +7,24 @@ const logger = useLogger();
7
7
 
8
8
  export default () => {
9
9
  useCommand('/搜图', async context => {
10
- const image = context.attachments?.find(attachment => attachment.content_type?.startsWith('image/'));
10
+ const [reference] = context.msg_elements ?? [];
11
+ const attachments = context.message_type === 103 ? reference?.attachments : context.attachments;
12
+ const images = attachments?.filter(attachment => attachment.content_type?.startsWith('image/')) ?? [];
13
+ const [image] = images;
11
14
 
12
15
  if (!image?.url) {
13
- throw new Error('请在指令中附带需要搜索的图片');
16
+ throw new Error('未检测到图片,请在指令消息中附带图片,或引用包含图片的消息后重试。');
14
17
  }
15
18
  const result = await fetchImageSources(image.url, logger);
16
19
  const { results } = result;
20
+ const notice = images.length > 1 ? '检测到消息中包含多张图片,已选取首张图片进行识别。' : undefined;
17
21
 
18
22
  logger.info('已找到图片来源', { count: results.length });
19
23
 
20
24
  await context.reply({
21
25
  msg_type: 2,
22
26
  markdown: {
23
- content: await createMarkdown(results),
27
+ content: await createMarkdown(results, notice),
24
28
  },
25
29
  });
26
30
  }).shortcut('搜图');
package/src/service.ts CHANGED
@@ -146,7 +146,7 @@ export async function fetchImageSources(url: string, logger?: Logger): Promise<S
146
146
  const response = await fetch(endpoint);
147
147
 
148
148
  if (!response.ok) {
149
- throw new Error(`接口请求失败,状态码 ${response.status}`);
149
+ throw new Error(`SauceNAO 请求失败,HTTP 状态码 ${response.status}`);
150
150
  }
151
151
  const result = <SauceNao>await response.json();
152
152
  const { header, results } = result;
@@ -158,7 +158,7 @@ export async function fetchImageSources(url: string, logger?: Logger): Promise<S
158
158
  }
159
159
 
160
160
  if (results.length === 0) {
161
- throw new Error('没有找到图片来源');
161
+ throw new Error('未找到图片来源');
162
162
  }
163
163
  return result;
164
164
  }
package/src/util.ts CHANGED
@@ -2,7 +2,7 @@ import { Image } from 'bun';
2
2
 
3
3
  import { type ImageSource } from './service';
4
4
 
5
- const { SAUCENAO_SIMILARITY_THRESHOLD = 50 } = import.meta.env;
5
+ const { SAUCENAO_SIMILARITY_THRESHOLD = '50' } = import.meta.env;
6
6
  const LOW_SIMILARITY_THUMBNAIL = 'https://kokkoro.js.org/saucenao-low-similarity.jpg';
7
7
  const similarityThreshold = Number(SAUCENAO_SIMILARITY_THRESHOLD);
8
8
 
@@ -28,8 +28,13 @@ function getUrl(data: ImageSource['data']) {
28
28
  }
29
29
  }
30
30
 
31
- /** 将 SauceNAO 搜索结果转换为 QQ Markdown。 */
32
- export async function createMarkdown(results: readonly ImageSource[]): Promise<string> {
31
+ /** 将 SauceNAO 搜索结果转换为 QQ Markdown,可在标题下方展示提示。 */
32
+ export async function createMarkdown(results: readonly ImageSource[], notice?: string): Promise<string> {
33
+ const lines = ['## SauceNAO 搜图结果'];
34
+
35
+ if (notice) {
36
+ lines.push('', `> ${notice}`);
37
+ }
33
38
  const content = await Promise.all(
34
39
  results.map(async ({ data, header }, index) => {
35
40
  const { index_name: indexName, similarity, thumbnail } = header;
@@ -45,7 +50,7 @@ export async function createMarkdown(results: readonly ImageSource[]): Promise<s
45
50
  const response = await fetch(thumbnail);
46
51
 
47
52
  if (!response.ok) {
48
- throw new Error(`缩略图请求失败,状态码 ${response.status}`);
53
+ throw new Error(`缩略图下载失败,HTTP 状态码 ${response.status}`);
49
54
  }
50
55
  const { height, width } = await new Image(await response.blob()).metadata();
51
56
 
@@ -60,5 +65,5 @@ export async function createMarkdown(results: readonly ImageSource[]): Promise<s
60
65
  }),
61
66
  );
62
67
 
63
- return ['## SauceNAO 搜图结果', ...content].join('\n***\n');
68
+ return [lines.join('\n'), ...content].join('\n***\n');
64
69
  }