-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy path咕咕牛图库下载器.js
859 lines (753 loc) · 37.9 KB
/
咕咕牛图库下载器.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
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
import fs from 'fs';
import path from 'path';
import { exec } from 'child_process';
import { fileURLToPath } from 'url';
import common from '../../lib/common/common.js';
import yaml from 'yaml'
// 『咕咕牛🐂』图库管理器 v2.9
// Github仓库地址:https://github.com/GuGuNiu/Miao-Plugin-MBT/
function formatBytes(bytes) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const dm = 2;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}
export class MiaoPluginMBT extends plugin {
constructor() {
super({
name: '『咕咕牛🐂』图库管理器 v2.9',
dsc: '『咕咕牛🐂』图库管理器',
event: 'message',
priority: 1000,
rule: [
{
reg: /^#(代理)?下载咕咕牛$/,
fnc: 'GallaryDownload'
},
{
reg: /^#(强制)?更新咕咕牛$/,
fnc: 'GallaryUpdate'
},
{
reg: /^#删除咕咕牛$/,
fnc: 'DeleteGallary',
permission: "master"
},
{
reg: /^#(启用|禁用)咕咕牛$/,
fnc: 'GalleryOption',
permission: "master"
},
{
reg: /^#(启用|禁用)官方立绘$/,
fnc: 'MihoyoSplashOption',
permission: "master"
},
{
reg: /^#咕咕牛帮助$/,
fnc: 'GuHelp'
},
{
reg: /^#重置咕咕牛$/,
fnc: 'RestartGuGuNiu',
permission: "master"
},
{
reg: /^#检查咕咕牛$/,
fnc: 'CheckFolder'
},
{
reg: /^#查看(.*)$/,
fnc: 'FindRoleSplash'
},
{
reg: /^#ban(加|删)(.*)$/,
fnc: 'BanRole',
permission: "master"
},
{
reg: /^#ban列表$/,
fnc: 'BanRolelist',
},
{
reg: /^#(确认)?净化咕咕牛$/,
fnc: 'RemoveBadimages',
},
{
reg: /^#咕咕牛$/,
fnc: 'GuGuNiu',
},
{
reg: /^#清理咕咕牛缓存$/,
fnc: 'CC',
},
{
reg: /^#清空咕咕牛封禁$/,
fnc: 'GOODBYEGUGUNIU',
}
]
})
this.task = {
name: '『咕咕牛🐂』定时更新任务',
cron: '0 5 */15 * *',
fnc: () => this.executeTask(),
log: false
}
const currentFileUrl = import.meta.url;
const currentFilePath = fileURLToPath(currentFileUrl);
this.proxy = 'https://mirror.ghproxy.com/';
this.proxy2 = 'https://ghp.ci/';
this.repositoryUrl = 'https://github.com/GuGuNiu/Miao-Plugin-MBT/';
this.localPath = path.resolve(path.dirname(currentFilePath), '../../resources/Miao-Plugin-MBT/');
this.GitPath = path.resolve(path.dirname(currentFilePath), '../../resources/Miao-Plugin-MBT/.git/');
this.copylocalPath = path.resolve(path.dirname(currentFilePath), '../../resources/Miao-Plugin-MBT/normal-character/');
this.characterPath = path.resolve(path.dirname(currentFilePath), '../../plugins/miao-plugin/resources/profile/normal-character/');
this.ZZZ_Plugin_copylocalPath = path.resolve(path.dirname(currentFilePath), '../../resources/Miao-Plugin-MBT/zzz-character/');
this.ZZZ_Plugin_characterPath = path.resolve(path.dirname(currentFilePath), '../../plugins/ZZZ-Plugin/resources/images/panel/');
this.GSaliasPath = path.resolve(path.dirname(currentFilePath), '../../plugins/miao-plugin/resources/meta-gs/character/');
this.SRaliasPath = path.resolve(path.dirname(currentFilePath), '../../plugins/miao-plugin/resources/meta-sr/character/');
this.ZZZ_Plugin_ZZZaliasPath = path.resolve(path.dirname(currentFilePath), '../../plugins/ZZZ-Plugin/defset/');
this.GuPath = path.resolve(path.dirname(currentFilePath), '../../resources/GuGuNiu-Gallery/');
this.JsPath = path.resolve(path.dirname(currentFilePath), '../../plugins/example/');
}
async GallaryDownload(e) {
const A = "Github";
const B = "Mirror";
const C = "Ghproxy";
const urls = {
[A]: this.repositoryUrl,
[B]: this.proxy + this.repositoryUrl,
[C]: this.proxy2 + this.repositoryUrl
};
let DownloadSource = A;
const tryDownload = async (sourceName) => {
const url = urls[sourceName];
return new Promise((resolve, reject) => {
const process = exec(`git clone --depth=1 ${url} ${this.localPath}`, { stdio: 'inherit' });
process.on('close', (code) => {
if (code === 0) {
resolve();
} else {
reject(new Error(`git clone failed with code ${code}`));
}
});
});
};
try {
await tryDownload(A);
await e.reply(`『咕咕牛』下载成功,来源:${A}\n正在准备进行下一步操作...`);
await this.PostDownload(e);
} catch (error) {
await e.reply('『咕咕牛』的Github仓库下载失败,已自动切换至代理下载中,请稍后....', true);
let proxyError;
for (let sourceName of [B, C]) {
try {
await tryDownload(sourceName);
DownloadSource = sourceName;
await e.reply(`『咕咕牛』代理下载成功,来源:${sourceName}\n正在准备进行下一步操作...`);
await this.PostDownload(e);
break;
} catch (error) {
proxyError = error;
if (sourceName === C) {
let DowloadeErrorForward = this.generateDownloadErrorFeedback(proxyError);
await e.reply('『咕咕牛』下载失败,请查看控制台日志!');
let DownloadErrorGumsg = await common.makeForwardMsg(this.e, DowloadeErrorForward, '『咕咕牛🐂』操作日志');
setTimeout(async () => {
this.reply(DownloadErrorGumsg);
}, 2000);
return;
}
}
}
}
}
async PostDownload(e) {
await this.CopyFolderRecursive(this.copylocalPath, this.characterPath);
await this.CopyFolderRecursive(this.ZZZ_Plugin_copylocalPath, this.ZZZ_Plugin_characterPath);
await e.reply(`『咕咕牛』正在咕咕噜的载入喵喵中...`);
fs.mkdirSync(this.GuPath, { recursive: true });
this.CopyFolderRecursive(path.join(this.localPath, 'GuGuNiu-Gallery'), this.GuPath);
setTimeout(async () => {
await e.reply(`『咕咕牛』成功进入喵喵里面!每隔15天自动更新,包括Js。`);
}, 20000);
this.DeleteBanList();
const sourceFile = path.join(this.localPath, '咕咕牛图库下载器.js');
const destFile = path.join(this.JsPath, '咕咕牛图库下载器.js');
await fs.promises.copyFile(sourceFile, destFile);
}
async GuHelp(e) {
if (!fs.existsSync(this.GuPath)) {
e.reply(segment.image("https://s2.loli.net/2024/06/28/LQnN3oPCl1vgXIS.png"))
return true;
}e.reply(segment.image(this.GuPath+'/help.png'))
}
async BanRole(e) {
const banListPath = path.join(this.GuPath, 'banlist.txt');
if (!fs.existsSync(banListPath)) {
fs.writeFileSync(banListPath, '', 'utf8');
}
let message = e.raw_message || e.message || e.content;
if (message.startsWith('#ban加')) {
const match = message.match(/^#ban加(.+)/);
if (!match) {
await e.reply('请输入要添加到禁止列表的名称\n例如:#ban加花火Gu1', true);
return true;
}
let inputRoleName = match[1].trim();
let roleName = inputRoleName.replace(/Gu\d+$/, '').trim();
let mainName = this.getMainRoleName(roleName);
if (mainName) {
mainName = `${mainName}${inputRoleName.match(/Gu\d+$/)[0]}`;
const fileName = `${mainName}.webp`;
let banList = fs.readFileSync(banListPath, 'utf8').split(';').filter(item => item.trim() !== '');
if (!banList.includes(fileName)) {
banList.push(fileName);
fs.writeFileSync(banListPath, `${banList.join(';')};`, 'utf8');
await e.reply(`${fileName} 🚫已封禁`, true);
this.DeleteBanList();
} else {
await e.reply(`${fileName} ❌️已存在`, true);
}
} else {
await e.reply(`未找到角色:${roleName}`, true);
}
} else if (message.startsWith('#ban删')) {
const match = message.match(/^#ban删(.+)/);
if (!match) {
await e.reply('请输入要从禁止列表中删除的名称\n例如:#ban删花火Gu1', true);
return true;
}
let inputRoleName = match[1].trim();
let roleName = inputRoleName.replace(/Gu\d+$/, '').trim();
let mainName = this.getMainRoleName(roleName);
if (mainName) {
mainName = `${mainName}${inputRoleName.match(/Gu\d+$/)[0]}`;
const fileName = `${mainName}.webp`;
let banList = fs.readFileSync(banListPath, 'utf8').split(';').filter(item => item.trim() !== '');
if (R18_images.includes(inputRoleName)) {
await e.reply(`${inputRoleName} ❌️已拒绝删除`, true);
return true;
}
if (banList.includes(fileName)) {
banList = banList.filter(item => item !== fileName);
fs.writeFileSync(banListPath, `${banList.join(';')}`, 'utf8');
await e.reply(`${fileName} ✅️已解禁`, true);
await e.reply("批量解除封禁可输入#清空咕咕牛封禁,仅重置封禁文件不影响净化模式")
await this.CopyFolderRecursive(this.copylocalPath, this.characterPath);
await this.CopyFolderRecursive(this.ZZZ_Plugin_copylocalPath, this.ZZZ_Plugin_characterPath);
} else {
await e.reply(`${fileName} ❌️不存在`, true);
}
} else {
await e.reply(`未找到角色:${roleName}`, true);
}
}
return true;
}
async CC(e) {e.reply("请使用#重置咕咕牛",true)}
async BanRolelist(e) {
const banListPath = path.join(this.GuPath, 'banlist.txt');
if (!fs.existsSync(banListPath)) {
await e.reply('禁用文件不存在,已重新生成', true);
fs.writeFileSync(banListPath, '', 'utf8');
return true;
}
try {
const fileContent = fs.readFileSync(banListPath, 'utf8').trim();
if (fileContent === '') {
await e.reply('封禁列表是空的', true);
return true;
}
const banList = fileContent.split(';').map(item => item.trim());
const uniqueBanList = [...new Set(banList)];
const totalItems = uniqueBanList.length -1;
const formattedBanList = uniqueBanList.map(item => item.replace(/\.webp$/, ''));
const BanListforwardMsg = [];
BanListforwardMsg.push(`当前已Ban的数量:${totalItems}张\n『#ban删花火Gu1』可以移除封禁`);
BanListforwardMsg.push(formattedBanList.join('\n'));
const banListMsg = await common.makeForwardMsg(this.e, BanListforwardMsg, '封禁中的面板图列表');
await e.reply(banListMsg);
return true;
} catch (error) {
await e.reply('读取封禁文件时出现错误,请查看控制台日志', true);
return true;
}
}
async FindRoleSplash(e) {
if (!fs.existsSync(this.localPath)) {
await e.reply('『咕咕牛🐂』未下载!', true);
return true;
}
const match = e.msg.match(/^#查看(.+)$/);
if (!match) {
await e.reply('请输入正确的命令格式\n例如:#查看花火', true);
return true;
}
let roleName = match[1].trim();
roleName = this.getMainRoleName(roleName);
const foldersONE = fs.readdirSync(this.copylocalPath);
const foldersTWO = fs.readdirSync(this.ZZZ_Plugin_copylocalPath);
const allFolders = [
...foldersONE.map(folder => path.join(this.copylocalPath, folder)),
...foldersTWO.map(folder => path.join(this.ZZZ_Plugin_copylocalPath, folder))
];
const matchedFolder = allFolders.find(folder => path.basename(folder).includes(roleName));
if (!matchedFolder) {
await e.reply(`未找到角色『${roleName}』`);
return true;
}
const files = fs.readdirSync(matchedFolder)
.filter(file => /\.webp$/.test(file))
.sort((a, b) => {
const numA = parseInt(a.match(/\d+/)[0]);
const numB = parseInt(b.match(/\d+/)[0]);
return numA - numB;
});
if (files.length === 0) {
await e.reply(`『${path.basename(matchedFolder)}』文件夹下没有图片`, true);
return true;
}
let checkrolename = `当前查看『${path.basename(matchedFolder)}』,有${files.length}张`;
let RoleWebpPhotoList = [];
RoleWebpPhotoList.push([`当前查看『${path.basename(matchedFolder)}』,有${files.length}张`]);
const banListPath = path.join(this.GuPath, 'banlist.txt');
const banListContent = fs.readFileSync(banListPath, 'utf-8');
const filesToBan = banListContent.split(';').map(item => item.trim()).filter(item => item !== '');
for (let i = 0; i < files.length; i++) {
let fileName = files[i];
const filePath = path.join(matchedFolder, fileName);
const isBanned = filesToBan.includes(fileName);
const isR18Image = R18_images.includes(fileName.replace('.webp', ''));
if (isBanned && isR18Image) {
fileName = `${fileName.replace('.webp', '')} ❌封禁🟢净化`;
} else if (isBanned) {
fileName = `${fileName.replace('.webp', '')} ❌封禁`;
} else {
fileName = `${fileName.replace('.webp', '')}`;
}
RoleWebpPhotoList.push([`${i + 1}、${fileName}`, segment.image(`file://${filePath}`)]);
}
try {
let RoleFindsuccessmsg = await common.makeForwardMsg(this.e, RoleWebpPhotoList, checkrolename);
await e.reply(RoleFindsuccessmsg);
if (!RoleFindsuccessmsg) {
e.reply('发送失败,请私聊查看!', true);
}
} catch (err) {
console.error(err);
await e.reply(`发送 ${path.basename(matchedFolder)} 的列表时出现错误,请查看控制台日志`);
}
}
async RemoveBadimages(e) {
const galleryConfigPath = path.join(this.GuPath, 'GalleryConfig.yaml');
const galleryConfigContent = fs.readFileSync(galleryConfigPath, 'utf8');
const galleryConfig = yaml.parse(galleryConfigContent);
if (e.msg == '#净化咕咕牛') {
e.reply("『咕咕牛』封禁高危面板图,净化无法解除需要你手动修改配置文件,下次更新依旧会延续净化,十分建议呢用#ban封禁",true)
setTimeout(async () => {
e.reply("输入#确认净化咕咕牛,进行下一步")
}, 3000);
}else if (e.msg == '#确认净化咕咕牛') {
if (galleryConfig && galleryConfig['Px18img-type'] === 1 ) {
await e.reply("好的,开始净化咕咕牛",true)
const banListPath = path.join(this.GuPath, 'banlist.txt');
if (!fs.existsSync(banListPath)) {
fs.writeFileSync(banListPath, '', 'utf8');
}
let banList = fs.readFileSync(banListPath, 'utf8').split(';').filter(item => item.trim() !== '');
R18_images.forEach(image => {
const fileName = `${image}.webp`;
if (!banList.includes(fileName)) {
banList.push(fileName);
}
});
fs.writeFileSync(banListPath, `${banList.join(';')};`, 'utf8')
this.DeleteBanList();
galleryConfig['Px18img-type'] = 0;
const newGalleryConfigContent = yaml.stringify(galleryConfig);
fs.writeFileSync(galleryConfigPath, newGalleryConfigContent, 'utf8');
setTimeout(async () => {
await e.reply(`净化完毕,绿色网络从你做起!`);
}, 10000);
} else if (galleryConfig && galleryConfig['Px18img-type'] === 0) {
await e.reply("你已经净化过了,亲",true);
}
}
}
async GuGuNiu(e) {
await e.reply("🐂");
const stats = await fs.promises.stat(this.localPath);
const creationTime = stats.birthtime.toISOString();
await e.reply(`图库安装时间: ${creationTime}`);
const gitLog = await new Promise((resolve, reject) => {
exec('git log -n 50 --date=format:"[%m-%d %H:%M:%S]" --pretty=format:"%cd %s"', { cwd: this.localPath }, (error, stdout, stderr) => {
if (error) {
reject(error);
} else {
resolve(stdout);
}
});
});
const uplogforwardMsg = [`最近的更新记录:\n${gitLog}`];
const forwardMsgFormatted = await common.makeForwardMsg(this.e, uplogforwardMsg, '『咕咕牛🐂』日志');
await e.reply(forwardMsgFormatted);
}
async GalleryOption(e){
const galleryConfigPath = path.join(this.GuPath, 'GalleryConfig.yaml');
const galleryConfigContent = fs.readFileSync(galleryConfigPath, 'utf8');
const galleryConfig = yaml.parse(galleryConfigContent);
if (e.msg == '#启用咕咕牛') {
if (!fs.existsSync(this.localPath)) {
await e.reply('『咕咕牛🐂』未下载!', true);
return;
}
await e.reply('『咕咕牛🐂』启用中,请稍后...',true);
await this.CopyFolderRecursive(this.copylocalPath, this.characterPath);
await this.CopyFolderRecursive(this.ZZZ_Plugin_copylocalPath, this.ZZZ_Plugin_characterPath);
await e.reply('『咕咕牛』重新进入喵喵里面!');
setTimeout(async () => {
this.DeleteBanList()
}, 2000);
galleryConfig['GGOP'] = 1;
const newGalleryConfigContent = yaml.stringify(galleryConfig);
fs.writeFileSync(galleryConfigPath, newGalleryConfigContent, 'utf8');
}else if (e.msg == '#禁用咕咕牛') {
await e.reply('『咕咕牛🐂』禁用中,请稍后...',true);
await this.DeleteFilesWithGuKeyword();
await e.reply('『咕咕牛』已离开喵喵');
galleryConfig['GGOP'] = 0;
const newGalleryConfigContent = yaml.stringify(galleryConfig);
fs.writeFileSync(galleryConfigPath, newGalleryConfigContent, 'utf8');
}
}
async DeleteGallary(e){
await e.reply('『咕咕牛🐂』完全删除中,请稍后.....',true);
await this.DeleteFilesWithGuKeyword();
if (!fs.existsSync(this.localPath)) {
return e.reply('『咕咕牛』已离开你的崽崽了!');
}
await fs.promises.rm(this.localPath, { recursive: true });
console.log('『咕咕牛🐂』图库删除成功!');
return e.reply('『咕咕牛』已离开你的崽崽了!!');
}
async executeTask(){
logger.info("[『咕咕牛🐂』定时更新任务]:开始执行")
const gitPullOutput = await new Promise((resolve, reject) => {
exec('git pull', { cwd: this.localPath }, (error, stdout, stderr) => {
if (error) {
reject(error);
} else {
resolve(stdout);
}
});
});
if (/Already up[ -]to[ -]date/.test(gitPullOutput)) {
logger.info("[『咕咕牛🐂』定时更新任务]:暂无更新内容")
}else{
await this.CopyFolderRecursive(this.copylocalPath, this.characterPath);
await this.CopyFolderRecursive(this.ZZZ_Plugin_copylocalPath, this.ZZZ_Plugin_characterPath);
fs.mkdirSync(this.GuPath, { recursive: true });
const sourceFile = path.join(this.localPath, 'GuGuNiu-Gallery', 'help.png');
const destFile = path.join(this.GuPath, 'help.png');
await fs.promises.copyFile(sourceFile, destFile);
const sourceJSFile = path.join(this.localPath, '咕咕牛图库下载器.js');
const destJSFile = path.join(this.JsPath, '咕咕牛图库下载器.js');
await fs.promises.copyFile(sourceJSFile, destJSFile);
this.DeleteBanList();
return logger.info("[『咕咕牛🐂』定时更新任务]:执行完毕")
}
}
async GOODBYEGUGUNIU(e){
const banListPath = path.join(this.GuPath, 'banlist.txt');
if (!fs.existsSync(banListPath)) {
fs.writeFileSync(banListPath, '', 'utf8');
e.reply("牛的封禁列表文件不存在,已重新创建",true)
}else {
fs.unlinkSync(banListPath);
fs.writeFileSync(banListPath, '', 'utf8');
e.reply("牛的封禁文件清空成功",true)
}
}
async RestartGuGuNiu(e) {
try {
if (!fs.existsSync(this.localPath)) {
await e.reply('『咕咕牛🐂』未下载!', true);
return true;
}
await fs.promises.rm(this.localPath, { recursive: true });
console.log('『咕咕牛🐂』重置成功!');
return e.reply('『咕咕牛🐂』重置成功!');
} catch (error) {
console.error('重置『咕咕牛🐂』时出现错误:', error);
let rerrforward = [];
rerrforward.push(`重置『咕咕牛🐂』时出现错误:\n ${error.message}`);
let restarterror = await common.makeForwardMsg(this.e, rerrforward, '『咕咕牛🐂』重置失败');
this.reply('『咕咕牛🐂』重置失败,请查看控制台日志!');
setTimeout(async () => {
this.reply(restarterror);
}, 2000);
}
}
async CheckFolder(e) {
const gitPath = this.GitPath;
const characterFolderPaths = [
'normal-character',
'zzz-character'
].map(folder => path.join(this.localPath, folder));
if (!fs.existsSync(this.localPath)) {
await e.reply('『咕咕牛🐂』未下载!', true);
return true;
}
let characterFolders = [];
for (const folderPath of characterFolderPaths) {
if (fs.existsSync(folderPath)) {
const folders = fs.readdirSync(folderPath, { withFileTypes: true })
.filter(dirent => dirent.isDirectory())
.map(dirent => path.join(folderPath, dirent.name));
characterFolders = characterFolders.concat(folders);
}
}
characterFolders = characterFolders.sort((a, b) => a.localeCompare(b));
let totalCharacterCount = characterFolders.length;
let CheckRoleforward = [];
let RoleNumMessage = [];
CheckRoleforward.push("---按A-Z字母排序---");
let totalPanelImageCount = 0;
for (const folderPath of characterFolders) {
if (fs.existsSync(folderPath)) {
const folder = path.basename(folderPath);
const panelImages = fs.readdirSync(folderPath).filter(file => file.endsWith('.webp'));
totalPanelImageCount += panelImages.length;
const name = `${folder}:${panelImages.length}张`;
CheckRoleforward.push(name);
}
}
let totalSize = 0;
for (const folderPath of characterFolderPaths) {
totalSize += await this.getFolderSize(folderPath);
}
const formattedTotalSize = formatBytes(totalSize);
const gitSize = await this.getFolderSize(gitPath);
const gitAllSize = formatBytes(gitSize);
const MBTSize = formatBytes(gitSize + totalSize);
let checkmessage = `----『咕咕牛🐂』----\n角色数量:${totalCharacterCount}名\n图片数量:${totalPanelImageCount}张\n图库容量:${formattedTotalSize}\nGit缓存容量:${gitAllSize}\n咕咕牛图库占用:${MBTSize}`;
RoleNumMessage = CheckRoleforward.join('\n');
await Promise.all([
e.reply(checkmessage),
(async () => {
const msg = await common.makeForwardMsg(this.e, RoleNumMessage, '『咕咕牛🐂』图库数量');
await e.reply(msg);
})()
]);
}
async MihoyoSplashOption(e) {
if (e.msg == '#启用官方立绘') {
await this.CopySplashWebp(this.SRaliasPath, this.characterPath);
await this.CopySplashWebp(this.GSaliasPath, this.characterPath);
return e.reply('官方立绘已经启用了',true);
}else if (e.msg == '#禁用官方立绘') {
await this.DeleteGuSplashWebp(this.characterPath);
return e.reply('官方立绘已经禁用了',true);
}
}
async DeleteBanList() {
const banListPath = path.join(this.GuPath, 'banlist.txt');
try {
const banListContent = await fs.promises.readFile(banListPath, 'utf8');
const filesToDelete = banListContent.split(';').map(item => item.trim()).filter(item => item !== '');
const deleteFilesRecursively = async (directory) => {
const files = await fs.promises.readdir(directory);
for (const file of files) {
const filePath = path.join(directory, file);
const stat = await fs.promises.stat(filePath);
if (stat.isDirectory()) {
await deleteFilesRecursively(filePath);
} else {
const fileName = path.basename(filePath);
if (filesToDelete.includes(fileName)) {
await fs.promises.unlink(filePath);
//------刷屏点----/ console.log(`${fileName} 已删除`);
}
}
}
}
await deleteFilesRecursively(this.characterPath);
await deleteFilesRecursively(this.ZZZ_Plugin_characterPath);
console.log('『咕咕牛🐂』封禁列表中的文件已删除');
} catch (error) {
console.error('删除文件时出现错误:', error);
}
}
async DeleteFilesWithGuKeyword() {
const ToCheck = [this.characterPath, this.ZZZ_Plugin_characterPath];
for (const normalCharacterPath of ToCheck) {
try {
const folders = await fs.promises.readdir(normalCharacterPath);
await Promise.all(folders.map(async (folder) => {
const folderPath = path.join(normalCharacterPath, folder);
const stats = await fs.promises.lstat(folderPath);
if (stats.isDirectory()) {
const files = await fs.promises.readdir(folderPath);
const deletePromises = files.map(async (file) => {
const filePath = path.join(folderPath, file);
const fileStats = await fs.promises.lstat(filePath);
if (fileStats.isFile() && file.includes('Gu') && !file.endsWith('.db')) {
await fs.promises.unlink(filePath);
}
});
await Promise.all(deletePromises);
}
}));
console.log('『咕咕牛🐂』图库删除成功');
} catch (err) {
console.error('『咕咕牛🐂』图库删除失败:', err);
}
}
}
async CopySplashWebp(sourceDir, targetDir) {
const folders = await fs.promises.readdir(sourceDir, { withFileTypes: true });
for (const folder of folders) {
if (!folder.isDirectory() || folder.name === 'common') continue;
const folderPath = path.join(sourceDir, folder.name);
const splashPath = path.join(folderPath, 'imgs', 'splash.webp');
const targetFolderPath = path.join(targetDir, folder.name);
const targetSplashPath = path.join(targetFolderPath, 'Gusplash.webp');
await fs.promises.mkdir(targetFolderPath, { recursive: true });
await fs.promises.copyFile(splashPath, targetSplashPath);
//------刷屏点----/console.log(`已复制 ${splashPath} 到 ${targetSplashPath}`);
}
}
async DeleteGuSplashWebp(directory) {
const entries = await fs.promises.readdir(directory, { withFileTypes: true });
for (const entry of entries) {
const entryPath = path.join(directory, entry.name);
if (entry.isDirectory()) {
await this.DeleteGuSplashWebp(entryPath);
} else if (entry.isFile() && entry.name === 'Gusplash.webp') {
await fs.promises.unlink(entryPath);
//------刷屏点----/console.log(`已删除 ${entryPath}`);
}
}
}
async getFolderSize(folderPath) {
let totalSize = 0;
const files = await fs.promises.readdir(folderPath);
for (const file of files) {
const filePath = path.join(folderPath, file);
const stats = await fs.promises.stat(filePath);
if (stats.isDirectory()) {
totalSize += await this.getFolderSize(filePath);
} else {
totalSize += stats.size;
}
}
return totalSize;
}
async CopyFolderRecursive(source, target) {
const targetExists = await fs.promises.access(target)
.then(() => true)
.catch(() => false);
if (!targetExists) {
await fs.promises.mkdir(target, { recursive: true });
}
const files = await fs.promises.readdir(source);
await Promise.all(files.map(async (file) => {
const curSource = path.join(source, file);
const curDest = path.join(target, file);
const stat = await fs.promises.lstat(curSource);
if (stat.isDirectory()) {
await this.CopyFolderRecursive(curSource, curDest);
} else {
await fs.promises.copyFile(curSource, curDest);
//------刷屏点----/ console.log(`已复制文件: ${curSource} -> ${curDest}`);
}
}));
//------刷屏点----/ console.log(`文件夹 ${source} 复制到 ${target} 完成`);
}
generateDownloadErrorFeedback(error) {
let feedback = [];
feedback.push(`下载『咕咕牛🐂』时出现错误:\n ${error}`);
if (error.message.includes('code 128')) {
feedback.push("检查网络连接:确保您的网络连接正常, 有时候网络问题可能导致Git无法正常执行操作。");
}
if (error.message.includes('code 28')) {
feedback.push("试着增加 Git 的 HTTP 缓冲区大小,这样可以帮助处理较大的数据传输。在控制台输入以下命令:");
feedback.push("git config --global http.postBuffer 524288000");
}
if (error.message.includes('443')) {
feedback.push("该报错可能是网络问题、被墙或访问被拒绝。");
}
return feedback;
}
getMainRoleName(roleName) {
let aliasSR;
const aliasSRFilePath = path.resolve(this.SRaliasPath, 'alias.js');
const aliasSRContent = fs.readFileSync(aliasSRFilePath, 'utf-8');
const aliasRegexSR = /{[^{}]*}/;
const aliasJSONSR = aliasSRContent.match(aliasRegexSR)[0];
aliasSR = eval('(' + aliasJSONSR + ')');
let aliasGS;
const aliasGSFilePath = path.resolve(this.GSaliasPath, 'alias.js');
const aliasGSContent = fs.readFileSync(aliasGSFilePath, 'utf-8');
const aliasRegexGS = /{[^{}]*}/;
const aliasJSONGS = aliasGSContent.match(aliasRegexGS)[0];
aliasGS = eval('(' + aliasJSONGS + ')');
let aliasZZZ;
const ZZZFilePath = path.resolve(this.ZZZ_Plugin_ZZZaliasPath, 'alias.yaml');
if (fs.existsSync(ZZZFilePath)) {
const ZZZContent = fs.readFileSync(ZZZFilePath, 'utf-8');
aliasZZZ = yaml.parse(ZZZContent);
}
let mainNameSR = Object.keys(aliasSR).find(main => {
const aliases = aliasSR[main].split(',');
return aliases.includes(roleName);
});
let mainNameGS = Object.keys(aliasGS).find(main => {
const aliases = aliasGS[main].split(',');
return aliases.includes(roleName);
});
let BTP_mainNameZZZ;
if (aliasZZZ) {
BTP_mainNameZZZ = Object.keys(aliasZZZ).find(main => {
const aliases = aliasZZZ[main];
return aliases.includes(roleName);
});
}
if (mainNameSR) {
return mainNameSR.trim();
} else if (mainNameGS) {
return mainNameGS.trim();
} else if (BTP_mainNameZZZ) {
return BTP_mainNameZZZ.trim();
}
return roleName;
}
}
const R18_images=[
//-------------------GS-------------------//
"安柏Gu3","安柏Gu10","八重神子Gu14","芭芭拉Gu4","芭芭拉Gu5","芭芭拉Gu11","芭芭拉Gu14","白术Gu8","北斗Gu2","北斗Gu3",
"北斗Gu4","北斗Gu6","迪希雅Gu8","迪希雅Gu9","珐露珊Gu1","甘雨Gu1","甘雨Gu4","甘雨Gu8","甘雨Gu13","甘雨Gu14","甘雨Gu22",
"甘雨Gu27","甘雨Gu26","甘雨Gu28","胡桃Gu14","胡桃Gu32","胡桃Gu31","胡桃Gu35","胡桃Gu47","胡桃Gu47","胡桃Gu49","久岐忍Gu6",
"久岐忍Gu7","久岐忍Gu11","久岐忍Gu10","坎蒂丝Gu1","坎蒂丝Gu4","坎蒂丝Gu6","克洛琳德Gu5","克洛琳德Gu6","刻晴Gu1","刻晴Gu3",
"刻晴Gu5","刻晴Gu15","刻晴Gu17","刻晴Gu19","刻晴Gu18","刻晴Gu20","刻晴Gu24","刻晴Gu26","雷电将军Gu1","雷电将军Gu11","雷电将军Gu14",
"雷电将军Gu33","雷电将军Gu34","雷电将军Gu39","雷电将军Gu45","丽莎Gu1","丽莎Gu2","琳尼特Gu3","琳尼特Gu5","琳尼特Gu6","琳尼特Gu7",
"琳尼特Gu13","琳尼特Gu16","莫娜Gu2","莫娜Gu12","莫娜Gu9","纳西妲Gu23","纳西妲Gu33","娜维娅Gu13","妮露Gu1","妮露Gu4","妮露Gu5",
"妮露Gu6","妮露Gu16","妮露Gu19","妮露Gu20","妮露Gu22","妮露Gu23","妮露Gu27","妮露Gu28","妮露Gu29","妮露Gu10","妮露Gu31","妮露Gu32",
"妮露Gu35","诺艾尔Gu1","诺艾尔Gu12","诺艾尔Gu13","琴Gu4","珊瑚宫心海Gu12","珊瑚宫心海Gu34","珊瑚宫心海Gu36","珊瑚宫心海Gu40",
"申鹤Gu1","申鹤Gu3","申鹤Gu4","申鹤Gu8","申鹤Gu9","申鹤Gu10","神里绫华Gu14","神里绫华Gu23","神里绫华Gu17","五郎Gu6",
"希格雯Gu13","希格雯Gu10","夏沃蕾Gu1","夏沃蕾Gu3","闲云Gu7","香菱Gu1","夜兰Gu7","夜兰Gu11","夜兰Gu13","夜兰Gu25","夜兰Gu26",
"夜兰Gu27","夜兰Gu28","夜兰Gu29","夜兰Gu12","荧Gu1","荧Gu2","荧Gu7","荧Gu11","荧Gu18","荧Gu20","荧Gu21","荧Gu14","优菈Gu7",
"优菈Gu12","优菈Gu13","妮露Gu33",
//-------------------SR-------------------//
"布洛妮娅Gu1","布洛妮娅Gu5","丹恒Gu2","符玄Gu1","黑天鹅Gu1","花火Gu1","花火Gu8","花火Gu21","花火Gu28","花火Gu29","花火Gu35",
"花火Gu48","花火Gu49","黄泉Gu2","藿藿Gu8","镜流Gu2","镜流Gu12","镜流Gu8","卡芙卡Gu2","卡芙卡Gu8","克拉拉Gu4","流萤Gu20","流萤Gu22",
"流萤Gu24","流萤Gu27","流萤Gu28","流萤Gu30","流萤Gu32","流萤Gu34","娜塔莎Gu2","青雀Gu12","青雀Gu15","青雀Gu16","阮梅Gu12","阮梅Gu16",
"阮梅Gu17","三月七Gu11","三月七Gu9","素裳Gu1","素裳Gu5","停云Gu5","托帕Gu2","托帕Gu4","托帕Gu5","托帕Gu7","托帕Gu14","托帕Gu15",
"星Gu10","星Gu3","星Gu5","雪衣Gu2","驭空Gu3",
//-------------------ZZZ-------------------//
//-------------------娘化-------------------//
"杰帕德Gu1","流浪者Gu4","魈Gu12","真理医生Gu4"
]