-
Notifications
You must be signed in to change notification settings - Fork 8
/
Yunzai_imgSearcher.js
340 lines (300 loc) · 12.5 KB
/
Yunzai_imgSearcher.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
import plugin from '../../lib/plugins/plugin.js'
import { segment } from "oicq";
import { createRequire } from "module";
import fetch from "node-fetch"
import fs from 'fs'
import lodash from 'lodash'
import common from '../../lib/common/common.js'
//const require_ = createRequire(import.meta.url);
//const fetch = require_('node-fetch');
var ApiKey = "5f70aa77c38361f679b06d5499bc7185aba2d9ad" //https://saucenao.com/user.php?page=search-api 处获取
var numres = 3 //返回几个结果(不建议大于5)
var safemode = 0
var imageURL = ""
const _path = `./soufanvideo/`
const _cwdpath = process.cwd();
if (!fs.existsSync(_path)) {
fs.mkdirSync(_path);
}
let minsim = 0.90; //#匹配度,0.90以下的可能会不太准
export class example extends plugin {
constructor() {
super({
name: 'pic_search',
event: 'message',
priority: 1000,
rule: [
{
reg: '^#?(搜|识)图$',
fnc: 'pic_search'
},
{
reg: '^#?(搜|识)番$',
fnc: 'ani_search'
},
{
reg: "^#?取直链$",
fnc: 'pic_link'
},
{
reg: "^#?(搜|识)图帮助$",
fnc: 'pic_search_help'
}
]
})
}
/**关键词搜图 */
async pic_search(e) {
await e.reply("别急,在找了……");
if (e.source) {
// console.log(e);
let reply;
if (e.isGroup) {
reply = (await e.group.getChatHistory(e.source.seq, 1)).pop()?.message;
} else {
reply = (await e.friend.getChatHistory(e.source.time, 1)).pop()?.message;
}
if (reply) {
for (let val of reply) {
if (val.type == "image") {
e.img = [val.url];
break;
}
}
}
}
if (!e.img) {
await this.cancel(e);
// return true;
return false;
}
imageURL=e.img[0];
//const response = await axios.get('https://saucenao.com/search.php?db=999&output_type=2&numres='+numres+'&api_key='+ApiKey+'&url='+imageURL,{headers: { "Accept-Encoding": "gzip,deflate,compress" }})
//var jsonobj = response.data;
var url = 'https://saucenao.com/search.php?db=999&output_type=2&numres='+numres+'&api_key='+ApiKey+'&url='+imageURL
const response = await fetch(url, { "method": "GET" });
var jsonobj = await response.json();
//await this.reply(JSON.stringify(jsonobj.results))
let message = []
let image = []
for (var i = 0;i < numres;i++){
message.push(`${i+1}.相似度:${JSON.stringify(jsonobj.results[i].header.similarity)}%\n链接/作品名称:`)
if(jsonobj.results[i].data.ext_urls){
for(var j = 0;j < Object.keys(jsonobj.results[i].data.ext_urls).length;j++)
message.push(`${JSON.stringify(jsonobj.results[i].data.ext_urls[0])},\n`)
}
if(jsonobj.results[i].data.eng_name){
message.push(`${JSON.stringify(jsonobj.results[i].data.eng_name)},\n`)
}
if(jsonobj.results[i].data.jp_name){
message.push(`${JSON.stringify(jsonobj.results[i].data.jp_name)},\n`)
}
if (safemode == 0)
image.push(`\n${i+1}.\n`)
image.push(segment.image(jsonobj.results[i].header.thumbnail))
if (safemode == 1)
image.push(`搜索结果图样:${jsonobj.results[i].header.thumbnail}`)
}
//message.push(`以下是原始数据,可供参考:\n${JSON.stringify(jsonobj.results)}`)
//this.reply(`以下是原始数据,可供参考:\n${JSON.stringify(jsonobj.results)}`)
let forwardMsg = await this.makeForwardMsg(`以下是使用saucenao引擎的搜图结果:`, message, image)
await this.reply(forwardMsg)
//await this.reply(JSON.stringify(jsonobj.results));
//await this.reply("诶呀,作者还在写,接口还没接上捏");
//await this.reply(segment.image(e.img[0]));
await this.reply("以上是所有结果~如果上头没东西,可能是bot被风控了~~");
}
async ani_search(e) {
await e.reply("别急,在找了……");
if (this.e.source) {
let reply;
if (this.e.isGroup) {
reply = (await this.e.group.getChatHistory(this.e.source.seq, 1)).pop()?.message;
} else {
reply = (await this.e.friend.getChatHistory(this.e.source.time, 1)).pop()?.message;
}
if (reply) {
for (let val of reply) {
if (val.type == "image") {
this.e.img = [val.url];
break;
}
}
}
}
if (!this.e.img) {
this.setContext('dealImg');
await this.reply(" 请发送动漫番剧截图", false, { at: true });
}else{
this.dealImg();
}
}
async dealImg() {
if (!this.e.img) {
return true;
}
let responseImage = await fetch(this.e.img[0]);
if (!responseImage.ok) {
await this.reply("获取番剧图片失败", false, { at: true });
}
let buffer = await responseImage.arrayBuffer();
let headers = {
"Content-Type": "image/jpeg"
};
let file = Buffer.from(buffer, 'binary');
let urlapi = "https://api.trace.moe/search?anilistInfo=&cutBorders=";
let response = await fetch(urlapi, { method: "POST", body: file, headers });
let res = await response.json();
if (res.result.length == 0) {
await this.reply('未找到相关番剧,此搜索引擎对截图尺寸和质量要求比较高,不支持以下类型截图识别:\n1、有额外添加的黑边\n2、裁切过的不完整截图\n3、左右翻转的\n4、经过滤镜处理的\n5、加了文字的表情包\n6、1990年之前的动画\n7、非正式发行的动画,即同人插图等\n8、非日本动画\n9、画面过暗的\n10、分辨率过低的(须大于 320x180)');
this.finish('dealImg');
return true;
}
let resultall = res.result[0];
let fromtime = resultall.from;
let totime = resultall.to;
if (resultall.similarity.toFixed(4) < minsim) {
await this.reply('未找到相关番剧,此搜索引擎对截图尺寸和质量要求比较高,不支持以下类型截图识别:\n1、有额外添加的黑边\n2、裁切过的不完整截图\n3、左右翻转的\n4、经过滤镜处理的\n5、加了文字的表情包\n6、1990年之前的动画\n7、非正式发行的动画,即同人插图等\n8、非日本动画\n9、画面过暗的\n10、分辨率过低的(须大于 320x180)');
this.finish('dealImg');
return true;
}
let details = await this.getDetails(resultall.anilist.id);
let synonyms = "";
for (const key in details.synonyms) {
synonyms += details.synonyms[key] + "\n";
}
let end = "";
if (details.status != "FINISHED") {
end = "未完结";
} else {
end = details.endDate.year + "年" + details.endDate.month + "月" + details.endDate.day + "日";
}
let fengmian;
if (!resultall.anilist.isAdult) {
fengmian = details.coverImage.large;
}
const message = []
let msg = [
fengmian ? segment.image(fengmian) : "",
"\n" + resultall.anilist.title.native + "\n",
resultall.anilist.title.romaji + "\n",
"别名\n" + synonyms + "\n",
`类型:${details.type} - ${details.format}` + ` 共${details.episodes}集\n`,
"开播时间:" + details.startDate.year + "年" + details.startDate.month + "月" + details.startDate.day + "日 - " + end + "\n",
"相似度:" + resultall.similarity.toFixed(4) * 100 + "%\n",
"该截图出自第" + resultall.episode + "集" + Math.floor(fromtime % 3600 / 60) + "分" + Math.floor(fromtime % 60) + "秒至"+ Math.floor(totime % 3600 / 60) + "分" + Math.floor(totime % 60) + "秒\n",
"以下是该片段截图:",
segment.image(resultall.image)
];
await this.e.reply(msg);
await this.e.reply("您也可以在这查看该片段的视讯资料:\n"+resultall.video)
if (!resultall.video) {
return true;
}
console.log(_cwdpath);
let url = resultall.video;
response = await fetch(url);
let buff = await response.arrayBuffer();
var me = this;
//fs.writeFile(`${_path}temp.mp4`, Buffer.from(buff), "binary", async function (err) {
// console.log(err || "下载视频成功");
//if (!err) {
//if (!resultall.anilist.isAdult) {
//await me.e.reply(segment.video(`file:///${_cwdpath}/plugins/suiyue/resources/soufanvideo/temp.mp4`));
//}
//}
//});
this.finish('dealImg');
}
async getDetails(id) {
let query = `{Media (id:${id}) {id coverImage {large}startDate {year,month,day}endDate {year,month,day}season,seasonYear,type,format,status,episodes,synonyms}}`;
let url = 'https://trace.moe/anilist/';
let response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ query: query }),
});
let res = await response.json();
//await this.reply(JSON.stringify(res))
return res.data.Media;
}
async pic_link(e) {
//await e.reply("正在转直链……");
if (e.source) {
// console.log(e);
let reply;
if (e.isGroup) {
reply = (await e.group.getChatHistory(e.source.seq, 1)).pop()?.message;
} else {
reply = (await e.friend.getChatHistory(e.source.time, 1)).pop()?.message;
}
if (reply) {
for (let val of reply) {
if (val.type == "image") {
e.img = [val.url];
break;
}
}
}
}
if (!e.img) {
await this.cancel(e);
// return true;
return false;
}
let message = []
let image = []
for (var i = 0;i < e.img.length;i++){
message.push(`${i+1}.${e.img[i]}\n`)
}
image.push(`已获取${i+1}条直链\n`)
let forwardMsg = await this.makeForwardMsg(`以下是您需要的直链:`, message, image)
await this.reply(forwardMsg)
await this.reply("以上是所有结果~如果上头没东西,可能是bot被风控了~~");
}
async cancel(e){
await e.reply("不对啊,这也没图啊,你还是带个图片再说吧!");
}
async makeForwardMsg (title, msg, img) {
let nickname = Bot.nickname
if (this.e.isGroup) {
let info = await Bot.getGroupMemberInfo(this.e.group_id, Bot.uin)
nickname = info.card ?? info.nickname
}
let userInfo = {
user_id: Bot.uin,
nickname
}
let forwardMsg = [
{
...userInfo,
message: title
},
{
...userInfo,
message: msg
},
{
...userInfo,
message: img
}
]
/** 制作转发内容 */
if (this.e.isGroup) {
forwardMsg = await this.e.group.makeForwardMsg(forwardMsg)
} else {
forwardMsg = await this.e.friend.makeForwardMsg(forwardMsg)
}
/** 处理描述 */
forwardMsg.data = forwardMsg.data
.replace(/\n/g, '')
.replace(/<title color="#777777" size="26">(.+?)<\/title>/g, '___')
.replace(/___+/, `<title color="#777777" size="26">${title}</title>`)
return forwardMsg
}
async pic_search_help(e){
await e.reply("回复图片“#搜图”或带图发送“#搜图”即可查询图片来源\n回复图片“#取直链”或带图发送“#取直链”即可获取图片直链")
}
}