This repository was archived by the owner on Jan 21, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathTerminal_LDModule.java
4755 lines (4649 loc) · 171 KB
/
Terminal_LDModule.java
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
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* import java packages */
import android.widget.Toast;
import java.io.*;
import java.lang.String;
import java.lang.StringBuffer;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.NoSuchAlgorithmException;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.regex.*;
import java.nio.charset.StandardCharsets;
import org.json.JSONArray;
import org.json.JSONObject;
/* 预设变量 */
public static final String scriptName = "Terminal.java";//本脚本名称
String scriptPath = "/storage/emulated/0/LD_Module/Plugin";
public static final String scriptVersion = "(20231017)";//本脚本版本
Toast(scriptName + " 开始加载,请稍候。\n许你一个美好的明天,愿世间的每一个角落都洒满璀璨的星光。");
public static final String linkText = "https://github.com/BatchClayderman/Terminal.java";//本脚本下载地址
public static final String allOrders = scriptName
+ "\n\n"
+ "自己或代管的命令:\n"
+ " #add 文字 添加 send 话语(区分大小写)\n"
+ " #af 文字 修改自动续火文字(区分大小写)\n"
+ " #atAll @所有人\n"
+ " #atoS 文字 将 atList 转为文本(区分大小写)\n"
+ " #atoU 文字 将 atList 转为 \\uUnicode 的格式(区分大小写)\n"
+ " #boom 次数 炸弹\n"
+ " #bq #bq 表示列出当前黑名单,#bqc 或 #bql 表示显示名单长度,#bq+@QQ 表示拉黑,#bq-@QQ 表示撤销拉黑\n"
+ " #brush/#flush 清屏(共提供三种方式)\n"
+ " #chk 群备注检查【年级专业姓名】(参数:/a 提醒、/f 禁言、/n仅检查空的、/x 顺便踢人、/r 顺便踢出并拒绝再次加入)\n"
+ " #clap QQ号 次数(或#clap 次数@QQ) 拍一拍\n"
+ " #countFriends 发送所有 QQ 好友数\n"
+ " #define longText 字段长 设置所管群消息最大上限(区分大小写)\n"
+ " #define gapTime 时间 设置操作时间间隔(毫秒)(区分大小写)\n"
+ " #define tailLength 小尾巴重载长度下限 设置翻译文本长度下限(区分大小写)\n"
+ " #define tipTime 时间 设置提示时间间隔(分钟)(0 视为停止)(区分大小写)\n"
+ " #define r[数字] 文字 设置指定位置的 send 话语(示例:#define r0 1)(区分大小写)\n"
+ " #define reply 重置 reply(区分大小写)\n"
+ " #del 位置 删除 send 话语(区分大小写)\n"
+ " #ds { 禁言值列表 } 设置禁言值\n"
+ " #dw #dw 表示列出当前违禁词名单,#dwc 或 #dwl 表示显示名单长度,#dw+文字 表示违禁词入库,#dw-文字 表示撤销违禁词入库\n"
+ " #Echo [On/Off] [打开/关闭]回显\n"
+ " #fb #fb 表示列出当前禁区名单,#fbc 或 #fbl 表示显示名单长度,#fb+群号 表示添加禁区群,#fb-群号 表示撤销禁区群,批量操作使用空格隔开\n"
+ " #fr(此命令仅对本人生效) #fr 表示列出当前代管名单,#frc 或 #frl 表示显示名单长度,#fr+@QQ 表示增加代管,#fr-@QQ 表示取消代管\n"
+ " #gc GetActivity()\n"
+ " #get 群成员QQ号 获取群成员(群聊)或好友(私聊)信息\n"
+ " #getx 群成员QQ号 获取群成员(群聊)或好友(私聊)所有信息(可能含敏感信息和冗余字段)\n"
+ " #getAllMsg Q群号 发送群聊资料(请谨慎使用)\n"
+ " #getFriends 发送所有 QQ 好友信息(请勿随意使用)\n"
+ " #group 发送本脚本开发者所在 QQ 群号\n"
+ " #hack 偷流量\n"
+ " #header 文字(可加@列表) 获取头衔(加@列表后为批量修改群成员头衔)(区分大小写)\n"
+ " #hw 次数 发送作业卡片\n"
+ " #len 计算长度\n"
+ " #lk 发送 QQ 群信息\n"
+ " #link 发送本脚本下载地址\n"
+ " #md5 文字 发送文字的 md5 信息(区分大小写)\n"
+ " #nick 文字(可加@列表) 修改昵称(加@列表后为批量修改群成员头衔)(区分大小写)\n"
+ " #openAll 全体解禁\n"
+ " #Recall [On/Off] [打开/关闭]开启自动延时撤回群里/对方所有消息\n"
+ " #recall(回复文本) 撤回回复内容(由于接口问题可能会失效)\n"
+ " #recall 文字 t时间 发送消息后延时撤回自己的消息(区分大小写)\n"
+ " #Repeat Enabled 开启复读增强\n"
+ " #Repeat Disabled 关闭复读增强\n"
+ " #Repeat [On/Off] [打开/关闭]自动复读\n"
+ " #reply (用于检测正在使用此脚本的用户)\n"
+ " #rm QQ号 踢人(需要群主或管理员权限)(区分大小写)\n"
+ " #rf QQ号 踢人并拉入群黑名单(需要群主或管理员权限)(区分大小写)\n"
+ " #rp[图片发送次数][图片1, 图片2, ...] 重复发送图片(#rp 后面没有空格且接一个一位数)\n"
+ " #save QQ号 救群 / 救私聊 QQ(区分大小写)\n"
+ " #saveA 私聊QQ号 救私聊 QQ(区分大小写)\n"
+ " #saveW Q群号 救群(区分大小写)\n"
+ " #Secure [On/Off] [打开/关闭]安全监控\n"
+ " #send 发送已设定好的话语(区分大小写)\n"
+ " #send 文字 d次数 多文字转多发(区分大小写)\n"
+ " #send 文字 f[开始:结束:步长:饱和值] 发送循环消息(饱和值为 0 为不限制)(区分大小写)\n"
+ " #send 文字 r次数 发送多个字符串(区分大小写)\n"
+ " #send 文字 s次数 消息多次发送(区分大小写)\n"
+ " #send 文字 x次数 发送多条消息(区分大小写)\n"
+ " #sfc 全局黑名单扫描(使用前请先刷新成员列表)(参数:/a 提醒、/f 禁言、/x 顺便踢人、/r 顺便踢出并拒绝再次加入)\n"
+ " #shake 次数 抖动\n"
+ " #shut QQ号 分钟(或#shut 分钟@QQ) 禁言(分钟数为 0 则解禁)\n"
+ " #shutAll 分钟 全体禁言\n"
+ " #tip 文字 发送系统消息(仅自己可见且可能已失效)(区分大小写)\n"
+ " #Terminal [On/Off] [打开/关闭]总开关\n"
+ " #Toast [On/Off] [打开/关闭] Toast 提示\n"
+ " #TranOn 开启小尾巴自动翻译\n"
+ " #TranOff 关闭小尾巴自动翻译\n"
+ " #Tran 重置小尾巴分割符为一个回车(不区分大小写)\n"
+ " #Tran 文字 小尾巴分割符(区分大小写)\n"
+ " #undef reply 清空 reply\n"
+ " #Welcome On 开启欢迎语\n"
+ " #Welcome Off 关闭欢迎语\n"
+ " #whoami 显示自己的备注和 QQ 号\n"
+ " 投票清零@QQ 投票清零\n"
+ "\n"
+ "他人的命令(仅对 welcomeList 生效):\n"
+ " #header 文字 群成员请求头衔(区分大小写)\n"
+ " #sleep 分钟 群成员请求禁言\n"
//+ " 闭关 随机禁言\n"
//+ " 抽签/打卡/签到/签退/冒泡 无意义\n"
//+ " [DirtyLists] 骂人的话(对私聊也生效)(文字识别过程不区分大小写)\n"
//+ " [Requests] 询问在不在(对私聊也生效)\n"
//+ " [TreatMeBad]@我 禁言 2 分钟\n"
//+ " [超长文字] 自动撤回\n"
+ "\n"
+ "通用命令(不区分大小写):\n"
+ " #AM 发送驱动启发式音乐列表\n"
+ " #bad 发送坏人\n"
+ " #BM 发送标准启发式音乐列表\n"
+ " #CM 发送云启发式音乐列表\n"
+ " #countUIN Q群号 发送群聊成员数量\n"
+ " #edxp 发送 Edxposed 配置与部署流程\n"
+ " #getUIN Q群号 发送群聊成员 QQ 号\n"
+ " #h(#help或菜单) 发送帮助\n"
+ " #ifexists QQ号/@QQ 是否存在群成员(调用前请先刷新成员列表)\n"
+ " #lsp 发送 LSPosed 配置与部署流程\n"
+ " #play 随机数 发送“好玩”的文字\n"
+ " #qp 发送 QQ 接收文件的路径\n"
+ " #tr 转换时间\n"
+ " #voice 发送语音(需要确保 replyVoice 里的文件存在)\n"
+ " #time 发送时间\n"
+ " #xp/#太极 (建议的操作)\n"
+ " 投票禁言@QQ 投票禁言\n"
+ " 投票踢人@QQ 投票踢人";
/* 全局变量 */
boolean Terminal_Flag = true;//总开关
boolean Search_Flag = true;//副开关
boolean isEcho = true;//是否发出指令
boolean isSecure = true;//是否开启安全监控
boolean isToast = true;//是否提示
boolean isTran = false;//是否翻译
boolean isTmpClose = false;//是否临时关闭开关
boolean repeatEnhance = false;//是否增强复读
short init_count = 5;// on_init()
int gapTime = 0;//间隔时间
int longText = 1000;//最长字符
int tailLength = 3;//小尾巴翻译字数下限
int tipTime = 30;//提示间隔时间
int upperLimit = 150;//群聊人数上线和消息长度最大限制的一半
int upperReturn = 15;//最大限制回车
int[] dealShut = { 120, 1200, 18000, 864000, 2592000 };
Map clockMap = new HashMap();//打卡计数
Map kickMap = new HashMap();//投票踢人
Map shutMap = new HashMap();//投票禁言
Map signMap = new HashMap();//打卡计数
Map verMap = new HashMap();//进群验证
StringBuffer sb = new StringBuffer();
sb.append("快出来看!!!有乌龟乌龟乌龟乌龟乌龟乌龟乌龟乌龟🐢😏🚒");
for (int i = 0; i < 80000; ++i)
sb.append("🐢😏🚒🐢😏🚒🐢😏🚒🐢😏🚒");
String boomText = new String(sb);
String arrowText = " -> ";//箭头符
String autoFire = "早午晚鸡鸭鹅咕唔";//自动续火
String commandText = "#";//指令符
String commentText = "//";//注释符
String delimText = "\n";//中英分隔符
String escText = "%";//转义符
String lastAtMe = "";//上次 @ 我的人
String lastFire = "";//上次续火的人
String lastText = "";//上次复读的内容
String myGroup = "1029321431";//交流群
String rpTmp = "";//重发图片路径
String silenceText = "@";//静默符
String total_text = scriptName + " 初始化成功!\n超越驱动,超越方纲,超越纲程。\n";// on_init()
String[] recallListGroup = new String[0];
String[] reply = {"我要闹啦!", "我快要闹啦!!", "我已经在闹啦!!!"};
String[] replyVoice = {scriptPath + "/PTT/atMe.slk", scriptPath + "/PTT/天狗.slk"};//语音路径
String[] Requests = {"在", "在?", "在吗", "在嘛", "在么", "在不", "在不?", "在吗?", "在嘛?", "在么?", "还在?", "不在?", "不在~", "不在~", "不在~~", "不在~~", "不在~~~", "不在~~~", "在不在", "群主在吗", "管理在吗", "老哥在吗", "大哥在吗"};
String[] swipeGroup = new String[0];//开启自动复读的群(仅针对群聊)
String[] TreatMeBad = {"禁言", "踢", "拉黑", "折磨", "强奸", "打", "抢劫", "买", "卖", "购买", "求婚", "查询", "日", "操", "#get", "#search", "#rm", "#rf", "#shut"};
private static final String APP_ID = "20201006000581880";
private static final String SECURITY_KEY = "Hg2NYBpPY3BFaHomJDBc";
private static final String searchURL = "aHR0cDovL2FwaS5janNyY3cuY24vcWItYXBpLnBocD9tb2Q9Y2hhJnFxPQ==";
/* 随机数 */
/**
* 根据min和max随机生成一个范围在[min, max]的随机数,包括min和max
* @param min
* @param max
* @return int
*/
public int getRandom(int min, int max)
{
Random random = new Random();
return random.nextInt(max - min + 1) + min;
}
/**
* 根据min和max随机生成count个不重复的随机数组
* @param min
* @param max
* @param count
* @return int[]
*/
public int[] getRandoms(int min, int max, int count)
{
if (count <= 0 || count > (max - min + 1))
return null;
int[] randoms = new int[count];
List listRandom = new ArrayList();//List<Integer> listRandom = new ArrayList<Integer>();
/* 将所有可能出现的数字放进候选 list */
for (int i = min; i <= max; ++i)
listRandom.add(i);
/* 从候选 list 中取出放入数组,已经被选中的就从这个 list 中移除 */
for (int i = 0; i < count; ++i)
{
int index = getRandom(0, listRandom.size() - 1);
randoms[i] = listRandom.get(index);
listRandom.remove(index);
}
return randoms;
}
/* 子函数 */
public static void pause()
{
try
{
Thread.sleep(gapTime <= 0 ? getRandom(1000, 10000) : gapTime);
}
catch (InterruptedException ie) {}
return;
}
public static String getTime()
{
SimpleDateFormat df1 = new SimpleDateFormat("yyyy年MM月dd日"), df2 = new SimpleDateFormat("E", Locale.CHINA), df3 = new SimpleDateFormat("HH:mm:ss.SSS");
Calendar calendar = Calendar.getInstance();
String TimeMsg1 = df1.format(calendar.getTime()), TimeMsg2 = df2.format(calendar.getTime()), TimeMsg3 = df3.format(calendar.getTime());
if (TimeMsg1.contains("年0"))//去掉多余的 0
TimeMsg1 = TimeMsg1.replace("年0", "年");
if (TimeMsg1.contains("月0"))
TimeMsg1 = TimeMsg1.replace("月0", "月");
if (TimeMsg2.contains("周"))
TimeMsg2 = TimeMsg2.replace("周", "星期");//转换为星期
return TimeMsg1 + TimeMsg2 + TimeMsg3;
}
public static boolean isInList(String targetValue, String[] arr)//是否在数组中
{
if (arr.length <= 0)
return false;
for (String s : arr)
if (s.equals(targetValue))
return true;
return false;
}
public static void send(Object data, String s)//继承并改进自 QQ 复读机的发送函数
{
isTmpClose = true;//暂时关闭
if (data.IsGroup)
sendMsg(data.GroupUin, "", s);
else
sendMsg("", data.UserUin, s);
return;
}
public static void send(Object data, String s, String[] atList)//继承并改进自 QQ 复读机的发送函数
{
isTmpClose = true;//暂时关闭
String atString = "";
for (String target : atList)
atString += "[AtQQ=" + target + "]";
if (data.IsGroup)
sendMsg(data.GroupUin, "", atString + s);
else//群组才能@
sendMsg("", data.UserUin, s);
return;
}
public static void send(String GroupUin, String s, String[] atList)//继承并改进自 QQ 复读机的发送函数
{
isTmpClose = true;//暂时关闭
String atString = "";
for (String target : atList)
atString += "[AtQQ=" + target + "]";
sendMsg(GroupUin, "", atString + s);
return;
}
public static void sendReply(Object data, String s)//继承并改进自 QQ 复读机的回复函数
{
isTmpClose = true;//暂时关闭
if (data.IsGroup)
sendReply(data.GroupUin, data, s);
else
sendReply("", data, s);
return;
}
public static void sendPhoto(Object data, String path)//继承自 QQ 复读机的图片发送函数
{
if (data.IsGroup)
sendPic(data.GroupUin, "", path);
else
sendPic("", data.UserUin, path);
return;
}
public static void sendShowPhoto(Object data, String path, int type)//继承自 QQ 复读机的秀图发送函数
{
if (data.IsGroup)
sendShow(data.GroupUin, path, type);
return;
}
public static void sendCard(Object data, String path)// 继承自 QQ 复读机的卡片发送函数
{
if (data.IsGroup)
sendCard(data.GroupUin, "", path);
else
sendCard("", data.UserUin, path);
return;
}
public static void sendPtt(Object data, String path)// 继承自 QQ 复读机的语音发送函数
{
if (data.IsGroup)
sendVoice(data.GroupUin, "", path);
else
sendVoice("", data.UserUin, path);
return;
}
public static boolean isAtMe(Object data)//改写自 QQ 复读机的 .atMe 属性
{
if (null == data.AtList || 0 == data.AtList.length)//空
return false;
for (String to_at : data.AtList)
if (to_at.equals(MyUin))
return true;
return false;
}
public static boolean isAdmin(String GroupUin, String UserUin)// 继承自 QQ 复读机的判断是否管理员函数
{
ArrayList groupList = getGroupList();
for (Object groupInfo : groupList)
if (groupInfo.GroupUin.equals(GroupUin))
return groupInfo.GroupOwner.equals(UserUin) || isInList(UserUin, groupInfo.AdminList);
return false;
}
public static boolean isAdmin(String GroupUin) { return isAdmin(GroupUin, MyUin); }
public static boolean isGroupOwner(String GroupUin, String UserUin)// 改进自 QQ 复读机的判断是否群主函数
{
ArrayList groupList = getGroupList();
for (Object groupInfo : groupList)
if (groupInfo.GroupUin.equals(GroupUin))
return groupInfo.GroupOwner.equals(UserUin);
return false;
}
public static boolean isGroupOwner(String GroupUin) { return isGroupOwner(GroupUin, MyUin); }
public static Object getGroupMemberInfo(String GroupUin, String UserUin)
{
ArrayList groupMemberList = getGroupMemberList(GroupUin);
for (Object groupMemberInfo : groupMemberList)
if (groupMemberInfo.UserUin.equals(UserUin))
return groupMemberInfo;
return null;
}
public static void sendResponse(Object data, String s)
{
if (data.IsGroup)
sendReply(data, s);
else if (data.UserUin.equals(MyUin))
send(data, s);
else
{
//// for (Object oo : getFriends())
//// if (oo.uin.equals(data.UserUin))
//// {
//// sendReply(data, s);
//// return;
//// }
send(data, s);
}
return;
}
public static void sendBad(Object data, boolean isShut)
{
if (isShut)
{
pause();
Forbidden(data.GroupUin, data.UserUin, 60 * getRandom(1, (int)(dealShut[0] / 60)));
}
pause();
send(data, "坏~坏人~~大坏蛋~~~");
pause();
sendPhoto(data, "http://gchat.qpic.cn/gchatpic_new/1306561600/1029321431-2587600298-4EEC26065EA08F0F51B0BEE0F61A462C/0?term=2");
pause();
sendCard(data, "<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><msg serviceID=\"5\" templateID=\"1\" action=\"\" brief=\"[图片表情]\" sourceMsgId=\"0\" url=\"\" flag=\"0\" adverSign=\"0\" multiMsgFlag=\"0\"><item layout=\"0\"><image uuid=\"4EEC26065EA08F0F51B0BEE0F61A462C.gif\" md5=\"4EEC26065EA08F0F51B0BEE0F61A462C\" GroupFiledid=\"0\" filesize=\"2964\" local_path=\"\" minWidth=\"400\" minHeight=\"400\" maxWidth=\"400\" maxHeight=\"400\" /></item><source name=\"\" icon=\"\" action=\"\" appid=\"-1\" /></msg>");
return;
}
public static void Forbidden(String GroupUin, String UserUin, long time) { return Forbidden(GroupUin, UserUin, (int)time); }
public static boolean isAllE(String isAllC)//判断是否全为英文字母
{
return isAllC.replaceAll("[A-Za-z]", "").length() == 0;
}
public static boolean isAllP(String isAllC)//判断是否全为标点和数字
{
return isAllC.replaceAll("\\p{P}", "").length() == 0 || isAllC.replaceAll("\\d+", "").length() == 0 || isAllC.replaceAll("\\p{P}", "").replaceAll("\\d+", "").length() == 0;
}
public static boolean isChinese(char c)
{
return c >= 0x4E00 && c <= 0x9FA5;//根据字节码判断
}
public static boolean isContainsZH(String str)//判断是否含有中文字符
{
if (null == str)
return false;
for (char c : str.toCharArray())
if (isChinese(c))
return true;// 有一个中文字符就返回
return false;
}
public static boolean isoook(String str)//判断是否为“哈哈哈哈好”类型的字符串
{
if (str == null)
return false;
if (str.charAt(str.length() - 1) == '好')
{
for (int i = 0; i < str.length() - 1; ++i)
if (str.charAt(i) != '哈')
return false;
return true;
}
else
return false;
}
public static boolean isSameChar(String msg)//是否同一字符
{
char tmp = msg.charAt(0);
for (int i = 1; i < msg.length(); ++i)
if (msg.charAt(i) != tmp)
return false;
return true;
}
public static boolean isNotEmojiCharacter(char codePoint)//判断是否为表情符号
{
return (codePoint == 0x0) || (codePoint == 0x9) || (codePoint == 0xA) || (codePoint == 0xD)
|| ((codePoint >= 0x20) && (codePoint <= 0xD7FF))
|| ((codePoint >= 0xE000) && (codePoint <= 0xFFFD))
|| ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF)
);
}
public static boolean isEmojiOnly(String isAllCodes)//是否仅含有表情
{
boolean bRet = true;
for (int i = 0; i < isAllCodes.length(); ++i)
if (isNotEmojiCharacter(isAllCodes.charAt(i)))
{
bRet = false;
break;//节省时间
}
return bRet;
}
public static String transTime(long dShut)//时间转换
{
String sShut = "";
int[] delimsTime = {2592000, 86400, 3600, 60, 1};
String[] delimsText = {"月", "天", "小时", "分钟", "秒钟"};
for (int i = 1; i < delimsTime.length; ++i)
{
int tmp = (int)((dShut % delimsTime[i - 1]) / delimsTime[i]);
if (tmp > 0)
sShut += tmp + delimsText[i];
}
return sShut;
}
public static String transTime(int dShut) { return transTime((long)dShut); }
public String timeStamp2Date(String timestampString)//时间戳转常规格式
{
Long timestamp = Long.parseLong(timestampString) * 1000;
return new SimpleDateFormat("yyyy 年 MM 月 dd 日 HH:mm:ss").format(new Date(timestamp));
}
public static String transString(String ori_string)//转换字符串
{
return "\"" + ori_string.replaceAll("\"", "\\\"").replaceAll("\\\\", "\\\\") + "\"";
}
public String getFileContent(File file)//获取文件内容
{
FileInputStream inputStream = new FileInputStream(file);
byte[] bytes = new byte[inputStream.available()];
inputStream.read(bytes);
inputStream.close();
String sRet = new String(bytes, StandardCharsets.UTF_8);
return sRet;
}
public static boolean isChk(String troopnick)//是否符合群备注
{
String troopname = troopnick.toLowerCase().replace("本科生", "本").replace("本科", "本").replace("研究生", "研").replace("硕士", "硕").replace("博士", "博").replace("在读", "").replace("专业", "");
//troopname = troopname.replace(" ", "").replace("\\-", "").replace("\t", "").replace("\r", "").replace("\n", "");
if (troopname.startsWith("暨大"))
troopname = troopname.substring(2);
else if (troopname.startsWith("暨南大学"))
troopname = troopname.substring(4);
if (troopname.contains("老师") || troopname.contains("助教") || troopname.contains("学生会") || troopname.contains("团委") || troopname.contains("机器人"))
return true;
String ext_major = "本硕博研";
if (troopname.contains("+"))
{
location = troopname.indexOf('+');
if (troopname.length() - troopname.replace("+", "").length() > 1)//三学位?
return false;
else if (troopname.endsWith("+"))// + 空气?
return false;
else if (location < 2)//第一学位只有年级
return false;
else if (
(troopname.charAt(0) == '1' || troopname.charAt(0) == '2')//年级
&& (troopname.charAt(1) >= '0' && troopname.charAt(1) <= '9')//年级
&& (
(isChinese(troopname.charAt(2)) && isChinese(troopname.charAt(3)) && location == 4)
|| (isChinese(troopname.charAt(2)) && isChinese(troopname.charAt(3)) && (
ext_major.indexOf(troopname.charAt(4)) >= 0//防止研究生备注
) && location == 5)
|| (troopname.charAt(2) >= 'a' && troopname.charAt(2) <= 'z')
)
)
troopname = troopname.substring(location + 1);
else
return false;
}
if (troopname.length() <= 2)//长度不足
return false;
if (
(troopname.charAt(0) == '1' || troopname.charAt(0) == '2')//年级
&& (troopname.charAt(1) >= '0' && troopname.charAt(1) <= '9')//年级
)
troopname = troopname.substring(2);
else
return false;
if (isChinese(troopname.charAt(0)))//中文专业
return (troopname.length() > 2 && isChinese(troopname.charAt(1))) || (troopname.length() > 3 && isChinese(troopname.charAt(1)) && ext_major.indexOf(troopname.charAt(2)) >= 0);
else
return true;//英文专业
}
/* 总开关 */
public static boolean Terminal_Check_Flag(String target)
{
return Terminal_Flag && (target.length() > 0 ? (!forbiddenList.find(target)) : true);
}
/* 并发线程 */
public static void on_init(String text)
{
total_text += "\n\n" + text;
--init_count;
if (init_count == 0)
{
if (("" + GetActivity()).toLowerCase().startsWith("com.tencent.mobileqq.activity."))
Toast(total_text);
}
else
return;
return;
new Thread(new Runnable()
{
public void run()
{
try
{
short attemptTime = 3;
try
{
Thread.sleep(tipTime * 1000);//暂停 tipTime 秒
}
catch (InterruptedException ie) {}
HashSet allFriendsA = new HashSet();
HashSet allFriendsB = new HashSet();
boolean usingA = true;
for (;;)
{
if (tipTime <= 0)//功能被关闭
return;
if (usingA)//向 B 更新 A
{
allFriendsA = new HashSet();
//// for (Object oo : getFriends())
//// allFriendsA.add(oo.uin);
if (allFriendsA.size() <= 1)
{
--attemptTime;
Toast("QQ 好友数获取异常,将于 " + tipTime + " 秒后将重新获取,如果您的 QQ 没有 QQ 好友,请使用“#define tipTime 0”命令将 tipTime 设置为 0,否则,请尝试打开 QQ 主界面以激活 getFriends() 函数。");
try
{
Thread.sleep(tipTime * 1000);//暂停 tipTime 秒
}
catch (InterruptedException ie) {}
if (attemptTime > 0)
continue;
else
{
Toast("3 次尝试均失效,并发线程已退出。");
return;
}
}
if (allFriendsB.size() == 0)//首次统计
{
if (("" + GetActivity()).toLowerCase().startsWith("com.tencent.mobileqq.activity."))
Toast(scriptName + " 并发线程开始运行,当前 QQ(" + MyUin + ")共有 QQ 好友 " + allFriendsA.size() + " 位。");
else
Toast(scriptName + " 并发线程已开始运行!");
}
else
{
int tmp = tipTime;
Iterator it = allFriendsB.iterator();
while (it.hasNext())
{
Object obj = it.next();
if (!allFriendsA.contains(obj.toString()))
{
if (tmp > 0)
{
//// send(createData(false, obj.toString()), "在?在吗??还在吗???");//说明此人已把你删除
pause();//防止发生群发事件
--tmp;
}
else
{
Toast("检测到您被好友删除的频率超过每分钟一次,如果这属于误报,这可能是程序运行异常导致的。目前,程序已停止向每一位将您删除的好友发送信息,如果您安装了 QNotified,请使用该插件查看历史好友。");
break;
}
}
}
if (allFriendsA.size() == allFriendsB.size())
Toast(scriptName + " 持续运行中!");
else if (allFriendsA.size() < allFriendsB.size())//好友总数减少
Toast("QQ好友 " + (allFriendsA.size() - allFriendsB.size()));
else//好友总数增加
Toast("QQ好友 +" + (allFriendsA.size() - allFriendsB.size()));
}
}
else//向 A 更新 B
{
allFriendsB = new HashSet();
//// for (Object oo : getFriends())
//// allFriendsB.add(oo.uin);
int tmp = tipTime;
Iterator it = allFriendsA.iterator();
while (it.hasNext())
{
Object obj = it.next();
if (!allFriendsB.contains(obj.toString()))
{
if (tmp > 0)
{
//// send(createData(false, obj.toString()), "在?在吗??还在吗???");//说明此人已把你删除
pause();//防止发生群发事件
--tmp;
}
else
{
Toast("检测到您被好友删除的频率超过每分钟一次,如果这属于误报,这可能是程序运行异常导致的。目前,程序已停止向每一位将您删除的好友发送信息,如果您安装并激活了 QNotified,请使用该插件查看历史好友。");
break;
}
}
}
if (allFriendsA.size() == allFriendsB.size())
Toast(scriptName + " 持续运行中!");
else if (allFriendsA.size() > allFriendsB.size())//好友总数减少
Toast("QQ好友 " + (allFriendsB.size() - allFriendsA.size()));
else//好友总数增加
Toast("QQ好友 +" + (allFriendsB.size() - allFriendsA.size()));
}
usingA = !usingA;//切换
for (int i = 0; i < tipTime; ++i)
{
try
{
Thread.sleep(60000);
}
catch (InterruptedException ie)
{
tipTime = 0;
}
}
}
}
catch (Throwable e)//减少其它模块开启未知异常抓取的弹窗频率
{
Toast(scriptName + " 并发线程发生异常!\n抛出异常信息如下:\n" + e);
}
}
}).start();
return;
}
/* 主类 */
public class Terminal
{
private String name;
private String path;
private String delims;
private HashSet hashset = new HashSet();
public Terminal(String name, String path, String delims, HashSet hashset)
{
this.name = name;
this.path = path;
this.delims = delims;
this.hashset = hashset;
return;
}
public Terminal(String name, String path, String delims, boolean capital)
{
this.name = name;
this.path = path;
this.delims = delims;
try
{
File file = new File(this.path);
if (!file.exists())
{
Toast(this.name + "初始化失败!\n系统找不到指定文件!这将会为您创建相关文件!");
return;
}
String list = getFileContent(file);
if (capital && list.startsWith(delims))
list = list.substring(delims.length());
else if (!capital && list.toLowerCase().startsWith(delims.toLowerCase()))
list = list.substring(delims.toLowerCase().length());
if (capital && list.endsWith(delims))
list = list.substring(0, list.length() - delims.length());
else if (!capital && list.toLowerCase().endsWith(delims.toLowerCase()))
list = list.substring(0, list.toLowerCase().length() - delims.toLowerCase().length());
if (list.length() > 0)
{
String[] lists = list.split(delims);
for (String element : lists)
this.hashset.add(element);
}
on_init(this.name + "初始化成功!\n共有 " + this.hashset.size() + " 个元素!");
}
catch (Throwable e)
{
Toast(this.name + "初始化失败!\n抛出异常信息如下:\n" + e);
}
return;
}
public boolean update()//更新到文件
{
boolean success = true;
FileWriter fwriter = null;
try
{
fwriter = new FileWriter(this.path);
fwriter.write(this.toString());
}
catch (Throwable e)
{
success = false;
}
finally
{
try
{
fwriter.flush();
fwriter.close();
}
catch (Throwable ex)
{
success = false;
}
}
return success;
}
public boolean find(String element)//简单查找
{
return this.hashset.contains(element);
}
public boolean find(String element, boolean capital)//复杂查找
{
if (this.hashset.size() == 0)
return false;
Iterator it = this.hashset.iterator();
while (it.hasNext())
{
Object obj = it.next();
if (capital && element.contains(obj.toString()))
return true;
else if (!capital && element.toLowerCase().contains(obj.toString().toLowerCase()))
return true;
}
return false;
}
public boolean[] add(String element)//简单添加
{
if (element.toLowerCase().contains(this.delims.toLowerCase()))
return this.add(element.toLowerCase().split(this.delims.toLowerCase()));
boolean[] bRet = { true, true };
if (this.hashset.contains(element))
{
bRet[1] = false;
return bRet;
}
this.hashset.add(element);
bRet[0] = this.update();
return bRet;
}
public boolean[] add(String[] elements)//批量简单添加
{
boolean[] bRet = { true, true };
for (String element : elements)
{
boolean[] tmp_Ret = this.add(element);
bRet[0] = bRet[0] && tmp_Ret[0];
bRet[1] = bRet[1] && tmp_Ret[1];
}
return bRet;
}
public boolean[] add(String element, boolean capital)//复杂添加
{
if (capital && element.contains(this.delims))
return this.add(element.split(this.delims), capital);
else if (!capital && element.toLowerCase().contains(this.delims.toLowerCase()))
return this.add(element.toLowerCase().split(this.delims.toLowerCase()), capital);
HashSet elements = new HashSet();
boolean[] bRet = { true, true };
if (this.find(element, capital))
{
bRet[1] = false;
return bRet;
}
Iterator it = hashset.iterator();
while (it.hasNext())
{
Object obj = it.next();
if (capital && (obj.toString().contains(element))) {}
else if (!capital && (obj.toString().toLowerCase().contains(element.toLowerCase()))) {}
else { elements.add(capital ? obj.toString() : obj.toString().toLowerCase()); }
}
elements.add(capital ? element : element.toLowerCase());
this.hashset = elements;
bRet[0] = this.update();
return bRet;
}
public boolean[] add(String[] elements, boolean capital)//批量复杂添加
{
boolean[] bRet = { true, true };
for (String element : elements)
{
boolean[] tmp_Ret = this.add(element, capital);
bRet[0] = bRet[0] && tmp_Ret[0];
bRet[1] = bRet[1] && tmp_Ret[1];
}
return bRet;
}
public boolean[] remove(String element)//简单删除
{
if (element.toLowerCase().contains(this.delims.toLowerCase()))
return this.remove(element.toLowerCase().split(this.delims.toLowerCase()));
boolean[] bRet = { true, true };
if (!this.hashset.contains(element))
{
bRet[1] = false;
return bRet;
}
this.hashset.remove(element);
bRet[0] = this.update();
return bRet;
}
public boolean[] remove(String[] elements)//批量简单删除
{
boolean[] bRet = { true, true };
for (String element : elements)
{
boolean[] tmp_Ret = this.remove(element);
bRet[0] = bRet[0] && tmp_Ret[0];
bRet[1] = bRet[1] && tmp_Ret[1];
}
return bRet;
}
public boolean[] remove(String element, boolean capital)//复杂删除
{
if (capital && element.contains(this.delims))
return this.remove(element.split(this.delims), capital);
else if (!capital && element.toLowerCase().contains(this.delims.toLowerCase()))
return this.remove(element.toLowerCase().split(this.delims.toLowerCase()), capital);
HashSet elements = new HashSet();
boolean[] bRet = { true, true };
if (!this.find(element, capital))
{
bRet[1] = false;
return bRet;
}
Iterator it = hashset.iterator();
while (it.hasNext())
{
Object obj = it.next();
if (capital && (element.contains(obj.toString()))) {}
else if (!capital && (element.toLowerCase().contains(obj.toString().toLowerCase()))) {}
else { elements.add(capital ? obj.toString() : obj.toString().toLowerCase()); }
}
this.hashset = elements;
bRet[0] = this.update();
return bRet;
}
public boolean[] remove(String[] elements, boolean capital)//批量复杂删除
{
boolean[] bRet = { true, true };
for (String element : elements)
{
boolean[] tmp_Ret = this.remove(element, capital);
bRet[0] = bRet[0] && tmp_Ret[0];
bRet[1] = bRet[1] && tmp_Ret[1];
}
return bRet;
}
public int count()
{
return this.hashset.size();
}
public String getDelims()
{
return this.delims;
}
public String toString()//输出
{
if (this.hashset.size() == 0)
return "";
String lists = "";
Iterator it = this.hashset.iterator();
while (it.hasNext())
{
Object obj = it.next();
lists += this.delims + obj.toString();
}
return lists.substring(this.delims.length());
}
}
Terminal blackQQ = new Terminal("QQ 黑名单", scriptPath + "/Terminal/blacklist.txt", ", ", false);
Terminal dirtyList = new Terminal("关键词表", scriptPath + "/Terminal/dirtylist.txt", "\n", false);
Terminal friendQQ = new Terminal("QQ 代管名单", scriptPath + "/Terminal/friendlist.txt", ", ", false);
Terminal welcomeList = new Terminal("QQ 群监控名单", scriptPath + "/Terminal/welcomelist.txt", ", ", false);
Terminal forbiddenList = new Terminal("QQ 群禁区名单", scriptPath + "/Terminal/forbidden.txt", ", ", false);
Map autoReply = new HashMap();//自动回复
File file = new File(scriptPath + "/Terminal/autoReply.txt");
if (file.exists())
{
String[] rules = getFileContent(file).split("\n");
for (String rule : rules)
if (!rule.startsWith(commandText) && !rule.startsWith(escText) && !rule.startsWith(silenceText) && !rule.startsWith(commentText) && rule.contains(arrowText))