Compare commits
1298 Commits
backup
...
v1.5.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ceb3df513d | ||
|
|
83372c4209 | ||
|
|
20d5e014b7 | ||
|
|
1c9a7eb158 | ||
|
|
31555cbf2f | ||
|
|
4a1d4644ed | ||
|
|
9182d214af | ||
|
|
45e3383031 | ||
|
|
fc91b69b55 | ||
|
|
13b6614dc2 | ||
|
|
fec5e4d73f | ||
|
|
585add29fc | ||
|
|
1e48e59cb7 | ||
|
|
41911af09a | ||
|
|
37b95e9559 | ||
|
|
a7901745e8 | ||
|
|
da9f085a50 | ||
|
|
192c2a8bd6 | ||
|
|
e6c00e9b68 | ||
|
|
1faa5aa5d8 | ||
|
|
7e7191536a | ||
|
|
16ff1975ff | ||
|
|
b32c86863e | ||
|
|
d9b361f765 | ||
|
|
5b2810e6c5 | ||
|
|
15a5b347e8 | ||
|
|
477ffa825b | ||
|
|
84363b1513 | ||
|
|
01bf6f049b | ||
|
|
a8d93de000 | ||
|
|
2da5de3743 | ||
|
|
bf6bac7be6 | ||
|
|
394d2e4a08 | ||
|
|
0dd447e270 | ||
|
|
92c913e3eb | ||
|
|
5dea461963 | ||
|
|
f768081849 | ||
|
|
668418c48a | ||
|
|
2bf387a57c | ||
|
|
42a4726985 | ||
|
|
5c4b5359e0 | ||
|
|
8e3f56a3a2 | ||
|
|
91a837477a | ||
|
|
a2dfc54068 | ||
|
|
7ded2fe13a | ||
|
|
b6f1b27a81 | ||
|
|
621fd614ea | ||
|
|
be3e7c892c | ||
|
|
1f640b7644 | ||
|
|
987b505d32 | ||
|
|
4b2f23f093 | ||
|
|
1d52d0bafc | ||
|
|
e73db14976 | ||
|
|
fe8a677541 | ||
|
|
926cba8197 | ||
|
|
ee6e5db0a6 | ||
|
|
0c62d8dd07 | ||
|
|
d6e352b3b4 | ||
|
|
59e46be262 | ||
|
|
746c048550 | ||
|
|
a92c584997 | ||
|
|
7f4c6eb4ac | ||
|
|
fbeb048c44 | ||
|
|
9f748a8119 | ||
|
|
b9fd590095 | ||
|
|
430e210b3c | ||
|
|
706d54db76 | ||
|
|
9ac276767d | ||
|
|
29144348b3 | ||
|
|
2f91b11672 | ||
|
|
caf0ef88ac | ||
|
|
c8154db108 | ||
|
|
7ce6b5592a | ||
|
|
e1bc4fdf36 | ||
|
|
fd7f5f719f | ||
|
|
6678ca6c93 | ||
|
|
180e03e249 | ||
|
|
357f15eb01 | ||
|
|
a08704b60f | ||
|
|
03ba81a9c5 | ||
|
|
2933962df8 | ||
|
|
4f248c4dc7 | ||
|
|
14096f24ba | ||
|
|
c0b75accf4 | ||
|
|
cb1b7d5da7 | ||
|
|
c8072171f0 | ||
|
|
485f6d4cef | ||
|
|
2b85097e30 | ||
|
|
0904789291 | ||
|
|
fda69793a5 | ||
|
|
3c22aaf99d | ||
|
|
151a5d480f | ||
|
|
88d136626d | ||
|
|
170f5bba79 | ||
|
|
c4cbb0cd59 | ||
|
|
0fa04070f1 | ||
|
|
f8bea241a2 | ||
|
|
bb6b2e4b29 | ||
|
|
557251a679 | ||
|
|
696783b0fe | ||
|
|
6eb29d2cc9 | ||
|
|
4b4cafcda8 | ||
|
|
ed2ed8d968 | ||
|
|
fbb387bd9f | ||
|
|
0db2db482f | ||
|
|
af2fe727fc | ||
|
|
a7387dcf22 | ||
|
|
5ce44fb161 | ||
|
|
9086b9c3ca | ||
|
|
4837c5387a | ||
|
|
5d73216238 | ||
|
|
5053091e44 | ||
|
|
6319ed0473 | ||
|
|
c67c109af6 | ||
|
|
b3cdb1464b | ||
|
|
3c01c3f0ba | ||
|
|
07d541be20 | ||
|
|
4a0dc59585 | ||
|
|
b1dd8f52e8 | ||
|
|
6907fe230f | ||
|
|
f2e4071b90 | ||
|
|
452f5e5f83 | ||
|
|
c94b9f54ce | ||
|
|
e993f93cf4 | ||
|
|
e9fac38c1b | ||
|
|
31a49b8ff9 | ||
|
|
7831cdf10c | ||
|
|
c0f176f0af | ||
|
|
dc96a557eb | ||
|
|
7a8c915e62 | ||
|
|
dec42cc72b | ||
|
|
92c9d1d2ce | ||
|
|
de017fcd27 | ||
|
|
1229f62abd | ||
|
|
512852b817 | ||
|
|
5a087000a9 | ||
|
|
6b56d6649e | ||
|
|
5081aab497 | ||
|
|
bbb4afde53 | ||
|
|
d28495c3eb | ||
|
|
1785e0c4a3 | ||
|
|
1e93e75aac | ||
|
|
a3ed7eeee2 | ||
|
|
c3582637df | ||
|
|
3b277b0eb0 | ||
|
|
5e0991681f | ||
|
|
354fbb7cdd | ||
|
|
a166d06096 | ||
|
|
b8a6e07095 | ||
|
|
a8fba6e7b5 | ||
|
|
17a8c10f8c | ||
|
|
7ccd29faac | ||
|
|
d432e48cce | ||
|
|
19091319cc | ||
|
|
d29e12a92c | ||
|
|
5db03b0441 | ||
|
|
f8c7e2bf6d | ||
|
|
a7fdc6a88f | ||
|
|
4aaf5b0779 | ||
|
|
6150e4c736 | ||
|
|
9a3b4b3ecb | ||
|
|
cbaeb4d5f2 | ||
|
|
592c306aa0 | ||
|
|
136e6bddf4 | ||
|
|
0e8bef0541 | ||
|
|
9d8c52303e | ||
|
|
e6ae7df546 | ||
|
|
5b57a759be | ||
|
|
cc96eeae32 | ||
|
|
484fef1228 | ||
|
|
ba4ca11c83 | ||
|
|
9372902348 | ||
|
|
0cc9420570 | ||
|
|
18fa48d283 | ||
|
|
9034fedbd0 | ||
|
|
ec3b6ec5fa | ||
|
|
8cc2a4174e | ||
|
|
8a0014928d | ||
|
|
228ca7f9c0 | ||
|
|
c0fa7efb27 | ||
|
|
3553683bb1 | ||
|
|
ccb58e0a6c | ||
|
|
93253e2188 | ||
|
|
e34bcc9bbd | ||
|
|
72169e3a4d | ||
|
|
41c499840f | ||
|
|
f5cef170f0 | ||
|
|
d7922a7c9b | ||
|
|
23fc77e8e1 | ||
|
|
51f3eda09a | ||
|
|
6ec08a5227 | ||
|
|
4855f694cb | ||
|
|
eaef37a831 | ||
|
|
b182ff36bb | ||
|
|
c4e543449c | ||
|
|
c76d9d4461 | ||
|
|
dfd184724b | ||
|
|
fef254031e | ||
|
|
89c4e59bf1 | ||
|
|
2e9acd3276 | ||
|
|
5cab59c93f | ||
|
|
ebfb5878a1 | ||
|
|
de6b11aa22 | ||
|
|
9e7e7159e8 | ||
|
|
00c909271b | ||
|
|
7401a0cbec | ||
|
|
a9327d1774 | ||
|
|
9e99ef1348 | ||
|
|
5b4b9fdb01 | ||
|
|
d2998c4908 | ||
|
|
4ab968d563 | ||
|
|
9b26eea754 | ||
|
|
a6bd717971 | ||
|
|
f2914adb65 | ||
|
|
aa5a426aac | ||
|
|
fef8144187 | ||
|
|
d8a429d3b3 | ||
|
|
56e53b75a5 | ||
|
|
f89b6f5feb | ||
|
|
ec513e8893 | ||
|
|
35d6792d2e | ||
|
|
74387aae2d | ||
|
|
959043962d | ||
|
|
4efb71bafb | ||
|
|
6fd0bc0445 | ||
|
|
176a2eb392 | ||
|
|
1a85deb36e | ||
|
|
5b409ff3de | ||
|
|
a9e13d3a92 | ||
|
|
0698d8e3b1 | ||
|
|
8e4c496b54 | ||
|
|
27054b9722 | ||
|
|
bcad2c4998 | ||
|
|
aae2bd4884 | ||
|
|
006ef6f672 | ||
|
|
7be1a61347 | ||
|
|
1ef48f6cd6 | ||
|
|
a9a061a4bb | ||
|
|
14ed8b7af7 | ||
|
|
d17b8fa720 | ||
|
|
68980a69b5 | ||
|
|
636f14c450 | ||
|
|
b066bc37b3 | ||
|
|
9ac43fecf8 | ||
|
|
d6ff14167d | ||
|
|
5837a765f1 | ||
|
|
1bfb76a4b3 | ||
|
|
2a78a602e2 | ||
|
|
884b0e4226 | ||
|
|
4e819eb5d9 | ||
|
|
e3a50cc014 | ||
|
|
25ab8c9234 | ||
|
|
901e680fa4 | ||
|
|
82768fff59 | ||
|
|
87e3297904 | ||
|
|
81a4297eb1 | ||
|
|
17f5b52931 | ||
|
|
2250adf854 | ||
|
|
5cd46b3926 | ||
|
|
6e2b10b788 | ||
|
|
5e301ccaaf | ||
|
|
206a38efab | ||
|
|
cdf844be52 | ||
|
|
70cc28c191 | ||
|
|
35282fba6c | ||
|
|
e43f8e594d | ||
|
|
21988fab76 | ||
|
|
2f3823abe2 | ||
|
|
2c545e7b7f | ||
|
|
22f2200778 | ||
|
|
2f63253ec0 | ||
|
|
be7e8134f9 | ||
|
|
b85408e3e5 | ||
|
|
4828451f9e | ||
|
|
b3b50e1353 | ||
|
|
95e8bf2f55 | ||
|
|
cde7669c0b | ||
|
|
ff4a33c51c | ||
|
|
06cf6f84aa | ||
|
|
556f6f134f | ||
|
|
b1ab7ef118 | ||
|
|
e5fd108a9c | ||
|
|
5a67bf2417 | ||
|
|
cb020c1bbd | ||
|
|
bf75b29e33 | ||
|
|
d730fd9cab | ||
|
|
a862e5be7c | ||
|
|
ebca124c86 | ||
|
|
3b7803a81b | ||
|
|
b7b9d92148 | ||
|
|
44575fb19e | ||
|
|
f181a4b9cd | ||
|
|
77e5d8b0c2 | ||
|
|
edd9feb8f8 | ||
|
|
81d6a06dbe | ||
|
|
8afbc67bf7 | ||
|
|
a27132f907 | ||
|
|
183be05d82 | ||
|
|
bccf789714 | ||
|
|
55944dddb3 | ||
|
|
f67932cc56 | ||
|
|
6d633fac6a | ||
|
|
86fc5c51c8 | ||
|
|
156e9f07ad | ||
|
|
1ba4722fc7 | ||
|
|
54c9857219 | ||
|
|
ea56c7d0d2 | ||
|
|
0cbe43df97 | ||
|
|
1f941d883a | ||
|
|
f5b3e423fb | ||
|
|
6c7f81ca55 | ||
|
|
3911b5ed82 | ||
|
|
f38f3ab69c | ||
|
|
846db6f063 | ||
|
|
ff068a05b0 | ||
|
|
051b7dd182 | ||
|
|
11870aeed6 | ||
|
|
9bcff82d9c | ||
|
|
309efe8cd8 | ||
|
|
bf54789f0f | ||
|
|
01e527abdb | ||
|
|
db6b558c75 | ||
|
|
9a792eb144 | ||
|
|
44e99664a3 | ||
|
|
9f3dd37bf0 | ||
|
|
f5936d9cb7 | ||
|
|
27e69ef022 | ||
|
|
6262aab6bd | ||
|
|
4781bc8eb7 | ||
|
|
b233c4b638 | ||
|
|
0a0cc807dc | ||
|
|
feeeb63e52 | ||
|
|
5c620d6268 | ||
|
|
a469000d7a | ||
|
|
0e15ac78b2 | ||
|
|
d9e195ccd0 | ||
|
|
cf52997279 | ||
|
|
88318a7151 | ||
|
|
91f522b666 | ||
|
|
1895f8815e | ||
|
|
7be5f52be4 | ||
|
|
0cfb2e4e06 | ||
|
|
5ccf753af3 | ||
|
|
bfcf3cac91 | ||
|
|
bc3d7bc278 | ||
|
|
7cf767f344 | ||
|
|
7aed9a2c89 | ||
|
|
454196a462 | ||
|
|
1597ba7128 | ||
|
|
480523ff27 | ||
|
|
7ec7ab8682 | ||
|
|
ba2d011d48 | ||
|
|
504e6cd1cc | ||
|
|
b8f3700fe4 | ||
|
|
b2cff862bb | ||
|
|
dc348f8500 | ||
|
|
8c40293fed | ||
|
|
48deaf3aca | ||
|
|
6932643788 | ||
|
|
7f972e3d68 | ||
|
|
edb0880999 | ||
|
|
45f0f5cd6c | ||
|
|
e468ac1933 | ||
|
|
55b6b40acf | ||
|
|
5f1190f72e | ||
|
|
b0fbd6507d | ||
|
|
598a664d30 | ||
|
|
211f0a667d | ||
|
|
28fb788778 | ||
|
|
628830fbf5 | ||
|
|
7d235d0077 | ||
|
|
861b0b6cef | ||
|
|
9986c57727 | ||
|
|
f1c9e2331c | ||
|
|
7c1ddc6ab1 | ||
|
|
44ad78761b | ||
|
|
bd6925f2f1 | ||
|
|
3838d74cb8 | ||
|
|
eaad8beb7b | ||
|
|
14acdfdbc3 | ||
|
|
a5fe7a5b40 | ||
|
|
61df3c55b5 | ||
|
|
eb0059c1a3 | ||
|
|
4ca5038ae9 | ||
|
|
121403231a | ||
|
|
b945338a8d | ||
|
|
ae5ea542a0 | ||
|
|
fe95dc8201 | ||
|
|
1eefb4e610 | ||
|
|
8660d8d990 | ||
|
|
37033fe48d | ||
|
|
30665ad8c6 | ||
|
|
f9e4b8db76 | ||
|
|
c486a210e4 | ||
|
|
0cd01959a0 | ||
|
|
d5ac9f7920 | ||
|
|
6b2dd112a6 | ||
|
|
01abfab133 | ||
|
|
e2a56872dc | ||
|
|
6f22a9c4bc | ||
|
|
a2426de70c | ||
|
|
ed7bbf54a7 | ||
|
|
69394377d0 | ||
|
|
8f20487a15 | ||
|
|
fae24db2df | ||
|
|
f8fb791d8f | ||
|
|
f320d9e1e5 | ||
|
|
18bd34fad2 | ||
|
|
cf72d0b36a | ||
|
|
c3722b0a6c | ||
|
|
3af701e803 | ||
|
|
bc4b2e89db | ||
|
|
3cbb589d2c | ||
|
|
63ef93a9f9 | ||
|
|
8c943d2c01 | ||
|
|
806b77acce | ||
|
|
3df0414621 | ||
|
|
04f70b0499 | ||
|
|
0b20087e61 | ||
|
|
5c82600972 | ||
|
|
45edd86cb8 | ||
|
|
8f6b3fa00d | ||
|
|
a16bcda7da | ||
|
|
259b29f6e3 | ||
|
|
477868c601 | ||
|
|
92de963c0c | ||
|
|
a7c56d9e77 | ||
|
|
4fe64eeb44 | ||
|
|
fc0d020a04 | ||
|
|
617e2c9885 | ||
|
|
bb1130490b | ||
|
|
ca18a323e3 | ||
|
|
0770c6e4a1 | ||
|
|
e1dbfe8f6a | ||
|
|
a2854069ac | ||
|
|
9f0efc2bda | ||
|
|
ec5798f264 | ||
|
|
ded20441fa | ||
|
|
47064dbcec | ||
|
|
2cda7ecb04 | ||
|
|
b372892a20 | ||
|
|
fabf62059e | ||
|
|
c524c68809 | ||
|
|
876fd425e4 | ||
|
|
72ed1293f6 | ||
|
|
fa973a9231 | ||
|
|
e245a8f124 | ||
|
|
aa71fa7cb8 | ||
|
|
da5aab3ee6 | ||
|
|
e0317d1fe1 | ||
|
|
3557a0ebc1 | ||
|
|
ddd0cc4538 | ||
|
|
0212ec51cc | ||
|
|
7109e30d93 | ||
|
|
6990819d5c | ||
|
|
b4ff754934 | ||
|
|
6ece644a7b | ||
|
|
f826b4d0bc | ||
|
|
aa1f82d46f | ||
|
|
f7c6d67428 | ||
|
|
cd30d6df31 | ||
|
|
7463792de7 | ||
|
|
80f49c47c6 | ||
|
|
4baead3490 | ||
|
|
2d0c69344a | ||
|
|
a94ea2b332 | ||
|
|
4ee50a6582 | ||
|
|
b21021bd6b | ||
|
|
7238fe0b6b | ||
|
|
e1b5c176c3 | ||
|
|
3aabc089d8 | ||
|
|
db5177027f | ||
|
|
0e2da1b983 | ||
|
|
1583006018 | ||
|
|
6b49c2842c | ||
|
|
9c4a5dc818 | ||
|
|
8256658ac2 | ||
|
|
4b11ff495d | ||
|
|
461dc925af | ||
|
|
1233b1d11c | ||
|
|
6dbc0b3891 | ||
|
|
db3cef9bb6 | ||
|
|
3de009727e | ||
|
|
8d35515497 | ||
|
|
4519dd5eb8 | ||
|
|
925e6847f3 | ||
|
|
9462cbc7e0 | ||
|
|
8ec4271419 | ||
|
|
173fd250cb | ||
|
|
89bdc1e496 | ||
|
|
48736d3f4a | ||
|
|
f8df60f06b | ||
|
|
9bd0ed03a5 | ||
|
|
cb1e4bcdb7 | ||
|
|
af8e6a63b9 | ||
|
|
8c8cd709b5 | ||
|
|
18ae566d34 | ||
|
|
9cfa44d434 | ||
|
|
23393d9157 | ||
|
|
b676e00f0b | ||
|
|
790200e519 | ||
|
|
ccde99e695 | ||
|
|
a80f8082cc | ||
|
|
4b194627bb | ||
|
|
d983c66597 | ||
|
|
30f6b57941 | ||
|
|
107979c459 | ||
|
|
f05f09d741 | ||
|
|
bc989f2fb0 | ||
|
|
9b4494a24f | ||
|
|
d3fafa7b9a | ||
|
|
ce1e85e0a3 | ||
|
|
560df5cade | ||
|
|
9f6e361e6e | ||
|
|
00be4a856f | ||
|
|
606aec4ec1 | ||
|
|
7f0f211333 | ||
|
|
42f761d44d | ||
|
|
577b5b108f | ||
|
|
4d39b32cf6 | ||
|
|
8279ed31d1 | ||
|
|
0185d0c730 | ||
|
|
4ac1674cc0 | ||
|
|
1c222a36ee | ||
|
|
16e05e0320 | ||
|
|
8ea64e7aba | ||
|
|
c22140103f | ||
|
|
8bd6e40ac8 | ||
|
|
2ed25c6991 | ||
|
|
d8991ec016 | ||
|
|
dc9ca1e63f | ||
|
|
7bb3203dfb | ||
|
|
8ebe9548f7 | ||
|
|
f90f20d3a8 | ||
|
|
1437e3b323 | ||
|
|
d44171de61 | ||
|
|
62a9e413fb | ||
|
|
c12c48dea6 | ||
|
|
7dd81525e4 | ||
|
|
ca36038bbd | ||
|
|
ca2f674696 | ||
|
|
8acf9b817f | ||
|
|
2dc1fbde96 | ||
|
|
919651a2b3 | ||
|
|
19b55a574f | ||
|
|
a6ab7de475 | ||
|
|
2ff229e9d9 | ||
|
|
18def7c624 | ||
|
|
59a731df88 | ||
|
|
6186356496 | ||
|
|
045ee091a7 | ||
|
|
a69d985139 | ||
|
|
c13641dd1d | ||
|
|
f0fc5d6598 | ||
|
|
2348039c16 | ||
|
|
7f8d34e8a0 | ||
|
|
205036b658 | ||
|
|
9519896d04 | ||
|
|
aa83b63617 | ||
|
|
3e89a372b3 | ||
|
|
d464695b66 | ||
|
|
657532f7e5 | ||
|
|
3f69308603 | ||
|
|
486160fc57 | ||
|
|
3939e0760f | ||
|
|
16624a9596 | ||
|
|
58e075e6ff | ||
|
|
ef081714d7 | ||
|
|
96802efa45 | ||
|
|
0a95f3198b | ||
|
|
cb44758036 | ||
|
|
1682c321d3 | ||
|
|
eeba8a5de7 | ||
|
|
2ea0f58e03 | ||
|
|
05235473c1 | ||
|
|
f0c083f4e6 | ||
|
|
6997c9a5c0 | ||
|
|
eebfa23509 | ||
|
|
59fe8a021f | ||
|
|
16672d9b89 | ||
|
|
1d39fd8685 | ||
|
|
ae41bdb7f8 | ||
|
|
4147f1056a | ||
|
|
7c5d08b723 | ||
|
|
a3b5a226ac | ||
|
|
f56cee9ec1 | ||
|
|
3b977535f1 | ||
|
|
ce8d98b77d | ||
|
|
2858d0b0a4 | ||
|
|
1f982566e0 | ||
|
|
779ec5b2fe | ||
|
|
8499921d67 | ||
|
|
1e49bad1a6 | ||
|
|
1d3a61386d | ||
|
|
25ef2ca220 | ||
|
|
b953385bc5 | ||
|
|
4fdedd0a7b | ||
|
|
f4bc43e7a5 | ||
|
|
596c75eeca | ||
|
|
67a493ee84 | ||
|
|
f9c7d9419e | ||
|
|
1a1a006283 | ||
|
|
fd85ce0923 | ||
|
|
5ff9069ff2 | ||
|
|
4ad7ff7971 | ||
|
|
a9f98763c4 | ||
|
|
3b637fad78 | ||
|
|
f202797964 | ||
|
|
242d780048 | ||
|
|
bf23364097 | ||
|
|
7eaac7a20b | ||
|
|
45448e6f53 | ||
|
|
08ee458a27 | ||
|
|
3f97541956 | ||
|
|
e2c603338e | ||
|
|
a363623df9 | ||
|
|
b871573dc3 | ||
|
|
ad33c1ca3c | ||
|
|
810cb284b6 | ||
|
|
d0ffb25594 | ||
|
|
2b6796d1d1 | ||
|
|
52093f3dd3 | ||
|
|
2a5c1ac92c | ||
|
|
6e0222f5e2 | ||
|
|
4bebf79266 | ||
|
|
b6dadc142b | ||
|
|
1cbc49251b | ||
|
|
d2d5b5863b | ||
|
|
65f9203597 | ||
|
|
4c1926e395 | ||
|
|
516d937149 | ||
|
|
7af17c3c65 | ||
|
|
33b85207f5 | ||
|
|
218119e10e | ||
|
|
4485d3d5a9 | ||
|
|
fcf62a31e1 | ||
|
|
ebdc83809c | ||
|
|
61a3c30a45 | ||
|
|
0e4cab7221 | ||
|
|
865c90a85a | ||
|
|
c9b06a4fa8 | ||
|
|
0e75143a42 | ||
|
|
ce333c5793 | ||
|
|
6b4045db45 | ||
|
|
3fba704c77 | ||
|
|
0712a80ea0 | ||
|
|
8969c44b3f | ||
|
|
f7a3c0e6c6 | ||
|
|
b1852a1de6 | ||
|
|
5645fa0168 | ||
|
|
c824b2e0b4 | ||
|
|
1c0d2b2f95 | ||
|
|
10b8ab297a | ||
|
|
e8b0e475d7 | ||
|
|
7fc4a6425b | ||
|
|
a8a3c48e6c | ||
|
|
9fca69302b | ||
|
|
ba6811224e | ||
|
|
ca4a682794 | ||
|
|
b9ddcfc3d7 | ||
|
|
b20cb1c0a0 | ||
|
|
1d9813691c | ||
|
|
08f8954e03 | ||
|
|
610f04ab87 | ||
|
|
793cac09cb | ||
|
|
d0d07604e5 | ||
|
|
fcf6d087a7 | ||
|
|
35587ccb85 | ||
|
|
9df5b6cc33 | ||
|
|
ffeedf576d | ||
|
|
151ce216ab | ||
|
|
20835f9858 | ||
|
|
63a61f2fb5 | ||
|
|
c553248cf4 | ||
|
|
cdd1dc68da | ||
|
|
37af3c1498 | ||
|
|
1bc3847345 | ||
|
|
f14d8ab5f6 | ||
|
|
bb63b98f39 | ||
|
|
f3f7e2d3c1 | ||
|
|
89121cfc57 | ||
|
|
d8a41a5ee1 | ||
|
|
f8ca9355d2 | ||
|
|
d4bceb1922 | ||
|
|
876d85ac4e | ||
|
|
ab34930beb | ||
|
|
35f7450ab2 | ||
|
|
2917ff6701 | ||
|
|
d1656b25c9 | ||
|
|
e6a20866b6 | ||
|
|
9de065d31a | ||
|
|
37d27e07e9 | ||
|
|
01853768db | ||
|
|
9d3787dfc2 | ||
|
|
e9f145056d | ||
|
|
ea17943bff | ||
|
|
180c32ef50 | ||
|
|
17bb844360 | ||
|
|
3d0a161176 | ||
|
|
1148867d3c | ||
|
|
c83d01e977 | ||
|
|
7c42d6f857 | ||
|
|
ac1c6bc74b | ||
|
|
12f96bb95c | ||
|
|
fa063a05f7 | ||
|
|
51d10d3234 | ||
|
|
2d2db15813 | ||
|
|
006c782819 | ||
|
|
37e36fb886 | ||
|
|
0e026a8b3b | ||
|
|
f37daa5ca6 | ||
|
|
dafcf7049b | ||
|
|
207da3fcd9 | ||
|
|
a3fbe5d747 | ||
|
|
c1717c71bd | ||
|
|
bcd111f585 | ||
|
|
d6f1113201 | ||
|
|
e812d2a074 | ||
|
|
a537306307 | ||
|
|
206889bdc5 | ||
|
|
58c7b5c818 | ||
|
|
eace561f73 | ||
|
|
e2032cdc74 | ||
|
|
34bc8e3a3c | ||
|
|
1304611ab7 | ||
|
|
7a0ce4b5d6 | ||
|
|
835df33e11 | ||
|
|
fb80c3606b | ||
|
|
f0c80693bb | ||
|
|
6997c2f2b9 | ||
|
|
cb1057cd5e | ||
|
|
eb1e2de917 | ||
|
|
4b9b66e7d0 | ||
|
|
c1e87ace78 | ||
|
|
ba9eb9c023 | ||
|
|
3084d4ad54 | ||
|
|
fcb13c19a1 | ||
|
|
d6b81d0363 | ||
|
|
fdd1135a66 | ||
|
|
f9ce439e56 | ||
|
|
9608d1e736 | ||
|
|
776d7fbbd9 | ||
|
|
7c69c24362 | ||
|
|
d205d48166 | ||
|
|
dd32aec462 | ||
|
|
c0327fe733 | ||
|
|
6f4c40f450 | ||
|
|
022ee6cd95 | ||
|
|
085e04c9ba | ||
|
|
19f58acb79 | ||
|
|
90dd60b942 | ||
|
|
755bfeaa5b | ||
|
|
82ee2f6b0a | ||
|
|
500d03f293 | ||
|
|
ee99abe6ff | ||
|
|
0563006c55 | ||
|
|
31db6fa4fb | ||
|
|
043b543cfa | ||
|
|
7b52599da7 | ||
|
|
4dc8e5619c | ||
|
|
21ff752322 | ||
|
|
0f687d6e95 | ||
|
|
22e23efbdc | ||
|
|
38935937ae | ||
|
|
a3685e2e83 | ||
|
|
3a5e391191 | ||
|
|
09a9dd53fd | ||
|
|
5e064249be | ||
|
|
67555512e7 | ||
|
|
591df6439c | ||
|
|
7dfb7dfe24 | ||
|
|
8e56f137b6 | ||
|
|
3b61c73c17 | ||
|
|
44dac98b37 | ||
|
|
1a7f98379a | ||
|
|
4109ef0612 | ||
|
|
93a9bf6c5b | ||
|
|
0b7b35cdcc | ||
|
|
350ef86dd6 | ||
|
|
2d69ae2e42 | ||
|
|
e95367f4b2 | ||
|
|
3101911aa2 | ||
|
|
ac73087f93 | ||
|
|
d375a3bbbb | ||
|
|
c46ca1d4c2 | ||
|
|
2a1cca8ebb | ||
|
|
d1fdc989b6 | ||
|
|
672215f753 | ||
|
|
4160175fcf | ||
|
|
8f8ba55fc9 | ||
|
|
1dbb4aa837 | ||
|
|
c183c4f17d | ||
|
|
fa6d14d89a | ||
|
|
65b92b9da3 | ||
|
|
a7056c4601 | ||
|
|
1dce0f7859 | ||
|
|
bdffbfab67 | ||
|
|
98b21d0fdf | ||
|
|
cccea70db1 | ||
|
|
d2bcd0bc9f | ||
|
|
08653fd3b6 | ||
|
|
75d0671d9b | ||
|
|
51ec3c32a9 | ||
|
|
ec0032c5ab | ||
|
|
2723f3662c | ||
|
|
539b050b97 | ||
|
|
a0b9623a9f | ||
|
|
6b263418a0 | ||
|
|
92989ce9fd | ||
|
|
173925b57a | ||
|
|
43735722bf | ||
|
|
d89e7aebec | ||
|
|
4677d789f2 | ||
|
|
2fb445746e | ||
|
|
505dfef48c | ||
|
|
19a9a8ef83 | ||
|
|
119730bada | ||
|
|
c46748524a | ||
|
|
29f833db41 | ||
|
|
1232856b21 | ||
|
|
770ae6ebd0 | ||
|
|
8c9ced0bda | ||
|
|
3b3dd3df99 | ||
|
|
0817e6233d | ||
|
|
aa4f428194 | ||
|
|
73717dec73 | ||
|
|
57e2ef3bab | ||
|
|
a5d0b8db8e | ||
|
|
3faec79371 | ||
|
|
c3e0520aec | ||
|
|
76db0b6fb4 | ||
|
|
40a8473ce0 | ||
|
|
21c1d104b8 | ||
|
|
0dda861863 | ||
|
|
b21f2f7166 | ||
|
|
e533170160 | ||
|
|
8236874779 | ||
|
|
4cc1dc2d1b | ||
|
|
18424bea7c | ||
|
|
0cc6251c0d | ||
|
|
63d87be789 | ||
|
|
7e3b898383 | ||
|
|
217fa62004 | ||
|
|
e667fb8708 | ||
|
|
2fef6f51b5 | ||
|
|
81bba8595a | ||
|
|
96aefc3938 | ||
|
|
5bb0493f02 | ||
|
|
e8fa6b8b07 | ||
|
|
ec15178ba7 | ||
|
|
1d469a40d5 | ||
|
|
4df30a56a3 | ||
|
|
6bc1e407d5 | ||
|
|
48442330c1 | ||
|
|
3623a88b16 | ||
|
|
ffca19edab | ||
|
|
52a8a9de6f | ||
|
|
b9e303196f | ||
|
|
da3a7e12bd | ||
|
|
21013bde98 | ||
|
|
ae6d83c675 | ||
|
|
f932e24573 | ||
|
|
a588ec9d18 | ||
|
|
bc23211f23 | ||
|
|
78ebf39624 | ||
|
|
bbc2ab5f17 | ||
|
|
2ffe1e9112 | ||
|
|
1036733fcb | ||
|
|
ebd5555955 | ||
|
|
83199cf3aa | ||
|
|
c724be743d | ||
|
|
42ba65e21b | ||
|
|
3405c1c45a | ||
|
|
5cb6608e17 | ||
|
|
aa891ad3fa | ||
|
|
158bda52a8 | ||
|
|
57e5ea87d8 | ||
|
|
74486f65cf | ||
|
|
27fcb63601 | ||
|
|
8d83d6be2f | ||
|
|
d31e67e598 | ||
|
|
629d3c1fa8 | ||
|
|
193d6efa67 | ||
|
|
c70dbd219c | ||
|
|
da289073e2 | ||
|
|
5aad22f254 | ||
|
|
815c8f97d0 | ||
|
|
7123fc7e37 | ||
|
|
fee3d9c145 | ||
|
|
6808e6e1b4 | ||
|
|
12f25a308a | ||
|
|
7fe401faa8 | ||
|
|
182fb7c783 | ||
|
|
c06b53afef | ||
|
|
65a5b53b88 | ||
|
|
e8503e97e3 | ||
|
|
f9a914926e | ||
|
|
8d4d6c7e5e | ||
|
|
dbb681e8a6 | ||
|
|
f0d7b38a73 | ||
|
|
70da534bfb | ||
|
|
308ec05405 | ||
|
|
5fe5e8a304 | ||
|
|
b02789b560 | ||
|
|
7e98064e09 | ||
|
|
eaada5667e | ||
|
|
b83ca94d98 | ||
|
|
bd88c68208 | ||
|
|
6e0b754a66 | ||
|
|
94abf34466 | ||
|
|
91396c8885 | ||
|
|
cb3cfa054b | ||
|
|
ebf58d4b73 | ||
|
|
f704cddae8 | ||
|
|
f03d2f3940 | ||
|
|
087c6c0298 | ||
|
|
be49ba83b3 | ||
|
|
843c77e9ba | ||
|
|
6cd117ded0 | ||
|
|
6c1da554f0 | ||
|
|
bbc96a83d7 | ||
|
|
0bffc38be4 | ||
|
|
4bce4b2dd1 | ||
|
|
95fa96e883 | ||
|
|
99a5960794 | ||
|
|
aab28717c6 | ||
|
|
763b0a0a47 | ||
|
|
3b1bef9c3d | ||
|
|
c83c4079cf | ||
|
|
ae46b57ea1 | ||
|
|
0529dcf0ef | ||
|
|
3ae333e047 | ||
|
|
bc7b84115a | ||
|
|
f3ddff720f | ||
|
|
8233950bad | ||
|
|
2f902837f6 | ||
|
|
6bd80b8ebd | ||
|
|
733529cf78 | ||
|
|
b36cd30987 | ||
|
|
5a9a566694 | ||
|
|
9665f6cb3f | ||
|
|
f790165358 | ||
|
|
7e2912d5d1 | ||
|
|
c8e7e19934 | ||
|
|
d7f3e3ed79 | ||
|
|
6dfa1efa5d | ||
|
|
3d5f72a64c | ||
|
|
a32658ea61 | ||
|
|
d142234af4 | ||
|
|
b60a6c7d0c | ||
|
|
3077f3c053 | ||
|
|
f762d5ea00 | ||
|
|
060e167dc7 | ||
|
|
47aa6213bf | ||
|
|
e1ecea5f79 | ||
|
|
b1d1e1e7b9 | ||
|
|
fe00ef8cfa | ||
|
|
3a3c9e5018 | ||
|
|
bf6714f231 | ||
|
|
b4e0e6fa0f | ||
|
|
332bbfc0bc | ||
|
|
ee666601d6 | ||
|
|
c7d4c63725 | ||
|
|
39141d54a4 | ||
|
|
35f9bb3758 | ||
|
|
0648c9785c | ||
|
|
b5666ef48e | ||
|
|
f3184bc08d | ||
|
|
4804cfa5a2 | ||
|
|
820daa7b1e | ||
|
|
529345da9c | ||
|
|
c251a7bf53 | ||
|
|
06d7804fe7 | ||
|
|
d31dc14271 | ||
|
|
adceba0d86 | ||
|
|
fb8ba1d66b | ||
|
|
e61ecd683c | ||
|
|
77bc391f6e | ||
|
|
ebeac37f21 | ||
|
|
ac4d8429d4 | ||
|
|
ceb9455250 | ||
|
|
736f645e9d | ||
|
|
5c8aa92792 | ||
|
|
7ac9d34cc4 | ||
|
|
5b8fd14d09 | ||
|
|
4776da4584 | ||
|
|
c10cb49c30 | ||
|
|
9f0d93bca2 | ||
|
|
59c6fe593a | ||
|
|
63f3b3861e | ||
|
|
433b0ae4c1 | ||
|
|
452b39075b | ||
|
|
1001a52a53 | ||
|
|
10c79456a5 | ||
|
|
d0b55bb9dd | ||
|
|
bf4aa59467 | ||
|
|
a402d91367 | ||
|
|
928719f5a1 | ||
|
|
33b00f369f | ||
|
|
6994b27656 | ||
|
|
d46a474364 | ||
|
|
0a5178e0a4 | ||
|
|
34e6cde781 | ||
|
|
9ea8e46a56 | ||
|
|
0e47191b65 | ||
|
|
c875d2beea | ||
|
|
997393bd27 | ||
|
|
f2fdad9f5a | ||
|
|
2552f7dbf4 | ||
|
|
0568a5da10 | ||
|
|
98a92afb95 | ||
|
|
c7d2a06147 | ||
|
|
ab7e86218d | ||
|
|
3005ee5b02 | ||
|
|
60c29b2d12 | ||
|
|
bf5feae717 | ||
|
|
f0fd1eaf22 | ||
|
|
1d2960a51c | ||
|
|
a094d1c2ba | ||
|
|
72fa62622f | ||
|
|
cd6534097e | ||
|
|
c3ad22ab27 | ||
|
|
0a0ab96f41 | ||
|
|
4308d7637c | ||
|
|
7d5d74eb62 | ||
|
|
a745f424ad | ||
|
|
220483c914 | ||
|
|
4abd3803a3 | ||
|
|
8147cd26dc | ||
|
|
28b9d0b18f | ||
|
|
81ccf8e4f5 | ||
|
|
93ee86520b | ||
|
|
2900b4b616 | ||
|
|
5af9959408 | ||
|
|
867e2143f2 | ||
|
|
b25cfc1345 | ||
|
|
370933df1d | ||
|
|
421c2028ca | ||
|
|
16bef14df4 | ||
|
|
5c39449715 | ||
|
|
f4375cb6c4 | ||
|
|
173626a638 | ||
|
|
b767f5500a | ||
|
|
a861a1d169 | ||
|
|
9ea41412ad | ||
|
|
ef1981934b | ||
|
|
b71d5de503 | ||
|
|
1989d4a61f | ||
|
|
c7a4d228ef | ||
|
|
80265d6513 | ||
|
|
70a970679f | ||
|
|
26f51dae86 | ||
|
|
a0da37d53b | ||
|
|
fcc92b698f | ||
|
|
1f063d686a | ||
|
|
c3c82e0022 | ||
|
|
4d4428047a | ||
|
|
ba78d521f5 | ||
|
|
9f99c063f0 | ||
|
|
43cd33156b | ||
|
|
c53c644a8c | ||
|
|
178b55ad52 | ||
|
|
932abcbdb6 | ||
|
|
3814d17926 | ||
|
|
58bc1758ec | ||
|
|
bf78603d19 | ||
|
|
ce406d8f55 | ||
|
|
e477e0b452 | ||
|
|
541c0d1bca | ||
|
|
fd64016e19 | ||
|
|
40f1b1c618 | ||
|
|
728e215ce9 | ||
|
|
b6533472c8 | ||
|
|
0d1da0877a | ||
|
|
1675a4446f | ||
|
|
e9ace4f3ed | ||
|
|
36ca320922 | ||
|
|
bda336dff5 | ||
|
|
f8e150786a | ||
|
|
d48110719f | ||
|
|
62ff4f4860 | ||
|
|
987f29fc65 | ||
|
|
a94e4e2968 | ||
|
|
41d83a3756 | ||
|
|
14b13fe9f3 | ||
|
|
77631a1342 | ||
|
|
fa3b0d770e | ||
|
|
d78b9d762f | ||
|
|
36a7dce1e9 | ||
|
|
a966dfac45 | ||
|
|
fa1bde2ed1 | ||
|
|
76c29042c8 | ||
|
|
a315afff9e | ||
|
|
116151efa9 | ||
|
|
aa9fa3af32 | ||
|
|
a439ffcc95 | ||
|
|
3aee9e355e | ||
|
|
bb58647b3e | ||
|
|
56e90f1c1e | ||
|
|
420f47a579 | ||
|
|
e99b80535a | ||
|
|
5bee890980 | ||
|
|
760e6334cd | ||
|
|
eb08d29e3d | ||
|
|
098e81d1c8 | ||
|
|
f8ccb467ba | ||
|
|
5a327a550f | ||
|
|
60dbd0d579 | ||
|
|
0ec54015e9 | ||
|
|
956c741c38 | ||
|
|
3b8df7f14a | ||
|
|
08b0cca9e4 | ||
|
|
80a839d60a | ||
|
|
6fb46706b5 | ||
|
|
67b070fefd | ||
|
|
e81e596029 | ||
|
|
18a96027f0 | ||
|
|
1eda0471bf | ||
|
|
f827b55883 | ||
|
|
738ff299ab | ||
|
|
65988c48a8 | ||
|
|
4d3a47820b | ||
|
|
24f723ed8e | ||
|
|
f7f6e06a9c | ||
|
|
e4ef5dded0 | ||
|
|
87ca7201bf | ||
|
|
bea8607a9f | ||
|
|
5a6c1e36e5 | ||
|
|
5db41b6598 | ||
|
|
fde6e9c278 | ||
|
|
b12147c598 | ||
|
|
2978063cb9 | ||
|
|
5a76a15e18 | ||
|
|
7132ac39ab | ||
|
|
8fd271f936 | ||
|
|
86eed1fc3c | ||
|
|
bcae07c9ac | ||
|
|
87d70a54f1 | ||
|
|
50994b75ae | ||
|
|
1a3a77c437 | ||
|
|
ef02a0c282 | ||
|
|
98f6d04431 | ||
|
|
5badee55e0 | ||
|
|
f9f7fa08fb | ||
|
|
f9995c76bb | ||
|
|
697c9078a6 | ||
|
|
04593e2147 | ||
|
|
a4e2389e69 | ||
|
|
564997fd1b | ||
|
|
4f738fda9a | ||
|
|
c3ff3f2b49 | ||
|
|
574d814c37 | ||
|
|
d69cea6399 | ||
|
|
15db2a2a6d | ||
|
|
66a8457a22 | ||
|
|
2453c54e56 | ||
|
|
b3c7580932 | ||
|
|
e4b23d16db | ||
|
|
66d43f2f86 | ||
|
|
3db97f9abd | ||
|
|
d29105f525 | ||
|
|
018039f15b | ||
|
|
560950f19f | ||
|
|
56a7a06e72 | ||
|
|
30eb5d5cef | ||
|
|
459683d3e8 | ||
|
|
792f866f93 | ||
|
|
01595010ae | ||
|
|
74305f7759 | ||
|
|
321c625f07 | ||
|
|
4fe22854be | ||
|
|
5fd814d1d3 | ||
|
|
533f4a73f2 | ||
|
|
35cff80260 | ||
|
|
8831168dcd | ||
|
|
439c52a400 | ||
|
|
0e8c7087a1 | ||
|
|
554306decd | ||
|
|
bb2bf05dbe | ||
|
|
16cca0da3e | ||
|
|
018c37018f | ||
|
|
754057f3c2 | ||
|
|
686c946d50 | ||
|
|
d2eea32985 | ||
|
|
164f441b29 | ||
|
|
d3b1bcb3d5 | ||
|
|
c1a9236d1d | ||
|
|
2a2ccc67fe | ||
|
|
e323e32f64 | ||
|
|
445d2e96ce | ||
|
|
cda7bec982 | ||
|
|
5d490be15b | ||
|
|
d9221585e1 | ||
|
|
3d3da9a495 | ||
|
|
4bd2d8f8c5 | ||
|
|
0d3dbbc8eb | ||
|
|
85dc473821 | ||
|
|
16b91d4e9d | ||
|
|
90e0886161 | ||
|
|
5440a84dbc | ||
|
|
244f517e58 | ||
|
|
747866084c | ||
|
|
eb1e7d0c44 | ||
|
|
e796468cd7 | ||
|
|
d06f161461 | ||
|
|
6f00c6c5cb | ||
|
|
285979675d | ||
|
|
8a46eed299 | ||
|
|
42b62f0463 | ||
|
|
84b0525f74 | ||
|
|
0ba5aedd2d | ||
|
|
faa3efaea2 | ||
|
|
f8746dcc0c | ||
|
|
2f0510f9df | ||
|
|
3e3e200e4f | ||
|
|
f911b71eee | ||
|
|
352fd2eb79 | ||
|
|
08b2102528 | ||
|
|
c199a0ac6d | ||
|
|
6b604d8b9f | ||
|
|
be9f4293fd | ||
|
|
e2c5905d0a | ||
|
|
36e338e9dd | ||
|
|
eb901a2f73 | ||
|
|
98b4a6af28 | ||
|
|
35ae11b991 | ||
|
|
580fd16ceb | ||
|
|
b25fe2d233 | ||
|
|
77b473f0a7 | ||
|
|
99581fcbc6 | ||
|
|
5e6061887e | ||
|
|
007cb50af8 | ||
|
|
8451ed7dfe | ||
|
|
8e401d6bb6 | ||
|
|
6f437cda85 | ||
|
|
d1beead157 | ||
|
|
3058badffa | ||
|
|
3e9605d484 | ||
|
|
ef95ecb415 | ||
|
|
8a6587752a | ||
|
|
8593557c47 | ||
|
|
f190316c07 | ||
|
|
f780325928 | ||
|
|
444a5c7bef | ||
|
|
f49026e307 | ||
|
|
80dfa69be0 | ||
|
|
dbbeac9238 | ||
|
|
fc86c213be | ||
|
|
d535d753c3 | ||
|
|
4f7d84f60f | ||
|
|
71bbea658a | ||
|
|
7421fcb5a4 | ||
|
|
d3d2dfcb2b | ||
|
|
117225fb72 | ||
|
|
40f1b730ca | ||
|
|
360d45d70e | ||
|
|
1b9b7c5f65 | ||
|
|
7a3aa751e3 | ||
|
|
12afb66114 | ||
|
|
4252548f4c | ||
|
|
b039b1305e | ||
|
|
b55c792406 | ||
|
|
fedb186064 | ||
|
|
96786aebe6 | ||
|
|
a9e516d7b9 | ||
|
|
26c7719f12 | ||
|
|
5d5c13a7e6 | ||
|
|
3268a056bc | ||
|
|
2f2e915066 | ||
|
|
9160f83449 | ||
|
|
710e3e4c01 | ||
|
|
392d2f1911 | ||
|
|
3275eab800 | ||
|
|
53d89cd56c | ||
|
|
f221696337 | ||
|
|
b6ff8865a3 | ||
|
|
35cd742f03 | ||
|
|
a90ac2f466 | ||
|
|
699ca04e0f | ||
|
|
e060f8557e | ||
|
|
5ea7de3c13 | ||
|
|
cdf8ff4066 | ||
|
|
a8c3cf96b8 | ||
|
|
bdc89a458e | ||
|
|
fafd95098c | ||
|
|
78cd9e2f9b | ||
|
|
0a57f3d78f | ||
|
|
9c38029607 | ||
|
|
2400ffe4d5 | ||
|
|
8d37d3adc5 | ||
|
|
e2a7f01e1b | ||
|
|
1cf005a394 | ||
|
|
66ff92e064 | ||
|
|
67622a7668 | ||
|
|
7dfbf3b527 | ||
|
|
16e82a0df5 | ||
|
|
5144fe629e | ||
|
|
97b66acf1d |
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.pb linguist-language=go
|
||||
42
.github/workflows/linux.yml
vendored
@@ -1,42 +0,0 @@
|
||||
name: Compile ZeroBot-Plugin-linux
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
|
||||
jobs:
|
||||
my-job:
|
||||
name: Build ZeroBot-Plugin-linux 🚀
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.16
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Cache Go
|
||||
id: cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
# A list of files, directories, and wildcard patterns to cache and restore
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-build-${{ hashFiles('**/go.sum') }}
|
||||
|
||||
- name: Tidy Go modules
|
||||
run: go mod tidy
|
||||
|
||||
- name: Build
|
||||
run: go build -ldflags="-s -w" -o artifacts/ZeroBot-Plugin-linux
|
||||
|
||||
- name: Upload Build Artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ZeroBot-Plugin-linux
|
||||
path: ./artifacts
|
||||
55
.github/workflows/nightly.yml
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
name: 最新版
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
env:
|
||||
BINARY_PREFIX: "zbp_"
|
||||
BINARY_SUFFIX: ""
|
||||
PR_PROMPT: "::warning:: Build artifact will not be uploaded due to the workflow is trigged by pull request."
|
||||
LD_FLAGS: "-w -s"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build binary CI
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
# build and publish in parallel: linux/386, linux/amd64, windows/386, windows/amd64, darwin/amd64, darwin/arm64
|
||||
goos: [linux, windows]
|
||||
goarch: ["386", amd64, arm, arm64]
|
||||
exclude:
|
||||
- goos: windows
|
||||
goarch: arm
|
||||
- goos: windows
|
||||
goarch: arm64
|
||||
fail-fast: true
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Setup Go environment
|
||||
uses: actions/setup-go@master
|
||||
with:
|
||||
go-version: 1.18
|
||||
- name: Cache downloaded module
|
||||
uses: actions/cache@master
|
||||
with:
|
||||
path: |
|
||||
~/.cache/go-build
|
||||
~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ matrix.goos }}-${{ matrix.goarch }}-${{ hashFiles('**/go.sum') }}
|
||||
- name: Build binary file
|
||||
env:
|
||||
GOOS: ${{ matrix.goos }}
|
||||
GOARCH: ${{ matrix.goarch }}
|
||||
IS_PR: ${{ !!github.head_ref }}
|
||||
run: |
|
||||
if [ $GOOS = "windows" ]; then export BINARY_SUFFIX="$BINARY_SUFFIX.exe"; fi
|
||||
if $IS_PR ; then echo $PR_PROMPT; fi
|
||||
export BINARY_NAME="$BINARY_PREFIX$GOOS_$GOARCH$BINARY_SUFFIX"
|
||||
export CGO_ENABLED=0
|
||||
go build -o "output/$BINARY_NAME" -trimpath -ldflags "$LD_FLAGS" .
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@master
|
||||
if: ${{ !github.head_ref }}
|
||||
with:
|
||||
name: ${{ matrix.goos }}_${{ matrix.goarch }}
|
||||
path: output/
|
||||
35
.github/workflows/pull.yml
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
name: PullLint
|
||||
on: [ pull_request ]
|
||||
jobs:
|
||||
golangci:
|
||||
name: lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@master
|
||||
with:
|
||||
go-version: 1.18
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@master
|
||||
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@master
|
||||
with:
|
||||
# Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
|
||||
version: latest
|
||||
|
||||
# Optional: working directory, useful for monorepos
|
||||
# working-directory: somedir
|
||||
|
||||
# Optional: golangci-lint command line arguments.
|
||||
# args: --issues-exit-code=0
|
||||
|
||||
# Optional: show only new issues if it's a pull request. The default value is `false`.
|
||||
# only-new-issues: true
|
||||
|
||||
# Optional: if set to true then the action don't cache or restore ~/go/pkg.
|
||||
# skip-pkg-cache: true
|
||||
|
||||
# Optional: if set to true then the action don't cache or restore ~/.cache/go-build.
|
||||
# skip-build-cache: true
|
||||
@@ -1,19 +1,23 @@
|
||||
name: Lint
|
||||
|
||||
on: [push]
|
||||
|
||||
name: PushLint
|
||||
on: [ push ]
|
||||
jobs:
|
||||
golangci:
|
||||
name: lint_golangci-lint
|
||||
name: lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2.3.4
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@master
|
||||
with:
|
||||
go-version: 1.18
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@master
|
||||
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v2.5.2
|
||||
uses: golangci/golangci-lint-action@master
|
||||
with:
|
||||
version: latest
|
||||
|
||||
args: --issues-exit-code=0
|
||||
- name: Commit back
|
||||
continue-on-error: true
|
||||
run: |
|
||||
27
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
name: 发行版
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
goreleaser:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@master
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@master
|
||||
with:
|
||||
go-version: '1.18'
|
||||
|
||||
- name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@master
|
||||
with:
|
||||
version: latest
|
||||
args: release --rm-dist
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
20
.github/workflows/suggester.yml
vendored
@@ -1,20 +0,0 @@
|
||||
name: Suggester
|
||||
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
golangci:
|
||||
name: lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2.3.4
|
||||
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v2.5.2
|
||||
with:
|
||||
version: latest
|
||||
|
||||
- name: Suggester
|
||||
uses: reviewdog/action-suggester@v1.0.1
|
||||
with:
|
||||
tool_name: golangci-lint
|
||||
41
.github/workflows/windows.yml
vendored
@@ -1,41 +0,0 @@
|
||||
name: Compile ZeroBot-Plugin-windows
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
|
||||
jobs:
|
||||
my-job:
|
||||
name: Build ZeroBot-Plugin-windows 🚀
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.16
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Cache Go
|
||||
id: cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-build-${{ hashFiles('**/go.sum') }}
|
||||
|
||||
- name: Tidy Go modules
|
||||
run: go mod tidy
|
||||
|
||||
- name: Build
|
||||
run: go build -ldflags="-s -w" -o artifacts/ZeroBot-Plugin-windows.exe
|
||||
|
||||
- name: Upload Build Artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ZeroBot-Plugin-windows.exe
|
||||
path: ./artifacts
|
||||
BIN
.github/yaya.jpg
vendored
|
Before Width: | Height: | Size: 63 KiB |
BIN
.github/黒金.jpg
vendored
Normal file
|
After Width: | Height: | Size: 191 KiB |
12
.gitignore
vendored
@@ -1,3 +1,9 @@
|
||||
data/SetuTime/cache
|
||||
data/SetuTime/search
|
||||
data/manager
|
||||
plugins/*.so
|
||||
plugins/*.dll
|
||||
.idea/
|
||||
.DS_Store
|
||||
.vscode
|
||||
go-zero*
|
||||
nohup.out
|
||||
zerobot
|
||||
ZeroBot-Plugin*
|
||||
|
||||
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule "data"]
|
||||
path = data
|
||||
url = https://github.com/FloatTech/zbpdata
|
||||
@@ -1,14 +1,10 @@
|
||||
linters-settings:
|
||||
errcheck:
|
||||
ignore: fmt:.*,io/ioutil:^Read.*
|
||||
ignore: fmt:.*
|
||||
ignoretests: true
|
||||
|
||||
goimports:
|
||||
local-prefixes: github.com/Yiwen-Chan/ZeroBot-Plugin
|
||||
|
||||
gocritic:
|
||||
disabled-checks:
|
||||
- exitAfterDefer
|
||||
local-prefixes: github.com/FloatTech/ZeroBot-Plugin
|
||||
|
||||
forbidigo:
|
||||
# Forbid the following identifiers
|
||||
@@ -18,13 +14,13 @@ linters-settings:
|
||||
linters:
|
||||
# please, do not use `enable-all`: it's deprecated and will be removed soon.
|
||||
# inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint
|
||||
fast: true
|
||||
disable-all: true
|
||||
fast: false
|
||||
enable:
|
||||
- bodyclose
|
||||
- deadcode
|
||||
- depguard
|
||||
- dogsled
|
||||
- dupl
|
||||
- errcheck
|
||||
- exportloopref
|
||||
- exhaustive
|
||||
@@ -39,7 +35,7 @@ linters:
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- misspell
|
||||
#- misspell
|
||||
- nolintlint
|
||||
- rowserrcheck
|
||||
- staticcheck
|
||||
@@ -54,23 +50,9 @@ linters:
|
||||
- prealloc
|
||||
- predeclared
|
||||
- asciicheck
|
||||
- revive
|
||||
- forbidigo
|
||||
- makezero
|
||||
- revive
|
||||
#- interfacer
|
||||
|
||||
# don't enable:
|
||||
# - scopelint
|
||||
# - gochecknoglobals
|
||||
# - gocognit
|
||||
# - godot
|
||||
# - godox
|
||||
# - goerr113
|
||||
# - interfacer
|
||||
# - maligned
|
||||
# - nestif
|
||||
# - testpackage
|
||||
# - wsl
|
||||
|
||||
run:
|
||||
# default concurrency is a available CPU number.
|
||||
@@ -78,6 +60,9 @@ run:
|
||||
deadline: 5m
|
||||
issues-exit-code: 1
|
||||
tests: false
|
||||
skip-dirs:
|
||||
- order
|
||||
go: '1.18'
|
||||
|
||||
# output configuration options
|
||||
output:
|
||||
@@ -91,4 +76,4 @@ issues:
|
||||
fix: true
|
||||
exclude-use-default: false
|
||||
exclude:
|
||||
- "Error return value of .((os.)?std(out|err)..*|.*Close|.*Flush|os.Remove(All)?|.*print(f|ln)?|os.(Un)?Setenv). is not check"
|
||||
- "Error return value of .((os.)?std(out|err)..*|.*Close|.*Seek|.*Flush|os.Remove(All)?|.*print(f|ln)?|os.(Un)?Setenv). is not check"
|
||||
73
.goreleaser.yml
Normal file
@@ -0,0 +1,73 @@
|
||||
project_name: zbp
|
||||
env:
|
||||
- GO111MODULE=on
|
||||
before:
|
||||
hooks:
|
||||
- go mod tidy
|
||||
builds:
|
||||
- id: nowin
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
- GO111MODULE=on
|
||||
goos:
|
||||
- linux
|
||||
goarch:
|
||||
- 386
|
||||
- amd64
|
||||
- arm
|
||||
- arm64
|
||||
goarm:
|
||||
- 6
|
||||
- 7
|
||||
mod_timestamp: "{{ .CommitTimestamp }}"
|
||||
flags:
|
||||
- -trimpath
|
||||
ldflags:
|
||||
- -s -w
|
||||
- id: win
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
- GO111MODULE=on
|
||||
goos:
|
||||
- windows
|
||||
goarch:
|
||||
- 386
|
||||
- amd64
|
||||
mod_timestamp: "{{ .CommitTimestamp }}"
|
||||
flags:
|
||||
- -trimpath
|
||||
ldflags:
|
||||
- -s -w
|
||||
|
||||
checksum:
|
||||
name_template: "zbp_checksums.txt"
|
||||
changelog:
|
||||
sort: asc
|
||||
filters:
|
||||
exclude:
|
||||
- "^docs:"
|
||||
- "^test:"
|
||||
- fix typo
|
||||
- Merge pull request
|
||||
- Merge branch
|
||||
- Merge remote-tracking
|
||||
- go mod tidy
|
||||
|
||||
archives:
|
||||
- id: nowin
|
||||
builds:
|
||||
- nowin
|
||||
- win
|
||||
name_template: "zbp_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
|
||||
format_overrides:
|
||||
- goos: windows
|
||||
format: zip
|
||||
|
||||
nfpms:
|
||||
- license: GPL 3.0
|
||||
homepage: https://github.com/FloatTech/ZeroBot-Plugin
|
||||
file_name_template: "zbp_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
|
||||
formats:
|
||||
- deb
|
||||
- rpm
|
||||
maintainer: FloatTech
|
||||
BIN
atri/AZ.jpg
|
Before Width: | Height: | Size: 41 KiB |
BIN
atri/AZ1.jpg
|
Before Width: | Height: | Size: 40 KiB |
BIN
atri/FN.jpg
|
Before Width: | Height: | Size: 33 KiB |
BIN
atri/NO.jpg
|
Before Width: | Height: | Size: 60 KiB |
BIN
atri/SUKI.jpg
|
Before Width: | Height: | Size: 79 KiB |
BIN
atri/SUKI1.jpg
|
Before Width: | Height: | Size: 149 KiB |
BIN
atri/SUKI2.png
|
Before Width: | Height: | Size: 693 KiB |
BIN
atri/WH.jpg
|
Before Width: | Height: | Size: 91 KiB |
BIN
atri/WH1.jpg
|
Before Width: | Height: | Size: 58 KiB |
BIN
atri/WH2.jpg
|
Before Width: | Height: | Size: 33 KiB |
BIN
atri/WH3.jpg
|
Before Width: | Height: | Size: 23 KiB |
BIN
atri/WQ.jpg
|
Before Width: | Height: | Size: 60 KiB |
BIN
atri/WQ1.jpg
|
Before Width: | Height: | Size: 121 KiB |
BIN
atri/YES.png
|
Before Width: | Height: | Size: 125 KiB |
13
config.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/driver"
|
||||
)
|
||||
|
||||
type zbpcfg struct {
|
||||
Z zero.Config `json:"zero"`
|
||||
W []*driver.WSClient `json:"ws"`
|
||||
}
|
||||
|
||||
var config zbpcfg
|
||||
1
data
Submodule
@@ -1,96 +0,0 @@
|
||||
package github
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
zero.OnRegex(`^>github\s(-.{1,10}? )?(.*)$`).SetBlock(true).FirstPriority().
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 发送请求
|
||||
header := http.Header{
|
||||
"User-Agent": []string{"User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36"},
|
||||
}
|
||||
api, _ := url.Parse("https://api.github.com/search/repositories")
|
||||
api.RawQuery = url.Values{
|
||||
"q": []string{ctx.State["regex_matched"].([]string)[2]},
|
||||
}.Encode()
|
||||
body, err := netGet(api.String(), header)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
}
|
||||
// 解析请求
|
||||
info := gjson.ParseBytes(body)
|
||||
if info.Get("total_count").Int() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 没有找到这样的仓库"))
|
||||
return
|
||||
}
|
||||
repo := info.Get("items.0")
|
||||
// 发送结果
|
||||
switch ctx.State["regex_matched"].([]string)[1] {
|
||||
case "-p ": // 图片模式
|
||||
ctx.SendChain(message.Image(
|
||||
"https://opengraph.githubassets.com/0/"+repo.Get("full_name").Str,
|
||||
).Add("cache", 0))
|
||||
default:
|
||||
ctx.SendChain(message.Text(
|
||||
repo.Get("full_name").Str, "\n",
|
||||
"Description: ",
|
||||
repo.Get("description").Str, "\n",
|
||||
"Star/Fork/Issue: ",
|
||||
repo.Get("watchers").Int(), "/", repo.Get("forks").Int(), "/", repo.Get("open_issues").Int(), "\n",
|
||||
"Language: ",
|
||||
notnull(repo.Get("language").Str, "None"), "\n",
|
||||
"License: ",
|
||||
notnull(strings.ToUpper(repo.Get("license.key").Str), "None"), "\n",
|
||||
"Last pushed: ",
|
||||
repo.Get("pushed_at").Str, "\n",
|
||||
"Jump: ",
|
||||
repo.Get("html_url").Str, "\n",
|
||||
))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// notnull 如果传入文本为空,则返回默认值
|
||||
func notnull(text, default_ string) string {
|
||||
if text == "" {
|
||||
return default_
|
||||
}
|
||||
return text
|
||||
}
|
||||
|
||||
// netGet 返回请求结果
|
||||
func netGet(dest string, header http.Header) ([]byte, error) {
|
||||
client := &http.Client{}
|
||||
|
||||
req, err := http.NewRequest("GET", dest, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header = header
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if code := resp.StatusCode; code != 200 {
|
||||
// 如果返回不是200则立刻抛出错误
|
||||
return nil, errors.New(fmt.Sprintf("code %d", code))
|
||||
}
|
||||
return body, nil
|
||||
}
|
||||
84
go.mod
@@ -1,19 +1,77 @@
|
||||
module github.com/FloatTech/ZeroBot-Plugin
|
||||
|
||||
go 1.16
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/FloatTech/AnimeAPI v0.0.0-20210619112022-a8fdd4fefc07
|
||||
github.com/FloatTech/ZeroBot-Plugin-Timer v1.2.2
|
||||
github.com/antchfx/xpath v1.2.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/FloatTech/AnimeAPI v1.4.1-0.20220715043235-1158db91e898
|
||||
github.com/FloatTech/sqlite v0.3.3
|
||||
github.com/FloatTech/zbpctrl v1.4.1-0.20220715042842-93f081cb0133
|
||||
github.com/FloatTech/zbputils v1.4.1-0.20220715043109-4e1d708dffe9
|
||||
github.com/antchfx/htmlquery v1.2.5
|
||||
github.com/corona10/goimagehash v1.0.3
|
||||
github.com/fogleman/gg v1.3.0
|
||||
github.com/fumiama/cron v1.3.0
|
||||
github.com/fumiama/go-base16384 v1.5.4
|
||||
github.com/fumiama/go-registry v0.1.6
|
||||
github.com/fumiama/gofastTEA v0.0.10
|
||||
github.com/fumiama/gotracemoe v0.0.3
|
||||
github.com/fumiama/sqlite3 v1.14.6
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
|
||||
github.com/jinzhu/gorm v1.9.16
|
||||
github.com/jozsefsallai/gophersauce v1.0.1
|
||||
github.com/lucas-clemente/quic-go v0.27.2
|
||||
github.com/mroth/weightedrand v0.4.1
|
||||
github.com/pkg/errors v0.8.1
|
||||
github.com/pkumza/numcn v1.0.0
|
||||
github.com/shirou/gopsutil/v3 v3.22.3
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816
|
||||
github.com/tidwall/gjson v1.8.0
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/wdvxdr1123/ZeroBot v1.2.1
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5 // indirect
|
||||
golang.org/x/sys v0.0.0-20210603125802-9665404d3644 // indirect
|
||||
modernc.org/sqlite v1.10.8
|
||||
github.com/tidwall/gjson v1.14.1
|
||||
github.com/wcharczuk/go-chart/v2 v2.1.0
|
||||
github.com/wdvxdr1123/ZeroBot v1.5.2-0.20220715040337-ef4327320c40
|
||||
gitlab.com/gomidi/midi/v2 v2.0.17
|
||||
golang.org/x/image v0.0.0-20220601225756-64ec528b34cd
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b // indirect
|
||||
github.com/RomiChan/syncx v0.0.0-20220404072119-d7ea0ae15a4c // indirect
|
||||
github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc // indirect
|
||||
github.com/antchfx/xpath v1.2.1 // indirect
|
||||
github.com/cheekybits/genny v1.0.0 // indirect
|
||||
github.com/disintegration/imaging v1.6.2 // indirect
|
||||
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.0.4 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/marten-seemann/qpack v0.2.1 // indirect
|
||||
github.com/marten-seemann/qtls-go1-16 v0.1.5 // indirect
|
||||
github.com/marten-seemann/qtls-go1-17 v0.1.2 // indirect
|
||||
github.com/marten-seemann/qtls-go1-18 v0.1.2 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
||||
github.com/nxadm/tail v1.4.8 // indirect
|
||||
github.com/onsi/ginkgo v1.16.4 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.10 // indirect
|
||||
github.com/tklauser/numcpus v0.4.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect
|
||||
golang.org/x/mod v0.4.2 // indirect
|
||||
golang.org/x/net v0.0.0-20220607020251-c690dde0001d // indirect
|
||||
golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/tools v0.1.1 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
modernc.org/libc v1.16.8 // indirect
|
||||
modernc.org/mathutil v1.4.1 // indirect
|
||||
modernc.org/memory v1.1.1 // indirect
|
||||
)
|
||||
|
||||
550
go.sum
@@ -1,157 +1,549 @@
|
||||
github.com/FloatTech/AnimeAPI v0.0.0-20210619112022-a8fdd4fefc07 h1:7fBPLLoZysaa9PI9ApgzyVMrMLMWBam273YgKwy7Ddg=
|
||||
github.com/FloatTech/AnimeAPI v0.0.0-20210619112022-a8fdd4fefc07/go.mod h1:GYrQD70HvBzry1XiZ1tHFNOsOqRkR+ao4XGYZqV4I9c=
|
||||
github.com/FloatTech/ZeroBot-Plugin-Timer v1.2.2 h1:I7RSCsJVT6elehdaSiWB4n96y06fQxMsvAG494S5Od0=
|
||||
github.com/FloatTech/ZeroBot-Plugin-Timer v1.2.2/go.mod h1:femu/wVuqVSN/rg209qksMx8/2OKUF8l1PZCNg4RwVA=
|
||||
github.com/antchfx/htmlquery v1.2.3 h1:sP3NFDneHx2stfNXCKbhHFo8XgNjCACnU/4AO5gWz6M=
|
||||
github.com/antchfx/htmlquery v1.2.3/go.mod h1:B0ABL+F5irhhMWg54ymEZinzMSi0Kt3I2if0BLYa3V0=
|
||||
github.com/antchfx/xpath v1.1.6/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk=
|
||||
github.com/antchfx/xpath v1.2.0 h1:mbwv7co+x0RwgeGAOHdrKy89GvHaGvxxBtPK0uF9Zr8=
|
||||
github.com/antchfx/xpath v1.2.0/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo=
|
||||
dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
|
||||
dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
|
||||
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
|
||||
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
|
||||
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/FloatTech/AnimeAPI v1.4.1-0.20220715043235-1158db91e898 h1:RCJXy/Ati+R4+CwMrXIUSaoiS9FW16i8483X6SNpnM8=
|
||||
github.com/FloatTech/AnimeAPI v1.4.1-0.20220715043235-1158db91e898/go.mod h1:DE4hXqmTv6BljRhOdDCpF9I7tFbJHeAIA65yDAakJeE=
|
||||
github.com/FloatTech/sqlite v0.3.3 h1:cSlpv+DcIehqaUG2YyjW0Twh396FoGsybpEpFZnX3Jg=
|
||||
github.com/FloatTech/sqlite v0.3.3/go.mod h1:i33d92OtR8jcp5fBUvQtospf27+MkfUxnGwnZ95E/dA=
|
||||
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b h1:tvciXWq2nuvTbFeJGLDNIdRX3BI546D3O7k7vrVueZw=
|
||||
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b/go.mod h1:fHZFWGquNXuHttu9dUYoKuNbm3dzLETnIOnm1muSfDs=
|
||||
github.com/FloatTech/zbpctrl v1.4.1-0.20220715042842-93f081cb0133 h1:nP9NI4I+vtwAbiU7wCJwjuzCzMZ/yJYg8h3667HGnv0=
|
||||
github.com/FloatTech/zbpctrl v1.4.1-0.20220715042842-93f081cb0133/go.mod h1:72BnjyBwQWUC8mqM9dPk5ZrjxXCilQCVp+jfgHATNdw=
|
||||
github.com/FloatTech/zbputils v1.4.1-0.20220715043109-4e1d708dffe9 h1:T4lYDvtdn5uEyDJMcCXt469/VMrC/CTpmfR7loAXK9o=
|
||||
github.com/FloatTech/zbputils v1.4.1-0.20220715043109-4e1d708dffe9/go.mod h1:tR0EUB0p5AMFuzlYssZjA1ClHPFQ23/QgBiMCTy+X40=
|
||||
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
||||
github.com/RomiChan/syncx v0.0.0-20220404072119-d7ea0ae15a4c h1:cNPOdTNiVwxLpROLjXCgbIPvdkE+BwvxDvgmdYmWx6Q=
|
||||
github.com/RomiChan/syncx v0.0.0-20220404072119-d7ea0ae15a4c/go.mod h1:KqZzu7slNKROh3TSYEH/IUMG6f4M+1qubZ5e52QypsE=
|
||||
github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc h1:AAx50/fb/xS4lvsdQg+bFbGvqSDhyV1MF+p2PLCamZ0=
|
||||
github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc/go.mod h1:OMmITAib6POA37xCichWM0aRnoVpSMZO1rB/G01wrr0=
|
||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/antchfx/htmlquery v1.2.5 h1:1lXnx46/1wtv1E/kzmH8vrfMuUKYgkdDBA9pIdMJnk4=
|
||||
github.com/antchfx/htmlquery v1.2.5/go.mod h1:2MCVBzYVafPBmKbrmwB9F5xdd+IEgRY61ci2oOsOQVw=
|
||||
github.com/antchfx/xpath v1.2.1 h1:qhp4EW6aCOVr5XIkT+l6LJ9ck/JsUH/yyauNgTQkBF8=
|
||||
github.com/antchfx/xpath v1.2.1/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
|
||||
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
||||
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
|
||||
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/corona10/goimagehash v1.0.3 h1:NZM518aKLmoNluluhfHGxT3LGOnrojrxhGn63DR/CZA=
|
||||
github.com/corona10/goimagehash v1.0.3/go.mod h1:VkvE0mLn84L4aF8vCb6mafVajEb6QYMHl2ZJLn0mOGI=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
|
||||
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 h1:BBade+JlV/f7JstZ4pitd4tHhpN+w+6I+LyOS7B4fyU=
|
||||
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4/go.mod h1:H7chHJglrhPPzetLdzBleF8d22WYOv7UM/lEKYiwlKM=
|
||||
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
|
||||
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
|
||||
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fumiama/cron v1.3.0 h1:ZWlwuexF+HQHl3cYytEE5HNwD99q+3vNZF1GrEiXCFo=
|
||||
github.com/fumiama/cron v1.3.0/go.mod h1:bz5Izvgi/xEUI8tlBN8BI2jr9Moo8N4or0KV8xXuPDY=
|
||||
github.com/fumiama/go-base16384 v1.5.4 h1:UKx925X7cTsqsVWBlBLBs1v38epFT/q3AGjvyP5E0PM=
|
||||
github.com/fumiama/go-base16384 v1.5.4/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM=
|
||||
github.com/fumiama/go-registry v0.1.6 h1:Ee/tXCCIR/xt8celhbbw0W/xDMdhAXLwy2YFBB/LWFk=
|
||||
github.com/fumiama/go-registry v0.1.6/go.mod h1:dIUVbiOgfk9oZcsgwDvNLC72i+ctibVukSXR/9bLviI=
|
||||
github.com/fumiama/gofastTEA v0.0.10 h1:JJJ+brWD4kie+mmK2TkspDXKzqq0IjXm89aGYfoGhhQ=
|
||||
github.com/fumiama/gofastTEA v0.0.10/go.mod h1:RIdbYZyB4MbH6ZBlPymRaXn3cD6SedlCu5W/HHfMPBk=
|
||||
github.com/fumiama/gotracemoe v0.0.3 h1:iI5EbE9A3UUbfukG6+/soYPjp1S31eCNYf4tw7s6/Jc=
|
||||
github.com/fumiama/gotracemoe v0.0.3/go.mod h1:tyqahdUzHf0bQIAVY/GYmDWvYYe5ik1ZbhnGYh+zl40=
|
||||
github.com/fumiama/sqlite3 v1.14.6 h1:+e+iygyiDXQJVi7xeXIviBvR7hAc5y20WA9hRwfKn10=
|
||||
github.com/fumiama/sqlite3 v1.14.6/go.mod h1:Xx9a2/OtHuy9pBjow0N+bE/RhNeZ7zZz5xh25vqbA5A=
|
||||
github.com/gabriel-vasile/mimetype v1.0.4 h1:uBejfH8l3/2f+5vjl1e4xIaSyNEhRBZ5N/ij7ohpNd8=
|
||||
github.com/gabriel-vasile/mimetype v1.0.4/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
|
||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
|
||||
github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o=
|
||||
github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M=
|
||||
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jozsefsallai/gophersauce v1.0.1 h1:BA3ovtQRrAb1qYU9JoRLbDHpxnDunlNcEkEfhCvDDCM=
|
||||
github.com/jozsefsallai/gophersauce v1.0.1/go.mod h1:YVEI7djliMTmZ1Vh01YPF8bUHi+oKhe3yXgKf1T49vg=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
|
||||
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lucas-clemente/quic-go v0.27.2 h1:zsMwwniyybb8B/UDNXRSYee7WpQJVOcjQEGgpw2ikXs=
|
||||
github.com/lucas-clemente/quic-go v0.27.2/go.mod h1:vXgO/11FBSKM+js1NxoaQ/bPtVFYfB7uxhfHXyMhl1A=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/marten-seemann/qpack v0.2.1 h1:jvTsT/HpCn2UZJdP+UUB53FfUUgeOyG5K1ns0OJOGVs=
|
||||
github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc=
|
||||
github.com/marten-seemann/qtls-go1-16 v0.1.5 h1:o9JrYPPco/Nukd/HpOHMHZoBDXQqoNtUCmny98/1uqQ=
|
||||
github.com/marten-seemann/qtls-go1-16 v0.1.5/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk=
|
||||
github.com/marten-seemann/qtls-go1-17 v0.1.2 h1:JADBlm0LYiVbuSySCHeY863dNkcpMmDR7s0bLKJeYlQ=
|
||||
github.com/marten-seemann/qtls-go1-17 v0.1.2/go.mod h1:C2ekUKcDdz9SDWxec1N/MvcXBpaX9l3Nx67XaR84L5s=
|
||||
github.com/marten-seemann/qtls-go1-18 v0.1.2 h1:JH6jmzbduz0ITVQ7ShevK10Av5+jBEKAHMntXmIV7kM=
|
||||
github.com/marten-seemann/qtls-go1-18 v0.1.2/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
|
||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA=
|
||||
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2-0.20210109003243-333559e1834b h1:6Xjqolv/0DDdUqlpnsTomXQvjvvkz7Ux7TcMALvozEw=
|
||||
github.com/modern-go/reflect2 v1.0.2-0.20210109003243-333559e1834b/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mroth/weightedrand v0.4.1 h1:rHcbUBopmi/3x4nnrvwGJBhX9d0vk+KgoLUZeDP6YyI=
|
||||
github.com/mroth/weightedrand v0.4.1/go.mod h1:3p2SIcC8al1YMzGhAIoXD+r9olo/g/cdJgAD905gyNE=
|
||||
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
||||
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
|
||||
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
|
||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
|
||||
github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
|
||||
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkumza/numcn v1.0.0 h1:ZT5cf9IJkUZgRgEtCiNNykk0RwsrKXSTsvDHOwUTzgE=
|
||||
github.com/pkumza/numcn v1.0.0/go.mod h1:QSeH+al9dWCd8di5HZM/ZqHqhZmUKfph572e9Ev/ETc=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/shirou/gopsutil/v3 v3.22.3 h1:UebRzEomgMpv61e3hgD1tGooqX5trFbdU/ehphbHd00=
|
||||
github.com/shirou/gopsutil/v3 v3.22.3/go.mod h1:D01hZJ4pVHPpCTZ3m3T2+wDF2YAGfd+H4ifUguaQzHM=
|
||||
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
|
||||
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
|
||||
github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
|
||||
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
|
||||
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
|
||||
github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw=
|
||||
github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI=
|
||||
github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU=
|
||||
github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag=
|
||||
github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg=
|
||||
github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw=
|
||||
github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y=
|
||||
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
||||
github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q=
|
||||
github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ=
|
||||
github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I=
|
||||
github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0=
|
||||
github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ=
|
||||
github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk=
|
||||
github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
|
||||
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
|
||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
|
||||
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816 h1:J6v8awz+me+xeb/cUTotKgceAYouhIB3pjzgRd6IlGk=
|
||||
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816/go.mod h1:tzym/CEb5jnFI+Q0k4Qq3+LvRF4gO3E2pxS8fHP8jcA=
|
||||
github.com/tidwall/gjson v1.8.0 h1:Qt+orfosKn0rbNTZqHYDqBrmm3UDA4KRkv70fDzG+PQ=
|
||||
github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
|
||||
github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE=
|
||||
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
||||
github.com/tidwall/gjson v1.14.1 h1:iymTbGkQBhveq21bEvAQ81I0LEBork8BFe1CUZXdyuo=
|
||||
github.com/tidwall/gjson v1.14.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/wdvxdr1123/ZeroBot v1.2.1 h1:ougeP+VOAGlQWCAUSB7fjA5trzEvPepU7pujsoYTCq8=
|
||||
github.com/wdvxdr1123/ZeroBot v1.2.1/go.mod h1:83nHtG8V5TAxPwH/LCDxLpZk4khIgs29dkr5TBWf7fc=
|
||||
github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw=
|
||||
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
|
||||
github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o=
|
||||
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
|
||||
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
|
||||
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
|
||||
github.com/wcharczuk/go-chart/v2 v2.1.0 h1:tY2slqVQ6bN+yHSnDYwZebLQFkphK4WNrVwnt7CJZ2I=
|
||||
github.com/wcharczuk/go-chart/v2 v2.1.0/go.mod h1:yx7MvAVNcP/kN9lKXM/NTce4au4DFN99j6i1OwDclNA=
|
||||
github.com/wdvxdr1123/ZeroBot v1.5.2-0.20220715040337-ef4327320c40 h1:j+cmfkjc8WcBKiOsvMzcIgAuPhiTs7FBeiRn/QLVFhA=
|
||||
github.com/wdvxdr1123/ZeroBot v1.5.2-0.20220715040337-ef4327320c40/go.mod h1:LJ+VOf523i3IrykuLK53UEeWqnAclRL5d2wGT4sS4Zk=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
||||
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
gitlab.com/gomidi/midi/v2 v2.0.17 h1:kf16wNwFFOskl0trvarOwMuZUQICdIGn37LP9QqIRuo=
|
||||
gitlab.com/gomidi/midi/v2 v2.0.17/go.mod h1:quTyMKSQ4Klevxu6gY4gy2USbeZra0fV5SalndmPfsY=
|
||||
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
||||
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
||||
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
|
||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20220601225756-64ec528b34cd h1:9NbNcTg//wfC5JskFW4Z3sqwVnjmJKHxLAol1bW2qgw=
|
||||
golang.org/x/image v0.0.0-20220601225756-64ec528b34cd/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
|
||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5 h1:wjuX4b5yYQnEQHzd+CBcrcC6OVR2J1CN6mUy0oSxIPo=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20220607020251-c690dde0001d h1:4SFsTMi4UahlKoloni7L4eYzhFRifURQLw+yv0QDCx8=
|
||||
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210603125802-9665404d3644 h1:CA1DEQ4NdKphKeL70tvsWNdT5oFh1lOjihRcEDROi0I=
|
||||
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68 h1:z8Hj/bl9cOV2grsOpEaQFUaly0JWN3i97mo3jXKJNp0=
|
||||
golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78 h1:M8tBwCtWD/cZV9DZpFYRUgaymAYAr+aIUTWzDaM3uPs=
|
||||
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.1 h1:wGiQel/hW0NnEkJUk8lbzkX2gFJU6PFxf1v5OlCfuOs=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
|
||||
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
modernc.org/cc/v3 v3.32.4/go.mod h1:0R6jl1aZlIl2avnYfbfHBS1QB6/f+16mihBObaBC878=
|
||||
modernc.org/cc/v3 v3.33.5 h1:gfsIOmcv80EelyQyOHn/Xhlzex8xunhQxWiJRMYmPrI=
|
||||
modernc.org/cc/v3 v3.33.5/go.mod h1:0R6jl1aZlIl2avnYfbfHBS1QB6/f+16mihBObaBC878=
|
||||
modernc.org/ccgo/v3 v3.9.2/go.mod h1:gnJpy6NIVqkETT+L5zPsQFj7L2kkhfPMzOghRNv/CFo=
|
||||
modernc.org/ccgo/v3 v3.9.4 h1:mt2+HyTZKxva27O6T4C9//0xiNQ/MornL3i8itM5cCs=
|
||||
modernc.org/ccgo/v3 v3.9.4/go.mod h1:19XAY9uOrYnDhOgfHwCABasBvK69jgC4I8+rizbk3Bc=
|
||||
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||
modernc.org/cc/v3 v3.33.6/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.33.9/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.33.11/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.34.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.4/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.5/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.7/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.8/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.10/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.15/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.16/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.17/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.18/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.20/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.22/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI=
|
||||
modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc=
|
||||
modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw=
|
||||
modernc.org/ccgo/v3 v3.9.5/go.mod h1:umuo2EP2oDSBnD3ckjaVUXMrmeAw8C8OSICVa0iFf60=
|
||||
modernc.org/ccgo/v3 v3.10.0/go.mod h1:c0yBmkRFi7uW4J7fwx/JiijwOjeAeR2NoSaRVFPmjMw=
|
||||
modernc.org/ccgo/v3 v3.11.0/go.mod h1:dGNposbDp9TOZ/1KBxghxtUp/bzErD0/0QW4hhSaBMI=
|
||||
modernc.org/ccgo/v3 v3.11.1/go.mod h1:lWHxfsn13L3f7hgGsGlU28D9eUOf6y3ZYHKoPaKU0ag=
|
||||
modernc.org/ccgo/v3 v3.11.3/go.mod h1:0oHunRBMBiXOKdaglfMlRPBALQqsfrCKXgw9okQ3GEw=
|
||||
modernc.org/ccgo/v3 v3.12.4/go.mod h1:Bk+m6m2tsooJchP/Yk5ji56cClmN6R1cqc9o/YtbgBQ=
|
||||
modernc.org/ccgo/v3 v3.12.6/go.mod h1:0Ji3ruvpFPpz+yu+1m0wk68pdr/LENABhTrDkMDWH6c=
|
||||
modernc.org/ccgo/v3 v3.12.8/go.mod h1:Hq9keM4ZfjCDuDXxaHptpv9N24JhgBZmUG5q60iLgUo=
|
||||
modernc.org/ccgo/v3 v3.12.11/go.mod h1:0jVcmyDwDKDGWbcrzQ+xwJjbhZruHtouiBEvDfoIsdg=
|
||||
modernc.org/ccgo/v3 v3.12.14/go.mod h1:GhTu1k0YCpJSuWwtRAEHAol5W7g1/RRfS4/9hc9vF5I=
|
||||
modernc.org/ccgo/v3 v3.12.18/go.mod h1:jvg/xVdWWmZACSgOiAhpWpwHWylbJaSzayCqNOJKIhs=
|
||||
modernc.org/ccgo/v3 v3.12.20/go.mod h1:aKEdssiu7gVgSy/jjMastnv/q6wWGRbszbheXgWRHc8=
|
||||
modernc.org/ccgo/v3 v3.12.21/go.mod h1:ydgg2tEprnyMn159ZO/N4pLBqpL7NOkJ88GT5zNU2dE=
|
||||
modernc.org/ccgo/v3 v3.12.22/go.mod h1:nyDVFMmMWhMsgQw+5JH6B6o4MnZ+UQNw1pp52XYFPRk=
|
||||
modernc.org/ccgo/v3 v3.12.25/go.mod h1:UaLyWI26TwyIT4+ZFNjkyTbsPsY3plAEB6E7L/vZV3w=
|
||||
modernc.org/ccgo/v3 v3.12.29/go.mod h1:FXVjG7YLf9FetsS2OOYcwNhcdOLGt8S9bQ48+OP75cE=
|
||||
modernc.org/ccgo/v3 v3.12.36/go.mod h1:uP3/Fiezp/Ga8onfvMLpREq+KUjUmYMxXPO8tETHtA8=
|
||||
modernc.org/ccgo/v3 v3.12.38/go.mod h1:93O0G7baRST1vNj4wnZ49b1kLxt0xCW5Hsa2qRaZPqc=
|
||||
modernc.org/ccgo/v3 v3.12.43/go.mod h1:k+DqGXd3o7W+inNujK15S5ZYuPoWYLpF5PYougCmthU=
|
||||
modernc.org/ccgo/v3 v3.12.46/go.mod h1:UZe6EvMSqOxaJ4sznY7b23/k13R8XNlyWsO5bAmSgOE=
|
||||
modernc.org/ccgo/v3 v3.12.47/go.mod h1:m8d6p0zNps187fhBwzY/ii6gxfjob1VxWb919Nk1HUk=
|
||||
modernc.org/ccgo/v3 v3.12.50/go.mod h1:bu9YIwtg+HXQxBhsRDE+cJjQRuINuT9PUK4orOco/JI=
|
||||
modernc.org/ccgo/v3 v3.12.51/go.mod h1:gaIIlx4YpmGO2bLye04/yeblmvWEmE4BBBls4aJXFiE=
|
||||
modernc.org/ccgo/v3 v3.12.53/go.mod h1:8xWGGTFkdFEWBEsUmi+DBjwu/WLy3SSOrqEmKUjMeEg=
|
||||
modernc.org/ccgo/v3 v3.12.54/go.mod h1:yANKFTm9llTFVX1FqNKHE0aMcQb1fuPJx6p8AcUx+74=
|
||||
modernc.org/ccgo/v3 v3.12.55/go.mod h1:rsXiIyJi9psOwiBkplOaHye5L4MOOaCjHg1Fxkj7IeU=
|
||||
modernc.org/ccgo/v3 v3.12.56/go.mod h1:ljeFks3faDseCkr60JMpeDb2GSO3TKAmrzm7q9YOcMU=
|
||||
modernc.org/ccgo/v3 v3.12.57/go.mod h1:hNSF4DNVgBl8wYHpMvPqQWDQx8luqxDnNGCMM4NFNMc=
|
||||
modernc.org/ccgo/v3 v3.12.60/go.mod h1:k/Nn0zdO1xHVWjPYVshDeWKqbRWIfif5dtsIOCUVMqM=
|
||||
modernc.org/ccgo/v3 v3.12.66/go.mod h1:jUuxlCFZTUZLMV08s7B1ekHX5+LIAurKTTaugUr/EhQ=
|
||||
modernc.org/ccgo/v3 v3.12.67/go.mod h1:Bll3KwKvGROizP2Xj17GEGOTrlvB1XcVaBrC90ORO84=
|
||||
modernc.org/ccgo/v3 v3.12.73/go.mod h1:hngkB+nUUqzOf3iqsM48Gf1FZhY599qzVg1iX+BT3cQ=
|
||||
modernc.org/ccgo/v3 v3.12.81/go.mod h1:p2A1duHoBBg1mFtYvnhAnQyI6vL0uw5PGYLSIgF6rYY=
|
||||
modernc.org/ccgo/v3 v3.12.84/go.mod h1:ApbflUfa5BKadjHynCficldU1ghjen84tuM5jRynB7w=
|
||||
modernc.org/ccgo/v3 v3.12.86/go.mod h1:dN7S26DLTgVSni1PVA3KxxHTcykyDurf3OgUzNqTSrU=
|
||||
modernc.org/ccgo/v3 v3.12.90/go.mod h1:obhSc3CdivCRpYZmrvO88TXlW0NvoSVvdh/ccRjJYko=
|
||||
modernc.org/ccgo/v3 v3.12.92/go.mod h1:5yDdN7ti9KWPi5bRVWPl8UNhpEAtCjuEE7ayQnzzqHA=
|
||||
modernc.org/ccgo/v3 v3.13.1/go.mod h1:aBYVOUfIlcSnrsRVU8VRS35y2DIfpgkmVkYZ0tpIXi4=
|
||||
modernc.org/ccgo/v3 v3.15.9/go.mod h1:md59wBwDT2LznX/OTCPoVS6KIsdRgY8xqQwBV+hkTH0=
|
||||
modernc.org/ccgo/v3 v3.15.10/go.mod h1:wQKxoFn0ynxMuCLfFD09c8XPUCc8obfchoVR9Cn0fI8=
|
||||
modernc.org/ccgo/v3 v3.15.12/go.mod h1:VFePOWoCd8uDGRJpq/zfJ29D0EVzMSyID8LCMWYbX6I=
|
||||
modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ=
|
||||
modernc.org/ccorpus v1.11.1/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
|
||||
modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
|
||||
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
|
||||
modernc.org/libc v1.7.13-0.20210308123627-12f642a52bb8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
|
||||
modernc.org/libc v1.9.5 h1:zv111ldxmP7DJ5mOIqzRbza7ZDl3kh4ncKfASB2jIYY=
|
||||
modernc.org/libc v1.9.5/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
|
||||
modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA=
|
||||
modernc.org/libc v1.9.8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
|
||||
modernc.org/libc v1.9.11/go.mod h1:NyF3tsA5ArIjJ83XB0JlqhjTabTCHm9aX4XMPHyQn0Q=
|
||||
modernc.org/libc v1.11.0/go.mod h1:2lOfPmj7cz+g1MrPNmX65QCzVxgNq2C5o0jdLY2gAYg=
|
||||
modernc.org/libc v1.11.2/go.mod h1:ioIyrl3ETkugDO3SGZ+6EOKvlP3zSOycUETe4XM4n8M=
|
||||
modernc.org/libc v1.11.5/go.mod h1:k3HDCP95A6U111Q5TmG3nAyUcp3kR5YFZTeDS9v8vSU=
|
||||
modernc.org/libc v1.11.6/go.mod h1:ddqmzR6p5i4jIGK1d/EiSw97LBcE3dK24QEwCFvgNgE=
|
||||
modernc.org/libc v1.11.11/go.mod h1:lXEp9QOOk4qAYOtL3BmMve99S5Owz7Qyowzvg6LiZso=
|
||||
modernc.org/libc v1.11.13/go.mod h1:ZYawJWlXIzXy2Pzghaf7YfM8OKacP3eZQI81PDLFdY8=
|
||||
modernc.org/libc v1.11.16/go.mod h1:+DJquzYi+DMRUtWI1YNxrlQO6TcA5+dRRiq8HWBWRC8=
|
||||
modernc.org/libc v1.11.19/go.mod h1:e0dgEame6mkydy19KKaVPBeEnyJB4LGNb0bBH1EtQ3I=
|
||||
modernc.org/libc v1.11.24/go.mod h1:FOSzE0UwookyT1TtCJrRkvsOrX2k38HoInhw+cSCUGk=
|
||||
modernc.org/libc v1.11.26/go.mod h1:SFjnYi9OSd2W7f4ct622o/PAYqk7KHv6GS8NZULIjKY=
|
||||
modernc.org/libc v1.11.27/go.mod h1:zmWm6kcFXt/jpzeCgfvUNswM0qke8qVwxqZrnddlDiE=
|
||||
modernc.org/libc v1.11.28/go.mod h1:Ii4V0fTFcbq3qrv3CNn+OGHAvzqMBvC7dBNyC4vHZlg=
|
||||
modernc.org/libc v1.11.31/go.mod h1:FpBncUkEAtopRNJj8aRo29qUiyx5AvAlAxzlx9GNaVM=
|
||||
modernc.org/libc v1.11.34/go.mod h1:+Tzc4hnb1iaX/SKAutJmfzES6awxfU1BPvrrJO0pYLg=
|
||||
modernc.org/libc v1.11.37/go.mod h1:dCQebOwoO1046yTrfUE5nX1f3YpGZQKNcITUYWlrAWo=
|
||||
modernc.org/libc v1.11.39/go.mod h1:mV8lJMo2S5A31uD0k1cMu7vrJbSA3J3waQJxpV4iqx8=
|
||||
modernc.org/libc v1.11.42/go.mod h1:yzrLDU+sSjLE+D4bIhS7q1L5UwXDOw99PLSX0BlZvSQ=
|
||||
modernc.org/libc v1.11.44/go.mod h1:KFq33jsma7F5WXiYelU8quMJasCCTnHK0mkri4yPHgA=
|
||||
modernc.org/libc v1.11.45/go.mod h1:Y192orvfVQQYFzCNsn+Xt0Hxt4DiO4USpLNXBlXg/tM=
|
||||
modernc.org/libc v1.11.47/go.mod h1:tPkE4PzCTW27E6AIKIR5IwHAQKCAtudEIeAV1/SiyBg=
|
||||
modernc.org/libc v1.11.49/go.mod h1:9JrJuK5WTtoTWIFQ7QjX2Mb/bagYdZdscI3xrvHbXjE=
|
||||
modernc.org/libc v1.11.51/go.mod h1:R9I8u9TS+meaWLdbfQhq2kFknTW0O3aw3kEMqDDxMaM=
|
||||
modernc.org/libc v1.11.53/go.mod h1:5ip5vWYPAoMulkQ5XlSJTy12Sz5U6blOQiYasilVPsU=
|
||||
modernc.org/libc v1.11.54/go.mod h1:S/FVnskbzVUrjfBqlGFIPA5m7UwB3n9fojHhCNfSsnw=
|
||||
modernc.org/libc v1.11.55/go.mod h1:j2A5YBRm6HjNkoSs/fzZrSxCuwWqcMYTDPLNx0URn3M=
|
||||
modernc.org/libc v1.11.56/go.mod h1:pakHkg5JdMLt2OgRadpPOTnyRXm/uzu+Yyg/LSLdi18=
|
||||
modernc.org/libc v1.11.58/go.mod h1:ns94Rxv0OWyoQrDqMFfWwka2BcaF6/61CqJRK9LP7S8=
|
||||
modernc.org/libc v1.11.71/go.mod h1:DUOmMYe+IvKi9n6Mycyx3DbjfzSKrdr/0Vgt3j7P5gw=
|
||||
modernc.org/libc v1.11.75/go.mod h1:dGRVugT6edz361wmD9gk6ax1AbDSe0x5vji0dGJiPT0=
|
||||
modernc.org/libc v1.11.82/go.mod h1:NF+Ek1BOl2jeC7lw3a7Jj5PWyHPwWD4aq3wVKxqV1fI=
|
||||
modernc.org/libc v1.11.86/go.mod h1:ePuYgoQLmvxdNT06RpGnaDKJmDNEkV7ZPKI2jnsvZoE=
|
||||
modernc.org/libc v1.11.87/go.mod h1:Qvd5iXTeLhI5PS0XSyqMY99282y+3euapQFxM7jYnpY=
|
||||
modernc.org/libc v1.11.88/go.mod h1:h3oIVe8dxmTcchcFuCcJ4nAWaoiwzKCdv82MM0oiIdQ=
|
||||
modernc.org/libc v1.11.98/go.mod h1:ynK5sbjsU77AP+nn61+k+wxUGRx9rOFcIqWYYMaDZ4c=
|
||||
modernc.org/libc v1.11.101/go.mod h1:wLLYgEiY2D17NbBOEp+mIJJJBGSiy7fLL4ZrGGZ+8jI=
|
||||
modernc.org/libc v1.12.0/go.mod h1:2MH3DaF/gCU8i/UBiVE1VFRos4o523M7zipmwH8SIgQ=
|
||||
modernc.org/libc v1.14.1/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk=
|
||||
modernc.org/libc v1.14.2/go.mod h1:MX1GBLnRLNdvmK9azU9LCxZ5lMyhrbEMK8rG3X/Fe34=
|
||||
modernc.org/libc v1.14.3/go.mod h1:GPIvQVOVPizzlqyRX3l756/3ppsAgg1QgPxjr5Q4agQ=
|
||||
modernc.org/libc v1.14.5/go.mod h1:2PJHINagVxO4QW/5OQdRrvMYo+bm5ClpUFfyXCYl9ak=
|
||||
modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A=
|
||||
modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU=
|
||||
modernc.org/libc v1.16.8 h1:Ux98PaOMvolgoFX/YwusFOHBnanXdGRmWgI8ciI2z4o=
|
||||
modernc.org/libc v1.16.8/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU=
|
||||
modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/mathutil v1.2.2 h1:+yFk8hBprV+4c0U9GjFtL+dV3N8hOJ8JCituQcMShFY=
|
||||
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/memory v1.0.4 h1:utMBrFcpnQDdNsmM6asmyH/FM9TqLPS7XF7otpJmrwM=
|
||||
modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8=
|
||||
modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc=
|
||||
modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A=
|
||||
modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM=
|
||||
modernc.org/memory v1.1.1 h1:bDOL0DIDLQv7bWhP3gMvIrnoFw+Eo6F7a2QK9HPDiFU=
|
||||
modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw=
|
||||
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||
modernc.org/sqlite v1.10.8 h1:tZzV+/FwlSBddiJAHLR+qxsw2nx7jpLMKOCVu6NTjxI=
|
||||
modernc.org/sqlite v1.10.8/go.mod h1:k45BYY2DU82vbS/dJ24OzHCtjPeMEcZ1DV2POiE8nRs=
|
||||
modernc.org/strutil v1.1.0 h1:+1/yCzZxY2pZwwrsbH+4T7BQMoLQ9QiBshRC9eicYsc=
|
||||
modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
|
||||
modernc.org/tcl v1.5.2 h1:sYNjGr4zK6cDH74USl8wVJRrvDX6UOLpG0j4lFvR0W0=
|
||||
modernc.org/tcl v1.5.2/go.mod h1:pmJYOLgpiys3oI4AeAafkcUfE+TKKilminxNyU/+Zlo=
|
||||
modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk=
|
||||
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
|
||||
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
modernc.org/z v1.0.1-0.20210308123920-1f282aa71362/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
|
||||
modernc.org/z v1.0.1 h1:WyIDpEpAIx4Hel6q/Pcgj/VhaQV5XPJ2I6ryIYbjnpc=
|
||||
modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
|
||||
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
|
||||
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
|
||||
|
||||
45
kanban/banner.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package kanban
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/fumiama/go-registry"
|
||||
)
|
||||
|
||||
var (
|
||||
info = [...]string{
|
||||
"* OneBot + ZeroBot + Golang",
|
||||
"* Version 1.5.0-beta5 - 2022-07-22 15:39:17 +0800 CST",
|
||||
"* Copyright © 2020 - 2022 FloatTech. All Rights Reserved.",
|
||||
"* Project: https://github.com/FloatTech/ZeroBot-Plugin",
|
||||
}
|
||||
// Banner ...
|
||||
Banner = strings.Join(info[:], "\n")
|
||||
reg = registry.NewRegReader("reilia.fumiama.top:32664", "fumiama")
|
||||
)
|
||||
|
||||
// PrintBanner ...
|
||||
func PrintBanner() {
|
||||
fmt.Print(
|
||||
"\n======================[ZeroBot-Plugin]======================",
|
||||
"\n", Banner, "\n",
|
||||
"----------------------[ZeroBot-公告栏]----------------------",
|
||||
"\n", Kanban(), "\n",
|
||||
"============================================================\n\n",
|
||||
)
|
||||
}
|
||||
|
||||
// Kanban ...
|
||||
func Kanban() string {
|
||||
err := reg.Connect()
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
defer reg.Close()
|
||||
text, err := reg.Get("ZeroBot-Plugin/kanban")
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
return text
|
||||
}
|
||||
6
kanban/init.go
Normal file
@@ -0,0 +1,6 @@
|
||||
// Package kanban 打印版本信息
|
||||
package kanban
|
||||
|
||||
func init() {
|
||||
PrintBanner()
|
||||
}
|
||||
289
main.go
@@ -1,71 +1,260 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
// 注:以下插件均可通过前面加 // 注释,注释后停用并不加载插件
|
||||
// 下列插件可与 wdvxdr1123/ZeroBot v1.1.2 以上配合单独使用
|
||||
// 词库类
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/atri" // ATRI词库
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/chat" // 基础词库
|
||||
"github.com/FloatTech/ZeroBot-Plugin/kanban" // 在最前打印 banner
|
||||
|
||||
// 实用类
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/github" // 搜索GitHub仓库
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/manager" // 群管
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/runcode" // 在线运行代码
|
||||
// ---------以下插件均可通过前面加 // 注释,注释后停用并不加载插件--------- //
|
||||
// ----------------------插件优先级按顺序从高到低---------------------- //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// ----------------------------高优先级区---------------------------- //
|
||||
// vvvvvvvvvvvvvvvvvvvvvvvvvvvv高优先级区vvvvvvvvvvvvvvvvvvvvvvvvvvvv //
|
||||
// vvvvvvvvvvvvvv高优先级区vvvvvvvvvvvvvv //
|
||||
// vvvvvvv高优先级区vvvvvvv //
|
||||
// vvvvvvvvvvvvvv //
|
||||
// vvvv //
|
||||
|
||||
// 娱乐类
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/music" // 点歌
|
||||
//_ "github.com/FloatTech/ZeroBot-ACGImage" //简易随机图片
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/setutime" // 涩图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/shindan" // 测定
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/chat" // 基础词库
|
||||
|
||||
// 以下为内置依赖,勿动
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/sleep_manage" // 统计睡眠时间
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/atri" // ATRI词库
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/manager" // 群管
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/thesaurus" // 词典匹配回复
|
||||
|
||||
_ "github.com/FloatTech/zbputils/job" // 定时指令触发器
|
||||
|
||||
// ^^^^ //
|
||||
// ^^^^^^^^^^^^^^ //
|
||||
// ^^^^^^^高优先级区^^^^^^^ //
|
||||
// ^^^^^^^^^^^^^^高优先级区^^^^^^^^^^^^^^ //
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^高优先级区^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
|
||||
// ----------------------------高优先级区---------------------------- //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// ----------------------------中优先级区---------------------------- //
|
||||
// vvvvvvvvvvvvvvvvvvvvvvvvvvvv中优先级区vvvvvvvvvvvvvvvvvvvvvvvvvvvv //
|
||||
// vvvvvvvvvvvvvv中优先级区vvvvvvvvvvvvvv //
|
||||
// vvvvvvv中优先级区vvvvvvv //
|
||||
// vvvvvvvvvvvvvv //
|
||||
// vvvv //
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ai_false" // 服务器监控
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aiwife" // 随机老婆
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/b14" // base16384加解密
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/baidu" // 百度一下
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibili" // b站相关
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/book_review" // 哀伤雪刃吧推书记录
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/cangtoushi" // 藏头诗
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/char_reverser" // 英文字符翻转
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/choose" // 选择困难症帮手
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/chouxianghua" // 说抽象话
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/coser" // 三次元小姐姐
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/cpstory" // cp短打
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/danbooru" // DeepDanbooru二次元图标签识别
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/diana" // 嘉心糖发病
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/drift_bottle" // 漂流瓶
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/emojimix" // 合成emoji
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/epidemic" // 城市疫情查询
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/font" // 渲染任意文字到图片
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/fortune" // 运势
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/funny" // 笑话
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/genshin" // 原神抽卡
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/gif" // 制图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/github" // 搜索GitHub仓库
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/guessmusic" // 猜歌
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/hs" // 炉石
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/hyaku" // 百人一首
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/image_finder" // 关键字搜图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/inject" // 注入指令
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/jandan" // 煎蛋网无聊图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/juejuezi" // 绝绝子生成器
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/lolicon" // lolicon 随机图片
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/midicreate" // 简易midi音乐制作
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/moyu" // 摸鱼
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/moyu_calendar" // 摸鱼人日历
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/music" // 点歌
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/nativesetu" // 本地涩图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/nativewife" // 本地老婆
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/nbnhhsh" // 拼音首字母缩写释义工具
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/novel" // 铅笔小说网搜索
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/nsfw" // nsfw图片识别
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/omikuji" // 浅草寺求签
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/qqwife" // 一群一天一夫一妻制群老婆
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/reborn" // 投胎
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/runcode" // 在线运行代码
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/saucenao" // 以图搜图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/scale" // 叔叔的AI二次元图片放大
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/score" // 分数
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/setutime" // 来份涩图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/shadiao" // 沙雕app
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/shindan" // 测定
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/tarot" // 抽塔罗牌
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/tiangou" // 舔狗日记
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/tracemoe" // 搜番
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/translation" // 翻译
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/vtb_quotation" // vtb语录
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wangyiyun" // 网易云音乐热评
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/word_count" // 聊天热词
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wordle" // 猜单词
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ymgal" // 月幕galgame
|
||||
|
||||
// _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wtf" // 鬼东西
|
||||
|
||||
// ^^^^ //
|
||||
// ^^^^^^^^^^^^^^ //
|
||||
// ^^^^^^^中优先级区^^^^^^^ //
|
||||
// ^^^^^^^^^^^^^^中优先级区^^^^^^^^^^^^^^ //
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^中优先级区^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
|
||||
// ----------------------------中优先级区---------------------------- //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// ----------------------------低优先级区---------------------------- //
|
||||
// vvvvvvvvvvvvvvvvvvvvvvvvvvvv低优先级区vvvvvvvvvvvvvvvvvvvvvvvvvvvv //
|
||||
// vvvvvvvvvvvvvv低优先级区vvvvvvvvvvvvvv //
|
||||
// vvvvvvv低优先级区vvvvvvv //
|
||||
// vvvvvvvvvvvvvv //
|
||||
// vvvv //
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/curse" // 骂人
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ai_reply" // 人工智能回复
|
||||
|
||||
// ^^^^ //
|
||||
// ^^^^^^^^^^^^^^ //
|
||||
// ^^^^^^^低优先级区^^^^^^^ //
|
||||
// ^^^^^^^^^^^^^^低优先级区^^^^^^^^^^^^^^ //
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^低优先级区^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
|
||||
// ----------------------------低优先级区---------------------------- //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// -----------------------以下为内置依赖,勿动------------------------ //
|
||||
"github.com/FloatTech/zbputils/process"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/driver"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
easy "github.com/t-tomalak/logrus-easy-formatter"
|
||||
// -----------------------以上为内置依赖,勿动------------------------ //
|
||||
)
|
||||
|
||||
func init() {
|
||||
log.SetFormatter(&easy.Formatter{
|
||||
TimestampFormat: "2006-01-02 15:04:05",
|
||||
LogFormat: "[zero][%time%][%lvl%]: %msg% \n",
|
||||
})
|
||||
log.SetLevel(log.DebugLevel)
|
||||
sus := make([]int64, 0, 16)
|
||||
// 解析命令行参数
|
||||
d := flag.Bool("d", false, "Enable debug level log and higher.")
|
||||
w := flag.Bool("w", false, "Enable warning level log and higher.")
|
||||
h := flag.Bool("h", false, "Display this help.")
|
||||
// 直接写死 AccessToken 时,请更改下面第二个参数
|
||||
token := flag.String("t", "", "Set AccessToken of WSClient.")
|
||||
// 直接写死 URL 时,请更改下面第二个参数
|
||||
url := flag.String("u", "ws://127.0.0.1:6700", "Set Url of WSClient.")
|
||||
// 默认昵称
|
||||
adana := flag.String("n", "椛椛", "Set default nickname.")
|
||||
prefix := flag.String("p", "/", "Set command prefix.")
|
||||
runcfg := flag.String("c", "", "Run from config file.")
|
||||
save := flag.String("s", "", "Save default config to file and exit.")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
if *h {
|
||||
kanban.PrintBanner()
|
||||
fmt.Println("Usage:")
|
||||
flag.PrintDefaults()
|
||||
os.Exit(0)
|
||||
} else {
|
||||
if *d && !*w {
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
}
|
||||
if *w {
|
||||
logrus.SetLevel(logrus.WarnLevel)
|
||||
}
|
||||
}
|
||||
|
||||
for _, s := range flag.Args() {
|
||||
i, err := strconv.ParseInt(s, 10, 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
sus = append(sus, i)
|
||||
}
|
||||
|
||||
// 通过代码写死的方式添加主人账号
|
||||
// sus = append(sus, 12345678)
|
||||
// sus = append(sus, 87654321)
|
||||
|
||||
if *runcfg != "" {
|
||||
f, err := os.Open(*runcfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
config.W = make([]*driver.WSClient, 0, 2)
|
||||
err = json.NewDecoder(f).Decode(&config)
|
||||
f.Close()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
config.Z.Driver = make([]zero.Driver, len(config.W))
|
||||
for i, w := range config.W {
|
||||
config.Z.Driver[i] = w
|
||||
}
|
||||
logrus.Infoln("[main] 从", *runcfg, "读取配置文件")
|
||||
return
|
||||
}
|
||||
|
||||
config.W = []*driver.WSClient{driver.NewWebSocketClient(*url, *token)}
|
||||
config.Z = zero.Config{
|
||||
NickName: append([]string{*adana}, "ATRI", "atri", "亚托莉", "アトリ"),
|
||||
CommandPrefix: *prefix,
|
||||
SuperUsers: sus,
|
||||
Driver: []zero.Driver{config.W[0]},
|
||||
}
|
||||
|
||||
if *save != "" {
|
||||
f, err := os.Create(*save)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = json.NewEncoder(f).Encode(&config)
|
||||
f.Close()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
logrus.Infoln("[main] 配置文件已保存到", *save)
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Print(`
|
||||
====================[ZeroBot-Plugin]====================
|
||||
* OneBot + ZeroBot + Golang
|
||||
* Version 1.0.3 - 2021-05-02 18:50:40.5489203 +0800 CST
|
||||
* Copyright © 2021 Kanri, DawnNights, Fumiama
|
||||
* Project: https://github.com/FloatTech/ZeroBot-Plugin
|
||||
========================================================
|
||||
`) // 启动打印
|
||||
zero.Run(zero.Config{
|
||||
NickName: []string{"椛椛", "ATRI", "atri", "亚托莉", "アトリ"},
|
||||
CommandPrefix: "/",
|
||||
SuperUsers: []string{"213864964"}, // 必须修改,否则无权限
|
||||
Driver: []zero.Driver{
|
||||
&driver.WSClient{
|
||||
Url: "ws://127.0.0.1:6700",
|
||||
AccessToken: "",
|
||||
},
|
||||
},
|
||||
})
|
||||
rand.Seed(time.Now().UnixNano()) // 全局 seed,其他插件无需再 seed
|
||||
// 帮助
|
||||
zero.OnFullMatchGroup([]string{"help", "/help", ".help", "菜单", "帮助"}, zero.OnlyToMe).SetBlock(true).SetPriority(999).
|
||||
zero.OnFullMatchGroup([]string{"/help", ".help", "菜单"}, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text(
|
||||
"* OneBot + ZeroBot + Golang ", "\n",
|
||||
"* Version 1.0.3 - 2021-05-02 18:50:40.5489203 +0800 CST", "\n",
|
||||
"* Copyright © 2021 Kanri, DawnNights, Fumiama ", "\n",
|
||||
"* Project: https://github.com/FloatTech/ZeroBot-Plugin",
|
||||
))
|
||||
ctx.SendChain(message.Text(kanban.Banner, "\n可发送\"/服务列表\"查看 bot 功能"))
|
||||
})
|
||||
select {}
|
||||
zero.OnFullMatch("查看zbp公告", zero.OnlyToMe, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text(kanban.Kanban()))
|
||||
})
|
||||
zero.RunAndBlock(config.Z, process.GlobalInitMutex.Unlock)
|
||||
}
|
||||
|
||||
70
main_win.go
Normal file
@@ -0,0 +1,70 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// windows 带颜色 log 自定义格式
|
||||
logrus.SetFormatter(&LogFormat{})
|
||||
}
|
||||
|
||||
const (
|
||||
colorCodePanic = "\x1b[1;31m" // color.Style{color.Bold, color.Red}.String()
|
||||
colorCodeFatal = "\x1b[1;31m" // color.Style{color.Bold, color.Red}.String()
|
||||
colorCodeError = "\x1b[31m" // color.Style{color.Red}.String()
|
||||
colorCodeWarn = "\x1b[33m" // color.Style{color.Yellow}.String()
|
||||
colorCodeInfo = "\x1b[37m" // color.Style{color.White}.String()
|
||||
colorCodeDebug = "\x1b[32m" // color.Style{color.Green}.String()
|
||||
colorCodeTrace = "\x1b[36m" // color.Style{color.Cyan}.String()
|
||||
colorReset = "\x1b[0m"
|
||||
)
|
||||
|
||||
// LogFormat specialize for zbp
|
||||
type LogFormat struct{}
|
||||
|
||||
// Format implements logrus.Formatter
|
||||
func (f LogFormat) Format(entry *logrus.Entry) ([]byte, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
buf.WriteString(getLogLevelColorCode(entry.Level))
|
||||
|
||||
buf.WriteByte('[')
|
||||
buf.WriteString(strings.ToUpper(entry.Level.String()))
|
||||
buf.WriteString("] ")
|
||||
buf.WriteString(entry.Message)
|
||||
buf.WriteString(" \n")
|
||||
|
||||
buf.WriteString(colorReset)
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// getLogLevelColorCode 获取日志等级对应色彩code
|
||||
func getLogLevelColorCode(level logrus.Level) string {
|
||||
switch level {
|
||||
case logrus.PanicLevel:
|
||||
return colorCodePanic
|
||||
case logrus.FatalLevel:
|
||||
return colorCodeFatal
|
||||
case logrus.ErrorLevel:
|
||||
return colorCodeError
|
||||
case logrus.WarnLevel:
|
||||
return colorCodeWarn
|
||||
case logrus.InfoLevel:
|
||||
return colorCodeInfo
|
||||
case logrus.DebugLevel:
|
||||
return colorCodeDebug
|
||||
case logrus.TraceLevel:
|
||||
return colorCodeTrace
|
||||
|
||||
default:
|
||||
return colorCodeInfo
|
||||
}
|
||||
}
|
||||
@@ -1,314 +0,0 @@
|
||||
package manager
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
timer "github.com/FloatTech/ZeroBot-Plugin-Timer"
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
// 菜单
|
||||
zero.OnFullMatch("群管系统", zero.AdminPermission).SetBlock(true).FirstPriority().
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text(
|
||||
"====群管====", "\n",
|
||||
"- 禁言@QQ 1分钟", "\n",
|
||||
"- 解除禁言 @QQ", "\n",
|
||||
"- 我要自闭 1分钟", "\n",
|
||||
"- 开启全员禁言", "\n",
|
||||
"- 解除全员禁言", "\n",
|
||||
"- 升为管理@QQ", "\n",
|
||||
"- 取消管理@QQ", "\n",
|
||||
"- 修改名片@QQ XXX", "\n",
|
||||
"- 修改头衔@QQ XXX", "\n",
|
||||
"- 申请头衔 XXX", "\n",
|
||||
"- 踢出群聊@QQ", "\n",
|
||||
"- 退出群聊 1234", "\n",
|
||||
"- 群聊转发 1234 XXX", "\n",
|
||||
"- 私聊转发 0000 XXX",
|
||||
))
|
||||
return
|
||||
})
|
||||
// 升为管理
|
||||
zero.OnRegex(`^升为管理.*?(\d+)`, zero.OnlyGroup, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SetGroupAdmin(
|
||||
ctx.Event.GroupID,
|
||||
strToInt(ctx.State["regex_matched"].([]string)[1]), // 被升为管理的人的qq
|
||||
true,
|
||||
)
|
||||
nickname := ctx.GetGroupMemberInfo( // 被升为管理的人的昵称
|
||||
ctx.Event.GroupID,
|
||||
strToInt(ctx.State["regex_matched"].([]string)[1]), // 被升为管理的人的qq
|
||||
false,
|
||||
).Get("nickname").Str
|
||||
ctx.SendChain(message.Text(nickname + " 升为了管理~"))
|
||||
return
|
||||
})
|
||||
// 取消管理
|
||||
zero.OnRegex(`^取消管理.*?(\d+)`, zero.OnlyGroup, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SetGroupAdmin(
|
||||
ctx.Event.GroupID,
|
||||
strToInt(ctx.State["regex_matched"].([]string)[1]), // 被取消管理的人的qq
|
||||
false,
|
||||
)
|
||||
nickname := ctx.GetGroupMemberInfo( // 被取消管理的人的昵称
|
||||
ctx.Event.GroupID,
|
||||
strToInt(ctx.State["regex_matched"].([]string)[1]), // 被取消管理的人的qq
|
||||
false,
|
||||
).Get("nickname").Str
|
||||
ctx.SendChain(message.Text("残念~ " + nickname + " 暂时失去了管理员的资格"))
|
||||
return
|
||||
})
|
||||
// 踢出群聊
|
||||
zero.OnRegex(`^踢出群聊.*?(\d+)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SetGroupKick(
|
||||
ctx.Event.GroupID,
|
||||
strToInt(ctx.State["regex_matched"].([]string)[1]), // 被踢出群聊的人的qq
|
||||
false,
|
||||
)
|
||||
nickname := ctx.GetGroupMemberInfo( // 被踢出群聊的人的昵称
|
||||
ctx.Event.GroupID,
|
||||
strToInt(ctx.State["regex_matched"].([]string)[1]), // 被踢出群聊的人的qq
|
||||
false,
|
||||
).Get("nickname").Str
|
||||
ctx.SendChain(message.Text("残念~ " + nickname + " 被放逐"))
|
||||
return
|
||||
})
|
||||
// 退出群聊
|
||||
zero.OnRegex(`^退出群聊.*?(\d+)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SetGroupLeave(
|
||||
strToInt(ctx.State["regex_matched"].([]string)[1]), // 要退出的群的群号
|
||||
true,
|
||||
)
|
||||
return
|
||||
})
|
||||
// 开启全体禁言
|
||||
zero.OnRegex(`^开启全员禁言$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SetGroupWholeBan(
|
||||
ctx.Event.GroupID,
|
||||
true,
|
||||
)
|
||||
ctx.SendChain(message.Text("全员自闭开始~"))
|
||||
return
|
||||
})
|
||||
// 解除全员禁言
|
||||
zero.OnRegex(`^解除全员禁言$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SetGroupWholeBan(
|
||||
ctx.Event.GroupID,
|
||||
false,
|
||||
)
|
||||
ctx.SendChain(message.Text("全员自闭结束~"))
|
||||
return
|
||||
})
|
||||
// 禁言
|
||||
zero.OnRegex(`^禁言.*?(\d+).*?\s(\d+)(.*)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
duration := strToInt(ctx.State["regex_matched"].([]string)[2])
|
||||
switch ctx.State["regex_matched"].([]string)[3] {
|
||||
case "分钟":
|
||||
//
|
||||
case "小时":
|
||||
duration = duration * 60
|
||||
case "天":
|
||||
duration = duration * 60 * 24
|
||||
default:
|
||||
//
|
||||
}
|
||||
if duration >= 43200 {
|
||||
duration = 43199 // qq禁言最大时长为一个月
|
||||
}
|
||||
ctx.SetGroupBan(
|
||||
ctx.Event.GroupID,
|
||||
strToInt(ctx.State["regex_matched"].([]string)[1]), // 要禁言的人的qq
|
||||
duration*60, // 要禁言的时间(分钟)
|
||||
)
|
||||
ctx.SendChain(message.Text("小黑屋收留成功~"))
|
||||
return
|
||||
})
|
||||
// 解除禁言
|
||||
zero.OnRegex(`^解除禁言.*?(\d+)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SetGroupBan(
|
||||
ctx.Event.GroupID,
|
||||
strToInt(ctx.State["regex_matched"].([]string)[1]), // 要解除禁言的人的qq
|
||||
0,
|
||||
)
|
||||
ctx.SendChain(message.Text("小黑屋释放成功~"))
|
||||
return
|
||||
})
|
||||
// 自闭禁言
|
||||
zero.OnRegex(`^我要自闭.*?(\d+)(.*)`, zero.OnlyGroup).SetBlock(true).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
duration := strToInt(ctx.State["regex_matched"].([]string)[1])
|
||||
switch ctx.State["regex_matched"].([]string)[2] {
|
||||
case "分钟":
|
||||
//
|
||||
case "小时":
|
||||
duration = duration * 60
|
||||
case "天":
|
||||
duration = duration * 60 * 24
|
||||
default:
|
||||
//
|
||||
}
|
||||
if duration >= 43200 {
|
||||
duration = 43199 // qq禁言最大时长为一个月
|
||||
}
|
||||
ctx.SetGroupBan(
|
||||
ctx.Event.GroupID,
|
||||
ctx.Event.UserID,
|
||||
duration*60, // 要自闭的时间(分钟)
|
||||
)
|
||||
ctx.SendChain(message.Text("那我就不手下留情了~"))
|
||||
return
|
||||
})
|
||||
// 修改名片
|
||||
zero.OnRegex(`^修改名片.*?(\d+).*?\s(.*)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SetGroupCard(
|
||||
ctx.Event.GroupID,
|
||||
strToInt(ctx.State["regex_matched"].([]string)[1]), // 被修改群名片的人
|
||||
ctx.State["regex_matched"].([]string)[2], // 修改成的群名片
|
||||
)
|
||||
ctx.SendChain(message.Text("嗯!已经修改了"))
|
||||
return
|
||||
})
|
||||
// 修改头衔
|
||||
zero.OnRegex(`^修改头衔.*?(\d+).*?\s(.*)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SetGroupSpecialTitle(
|
||||
ctx.Event.GroupID,
|
||||
strToInt(ctx.State["regex_matched"].([]string)[1]), // 被修改群头衔的人
|
||||
ctx.State["regex_matched"].([]string)[2], // 修改成的群头衔
|
||||
)
|
||||
ctx.SendChain(message.Text("嗯!已经修改了"))
|
||||
return
|
||||
})
|
||||
// 申请头衔
|
||||
zero.OnRegex(`^申请头衔(.*)`, zero.OnlyGroup).SetBlock(true).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SetGroupSpecialTitle(
|
||||
ctx.Event.GroupID,
|
||||
ctx.Event.UserID, // 被修改群头衔的人
|
||||
ctx.State["regex_matched"].([]string)[1], // 修改成的群头衔
|
||||
)
|
||||
ctx.SendChain(message.Text("嗯!不错的头衔呢~"))
|
||||
return
|
||||
})
|
||||
// 群聊转发
|
||||
zero.OnRegex(`^群聊转发.*?(\d+)\s(.*)`, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 对CQ码进行反转义
|
||||
content := ctx.State["regex_matched"].([]string)[2]
|
||||
content = strings.ReplaceAll(content, "[", "[")
|
||||
content = strings.ReplaceAll(content, "]", "]")
|
||||
ctx.SendGroupMessage(
|
||||
strToInt(ctx.State["regex_matched"].([]string)[1]), // 需要发送的群
|
||||
content, // 需要发送的信息
|
||||
)
|
||||
ctx.SendChain(message.Text("📧 --> " + ctx.State["regex_matched"].([]string)[1]))
|
||||
return
|
||||
})
|
||||
// 私聊转发
|
||||
zero.OnRegex(`^私聊转发.*?(\d+)\s(.*)`, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 对CQ码进行反转义
|
||||
content := ctx.State["regex_matched"].([]string)[2]
|
||||
content = strings.ReplaceAll(content, "[", "[")
|
||||
content = strings.ReplaceAll(content, "]", "]")
|
||||
ctx.SendPrivateMessage(
|
||||
strToInt(ctx.State["regex_matched"].([]string)[1]), // 需要发送的人的qq
|
||||
content, // 需要发送的信息
|
||||
)
|
||||
ctx.SendChain(message.Text("📧 --> " + ctx.State["regex_matched"].([]string)[1]))
|
||||
return
|
||||
})
|
||||
|
||||
// 定时提醒
|
||||
zero.OnRegex(`^在(.{1,2})月(.{1,3}日|每?周.?)的(.{1,3})点(.{1,3})分时(用.+)?提醒大家(.*)`, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
dateStrs := ctx.State["regex_matched"].([]string)
|
||||
ts := timer.GetFilledTimeStamp(dateStrs, false)
|
||||
ts.Grpid = uint64(ctx.Event.GroupID)
|
||||
if ts.Enable {
|
||||
go timer.RegisterTimer(ts, true)
|
||||
ctx.Send("记住了~")
|
||||
} else {
|
||||
ctx.Send("参数非法!")
|
||||
}
|
||||
return
|
||||
})
|
||||
// 取消定时
|
||||
zero.OnRegex(`^取消在(.{1,2})月(.{1,3}日|每?周.?)的(.{1,3})点(.{1,3})分的提醒`, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
dateStrs := ctx.State["regex_matched"].([]string)
|
||||
ts := timer.GetFilledTimeStamp(dateStrs, true)
|
||||
ti := timer.GetTimerInfo(ts)
|
||||
t, ok := (*timer.Timers)[ti]
|
||||
if ok {
|
||||
t.Enable = false
|
||||
delete(*timer.Timers, ti) //避免重复取消
|
||||
timer.SaveTimers()
|
||||
ctx.Send("取消成功~")
|
||||
} else {
|
||||
ctx.Send("没有这个定时器哦~")
|
||||
}
|
||||
return
|
||||
})
|
||||
|
||||
// 随机点名
|
||||
zero.OnFullMatchGroup([]string{"翻牌"}).SetBlock(true).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if ctx.Event.GroupID > 0 {
|
||||
list := ctx.GetGroupMemberList(ctx.Event.GroupID)
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
rand_index := fmt.Sprint(rand.Intn(int(list.Get("#").Int())))
|
||||
random_card := list.Get(rand_index + ".card").String()
|
||||
if random_card == "" {
|
||||
random_card = list.Get(rand_index + ".nickname").String()
|
||||
}
|
||||
ctx.Send(random_card + ",就是你啦!")
|
||||
}
|
||||
})
|
||||
// 入群欢迎
|
||||
zero.OnNotice().SetBlock(false).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if ctx.Event.NoticeType == "group_increase" {
|
||||
ctx.SendChain(message.Text("欢迎~"))
|
||||
}
|
||||
return
|
||||
})
|
||||
// 退群提醒
|
||||
zero.OnNotice().SetBlock(false).SetPriority(40).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if ctx.Event.NoticeType == "group_decrease" {
|
||||
ctx.SendChain(message.Text("有人跑路了~"))
|
||||
}
|
||||
return
|
||||
})
|
||||
// 运行 CQ 码
|
||||
zero.OnRegex(`^run(.*)$`, zero.SuperUserPermission).SetBlock(true).SetPriority(0).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
var cmd = ctx.State["regex_matched"].([]string)[1]
|
||||
cmd = strings.ReplaceAll(cmd, "[", "[")
|
||||
cmd = strings.ReplaceAll(cmd, "]", "]")
|
||||
ctx.Send(cmd)
|
||||
})
|
||||
}
|
||||
|
||||
func strToInt(str string) int64 {
|
||||
val, _ := strconv.ParseInt(str, 10, 64)
|
||||
return val
|
||||
}
|
||||
121
plugin/ai_false/ai_false.go
Normal file
@@ -0,0 +1,121 @@
|
||||
// Package aifalse 暂时只有服务器监控
|
||||
package aifalse
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/shirou/gopsutil/v3/cpu"
|
||||
"github.com/shirou/gopsutil/v3/disk"
|
||||
"github.com/shirou/gopsutil/v3/mem"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("aifalse", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "AIfalse\n" +
|
||||
"- 查询计算机当前活跃度: [检查身体 | 自检 | 启动自检 | 系统状态]\n" +
|
||||
"- 设置默认限速为每 m [分钟 | 秒] n 次触发",
|
||||
})
|
||||
c, ok := control.Lookup("aifalse")
|
||||
if !ok {
|
||||
panic("register aifalse error")
|
||||
}
|
||||
m := c.GetData(0)
|
||||
n := (m >> 16) & 0xffff
|
||||
m &= 0xffff
|
||||
if m != 0 || n != 0 {
|
||||
ctxext.SetDefaultLimiterManagerParam(time.Duration(m)*time.Second, int(n))
|
||||
logrus.Infoln("设置默认限速为每", m, "秒触发", n, "次")
|
||||
}
|
||||
engine.OnFullMatchGroup([]string{"检查身体", "自检", "启动自检", "系统状态"}, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text(
|
||||
"* CPU占用: ", cpuPercent(), "%\n",
|
||||
"* RAM占用: ", memPercent(), "%\n",
|
||||
"* 硬盘使用: ", diskPercent(),
|
||||
),
|
||||
)
|
||||
})
|
||||
engine.OnRegex(`^设置默认限速为每\s*(\d+)\s*(分钟|秒)\s*(\d+)\s*次触发$`, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if !ok {
|
||||
ctx.SendChain(message.Text("ERROR:no such plugin"))
|
||||
return
|
||||
}
|
||||
m, err := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
if ctx.State["regex_matched"].([]string)[2] == "分钟" {
|
||||
m *= 60
|
||||
}
|
||||
if m >= 65536 || m <= 0 {
|
||||
ctx.SendChain(message.Text("ERROR:interval too big"))
|
||||
return
|
||||
}
|
||||
n, err := strconv.ParseInt(ctx.State["regex_matched"].([]string)[3], 10, 64)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
if n >= 65536 || n <= 0 {
|
||||
ctx.SendChain(message.Text("ERROR:burst too big"))
|
||||
return
|
||||
}
|
||||
ctxext.SetDefaultLimiterManagerParam(time.Duration(m)*time.Second, int(n))
|
||||
err = c.SetData(0, (m&0xffff)|((n<<16)&0xffff0000))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("设置默认限速为每", m, "秒触发", n, "次"))
|
||||
})
|
||||
}
|
||||
|
||||
func cpuPercent() float64 {
|
||||
percent, err := cpu.Percent(time.Second, false)
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
return math.Round(percent[0])
|
||||
}
|
||||
|
||||
func memPercent() float64 {
|
||||
memInfo, err := mem.VirtualMemory()
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
return math.Round(memInfo.UsedPercent)
|
||||
}
|
||||
|
||||
func diskPercent() string {
|
||||
parts, err := disk.Partitions(true)
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
msg := ""
|
||||
for _, p := range parts {
|
||||
diskInfo, err := disk.Usage(p.Mountpoint)
|
||||
if err != nil {
|
||||
msg += "\n - " + err.Error()
|
||||
continue
|
||||
}
|
||||
pc := uint(math.Round(diskInfo.UsedPercent))
|
||||
if pc > 0 {
|
||||
msg += fmt.Sprintf("\n - %s(%dM) %d%%", p.Mountpoint, diskInfo.Total/1024/1024, pc)
|
||||
}
|
||||
}
|
||||
return msg
|
||||
}
|
||||
181
plugin/ai_reply/ai_tts.go
Normal file
@@ -0,0 +1,181 @@
|
||||
package aireply
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/pkumza/numcn"
|
||||
log "github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/aireply"
|
||||
"github.com/FloatTech/AnimeAPI/tts"
|
||||
"github.com/FloatTech/AnimeAPI/tts/baidutts"
|
||||
"github.com/FloatTech/AnimeAPI/tts/mockingbird"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
)
|
||||
|
||||
const ttsServiceName = "tts"
|
||||
|
||||
var re = regexp.MustCompile(`(\-|\+)?\d+(\.\d+)?`)
|
||||
|
||||
type ttsInstances struct {
|
||||
sync.RWMutex
|
||||
m map[string]tts.TTS
|
||||
l []string
|
||||
}
|
||||
|
||||
func (t *ttsInstances) List() []string {
|
||||
t.RLock()
|
||||
cl := make([]string, len(t.l))
|
||||
_ = copy(cl, t.l)
|
||||
t.RUnlock()
|
||||
return cl
|
||||
}
|
||||
|
||||
func init() {
|
||||
t := &ttsInstances{
|
||||
m: map[string]tts.TTS{
|
||||
"百度女声": baidutts.NewBaiduTTS(0),
|
||||
"百度男声": baidutts.NewBaiduTTS(1),
|
||||
"百度度逍遥": baidutts.NewBaiduTTS(3),
|
||||
"百度度丫丫": baidutts.NewBaiduTTS(4),
|
||||
"拟声鸟阿梓": nil,
|
||||
"拟声鸟文静": nil,
|
||||
"拟声鸟药水哥": nil,
|
||||
},
|
||||
l: []string{"拟声鸟阿梓", "拟声鸟文静", "拟声鸟药水哥", "百度女声", "百度男声", "百度度逍遥", "百度度丫丫"},
|
||||
}
|
||||
engine := control.Register(ttsServiceName, &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: true,
|
||||
Help: "语音回复(包括拟声鸟和百度)\n" +
|
||||
"- @Bot 任意文本(任意一句话回复)\n" +
|
||||
"- 设置语音模式[拟声鸟阿梓 | 拟声鸟文静 | 拟声鸟药水哥 | 百度女声 | 百度男声| 百度度逍遥 | 百度度丫丫]\n" +
|
||||
"- 设置默认语音模式[拟声鸟阿梓 | 拟声鸟文静 | 拟声鸟药水哥 | 百度女声 | 百度男声| 百度度逍遥 | 百度度丫丫]\n",
|
||||
})
|
||||
engine.OnMessage(zero.OnlyToMe).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
msg := ctx.ExtractPlainText()
|
||||
r := aireply.NewAIReply(getReplyMode(ctx))
|
||||
tts, err := t.new(t.getSoundMode(ctx))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
var reply string
|
||||
if tts != nil {
|
||||
rec, err := tts.Speak(ctx.Event.UserID, func() string {
|
||||
reply = r.TalkPlain(msg, zero.BotConfig.NickName[0])
|
||||
reply = re.ReplaceAllStringFunc(reply, func(s string) string {
|
||||
f, err := strconv.ParseFloat(s, 64)
|
||||
if err != nil {
|
||||
log.Errorln("[tts]:", err)
|
||||
return s
|
||||
}
|
||||
return numcn.EncodeFromFloat64(f)
|
||||
})
|
||||
log.Debugln("[tts]:", reply)
|
||||
return reply
|
||||
})
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Record(rec))
|
||||
} else {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(reply))
|
||||
}
|
||||
}
|
||||
})
|
||||
engine.OnRegex(`^设置语音模式(.*)$`, ctxext.ValueInList(func(ctx *zero.Ctx) string { return ctx.State["regex_matched"].([]string)[1] }, t)).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
param := ctx.State["regex_matched"].([]string)[1]
|
||||
err := t.setSoundMode(ctx, param)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("设置成功,当前模式为", param))
|
||||
})
|
||||
engine.OnRegex(`^设置默认语音模式(.*)$`, ctxext.ValueInList(func(ctx *zero.Ctx) string { return ctx.State["regex_matched"].([]string)[1] }, t)).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
param := ctx.State["regex_matched"].([]string)[1]
|
||||
t.setDefaultSoundMode(param)
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("设置成功,默认模式为", param))
|
||||
})
|
||||
}
|
||||
|
||||
// new 语音简单工厂
|
||||
func (t *ttsInstances) new(name string) (ts tts.TTS, err error) {
|
||||
t.RLock()
|
||||
ts = t.m[name]
|
||||
t.RUnlock()
|
||||
if ts == nil {
|
||||
switch name {
|
||||
case "拟声鸟阿梓":
|
||||
t.Lock()
|
||||
ts, err = mockingbird.NewMockingBirdTTS(0)
|
||||
t.Unlock()
|
||||
case "拟声鸟文静":
|
||||
t.Lock()
|
||||
ts, err = mockingbird.NewMockingBirdTTS(1)
|
||||
t.Unlock()
|
||||
case "拟声鸟药水哥":
|
||||
t.Lock()
|
||||
ts, err = mockingbird.NewMockingBirdTTS(2)
|
||||
t.Unlock()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (t *ttsInstances) setSoundMode(ctx *zero.Ctx, name string) error {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
var index int64
|
||||
t.RLock()
|
||||
for i, s := range t.l {
|
||||
if s == name {
|
||||
index = int64(i)
|
||||
break
|
||||
}
|
||||
}
|
||||
t.RUnlock()
|
||||
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
return m.SetData(gid, index)
|
||||
}
|
||||
|
||||
func (t *ttsInstances) getSoundMode(ctx *zero.Ctx) (name string) {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
m, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if ok {
|
||||
t.RLock()
|
||||
defer t.RUnlock()
|
||||
index := m.GetData(gid)
|
||||
if int(index) < len(t.l) {
|
||||
return t.l[index]
|
||||
}
|
||||
}
|
||||
return "拟声鸟阿梓"
|
||||
}
|
||||
|
||||
func (t *ttsInstances) setDefaultSoundMode(name string) {
|
||||
var index int
|
||||
t.RLock()
|
||||
for _, s := range t.l {
|
||||
if s == name {
|
||||
break
|
||||
}
|
||||
index++
|
||||
}
|
||||
t.RUnlock()
|
||||
t.Lock()
|
||||
t.l[0], t.l[index] = t.l[index], t.l[0]
|
||||
t.Unlock()
|
||||
}
|
||||
91
plugin/ai_reply/main.go
Normal file
@@ -0,0 +1,91 @@
|
||||
// Package aireply AI 回复
|
||||
package aireply
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/aireply"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
const (
|
||||
replyServiceName = "aireply"
|
||||
)
|
||||
|
||||
var replyModes = [...]string{"青云客", "小爱"}
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register(replyServiceName, &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "人工智能回复\n" +
|
||||
"- @Bot 任意文本(任意一句话回复)\n- 设置回复模式[青云客 | 小爱]\n- ",
|
||||
})
|
||||
// 回复 @和包括名字
|
||||
engine.OnMessage(zero.OnlyToMe).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
aireply := aireply.NewAIReply(getReplyMode(ctx))
|
||||
reply := message.ParseMessageFromString(aireply.Talk(ctx.ExtractPlainText(), zero.BotConfig.NickName[0]))
|
||||
// 回复
|
||||
time.Sleep(time.Second * 1)
|
||||
if zero.OnlyPublic(ctx) {
|
||||
reply = append(reply, message.Reply(ctx.Event.MessageID))
|
||||
ctx.Send(reply)
|
||||
return
|
||||
}
|
||||
ctx.Send(reply)
|
||||
})
|
||||
engine.OnPrefix(`设置回复模式`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
param := ctx.State["args"].(string)
|
||||
err := setReplyMode(ctx, param)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("成功"))
|
||||
})
|
||||
}
|
||||
|
||||
func setReplyMode(ctx *zero.Ctx, name string) error {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
var ok bool
|
||||
var index int64
|
||||
for i, s := range replyModes {
|
||||
if s == name {
|
||||
ok = true
|
||||
index = int64(i)
|
||||
break
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
return errors.New("no such mode")
|
||||
}
|
||||
m, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if !ok {
|
||||
return errors.New("no such plugin")
|
||||
}
|
||||
return m.SetData(gid, index)
|
||||
}
|
||||
|
||||
func getReplyMode(ctx *zero.Ctx) (name string) {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
m, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if ok {
|
||||
index := m.GetData(gid)
|
||||
if int(index) < len(replyModes) {
|
||||
return replyModes[index]
|
||||
}
|
||||
}
|
||||
return "青云客"
|
||||
}
|
||||
29
plugin/aiwife/non-existent.go
Normal file
@@ -0,0 +1,29 @@
|
||||
// Package aiwife 随机老婆
|
||||
package aiwife
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
const (
|
||||
bed = "https://www.thiswaifudoesnotexist.net/example-%d.jpg"
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
control.Register("aiwife", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "AIWife\n" +
|
||||
"- waifu | 随机waifu",
|
||||
}).ApplySingle(ctxext.DefaultSingle).OnFullMatchGroup([]string{"waifu", "随机waifu"}).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
miku := rand.Intn(100000) + 1
|
||||
ctx.SendChain(message.At(ctx.Event.UserID), message.Image(fmt.Sprintf(bed, miku)))
|
||||
})
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
// 本文件基于 https://github.com/Kyomotoi/ATRI
|
||||
// 为 Golang 移植版,语料、素材均来自上述项目
|
||||
// 本项目遵守 AGPL v3 协议进行开源
|
||||
/*
|
||||
Package atri 本文件基于 https://github.com/Kyomotoi/ATRI
|
||||
为 Golang 移植版,语料、素材均来自上述项目
|
||||
本项目遵守 AGPL v3 协议进行开源
|
||||
*/
|
||||
package atri
|
||||
|
||||
import (
|
||||
@@ -9,27 +11,40 @@ import (
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/process"
|
||||
)
|
||||
|
||||
var (
|
||||
PRIO = -1
|
||||
RES = "https://raw.dihe.moe/Yiwen-Chan/ZeroBot-Plugin/master/atri/"
|
||||
ENABLE = true
|
||||
const (
|
||||
// 服务名
|
||||
servicename = "atri"
|
||||
// ATRI 表情的 codechina 镜像
|
||||
res = "https://gitcode.net/u011570312/zbpdata/-/raw/main/Atri/"
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
zero.OnFullMatch("ATRI醒醒", zero.AdminPermission).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ENABLE = true
|
||||
ctx.SendChain(randText("嗯呜呜……夏生先生……?"))
|
||||
})
|
||||
zero.OnFullMatch("ATRI睡吧", zero.AdminPermission).SetBlock(true).SetPriority(PRIO).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ENABLE = false
|
||||
ctx.SendChain(randText("Zzz……Zzz……"))
|
||||
})
|
||||
zero.OnFullMatch("萝卜子", AtriSwitch(), AtriSleep()).SetBlock(true).SetPriority(PRIO).
|
||||
engine := control.Register(servicename, &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "本插件基于 ATRI ,为 Golang 移植版\n" +
|
||||
"- ATRI醒醒\n- ATRI睡吧\n- 萝卜子\n- 喜欢 | 爱你 | 爱 | suki | daisuki | すき | 好き | 贴贴 | 老婆 | 亲一个 | mua\n" +
|
||||
"- 草你妈 | 操你妈 | 脑瘫 | 废柴 | fw | 废物 | 战斗 | 爬 | 爪巴 | sb | SB | 傻B\n- 早安 | 早哇 | 早上好 | ohayo | 哦哈哟 | お早う | 早好 | 早 | 早早早\n" +
|
||||
"- 中午好 | 午安 | 午好\n- 晚安 | oyasuminasai | おやすみなさい | 晚好 | 晚上好\n- 高性能 | 太棒了 | すごい | sugoi | 斯国一 | よかった\n" +
|
||||
"- 没事 | 没关系 | 大丈夫 | 还好 | 不要紧 | 没出大问题 | 没伤到哪\n- 好吗 | 是吗 | 行不行 | 能不能 | 可不可以\n- 啊这\n- 我好了\n- ? | ? | ¿\n" +
|
||||
"- 离谱\n- 答应我",
|
||||
OnEnable: func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(message.Text("嗯呜呜……夏生先生……?"))
|
||||
},
|
||||
OnDisable: func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(message.Text("Zzz……Zzz……"))
|
||||
},
|
||||
})
|
||||
engine.OnFullMatch("萝卜子", isAtriSleeping).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
switch rand.Intn(2) {
|
||||
case 0:
|
||||
ctx.SendChain(randText("萝卜子是对机器人的蔑称!", "是亚托莉......萝卜子可是对机器人的蔑称"))
|
||||
@@ -37,22 +52,23 @@ func init() { // 插件主体
|
||||
ctx.SendChain(randRecord("RocketPunch.amr"))
|
||||
}
|
||||
})
|
||||
zero.OnKeywordGroup([]string{"喜欢", "爱你", "爱", "suki", "daisuki", "すき", "好き", "贴贴", "老婆", "亲一个", "mua"}, AtriSwitch(), AtriSleep(), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
engine.OnFullMatchGroup([]string{"喜欢", "爱你", "爱", "suki", "daisuki", "すき", "好き", "贴贴", "老婆", "亲一个", "mua"}, isAtriSleeping, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if rand.Intn(10) == 0 {
|
||||
ctx.SendChain(randImage("SUKI.jpg", "SUKI1.jpg", "SUKI2.png"))
|
||||
}
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(randImage("SUKI.jpg", "SUKI1.jpg", "SUKI2.png"))
|
||||
})
|
||||
zero.OnKeywordGroup([]string{"草你妈", "操你妈", "脑瘫", "废柴", "fw", "five", "废物", "战斗", "爬", "爪巴", "sb", "SB", "傻B"}, AtriSwitch(), AtriSleep(), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO - 1).
|
||||
engine.OnKeywordGroup([]string{"草你妈", "操你妈", "脑瘫", "废柴", "fw", "five", "废物", "战斗", "爬", "爪巴", "sb", "SB", "傻B"}, isAtriSleeping, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(randImage("FN.jpg", "WQ.jpg", "WQ1.jpg"))
|
||||
})
|
||||
zero.OnFullMatchGroup([]string{"早安", "早哇", "早上好", "ohayo", "哦哈哟", "お早う"}, AtriSwitch()).SetBlock(true).SetPriority(PRIO).
|
||||
engine.OnFullMatchGroup([]string{"早安", "早哇", "早上好", "ohayo", "哦哈哟", "お早う", "早好", "早", "早早早"}).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
now := time.Now().Hour()
|
||||
process.SleepAbout1sTo2s()
|
||||
switch {
|
||||
case now < 6: // 凌晨
|
||||
ctx.SendChain(randText(
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), randText(
|
||||
"zzzz......",
|
||||
"zzzzzzzz......",
|
||||
"zzz...好涩哦..zzz....",
|
||||
@@ -61,7 +77,7 @@ func init() { // 插件主体
|
||||
"...zzz....哧溜哧溜....",
|
||||
))
|
||||
case now >= 6 && now < 9:
|
||||
ctx.SendChain(randText(
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), randText(
|
||||
"啊......早上好...(哈欠)",
|
||||
"唔......吧唧...早上...哈啊啊~~~\n早上好......",
|
||||
"早上好......",
|
||||
@@ -73,25 +89,25 @@ func init() { // 插件主体
|
||||
"早上好......欸~~~脸好近呢",
|
||||
))
|
||||
case now >= 9 && now < 18:
|
||||
ctx.SendChain(randText(
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), randText(
|
||||
"哼!这个点还早啥,昨晚干啥去了!?",
|
||||
"熬夜了对吧熬夜了对吧熬夜了对吧???!",
|
||||
"是不是熬夜是不是熬夜是不是熬夜?!",
|
||||
))
|
||||
case now >= 18 && now < 24:
|
||||
ctx.SendChain(randText(
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), randText(
|
||||
"早个啥?哼唧!我都准备洗洗睡了!",
|
||||
"不是...你看看几点了,哼!",
|
||||
"晚上好哇",
|
||||
))
|
||||
}
|
||||
})
|
||||
zero.OnFullMatchGroup([]string{"中午好", "午安"}, AtriSwitch()).SetBlock(true).SetPriority(PRIO).
|
||||
engine.OnFullMatchGroup([]string{"中午好", "午安", "午好"}).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
now := time.Now().Hour()
|
||||
switch {
|
||||
case now < 6: // 凌晨
|
||||
ctx.SendChain(randText(
|
||||
if now > 11 && now < 15 { // 中午
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), randText(
|
||||
"午安w",
|
||||
"午觉要好好睡哦,ATRI会陪伴在你身旁的w",
|
||||
"嗯哼哼~睡吧,就像平常一样安眠吧~o(≧▽≦)o",
|
||||
@@ -99,12 +115,13 @@ func init() { // 插件主体
|
||||
))
|
||||
}
|
||||
})
|
||||
zero.OnFullMatchGroup([]string{"晚安", "oyasuminasai", "おやすみなさい"}, AtriSwitch()).SetBlock(true).SetPriority(PRIO).
|
||||
engine.OnFullMatchGroup([]string{"晚安", "oyasuminasai", "おやすみなさい", "晚好", "晚上好"}).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
now := time.Now().Hour()
|
||||
process.SleepAbout1sTo2s()
|
||||
switch {
|
||||
case now < 6: // 凌晨
|
||||
ctx.SendChain(randText(
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), randText(
|
||||
"zzzz......",
|
||||
"zzzzzzzz......",
|
||||
"zzz...好涩哦..zzz....",
|
||||
@@ -113,27 +130,27 @@ func init() { // 插件主体
|
||||
"...zzz....哧溜哧溜....",
|
||||
))
|
||||
case now >= 6 && now < 11:
|
||||
ctx.SendChain(randText(
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), randText(
|
||||
"你可猝死算了吧!",
|
||||
"?啊这",
|
||||
"亲,这边建议赶快去睡觉呢~~~",
|
||||
"不可忍不可忍不可忍!!为何这还不猝死!!",
|
||||
))
|
||||
case now >= 11 && now < 15:
|
||||
ctx.SendChain(randText(
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), randText(
|
||||
"午安w",
|
||||
"午觉要好好睡哦,ATRI会陪伴在你身旁的w",
|
||||
"嗯哼哼~睡吧,就像平常一样安眠吧~o(≧▽≦)o",
|
||||
"睡你午觉去!哼唧!!",
|
||||
))
|
||||
case now >= 15 && now < 19:
|
||||
ctx.SendChain(randText(
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), randText(
|
||||
"难不成??晚上不想睡觉??现在休息",
|
||||
"就......挺离谱的...现在睡觉",
|
||||
"现在还是白天哦,睡觉还太早了",
|
||||
))
|
||||
case now >= 19 && now < 24:
|
||||
ctx.SendChain(randText(
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), randText(
|
||||
"嗯哼哼~睡吧,就像平常一样安眠吧~o(≧▽≦)o",
|
||||
"......(打瞌睡)",
|
||||
"呼...呼...已经睡着了哦~...呼......",
|
||||
@@ -141,8 +158,9 @@ func init() { // 插件主体
|
||||
))
|
||||
}
|
||||
})
|
||||
zero.OnKeywordGroup([]string{"高性能", "太棒了", "すごい", "sugoi", "斯国一", "よかった"}, AtriSwitch(), AtriSleep(), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
engine.OnKeywordGroup([]string{"高性能", "太棒了", "すごい", "sugoi", "斯国一", "よかった"}, isAtriSleeping, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(randText(
|
||||
"当然,我是高性能的嘛~!",
|
||||
"小事一桩,我是高性能的嘛",
|
||||
@@ -161,8 +179,9 @@ func init() { // 插件主体
|
||||
"呣......我的高性能,毫无遗憾地施展出来了......",
|
||||
))
|
||||
})
|
||||
zero.OnKeywordGroup([]string{"没事", "没关系", "大丈夫", "还好", "不要紧", "没出大问题", "没伤到哪"}, AtriSwitch(), AtriSleep(), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
engine.OnKeywordGroup([]string{"没事", "没关系", "大丈夫", "还好", "不要紧", "没出大问题", "没伤到哪"}, isAtriSleeping, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(randText(
|
||||
"当然,我是高性能的嘛~!",
|
||||
"没事没事,因为我是高性能的嘛!嗯哼!",
|
||||
@@ -175,24 +194,28 @@ func init() { // 插件主体
|
||||
))
|
||||
})
|
||||
|
||||
zero.OnKeywordGroup([]string{"好吗", "是吗", "行不行", "能不能", "可不可以"}, AtriSwitch(), AtriSleep()).SetBlock(true).SetPriority(PRIO).
|
||||
engine.OnKeywordGroup([]string{"好吗", "是吗", "行不行", "能不能", "可不可以"}, isAtriSleeping).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
if rand.Intn(2) == 0 {
|
||||
ctx.SendChain(randImage("YES.png", "NO.jpg"))
|
||||
}
|
||||
})
|
||||
zero.OnFullMatchGroup([]string{"啊这"}, AtriSwitch(), AtriSleep()).SetBlock(true).SetPriority(PRIO).
|
||||
engine.OnKeywordGroup([]string{"啊这"}, isAtriSleeping).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
if rand.Intn(2) == 0 {
|
||||
ctx.SendChain(randImage("AZ.jpg", "AZ1.jpg"))
|
||||
}
|
||||
})
|
||||
zero.OnFullMatchGroup([]string{"我好了"}, AtriSwitch(), AtriSleep()).SetBlock(true).SetPriority(PRIO).
|
||||
engine.OnKeywordGroup([]string{"我好了"}, isAtriSleeping).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(randText("不许好!", "憋回去!"))
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), randText("不许好!", "憋回去!"))
|
||||
})
|
||||
zero.OnFullMatchGroup([]string{"?", "?", "¿"}, AtriSwitch(), AtriSleep()).SetBlock(true).SetPriority(PRIO).
|
||||
engine.OnFullMatchGroup([]string{"?", "?", "¿"}, isAtriSleeping).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
switch rand.Intn(5) {
|
||||
case 0:
|
||||
ctx.SendChain(randText("?", "?", "嗯?", "(。´・ω・)ん?", "ん?"))
|
||||
@@ -200,7 +223,7 @@ func init() { // 插件主体
|
||||
ctx.SendChain(randImage("WH.jpg", "WH1.jpg", "WH2.jpg", "WH3.jpg"))
|
||||
}
|
||||
})
|
||||
zero.OnKeyword("离谱", AtriSwitch(), AtriSleep()).SetBlock(true).SetPriority(PRIO).
|
||||
engine.OnKeyword("离谱", isAtriSleeping).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
switch rand.Intn(5) {
|
||||
case 0:
|
||||
@@ -209,40 +232,29 @@ func init() { // 插件主体
|
||||
ctx.SendChain(randImage("WH.jpg"))
|
||||
}
|
||||
})
|
||||
zero.OnKeyword("答应我", AtriSwitch(), AtriSleep(), zero.OnlyToMe).SetBlock(true).SetPriority(PRIO).
|
||||
engine.OnKeyword("答应我", isAtriSleeping, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(randText("我无法回应你的请求"))
|
||||
})
|
||||
}
|
||||
|
||||
func randText(text ...string) message.MessageSegment {
|
||||
length := len(text)
|
||||
return message.Text(text[rand.Intn(length)])
|
||||
return message.Text(text[rand.Intn(len(text))])
|
||||
}
|
||||
|
||||
func randImage(file ...string) message.MessageSegment {
|
||||
length := len(file)
|
||||
return message.Image(RES + file[rand.Intn(length)])
|
||||
return message.Image(res + file[rand.Intn(len(file))])
|
||||
}
|
||||
|
||||
func randRecord(file ...string) message.MessageSegment {
|
||||
length := len(file)
|
||||
return message.Record(RES + file[rand.Intn(length)])
|
||||
return message.Record(res + file[rand.Intn(len(file))])
|
||||
}
|
||||
|
||||
// AtriSwitch 控制 ATRI 的开关
|
||||
func AtriSwitch() zero.Rule {
|
||||
return func(ctx *zero.Ctx) bool {
|
||||
return ENABLE
|
||||
}
|
||||
}
|
||||
|
||||
// AtriSleep 凌晨0点到6点,ATRI 在睡觉,不回应任何请求
|
||||
func AtriSleep() zero.Rule {
|
||||
return func(ctx *zero.Ctx) bool {
|
||||
if now := time.Now().Hour(); now >= 1 && now < 6 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
// isAtriSleeping 凌晨0点到6点,ATRI 在睡觉,不回应任何请求
|
||||
func isAtriSleeping(ctx *zero.Ctx) bool {
|
||||
if now := time.Now().Hour(); now >= 1 && now < 6 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
76
plugin/b14/main.go
Normal file
@@ -0,0 +1,76 @@
|
||||
// Package b14coder base16384 与 tea 加解密
|
||||
package b14coder
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
base14 "github.com/fumiama/go-base16384"
|
||||
tea "github.com/fumiama/gofastTEA"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
)
|
||||
|
||||
func init() {
|
||||
en := control.Register("base16384", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "base16384加解密\n" +
|
||||
"- 加密xxx\n- 解密xxx\n- 用yyy加密xxx\n- 用yyy解密xxx",
|
||||
})
|
||||
en.OnRegex(`^加密\s*(.+)$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
str := ctx.State["regex_matched"].([]string)[1]
|
||||
es := base14.EncodeString(str)
|
||||
if es != "" {
|
||||
ctx.SendChain(message.Text(es))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("加密失败!"))
|
||||
}
|
||||
})
|
||||
en.OnRegex(`^解密\s*([一-踀]+[㴁-㴆]?)$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
str := ctx.State["regex_matched"].([]string)[1]
|
||||
es := base14.DecodeString(str)
|
||||
if es != "" {
|
||||
ctx.SendChain(message.Text(es))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("解密失败!"))
|
||||
}
|
||||
})
|
||||
en.OnRegex(`^用(.+)加密\s*(.+)$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
key, str := ctx.State["regex_matched"].([]string)[1], ctx.State["regex_matched"].([]string)[2]
|
||||
t := getea(key)
|
||||
es, err := base14.UTF16BE2UTF8(base14.Encode(t.Encrypt(helper.StringToBytes(str))))
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text(helper.BytesToString(es)))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("加密失败!"))
|
||||
}
|
||||
})
|
||||
en.OnRegex(`^用(.+)解密\s*([一-踀]+[㴁-㴆]?)$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
key, str := ctx.State["regex_matched"].([]string)[1], ctx.State["regex_matched"].([]string)[2]
|
||||
t := getea(key)
|
||||
es, err := base14.UTF82UTF16BE(helper.StringToBytes(str))
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text(helper.BytesToString(t.Decrypt(base14.Decode(es)))))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("解密失败!"))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func getea(key string) tea.TEA {
|
||||
kr := []rune(key)
|
||||
if len(kr) > 4 {
|
||||
kr = kr[:4]
|
||||
} else {
|
||||
for len(kr) < 4 {
|
||||
kr = append(kr, rune(4-len(kr)))
|
||||
}
|
||||
}
|
||||
return *(*tea.TEA)(*(*unsafe.Pointer)(unsafe.Pointer(&kr)))
|
||||
}
|
||||
27
plugin/baidu/search.go
Normal file
@@ -0,0 +1,27 @@
|
||||
// Package baidu 百度一下
|
||||
package baidu
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
)
|
||||
|
||||
func init() {
|
||||
control.Register("baidu", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "baidu\n" +
|
||||
"- 百度下[xxx]",
|
||||
}).OnPrefix("百度下").SetBlock(true).Limit(ctxext.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
txt := ctx.State["args"].(string)
|
||||
if txt != "" {
|
||||
ctx.SendChain(message.Text("https://buhuibaidu.me/?s=" + url.QueryEscape(txt)))
|
||||
}
|
||||
})
|
||||
}
|
||||
128
plugin/bilibili/api.go
Normal file
@@ -0,0 +1,128 @@
|
||||
package bilibili
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/FloatTech/zbputils/binary"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
var (
|
||||
errNeedCookie = errors.New("该api需要设置b站cookie,请发送命令设置cookie,例如\"设置b站cookie SESSDATA=82da790d,1663822823,06ecf*31\"")
|
||||
)
|
||||
|
||||
// searchUser 查找b站用户
|
||||
func searchUser(keyword string) (r []searchResult, err error) {
|
||||
data, err := web.GetData(fmt.Sprintf(searchUserURL, keyword))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
j := gjson.ParseBytes(data)
|
||||
if j.Get("data.numResults").Int() == 0 {
|
||||
err = errors.New("查无此人")
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(binary.StringToBytes(j.Get("data.result").Raw), &r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// getVtbDetail 查找vtb信息
|
||||
func getVtbDetail(uid string) (result vtbDetail, err error) {
|
||||
data, err := web.GetData(fmt.Sprintf(vtbDetailURL, uid))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err = json.Unmarshal(data, &result); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// getMemberCard 获取b站个人详情
|
||||
func getMemberCard(uid interface{}) (result memberCard, err error) {
|
||||
data, err := web.GetData(fmt.Sprintf(memberCardURL, uid))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(binary.StringToBytes(gjson.ParseBytes(data).Get("card").Raw), &result)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// getMedalwall 用b站uid获得牌子
|
||||
func getMedalwall(uid string) (result []medal, err error) {
|
||||
client := &http.Client{}
|
||||
req, err := http.NewRequest("GET", fmt.Sprintf(medalwallURL, uid), nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c := vdb.getBilibiliCookie()
|
||||
req.Header.Add("cookie", c.Value)
|
||||
res, err := client.Do(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer res.Body.Close()
|
||||
var md medalData
|
||||
err = json.NewDecoder(res.Body).Decode(&md)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if md.Code == -101 {
|
||||
err = errNeedCookie
|
||||
return
|
||||
}
|
||||
if md.Code != 0 {
|
||||
err = errors.New(md.Message)
|
||||
}
|
||||
result = md.Data.List
|
||||
return
|
||||
}
|
||||
|
||||
// getArticleInfo 用id查专栏信息
|
||||
func getArticleInfo(id string) (card Card, err error) {
|
||||
var data []byte
|
||||
data, err = web.GetData(fmt.Sprintf(articleInfoURL, id))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(binary.StringToBytes(gjson.ParseBytes(data).Get("data").Raw), &card)
|
||||
return
|
||||
}
|
||||
|
||||
// getLiveRoomInfo 用直播间id查直播间信息
|
||||
func getLiveRoomInfo(roomID string) (card roomCard, err error) {
|
||||
var data []byte
|
||||
data, err = web.GetData(fmt.Sprintf(liveRoomInfoURL, roomID))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(binary.StringToBytes(gjson.ParseBytes(data).Get("data").Raw), &card)
|
||||
return
|
||||
}
|
||||
|
||||
// getVideoInfo 用av或bv查视频信息
|
||||
func getVideoInfo(id string) (card Card, err error) {
|
||||
var data []byte
|
||||
_, err = strconv.Atoi(id)
|
||||
if err == nil {
|
||||
data, err = web.GetData(fmt.Sprintf(videoInfoURL, id, ""))
|
||||
} else {
|
||||
data, err = web.GetData(fmt.Sprintf(videoInfoURL, "", id))
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(binary.StringToBytes(gjson.ParseBytes(data).Get("data").Raw), &card)
|
||||
return
|
||||
}
|
||||
347
plugin/bilibili/bilibili.go
Normal file
@@ -0,0 +1,347 @@
|
||||
// Package bilibili 查询b站用户信息
|
||||
package bilibili
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/FloatTech/zbputils/img"
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
"github.com/FloatTech/zbputils/img/writer"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
"github.com/fogleman/gg"
|
||||
log "github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
var re = regexp.MustCompile(`^\d+$`)
|
||||
|
||||
// 查成分的
|
||||
func init() {
|
||||
engine := control.Register("bilibili", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "bilibili\n" +
|
||||
"- >vup info [xxx]\n" +
|
||||
"- >user info [xxx]\n" +
|
||||
"- 查成分 [xxx]\n" +
|
||||
"- 设置b站cookie SESSDATA=82da790d,1663822823,06ecf*31\n" +
|
||||
"- 更新vup",
|
||||
PublicDataFolder: "Bilibili",
|
||||
})
|
||||
cachePath := engine.DataFolder() + "cache/"
|
||||
_ = os.RemoveAll(cachePath)
|
||||
_ = os.MkdirAll(cachePath, 0755)
|
||||
var getdb = ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||
var err error
|
||||
_, _ = engine.GetLazyData("bilibili.db", false)
|
||||
vdb, err = initialize(engine.DataFolder() + "bilibili.db")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
engine.OnRegex(`^>user info\s?(.{1,25})$`, getPara).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
id := ctx.State["uid"].(string)
|
||||
card, err := getMemberCard(id)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(
|
||||
"uid: ", card.Mid, "\n",
|
||||
"name: ", card.Name, "\n",
|
||||
"sex: ", card.Sex, "\n",
|
||||
"sign: ", card.Sign, "\n",
|
||||
"level: ", card.LevelInfo.CurrentLevel, "\n",
|
||||
"birthday: ", card.Birthday,
|
||||
))
|
||||
})
|
||||
|
||||
engine.OnRegex(`^>vup info\s?(.{1,25})$`, getPara).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
id := ctx.State["uid"].(string)
|
||||
// 获取详情
|
||||
fo, err := getVtbDetail(id)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(
|
||||
"b站id: ", fo.Mid, "\n",
|
||||
"名字: ", fo.Uname, "\n",
|
||||
"当前粉丝数: ", fo.Follower, "\n",
|
||||
"24h涨粉数: ", fo.Rise, "\n",
|
||||
"视频投稿数: ", fo.Video, "\n",
|
||||
"直播间id: ", fo.Roomid, "\n",
|
||||
"舰队: ", fo.GuardNum, "\n",
|
||||
"直播总排名: ", fo.AreaRank, "\n",
|
||||
"数据来源: ", "https://vtbs.moe/detail/", fo.Mid, "\n",
|
||||
"数据获取时间: ", time.Now().Format("2006-01-02 15:04:05"),
|
||||
))
|
||||
})
|
||||
|
||||
engine.OnRegex(`^查成分\s?(.{1,25})$`, getdb, getPara).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
id := ctx.State["uid"].(string)
|
||||
today := time.Now().Format("20060102")
|
||||
drawedFile := cachePath + id + today + "vupLike.png"
|
||||
if file.IsExist(drawedFile) {
|
||||
ctx.SendChain(message.Image("file:///" + file.BOTPATH + "/" + drawedFile))
|
||||
return
|
||||
}
|
||||
u, err := getMemberCard(id)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
vups, err := vdb.filterVup(u.Attentions)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
vupLen := len(vups)
|
||||
medals, err := getMedalwall(id)
|
||||
sort.Sort(medalSlice(medals))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
}
|
||||
frontVups := make([]vup, 0)
|
||||
medalMap := make(map[int64]medal)
|
||||
for _, v := range medals {
|
||||
up := vup{
|
||||
Mid: v.Mid,
|
||||
Uname: v.Uname,
|
||||
}
|
||||
frontVups = append(frontVups, up)
|
||||
medalMap[v.Mid] = v
|
||||
}
|
||||
vups = append(vups, frontVups...)
|
||||
copy(vups[len(frontVups):], vups)
|
||||
copy(vups, frontVups)
|
||||
for i := len(frontVups); i < len(vups); i++ {
|
||||
if _, ok := medalMap[vups[i].Mid]; ok {
|
||||
vups = append(vups[:i], vups[i+1:]...)
|
||||
i--
|
||||
}
|
||||
}
|
||||
facePath := cachePath + id + "vupFace" + path.Ext(u.Face)
|
||||
backX := 500
|
||||
backY := 500
|
||||
var back image.Image
|
||||
if path.Ext(u.Face) != ".webp" {
|
||||
err = initFacePic(facePath, u.Face)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
back, err = gg.LoadImage(facePath)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
back = img.Size(back, backX, backY).Im
|
||||
}
|
||||
if len(vups) > 50 {
|
||||
ctx.SendChain(message.Text(u.Name + "关注的up主太多了,只展示前50个up"))
|
||||
vups = vups[:50]
|
||||
}
|
||||
canvas := gg.NewContext(1500, int(500*(1.1+float64(len(vups))/3)))
|
||||
fontSize := 50.0
|
||||
canvas.SetColor(color.White)
|
||||
canvas.Clear()
|
||||
if back != nil {
|
||||
canvas.DrawImage(back, 0, 0)
|
||||
}
|
||||
canvas.SetColor(color.Black)
|
||||
_, err = file.GetLazyData(text.BoldFontFile, true)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
}
|
||||
if err = canvas.LoadFontFace(text.BoldFontFile, fontSize); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
sl, _ := canvas.MeasureString("好")
|
||||
length, h := canvas.MeasureString(u.Mid)
|
||||
n, _ := canvas.MeasureString(u.Name)
|
||||
canvas.DrawString(u.Name, 550, 160-h)
|
||||
canvas.DrawRoundedRectangle(600+n-length*0.1, 160-h*2.5, length*1.2, h*2, fontSize*0.2)
|
||||
canvas.SetRGB255(221, 221, 221)
|
||||
canvas.Fill()
|
||||
canvas.SetColor(color.Black)
|
||||
canvas.DrawString(u.Mid, 600+n, 160-h)
|
||||
canvas.DrawString(fmt.Sprintf("粉丝:%d", u.Fans), 550, 240-h)
|
||||
canvas.DrawString(fmt.Sprintf("关注:%d", len(u.Attentions)), 1000, 240-h)
|
||||
canvas.DrawString(fmt.Sprintf("管人痴成分:%.2f%%(%d/%d)", float64(vupLen)/float64(len(u.Attentions))*100, vupLen, len(u.Attentions)), 550, 320-h)
|
||||
regtime := time.Unix(u.Regtime, 0).Format("2006-01-02 15:04:05")
|
||||
canvas.DrawString("注册日期:"+regtime, 550, 400-h)
|
||||
canvas.DrawString("查询日期:"+time.Now().Format("2006-01-02"), 550, 480-h)
|
||||
for i, v := range vups {
|
||||
if i%2 == 1 {
|
||||
canvas.SetRGB255(245, 245, 245)
|
||||
canvas.DrawRectangle(0, float64(backY)*1.1+float64(i)*float64(backY)/3, float64(backX*3), float64(backY)/3)
|
||||
canvas.Fill()
|
||||
}
|
||||
canvas.SetColor(color.Black)
|
||||
nl, _ := canvas.MeasureString(v.Uname)
|
||||
canvas.DrawString(v.Uname, float64(backX)*0.1, float64(backY)*1.1+float64(i+1)*float64(backY)/3-2*h)
|
||||
ml, _ := canvas.MeasureString(strconv.FormatInt(v.Mid, 10))
|
||||
canvas.DrawRoundedRectangle(nl-0.1*ml+float64(backX)*0.2, float64(backY)*1.1+float64(i+1)*float64(backY)/3-h*3.5, ml*1.2, h*2, fontSize*0.2)
|
||||
canvas.SetRGB255(221, 221, 221)
|
||||
canvas.Fill()
|
||||
canvas.SetColor(color.Black)
|
||||
canvas.DrawString(strconv.FormatInt(v.Mid, 10), nl+float64(backX)*0.2, float64(backY)*1.1+float64(i+1)*float64(backY)/3-2*h)
|
||||
if m, ok := medalMap[v.Mid]; ok {
|
||||
mnl, _ := canvas.MeasureString(m.MedalName)
|
||||
grad := gg.NewLinearGradient(nl+ml-sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-3.5*h, nl+ml+mnl+sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-1.5*h)
|
||||
r, g, b := int2rbg(m.MedalColorStart)
|
||||
grad.AddColorStop(0, color.RGBA{R: uint8(r), G: uint8(g), B: uint8(b), A: 255})
|
||||
r, g, b = int2rbg(m.MedalColorEnd)
|
||||
grad.AddColorStop(1, color.RGBA{R: uint8(r), G: uint8(g), B: uint8(b), A: 255})
|
||||
canvas.SetFillStyle(grad)
|
||||
canvas.SetLineWidth(4)
|
||||
canvas.MoveTo(nl+ml-sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-3.5*h)
|
||||
canvas.LineTo(nl+ml+mnl+sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-3.5*h)
|
||||
canvas.LineTo(nl+ml+mnl+sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-1.5*h)
|
||||
canvas.LineTo(nl+ml-sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-1.5*h)
|
||||
canvas.ClosePath()
|
||||
canvas.Fill()
|
||||
canvas.SetColor(color.White)
|
||||
canvas.DrawString(m.MedalName, nl+ml+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-2*h)
|
||||
r, g, b = int2rbg(m.MedalColorBorder)
|
||||
canvas.SetRGB255(int(r), int(g), int(b))
|
||||
canvas.DrawString(strconv.FormatInt(m.Level, 10), nl+ml+mnl+sl+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-2*h)
|
||||
mll, _ := canvas.MeasureString(strconv.FormatInt(m.Level, 10))
|
||||
canvas.SetLineWidth(4)
|
||||
canvas.MoveTo(nl+ml-sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-3.5*h)
|
||||
canvas.LineTo(nl+ml+mnl+mll+sl/2+float64(backX)*0.5, float64(backY)*1.1+float64(i+1)*float64(backY)/3-3.5*h)
|
||||
canvas.LineTo(nl+ml+mnl+mll+sl/2+float64(backX)*0.5, float64(backY)*1.1+float64(i+1)*float64(backY)/3-1.5*h)
|
||||
canvas.LineTo(nl+ml-sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-1.5*h)
|
||||
canvas.ClosePath()
|
||||
canvas.Stroke()
|
||||
}
|
||||
}
|
||||
f, err := os.Create(drawedFile)
|
||||
if err != nil {
|
||||
log.Errorln("[bilibili]", err)
|
||||
data, cl := writer.ToBytes(canvas.Image())
|
||||
ctx.SendChain(message.ImageBytes(data))
|
||||
cl()
|
||||
return
|
||||
}
|
||||
_, err = writer.WriteTo(canvas.Image(), f)
|
||||
_ = f.Close()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Image("file:///" + file.BOTPATH + "/" + drawedFile))
|
||||
})
|
||||
|
||||
engine.OnRegex(`^设置b站cookie?\s+(.{1,100})$`, zero.SuperUserPermission, getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
cookie := ctx.State["regex_matched"].([]string)[1]
|
||||
err := vdb.setBilibiliCookie(cookie)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("成功设置b站cookie为" + cookie))
|
||||
})
|
||||
|
||||
engine.OnFullMatch("更新vup", zero.SuperUserPermission, getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text("少女祈祷中..."))
|
||||
err := updateVup()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("vup已更新"))
|
||||
})
|
||||
}
|
||||
|
||||
func initFacePic(filename, faceURL string) error {
|
||||
if file.IsNotExist(filename) {
|
||||
data, err := web.GetData(faceURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.WriteFile(filename, data, 0666)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func int2rbg(t int64) (int64, int64, int64) {
|
||||
var buf [8]byte
|
||||
binary.LittleEndian.PutUint64(buf[:], uint64(t))
|
||||
b, g, r := int64(buf[0]), int64(buf[1]), int64(buf[2])
|
||||
return r, g, b
|
||||
}
|
||||
|
||||
func getPara(ctx *zero.Ctx) bool {
|
||||
keyword := ctx.State["regex_matched"].([]string)[1]
|
||||
if !re.MatchString(keyword) {
|
||||
searchRes, err := searchUser(keyword)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
ctx.State["uid"] = strconv.FormatInt(searchRes[0].Mid, 10)
|
||||
return true
|
||||
}
|
||||
next := zero.NewFutureEvent("message", 999, false, ctx.CheckSession())
|
||||
recv, cancel := next.Repeat()
|
||||
defer cancel()
|
||||
ctx.SendChain(message.Text("输入为纯数字,请选择查询uid还是用户名,输入对应序号:\n0. 查询uid\n1. 查询用户名"))
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Second * 10):
|
||||
ctx.SendChain(message.Text("时间太久啦!", zero.BotConfig.NickName[0], "帮你选择查询uid"))
|
||||
ctx.State["uid"] = keyword
|
||||
return true
|
||||
case c := <-recv:
|
||||
msg := c.Event.Message.ExtractPlainText()
|
||||
num, err := strconv.Atoi(msg)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("请输入数字!"))
|
||||
continue
|
||||
}
|
||||
if num < 0 || num > 1 {
|
||||
ctx.SendChain(message.Text("序号非法!"))
|
||||
continue
|
||||
}
|
||||
if num == 0 {
|
||||
ctx.State["uid"] = keyword
|
||||
return true
|
||||
} else if num == 1 {
|
||||
searchRes, err := searchUser(keyword)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
ctx.State["uid"] = strconv.FormatInt(searchRes[0].Mid, 10)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
105
plugin/bilibili/bilibili_parse.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package bilibili
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
var (
|
||||
limit = ctxext.NewLimiterManager(time.Second*10, 1)
|
||||
searchVideo = `bilibili.com\\?/video\\?/(?:av(\d+)|([bB][vV][0-9a-zA-Z]+))`
|
||||
searchDynamic = `(t.bilibili.com|m.bilibili.com\\?/dynamic)\\?/(\d+)`
|
||||
searchArticle = `bilibili.com\\?/read\\?/(?:cv|mobile\\?/)(\d+)`
|
||||
searchLiveRoom = `live.bilibili.com\\?/(\d+)`
|
||||
searchVideoRe = regexp.MustCompile(searchVideo)
|
||||
searchDynamicRe = regexp.MustCompile(searchDynamic)
|
||||
searchArticleRe = regexp.MustCompile(searchArticle)
|
||||
searchLiveRoomRe = regexp.MustCompile(searchLiveRoom)
|
||||
)
|
||||
|
||||
// 插件主体
|
||||
func init() {
|
||||
en := control.Register("bilibiliparse", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "b站动态、专栏、视频、直播解析\n" +
|
||||
"- t.bilibili.com/642277677329285174 | bilibili.com/read/cv17134450 | bilibili.com/video/BV13B4y1x7pS | live.bilibili.com/22603245 ",
|
||||
})
|
||||
en.OnRegex(`((b23|acg).tv|bili2233.cn)/[0-9a-zA-Z]+`).SetBlock(true).Limit(limit.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
url := ctx.State["regex_matched"].([]string)[0]
|
||||
realurl, err := getrealurl("https://" + url)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
switch {
|
||||
case searchVideoRe.MatchString(realurl):
|
||||
ctx.State["regex_matched"] = searchVideoRe.FindStringSubmatch(realurl)
|
||||
handleVideo(ctx)
|
||||
case searchDynamicRe.MatchString(realurl):
|
||||
ctx.State["regex_matched"] = searchDynamicRe.FindStringSubmatch(realurl)
|
||||
handleDynamic(ctx)
|
||||
case searchArticleRe.MatchString(realurl):
|
||||
ctx.State["regex_matched"] = searchArticleRe.FindStringSubmatch(realurl)
|
||||
handleArticle(ctx)
|
||||
case searchLiveRoomRe.MatchString(realurl):
|
||||
ctx.State["regex_matched"] = searchLiveRoomRe.FindStringSubmatch(realurl)
|
||||
handleLive(ctx)
|
||||
}
|
||||
})
|
||||
en.OnRegex(searchVideo).SetBlock(true).Limit(limit.LimitByGroup).Handle(handleVideo)
|
||||
en.OnRegex(searchDynamic).SetBlock(true).Limit(limit.LimitByGroup).Handle(handleDynamic)
|
||||
en.OnRegex(searchArticle).SetBlock(true).Limit(limit.LimitByGroup).Handle(handleArticle)
|
||||
en.OnRegex(searchLiveRoom).SetBlock(true).Limit(limit.LimitByGroup).Handle(handleLive)
|
||||
}
|
||||
|
||||
func handleVideo(ctx *zero.Ctx) {
|
||||
id := ctx.State["regex_matched"].([]string)[1]
|
||||
if id == "" {
|
||||
id = ctx.State["regex_matched"].([]string)[2]
|
||||
}
|
||||
card, err := getVideoInfo(id)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
msg, err := videoCard2msg(card)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(msg...)
|
||||
}
|
||||
|
||||
func handleDynamic(ctx *zero.Ctx) {
|
||||
msg, err := dynamicDetail(ctx.State["regex_matched"].([]string)[2])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(msg...)
|
||||
}
|
||||
|
||||
func handleArticle(ctx *zero.Ctx) {
|
||||
card, err := getArticleInfo(ctx.State["regex_matched"].([]string)[1])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(articleCard2msg(card, ctx.State["regex_matched"].([]string)[1])...)
|
||||
}
|
||||
|
||||
func handleLive(ctx *zero.Ctx) {
|
||||
card, err := getLiveRoomInfo(ctx.State["regex_matched"].([]string)[1])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(liveCard2msg(card)...)
|
||||
}
|
||||
233
plugin/bilibili/card2msg.go
Normal file
@@ -0,0 +1,233 @@
|
||||
package bilibili
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/zbputils/binary"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
"github.com/tidwall/gjson"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
var (
|
||||
typeMsg = map[int]string{
|
||||
1: "转发了动态",
|
||||
2: "有图营业",
|
||||
4: "无图营业",
|
||||
8: "投稿了视频",
|
||||
16: "投稿了短视频",
|
||||
64: "投稿了文章",
|
||||
256: "投稿了音频",
|
||||
2048: "发布了简报",
|
||||
4200: "发布了直播",
|
||||
4308: "发布了直播",
|
||||
}
|
||||
)
|
||||
|
||||
// dynamicCard2msg cType=0时,处理DynCard字符串,cType=1, 2, 4, 8, 16, 64, 256, 2048, 4200, 4308时,处理Card字符串,cType为card类型
|
||||
func dynamicCard2msg(str string, cType int) (msg []message.MessageSegment, err error) {
|
||||
var (
|
||||
dynamicCard dynamicCard
|
||||
card Card
|
||||
vote Vote
|
||||
)
|
||||
msg = make([]message.MessageSegment, 0, 16)
|
||||
// 初始化结构体
|
||||
switch cType {
|
||||
case 0:
|
||||
err = json.Unmarshal(binary.StringToBytes(str), &dynamicCard)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(binary.StringToBytes(dynamicCard.Card), &card)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if dynamicCard.Extension.Vote != "" {
|
||||
err = json.Unmarshal(binary.StringToBytes(dynamicCard.Extension.Vote), &vote)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
cType = dynamicCard.Desc.Type
|
||||
case 1, 2, 4, 8, 16, 64, 256, 2048, 4200, 4308:
|
||||
err = json.Unmarshal(binary.StringToBytes(str), &card)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
default:
|
||||
err = errors.New("只有0, 1, 2, 4, 8, 16, 64, 256, 2048, 4200, 4308模式")
|
||||
return
|
||||
}
|
||||
// 生成消息
|
||||
switch cType {
|
||||
case 1:
|
||||
msg = append(msg, message.Text(card.User.Uname, typeMsg[cType], "\n",
|
||||
card.Item.Content, "\n",
|
||||
"转发的内容: \n"))
|
||||
var originMsg []message.MessageSegment
|
||||
originMsg, err = dynamicCard2msg(card.Origin, card.Item.OrigType)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
msg = append(msg, originMsg...)
|
||||
case 2:
|
||||
msg = append(msg, message.Text(card.User.Name, "在", time.Unix(int64(card.Item.UploadTime), 0).Format("2006-01-02 15:04:05"), typeMsg[cType], "\n",
|
||||
card.Item.Description))
|
||||
for i := 0; i < len(card.Item.Pictures); i++ {
|
||||
msg = append(msg, message.Image(card.Item.Pictures[i].ImgSrc))
|
||||
}
|
||||
case 4:
|
||||
msg = append(msg, message.Text(card.User.Uname, "在", time.Unix(int64(card.Item.Timestamp), 0).Format("2006-01-02 15:04:05"), typeMsg[cType], "\n",
|
||||
card.Item.Content, "\n"))
|
||||
if dynamicCard.Extension.Vote != "" {
|
||||
msg = append(msg, message.Text("【投票】", vote.Desc, "\n",
|
||||
"截止日期: ", time.Unix(int64(vote.Endtime), 0).Format("2006-01-02 15:04:05"), "\n",
|
||||
"参与人数: ", humanNum(vote.JoinNum), "\n",
|
||||
"投票选项( 最多选择", vote.ChoiceCnt, "项 )\n"))
|
||||
for i := 0; i < len(vote.Options); i++ {
|
||||
msg = append(msg, message.Text("- ", vote.Options[i].Idx, ". ", vote.Options[i].Desc, "\n"))
|
||||
if vote.Options[i].ImgURL != "" {
|
||||
msg = append(msg, message.Image(vote.Options[i].ImgURL))
|
||||
}
|
||||
}
|
||||
}
|
||||
case 8:
|
||||
msg = append(msg, message.Text(card.Owner.Name, "在", time.Unix(int64(card.Pubdate), 0).Format("2006-01-02 15:04:05"), typeMsg[cType], "\n",
|
||||
card.Title))
|
||||
msg = append(msg, message.Image(card.Pic))
|
||||
msg = append(msg, message.Text(card.Desc, "\n",
|
||||
card.ShareSubtitle, "\n",
|
||||
"视频链接: ", card.ShortLink, "\n"))
|
||||
case 16:
|
||||
msg = append(msg, message.Text(card.User.Name, "在", time.Unix(int64(card.Item.UploadTime), 0).Format("2006-01-02 15:04:05"), typeMsg[cType], "\n",
|
||||
card.Item.Description))
|
||||
msg = append(msg, message.Image(card.Item.Cover.Default))
|
||||
case 64:
|
||||
msg = append(msg, message.Text(card.Author.(map[string]interface{})["name"], "在", time.Unix(int64(card.PublishTime), 0).Format("2006-01-02 15:04:05"), typeMsg[cType], "\n",
|
||||
card.Title, "\n",
|
||||
card.Summary))
|
||||
for i := 0; i < len(card.ImageUrls); i++ {
|
||||
msg = append(msg, message.Image(card.ImageUrls[i]))
|
||||
}
|
||||
if card.ID != 0 {
|
||||
msg = append(msg, message.Text("文章链接: https://www.bilibili.com/read/cv", card.ID, "\n"))
|
||||
}
|
||||
case 256:
|
||||
msg = append(msg, message.Text(card.Upper, "在", time.Unix(int64(card.Ctime), 0).Format("2006-01-02 15:04:05"), typeMsg[cType], "\n",
|
||||
card.Title))
|
||||
msg = append(msg, message.Image(card.Cover))
|
||||
msg = append(msg, message.Text(card.Intro, "\n"))
|
||||
if card.ID != 0 {
|
||||
msg = append(msg, message.Text("音频链接: https://www.bilibili.com/audio/au", card.ID, "\n"))
|
||||
}
|
||||
|
||||
case 2048:
|
||||
msg = append(msg, message.Text(card.User.Uname, typeMsg[cType], "\n",
|
||||
card.Vest.Content, "\n",
|
||||
card.Sketch.Title, "\n",
|
||||
card.Sketch.DescText, "\n"))
|
||||
msg = append(msg, message.Image(card.Sketch.CoverURL))
|
||||
msg = append(msg, message.Text("分享链接: ", card.Sketch.TargetURL, "\n"))
|
||||
case 4308:
|
||||
if dynamicCard.Desc.UserProfile.Info.Uname != "" {
|
||||
msg = append(msg, message.Text(dynamicCard.Desc.UserProfile.Info.Uname, typeMsg[cType], "\n"))
|
||||
}
|
||||
msg = append(msg, message.Image(card.LivePlayInfo.Cover))
|
||||
msg = append(msg, message.Text(card.LivePlayInfo.Title, "\n",
|
||||
"房间号: ", card.LivePlayInfo.RoomID, "\n",
|
||||
"分区: ", card.LivePlayInfo.ParentAreaName))
|
||||
if card.LivePlayInfo.ParentAreaName != card.LivePlayInfo.AreaName {
|
||||
msg = append(msg, message.Text("-", card.LivePlayInfo.AreaName))
|
||||
}
|
||||
if card.LivePlayInfo.LiveStatus == 0 {
|
||||
msg = append(msg, message.Text("未开播 \n"))
|
||||
} else {
|
||||
msg = append(msg, message.Text("直播中 ", card.LivePlayInfo.WatchedShow, "\n"))
|
||||
}
|
||||
msg = append(msg, message.Text("直播链接: ", card.LivePlayInfo.Link))
|
||||
default:
|
||||
msg = append(msg, message.Text("动态id: ", dynamicCard.Desc.DynamicIDStr, "未知动态类型: ", cType, "\n"))
|
||||
}
|
||||
if dynamicCard.Desc.DynamicIDStr != "" {
|
||||
msg = append(msg, message.Text("动态链接: ", tURL, dynamicCard.Desc.DynamicIDStr))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// dynamicDetail 用动态id查动态信息
|
||||
func dynamicDetail(dynamicIDStr string) (msg []message.MessageSegment, err error) {
|
||||
var data []byte
|
||||
data, err = web.GetData(fmt.Sprintf(dynamicDetailURL, dynamicIDStr))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return dynamicCard2msg(gjson.ParseBytes(data).Get("data.card").Raw, 0)
|
||||
}
|
||||
|
||||
// articleCard2msg 专栏转消息
|
||||
func articleCard2msg(card Card, defaultID string) (msg []message.MessageSegment) {
|
||||
msg = make([]message.MessageSegment, 0, 16)
|
||||
for i := 0; i < len(card.OriginImageUrls); i++ {
|
||||
msg = append(msg, message.Image(card.OriginImageUrls[i]))
|
||||
}
|
||||
msg = append(msg, message.Text(card.Title, "\n", "UP主: ", card.AuthorName, "\n",
|
||||
"阅读: ", humanNum(card.Stats.View), " 评论: ", humanNum(card.Stats.Reply), "\n",
|
||||
cvURL, defaultID))
|
||||
return
|
||||
}
|
||||
|
||||
// liveCard2msg 直播卡片转消息
|
||||
func liveCard2msg(card roomCard) (msg []message.MessageSegment) {
|
||||
msg = make([]message.MessageSegment, 0, 16)
|
||||
msg = append(msg, message.Image(card.RoomInfo.Keyframe))
|
||||
msg = append(msg, message.Text(card.RoomInfo.Title, "\n",
|
||||
"主播: ", card.AnchorInfo.BaseInfo.Uname, "\n",
|
||||
"房间号: ", card.RoomInfo.RoomID, "\n"))
|
||||
if card.RoomInfo.ShortID != 0 {
|
||||
msg = append(msg, message.Text("短号: ", card.RoomInfo.ShortID, "\n"))
|
||||
}
|
||||
msg = append(msg, message.Text("分区: ", card.RoomInfo.ParentAreaName))
|
||||
if card.RoomInfo.ParentAreaName != card.RoomInfo.AreaName {
|
||||
msg = append(msg, message.Text("-", card.RoomInfo.AreaName))
|
||||
}
|
||||
if card.RoomInfo.LiveStatus == 0 {
|
||||
msg = append(msg, message.Text("未开播 \n"))
|
||||
} else {
|
||||
msg = append(msg, message.Text("直播中 ", humanNum(card.RoomInfo.Online), "人气\n"))
|
||||
}
|
||||
if card.RoomInfo.ShortID != 0 {
|
||||
msg = append(msg, message.Text("直播间链接: ", lURL, card.RoomInfo.ShortID))
|
||||
} else {
|
||||
msg = append(msg, message.Text("直播间链接: ", lURL, card.RoomInfo.RoomID))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// videoCard2msg 视频卡片转消息
|
||||
func videoCard2msg(card Card) (msg []message.MessageSegment, err error) {
|
||||
var mCard memberCard
|
||||
msg = make([]message.MessageSegment, 0, 16)
|
||||
mCard, err = getMemberCard(card.Owner.Mid)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
msg = append(msg, message.Text("标题: ", card.Title, "\n"))
|
||||
if card.Rights.IsCooperation == 1 {
|
||||
for i := 0; i < len(card.Staff); i++ {
|
||||
msg = append(msg, message.Text(card.Staff[i].Title, ": ", card.Staff[i].Name, " 粉丝: ", humanNum(card.Staff[i].Follower), "\n"))
|
||||
}
|
||||
} else {
|
||||
msg = append(msg, message.Text("UP主: ", card.Owner.Name, " 粉丝: ", humanNum(mCard.Fans), "\n"))
|
||||
}
|
||||
msg = append(msg, message.Text("播放: ", humanNum(card.Stat.View), " 弹幕: ", humanNum(card.Stat.Danmaku)))
|
||||
msg = append(msg, message.Image(card.Pic))
|
||||
msg = append(msg, message.Text("点赞: ", humanNum(card.Stat.Like), " 投币: ", humanNum(card.Stat.Coin), "\n",
|
||||
"收藏: ", humanNum(card.Stat.Favorite), " 分享: ", humanNum(card.Stat.Share), "\n",
|
||||
vURL, card.BvID))
|
||||
return
|
||||
}
|
||||
82
plugin/bilibili/card2msg_test.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package bilibili
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestArticleInfo(t *testing.T) {
|
||||
card, err := getArticleInfo("17279244")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(articleCard2msg(card, "17279244"))
|
||||
|
||||
}
|
||||
|
||||
func TestDynamicDetail(t *testing.T) {
|
||||
t.Log("cType = 1")
|
||||
t.Log(dynamicDetail("642279068898689029"))
|
||||
|
||||
t.Log("cType = 2")
|
||||
t.Log(dynamicDetail("642470680290394121"))
|
||||
|
||||
t.Log("cType = 2048")
|
||||
t.Log(dynamicDetail("642277677329285174"))
|
||||
|
||||
t.Log("cType = 4")
|
||||
t.Log(dynamicDetail("642154347357011968"))
|
||||
|
||||
t.Log("cType = 8")
|
||||
t.Log(dynamicDetail("675892999274627104"))
|
||||
|
||||
t.Log("cType = 4308")
|
||||
t.Log(dynamicDetail("668598718656675844"))
|
||||
|
||||
t.Log("cType = 64")
|
||||
t.Log(dynamicDetail("675966082178088963"))
|
||||
|
||||
t.Log("cType = 256")
|
||||
t.Log(dynamicDetail("599253048535707632"))
|
||||
|
||||
t.Log("cType = 4,投票类型")
|
||||
t.Log(dynamicDetail("677231070435868704"))
|
||||
}
|
||||
|
||||
func TestMemberCard(t *testing.T) {
|
||||
card, err := getMemberCard(2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Logf("%+v\n", card)
|
||||
}
|
||||
|
||||
func TestVideoInfo(t *testing.T) {
|
||||
card, err := getVideoInfo("10007")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(videoCard2msg(card))
|
||||
card, err = getVideoInfo("BV1xx411c7mD")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(videoCard2msg(card))
|
||||
card, err = getVideoInfo("bv1xx411c7mD")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(videoCard2msg(card))
|
||||
card, err = getVideoInfo("BV1mF411j7iU")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(videoCard2msg(card))
|
||||
}
|
||||
|
||||
func TestLiveRoomInfo(t *testing.T) {
|
||||
card, err := getLiveRoomInfo("83171")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(liveCard2msg(card))
|
||||
}
|
||||
130
plugin/bilibili/model.go
Normal file
@@ -0,0 +1,130 @@
|
||||
package bilibili
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/FloatTech/zbputils/binary"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
_ "github.com/fumiama/sqlite3" // use sql
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
const (
|
||||
bilibiliCookie = "bilbili_cookie"
|
||||
)
|
||||
|
||||
var (
|
||||
vtbURLs = [...]string{"https://api.vtbs.moe/v1/short", "https://api.tokyo.vtbs.moe/v1/short", "https://vtbs.musedash.moe/v1/short"}
|
||||
vdb *vupdb
|
||||
)
|
||||
|
||||
// vupdb 分数数据库
|
||||
type vupdb gorm.DB
|
||||
|
||||
type vup struct {
|
||||
Mid int64 `gorm:"column:mid;primary_key"`
|
||||
Uname string `gorm:"column:uname"`
|
||||
Roomid int64 `gorm:"column:roomid"`
|
||||
}
|
||||
|
||||
func (vup) TableName() string {
|
||||
return "vup"
|
||||
}
|
||||
|
||||
type config struct {
|
||||
Key string `gorm:"column:key;primary_key"`
|
||||
Value string `gorm:"column:value"`
|
||||
}
|
||||
|
||||
func (config) TableName() string {
|
||||
return "config"
|
||||
}
|
||||
|
||||
// initialize 初始化vtb数据库
|
||||
func initialize(dbpath string) (*vupdb, error) {
|
||||
if _, err := os.Stat(dbpath); err != nil || os.IsNotExist(err) {
|
||||
// 生成文件
|
||||
f, err := os.Create(dbpath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
}
|
||||
gdb, err := gorm.Open("sqlite3", dbpath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gdb.AutoMigrate(&vup{}).AutoMigrate(&config{})
|
||||
return (*vupdb)(gdb), nil
|
||||
}
|
||||
|
||||
func (vdb *vupdb) insertVupByMid(mid int64, uname string, roomid int64) (err error) {
|
||||
db := (*gorm.DB)(vdb)
|
||||
v := vup{
|
||||
Mid: mid,
|
||||
Uname: uname,
|
||||
Roomid: roomid,
|
||||
}
|
||||
if err = db.Model(&vup{}).First(&v, "mid = ? ", mid).Error; err != nil {
|
||||
if gorm.IsRecordNotFoundError(err) {
|
||||
err = db.Model(&vup{}).Create(&v).Error
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// filterVup 筛选vup
|
||||
func (vdb *vupdb) filterVup(ids []int64) (vups []vup, err error) {
|
||||
db := (*gorm.DB)(vdb)
|
||||
if err = db.Model(&vup{}).Find(&vups, "mid in (?)", ids).Error; err != nil {
|
||||
return vups, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func updateVup() error {
|
||||
for _, v := range vtbURLs {
|
||||
data, err := web.GetData(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
gjson.Get(binary.BytesToString(data), "@this").ForEach(func(key, value gjson.Result) bool {
|
||||
mid := value.Get("mid").Int()
|
||||
uname := value.Get("uname").String()
|
||||
roomid := value.Get("roomid").Int()
|
||||
err = vdb.insertVupByMid(mid, uname, roomid)
|
||||
return err == nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vdb *vupdb) setBilibiliCookie(cookie string) (err error) {
|
||||
db := (*gorm.DB)(vdb)
|
||||
c := config{
|
||||
Key: bilibiliCookie,
|
||||
Value: cookie,
|
||||
}
|
||||
if err = db.Model(&config{}).First(&c, "key = ? ", bilibiliCookie).Error; err != nil {
|
||||
// error handling...
|
||||
if gorm.IsRecordNotFoundError(err) {
|
||||
err = db.Model(&config{}).Create(&c).Error
|
||||
}
|
||||
} else {
|
||||
err = db.Model(&config{}).Where("key = ? ", bilibiliCookie).Update(
|
||||
map[string]interface{}{
|
||||
"value": cookie,
|
||||
}).Error
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (vdb *vupdb) getBilibiliCookie() (c config) {
|
||||
db := (*gorm.DB)(vdb)
|
||||
db.Model(&config{}).First(&c, "key = ?", bilibiliCookie)
|
||||
return
|
||||
}
|
||||
267
plugin/bilibili/types.go
Normal file
@@ -0,0 +1,267 @@
|
||||
package bilibili
|
||||
|
||||
const (
|
||||
// tURL bilibili动态前缀
|
||||
tURL = "https://t.bilibili.com/"
|
||||
// dynamicDetailURL 当前动态信息,一个card
|
||||
dynamicDetailURL = "https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/get_dynamic_detail?dynamic_id=%v"
|
||||
// memberCardURL 个人信息
|
||||
memberCardURL = "https://account.bilibili.com/api/member/getCardByMid?mid=%v"
|
||||
// articleInfoURL 查看专栏信息
|
||||
articleInfoURL = "https://api.bilibili.com/x/article/viewinfo?id=%v"
|
||||
// cvURL b站专栏前缀
|
||||
cvURL = "https://www.bilibili.com/read/cv"
|
||||
// liveRoomInfoURL 查看直播间信息
|
||||
liveRoomInfoURL = "https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByRoom?room_id=%v"
|
||||
// lURL b站直播间前缀
|
||||
lURL = "https://live.bilibili.com/"
|
||||
// videoInfoURL 查看视频信息
|
||||
videoInfoURL = "https://api.bilibili.com/x/web-interface/view?aid=%v&bvid=%v"
|
||||
// vURL 视频网址前缀
|
||||
vURL = "https://www.bilibili.com/video/"
|
||||
// searchUserURL 查找b站用户
|
||||
searchUserURL = "http://api.bilibili.com/x/web-interface/search/type?search_type=bili_user&keyword=%v"
|
||||
// vtbDetailURL 查找vtb信息
|
||||
vtbDetailURL = "https://api.vtbs.moe/v1/detail/%v"
|
||||
// medalwallURL 查找牌子
|
||||
medalwallURL = "https://api.live.bilibili.com/xlive/web-ucenter/user/MedalWall?target_id=%v"
|
||||
)
|
||||
|
||||
// dynamicCard 总动态结构体,包括desc,card
|
||||
type dynamicCard struct {
|
||||
Desc Desc `json:"desc"`
|
||||
Card string `json:"card"`
|
||||
Extension struct {
|
||||
VoteCfg struct {
|
||||
VoteID int `json:"vote_id"`
|
||||
Desc string `json:"desc"`
|
||||
JoinNum int `json:"join_num"`
|
||||
} `json:"vote_cfg"`
|
||||
Vote string `json:"vote"`
|
||||
} `json:"extension"`
|
||||
}
|
||||
|
||||
// Card 卡片结构体
|
||||
type Card struct {
|
||||
Item struct {
|
||||
Content string `json:"content"`
|
||||
UploadTime int `json:"upload_time"`
|
||||
Description string `json:"description"`
|
||||
Pictures []struct {
|
||||
ImgSrc string `json:"img_src"`
|
||||
} `json:"pictures"`
|
||||
Timestamp int `json:"timestamp"`
|
||||
Cover struct {
|
||||
Default string `json:"default"`
|
||||
} `json:"cover"`
|
||||
OrigType int `json:"orig_type"`
|
||||
} `json:"item"`
|
||||
AID interface{} `json:"aid"`
|
||||
BvID interface{} `json:"bvid"`
|
||||
Dynamic interface{} `json:"dynamic"`
|
||||
Pic string `json:"pic"`
|
||||
Title string `json:"title"`
|
||||
ID int `json:"id"`
|
||||
Summary string `json:"summary"`
|
||||
ImageUrls []string `json:"image_urls"`
|
||||
OriginImageUrls []string `json:"origin_image_urls"`
|
||||
Sketch struct {
|
||||
Title string `json:"title"`
|
||||
DescText string `json:"desc_text"`
|
||||
CoverURL string `json:"cover_url"`
|
||||
TargetURL string `json:"target_url"`
|
||||
} `json:"sketch"`
|
||||
Stat struct {
|
||||
Aid int `json:"aid"`
|
||||
View int `json:"view"`
|
||||
Danmaku int `json:"danmaku"`
|
||||
Reply int `json:"reply"`
|
||||
Favorite int `json:"favorite"`
|
||||
Coin int `json:"coin"`
|
||||
Share int `json:"share"`
|
||||
Like int `json:"like"`
|
||||
} `json:"stat"`
|
||||
Stats struct {
|
||||
Aid int `json:"aid"`
|
||||
View int `json:"view"`
|
||||
Danmaku int `json:"danmaku"`
|
||||
Reply int `json:"reply"`
|
||||
Favorite int `json:"favorite"`
|
||||
Coin int `json:"coin"`
|
||||
Share int `json:"share"`
|
||||
Like int `json:"like"`
|
||||
} `json:"stats"`
|
||||
Owner struct {
|
||||
Name string `json:"name"`
|
||||
Pubdate int `json:"pubdate"`
|
||||
Mid int `json:"mid"`
|
||||
} `json:"owner"`
|
||||
Cover string `json:"cover"`
|
||||
ShortID interface{} `json:"short_id"`
|
||||
LivePlayInfo struct {
|
||||
ParentAreaName string `json:"parent_area_name"`
|
||||
AreaName string `json:"area_name"`
|
||||
Cover string `json:"cover"`
|
||||
Link string `json:"link"`
|
||||
Online int `json:"online"`
|
||||
RoomID int `json:"room_id"`
|
||||
LiveStatus int `json:"live_status"`
|
||||
WatchedShow string `json:"watched_show"`
|
||||
Title string `json:"title"`
|
||||
} `json:"live_play_info"`
|
||||
Intro string `json:"intro"`
|
||||
Schema string `json:"schema"`
|
||||
Author interface{} `json:"author"`
|
||||
AuthorName string `json:"author_name"`
|
||||
PlayCnt int `json:"play_cnt"`
|
||||
ReplyCnt int `json:"reply_cnt"`
|
||||
TypeInfo string `json:"type_info"`
|
||||
User struct {
|
||||
Name string `json:"name"`
|
||||
Uname string `json:"uname"`
|
||||
} `json:"user"`
|
||||
Desc string `json:"desc"`
|
||||
ShareSubtitle string `json:"share_subtitle"`
|
||||
ShortLink string `json:"short_link"`
|
||||
PublishTime int `json:"publish_time"`
|
||||
BannerURL string `json:"banner_url"`
|
||||
Ctime int `json:"ctime"`
|
||||
Vest struct {
|
||||
Content string `json:"content"`
|
||||
} `json:"vest"`
|
||||
Upper string `json:"upper"`
|
||||
Origin string `json:"origin"`
|
||||
Pubdate int `json:"pubdate"`
|
||||
Rights struct {
|
||||
IsCooperation int `json:"is_cooperation"`
|
||||
} `json:"rights"`
|
||||
Staff []struct {
|
||||
Title string `json:"title"`
|
||||
Name string `json:"name"`
|
||||
Follower int `json:"follower"`
|
||||
} `json:"staff"`
|
||||
}
|
||||
|
||||
// Desc 描述结构体
|
||||
type Desc struct {
|
||||
Type int `json:"type"`
|
||||
DynamicIDStr string `json:"dynamic_id_str"`
|
||||
OrigType int `json:"orig_type"`
|
||||
Timestamp int `json:"timestamp"`
|
||||
Origin struct {
|
||||
DynamicIDStr string `json:"dynamic_id_str"`
|
||||
} `json:"origin"`
|
||||
UserProfile struct {
|
||||
Info struct {
|
||||
Uname string `json:"uname"`
|
||||
} `json:"info"`
|
||||
} `json:"user_profile"`
|
||||
}
|
||||
|
||||
// Vote 投票结构体
|
||||
type Vote struct {
|
||||
ChoiceCnt int `json:"choice_cnt"`
|
||||
Desc string `json:"desc"`
|
||||
Endtime int `json:"endtime"`
|
||||
JoinNum int `json:"join_num"`
|
||||
Options []struct {
|
||||
Idx int `json:"idx"`
|
||||
Desc string `json:"desc"`
|
||||
ImgURL string `json:"img_url"`
|
||||
} `json:"options"`
|
||||
}
|
||||
|
||||
// memberCard 个人信息卡片
|
||||
type memberCard struct {
|
||||
Mid string `json:"mid"`
|
||||
Name string `json:"name"`
|
||||
Sex string `json:"sex"`
|
||||
Face string `json:"face"`
|
||||
Coins float64 `json:"coins"`
|
||||
Regtime int64 `json:"regtime"`
|
||||
Birthday string `json:"birthday"`
|
||||
Sign string `json:"sign"`
|
||||
Attentions []int64 `json:"attentions"`
|
||||
Fans int `json:"fans"`
|
||||
Friend int `json:"friend"`
|
||||
Attention int `json:"attention"`
|
||||
LevelInfo struct {
|
||||
CurrentLevel int `json:"current_level"`
|
||||
} `json:"level_info"`
|
||||
}
|
||||
|
||||
// roomCard 直播间卡片
|
||||
type roomCard struct {
|
||||
RoomInfo struct {
|
||||
RoomID int `json:"room_id"`
|
||||
ShortID int `json:"short_id"`
|
||||
Title string `json:"title"`
|
||||
LiveStatus int `json:"live_status"`
|
||||
AreaName string `json:"area_name"`
|
||||
ParentAreaName string `json:"parent_area_name"`
|
||||
Keyframe string `json:"keyframe"`
|
||||
Online int `json:"online"`
|
||||
} `json:"room_info"`
|
||||
AnchorInfo struct {
|
||||
BaseInfo struct {
|
||||
Uname string `json:"uname"`
|
||||
} `json:"base_info"`
|
||||
} `json:"anchor_info"`
|
||||
}
|
||||
|
||||
// searchResult 查找b站用户结果
|
||||
type searchResult struct {
|
||||
Mid int64 `json:"mid"`
|
||||
Uname string `json:"uname"`
|
||||
Gender int64 `json:"gender"`
|
||||
Usign string `json:"usign"`
|
||||
Level int64 `json:"level"`
|
||||
}
|
||||
|
||||
// medalData 牌子接口返回结构体
|
||||
type medalData struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data struct {
|
||||
List []medal `json:"list"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// medalInfo b站牌子信息
|
||||
type medalInfo struct {
|
||||
Mid int64 `json:"target_id"`
|
||||
MedalName string `json:"medal_name"`
|
||||
Level int64 `json:"level"`
|
||||
MedalColorStart int64 `json:"medal_color_start"`
|
||||
MedalColorEnd int64 `json:"medal_color_end"`
|
||||
MedalColorBorder int64 `json:"medal_color_border"`
|
||||
}
|
||||
|
||||
type medal struct {
|
||||
Uname string `json:"target_name"`
|
||||
medalInfo `json:"medal_info"`
|
||||
}
|
||||
|
||||
type medalSlice []medal
|
||||
|
||||
func (m medalSlice) Len() int {
|
||||
return len(m)
|
||||
}
|
||||
func (m medalSlice) Swap(i, j int) {
|
||||
m[i], m[j] = m[j], m[i]
|
||||
}
|
||||
func (m medalSlice) Less(i, j int) bool {
|
||||
return m[i].Level > m[j].Level
|
||||
}
|
||||
|
||||
// vtb信息
|
||||
type vtbDetail struct {
|
||||
Mid int `json:"mid"`
|
||||
Uname string `json:"uname"`
|
||||
Video int `json:"video"`
|
||||
Roomid int `json:"roomid"`
|
||||
Rise int `json:"rise"`
|
||||
Follower int `json:"follower"`
|
||||
GuardNum int `json:"guardNum"`
|
||||
AreaRank int `json:"areaRank"`
|
||||
}
|
||||
24
plugin/bilibili/util.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package bilibili
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// humanNum 格式化人数
|
||||
func humanNum(res int) string {
|
||||
if res/10000 != 0 {
|
||||
return strconv.FormatFloat(float64(res)/10000, 'f', 2, 64) + "万"
|
||||
}
|
||||
return strconv.Itoa(res)
|
||||
}
|
||||
|
||||
// getrealurl 获取跳转后的链接
|
||||
func getrealurl(url string) (realurl string, err error) {
|
||||
data, err := http.Head(url)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
realurl = data.Request.URL.String()
|
||||
return
|
||||
}
|
||||
74
plugin/book_review/book_review.go
Normal file
@@ -0,0 +1,74 @@
|
||||
// Package bookreview 书评
|
||||
package bookreview
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/binary"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("bookreview", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "哀伤雪刃推书记录\n- 书评[xxx]\n- 随机书评",
|
||||
PublicDataFolder: "BookReview",
|
||||
})
|
||||
|
||||
getdb := ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||
db.DBPath = engine.DataFolder() + "bookreview.db"
|
||||
// os.RemoveAll(dbpath)
|
||||
_, _ = engine.GetLazyData("bookreview.db", true)
|
||||
err := db.Open(time.Hour * 24)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
err = db.Create("bookreview", &book{})
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
n, err := db.Count("bookreview")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
log.Infof("[bookreview]读取%d条书评", n)
|
||||
return true
|
||||
})
|
||||
|
||||
// 中文、英文、数字但不包括下划线等符号
|
||||
engine.OnRegex("^书评([\u4E00-\u9FA5A-Za-z0-9]{1,25})$", getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
b := getBookReviewByKeyword(ctx.State["regex_matched"].([]string)[1])
|
||||
data, err := text.RenderToBase64(b.BookReview, text.FontFile, 400, 20)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
if id := ctx.SendChain(message.Image("base64://" + binary.BytesToString(data))); id.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR:可能被风控了"))
|
||||
}
|
||||
})
|
||||
|
||||
engine.OnFullMatch("随机书评", getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
br := getRandomBookReview()
|
||||
data, err := text.RenderToBase64(br.BookReview, text.FontFile, 400, 20)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
if id := ctx.SendChain(message.Image("base64://" + binary.BytesToString(data))); id.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR:可能被风控了"))
|
||||
}
|
||||
})
|
||||
}
|
||||
21
plugin/book_review/model.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package bookreview
|
||||
|
||||
import sql "github.com/FloatTech/sqlite"
|
||||
|
||||
type book struct {
|
||||
ID uint64 `db:"id"`
|
||||
BookReview string `db:"bookreview"`
|
||||
}
|
||||
|
||||
var db = &sql.Sqlite{}
|
||||
|
||||
// 暂时随机选择一个书评
|
||||
func getBookReviewByKeyword(keyword string) (b book) {
|
||||
_ = db.Find("bookreview", &b, "where bookreview LIKE '%"+keyword+"%'")
|
||||
return
|
||||
}
|
||||
|
||||
func getRandomBookReview() (b book) {
|
||||
_ = db.Pick("bookreview", &b)
|
||||
return
|
||||
}
|
||||
139
plugin/cangtoushi/cangtoushi.go
Normal file
@@ -0,0 +1,139 @@
|
||||
// Package cangtoushi 藏头诗
|
||||
package cangtoushi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/cookiejar"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/antchfx/htmlquery"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
)
|
||||
|
||||
const (
|
||||
loginURL = "https://www.shicimingju.com/cangtoushi/"
|
||||
searchURL = "https://www.shicimingju.com/cangtoushi/index.html"
|
||||
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"
|
||||
referer = "https://www.shicimingju.com/cangtoushi/index.html"
|
||||
)
|
||||
|
||||
var (
|
||||
gCurCookieJar *cookiejar.Jar
|
||||
csrf string
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("cangtoushi", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "藏头诗\n" +
|
||||
"- 藏头诗[xxx]\n- 藏尾诗[xxx]",
|
||||
})
|
||||
engine.OnRegex(`藏头诗\s?([一-龥]{3,10})$`).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
kw := ctx.State["regex_matched"].([]string)[1]
|
||||
err := login()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
data, err := search(kw, "7", "0")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
text, err := dealHTML(helper.BytesToString(data))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(text))
|
||||
})
|
||||
|
||||
engine.OnRegex(`藏尾诗\s?([一-龥]{3,10})$`).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
kw := ctx.State["regex_matched"].([]string)[1]
|
||||
err := login()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
data, err := search(kw, "7", "2")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
text, err := dealHTML(helper.BytesToString(data))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(text))
|
||||
})
|
||||
}
|
||||
|
||||
func login() error {
|
||||
gCurCookieJar, _ = cookiejar.New(nil)
|
||||
client := &http.Client{
|
||||
Jar: gCurCookieJar,
|
||||
}
|
||||
request, err := http.NewRequest("GET", loginURL, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
request.Header.Add("User-Agent", ua)
|
||||
response, err := client.Do(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
response.Body.Close()
|
||||
doc, err := htmlquery.Parse(strings.NewReader(helper.BytesToString(data)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
csrf = htmlquery.SelectAttr(htmlquery.FindOne(doc, "//input[@name='_csrf']"), "value")
|
||||
return nil
|
||||
}
|
||||
|
||||
func search(kw, zishu, position string) (data []byte, err error) {
|
||||
postStr := fmt.Sprintf("_csrf=%s&kw=%s&zishu=%s&position=%s", url.QueryEscape(csrf), url.QueryEscape(kw), zishu, position)
|
||||
client := &http.Client{
|
||||
Jar: gCurCookieJar,
|
||||
}
|
||||
request, err := http.NewRequest("POST", searchURL, strings.NewReader(postStr))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
request.Header.Add("Referer", referer)
|
||||
request.Header.Add("User-Agent", ua)
|
||||
request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||
response, err := client.Do(request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data, err = io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
response.Body.Close()
|
||||
return
|
||||
}
|
||||
|
||||
func dealHTML(data string) (text string, err error) {
|
||||
doc, err := htmlquery.Parse(strings.NewReader(data))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
text = htmlquery.InnerText(htmlquery.FindOne(doc, "//div[@class='card']/div[@class='card']"))
|
||||
text = strings.ReplaceAll(text, " ", "")
|
||||
text = strings.Replace(text, "\n", "", 1)
|
||||
return text, nil
|
||||
}
|
||||
111
plugin/char_reverser/init.go
Normal file
@@ -0,0 +1,111 @@
|
||||
// Package charreverser 英文字符反转
|
||||
package charreverser
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
const commandRegex = `[A-z]{1}([A-z]|\s)+[A-z]{1}` // 命令正则表达式
|
||||
|
||||
var (
|
||||
charMap = map[rune]rune{
|
||||
'a': 'ɐ',
|
||||
'b': 'q',
|
||||
'c': 'ɔ',
|
||||
'd': 'p',
|
||||
'e': 'ǝ',
|
||||
'f': 'ɟ',
|
||||
'g': 'ƃ',
|
||||
'h': 'ɥ',
|
||||
'i': 'ᴉ',
|
||||
'j': 'ɾ',
|
||||
'k': 'ʞ',
|
||||
'l': 'l',
|
||||
'm': 'ɯ',
|
||||
'n': 'u',
|
||||
'o': 'o',
|
||||
'p': 'd',
|
||||
'q': 'b',
|
||||
'r': 'ɹ',
|
||||
's': 's',
|
||||
't': 'ʇ',
|
||||
'u': 'n',
|
||||
'v': 'ʌ',
|
||||
'w': 'ʍ',
|
||||
'x': 'x',
|
||||
'y': 'ʎ',
|
||||
'z': 'z',
|
||||
'A': '∀',
|
||||
'B': 'ᗺ',
|
||||
'C': 'Ɔ',
|
||||
'D': 'ᗡ',
|
||||
'E': 'Ǝ',
|
||||
'F': 'Ⅎ',
|
||||
'G': '⅁',
|
||||
'H': 'H',
|
||||
'I': 'I',
|
||||
'J': 'ſ',
|
||||
'K': 'ʞ',
|
||||
'L': '˥',
|
||||
'M': 'W',
|
||||
'N': 'N',
|
||||
'O': 'O',
|
||||
'P': 'Ԁ',
|
||||
'Q': 'Ò',
|
||||
'R': 'ᴚ',
|
||||
'S': 'S',
|
||||
'T': '⏊',
|
||||
'U': '∩',
|
||||
'V': 'Λ',
|
||||
'W': 'M',
|
||||
'X': 'X',
|
||||
'Y': '⅄',
|
||||
'Z': 'Z',
|
||||
}
|
||||
|
||||
compiledRegex = regexp.MustCompile(commandRegex)
|
||||
)
|
||||
|
||||
func init() {
|
||||
// 初始化engine
|
||||
engine := control.Register(
|
||||
"charreverser",
|
||||
&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "字符翻转\n -翻转 <英文字符串>",
|
||||
},
|
||||
)
|
||||
// 处理字符翻转指令
|
||||
engine.OnRegex(`翻转( )+[A-z]{1}([A-z]|\s)+[A-z]{1}`).SetBlock(true).Handle(
|
||||
func(ctx *zero.Ctx) {
|
||||
// 获取需要翻转的字符串
|
||||
results := compiledRegex.FindAllString(ctx.MessageString(), -1)
|
||||
str := results[0]
|
||||
|
||||
// 将字符顺序翻转
|
||||
var tempBuilder strings.Builder
|
||||
for i := len(str) - 1; i >= 0; i-- {
|
||||
tempBuilder.WriteByte(str[i])
|
||||
}
|
||||
|
||||
// 翻转字符字形
|
||||
var reversedStrBuilder strings.Builder
|
||||
for _, char := range tempBuilder.String() {
|
||||
if char != ' ' {
|
||||
reversedStrBuilder.WriteRune(charMap[char])
|
||||
} else {
|
||||
reversedStrBuilder.WriteRune(' ')
|
||||
}
|
||||
}
|
||||
|
||||
// 发送翻转后的字符串
|
||||
ctx.SendChain(message.Text(reversedStrBuilder.String()))
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// Package chat 对话插件
|
||||
package chat
|
||||
|
||||
import (
|
||||
@@ -5,16 +6,24 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/extension/rate"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
var poke = rate.NewManager(time.Minute*5, 8) // 戳一戳
|
||||
var (
|
||||
poke = rate.NewManager[int64](time.Minute*5, 8) // 戳一戳
|
||||
engine = control.Register("chat", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "chat\n- [BOT名字]\n- [戳一戳BOT]\n- 空调开\n- 空调关\n- 群温度\n- 设置温度[正整数]",
|
||||
})
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
// 被喊名字
|
||||
zero.OnFullMatch("", zero.OnlyToMe).SetBlock(false).FirstPriority().
|
||||
engine.OnFullMatch("", zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
var nickname = zero.BotConfig.NickName[0]
|
||||
time.Sleep(time.Second * 1)
|
||||
@@ -28,38 +37,37 @@ func init() { // 插件主体
|
||||
))
|
||||
})
|
||||
// 戳一戳
|
||||
zero.On("notice/notify/poke", zero.OnlyToMe).SetBlock(false).FirstPriority().
|
||||
engine.On("notice/notify/poke", zero.OnlyToMe).SetBlock(false).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
var nickname = zero.BotConfig.NickName[0]
|
||||
switch {
|
||||
case poke.Load(ctx.Event.UserID).AcquireN(3):
|
||||
case poke.Load(ctx.Event.GroupID).AcquireN(3):
|
||||
// 5分钟共8块命令牌 一次消耗3块命令牌
|
||||
time.Sleep(time.Second * 1)
|
||||
ctx.SendChain(message.Text("请不要戳", nickname, " >_<"))
|
||||
case poke.Load(ctx.Event.UserID).Acquire():
|
||||
case poke.Load(ctx.Event.GroupID).Acquire():
|
||||
// 5分钟共8块命令牌 一次消耗1块命令牌
|
||||
time.Sleep(time.Second * 1)
|
||||
ctx.SendChain(message.Text("喂(#`O′) 戳", nickname, "干嘛!"))
|
||||
default:
|
||||
// 频繁触发,不回复
|
||||
}
|
||||
return
|
||||
})
|
||||
// 群空调
|
||||
var AirConditTemp = map[int64]int{}
|
||||
var AirConditSwitch = map[int64]bool{}
|
||||
zero.OnFullMatch("空调开").SetBlock(true).FirstPriority().
|
||||
engine.OnFullMatch("空调开").SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
AirConditSwitch[ctx.Event.GroupID] = true
|
||||
ctx.SendChain(message.Text("❄️哔~"))
|
||||
})
|
||||
zero.OnFullMatch("空调关").SetBlock(true).FirstPriority().
|
||||
engine.OnFullMatch("空调关").SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
AirConditSwitch[ctx.Event.GroupID] = false
|
||||
delete(AirConditTemp, ctx.Event.GroupID)
|
||||
ctx.SendChain(message.Text("💤哔~"))
|
||||
})
|
||||
zero.OnRegex(`设置温度(\d+)`).SetBlock(true).FirstPriority().
|
||||
engine.OnRegex(`设置温度(\d+)`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if _, exist := AirConditTemp[ctx.Event.GroupID]; !exist {
|
||||
AirConditTemp[ctx.Event.GroupID] = 26
|
||||
@@ -71,16 +79,14 @@ func init() { // 插件主体
|
||||
"❄️风速中", "\n",
|
||||
"群温度 ", AirConditTemp[ctx.Event.GroupID], "℃",
|
||||
))
|
||||
return
|
||||
} else {
|
||||
ctx.SendChain(message.Text(
|
||||
"💤", "\n",
|
||||
"群温度 ", AirConditTemp[ctx.Event.GroupID], "℃",
|
||||
))
|
||||
return
|
||||
}
|
||||
})
|
||||
zero.OnFullMatch(`群温度`).SetBlock(true).FirstPriority().
|
||||
engine.OnFullMatch(`群温度`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if _, exist := AirConditTemp[ctx.Event.GroupID]; !exist {
|
||||
AirConditTemp[ctx.Event.GroupID] = 26
|
||||
@@ -90,13 +96,11 @@ func init() { // 插件主体
|
||||
"❄️风速中", "\n",
|
||||
"群温度 ", AirConditTemp[ctx.Event.GroupID], "℃",
|
||||
))
|
||||
return
|
||||
} else {
|
||||
ctx.SendChain(message.Text(
|
||||
"💤", "\n",
|
||||
"群温度 ", AirConditTemp[ctx.Event.GroupID], "℃",
|
||||
))
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
37
plugin/choose/choose.go
Normal file
@@ -0,0 +1,37 @@
|
||||
// Package choose 选择困难症帮手
|
||||
package choose
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("choose", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "choose\n" +
|
||||
"- 选择可口可乐还是百事可乐\n" +
|
||||
"- 选择肯德基还是麦当劳还是必胜客",
|
||||
})
|
||||
engine.OnPrefix("选择").SetBlock(true).Handle(handle)
|
||||
}
|
||||
func handle(ctx *zero.Ctx) {
|
||||
rawOptions := strings.Split(ctx.State["args"].(string), "还是")
|
||||
var options = make([]string, 0)
|
||||
for count, option := range rawOptions {
|
||||
options = append(options, strconv.Itoa(count+1)+", "+option)
|
||||
}
|
||||
result := rawOptions[rand.Intn(len(rawOptions))]
|
||||
name := ctx.Event.Sender.NickName
|
||||
ctx.SendChain(message.Text("> ", name, "\n",
|
||||
"你的选项有:", "\n",
|
||||
strings.Join(options, "\n"), "\n",
|
||||
"你最终会选: ", result,
|
||||
))
|
||||
}
|
||||
72
plugin/chouxianghua/chouxianghua.go
Normal file
@@ -0,0 +1,72 @@
|
||||
// Package chouxianghua 抽象话转化
|
||||
package chouxianghua
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
)
|
||||
|
||||
func init() {
|
||||
en := control.Register("chouxianghua", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "抽象话\n- 抽象翻译xxx",
|
||||
PublicDataFolder: "ChouXiangHua",
|
||||
})
|
||||
|
||||
en.OnRegex("^抽象翻译((\\s|[\\r\\n]|[\\p{Han}\\p{P}A-Za-z0-9])+)$",
|
||||
ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||
db.DBPath = en.DataFolder() + "cxh.db"
|
||||
// os.RemoveAll(dbpath)
|
||||
_, _ = en.GetLazyData("cxh.db", true)
|
||||
err := db.Open(time.Hour * 24)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
err = db.Create("pinyin", &pinyin{})
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
n, err := db.Count("pinyin")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
logrus.Printf("[chouxianghua]读取%d条拼音", n)
|
||||
return true
|
||||
}),
|
||||
).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
r := cx(ctx.State["regex_matched"].([]string)[1])
|
||||
ctx.SendChain(message.Text(r))
|
||||
})
|
||||
}
|
||||
|
||||
func cx(s string) (r string) {
|
||||
h := []rune(s)
|
||||
for i := 0; i < len(h); i++ {
|
||||
if i < len(h)-1 {
|
||||
e := getEmojiByPronun(getPronunByDWord(h[i], h[i+1]))
|
||||
if e != "" {
|
||||
r += e
|
||||
i++
|
||||
continue
|
||||
}
|
||||
}
|
||||
e := getEmojiByPronun(getPinyinByWord(string(h[i])))
|
||||
if e != "" {
|
||||
r += e
|
||||
continue
|
||||
}
|
||||
r += string(h[i])
|
||||
}
|
||||
return
|
||||
}
|
||||
30
plugin/chouxianghua/model.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package chouxianghua
|
||||
|
||||
import sql "github.com/FloatTech/sqlite"
|
||||
|
||||
type pinyin struct {
|
||||
Word string `db:"word"`
|
||||
Pronun string `db:"pronunciation"`
|
||||
}
|
||||
type emoji struct {
|
||||
Pronun string `db:"pronunciation"`
|
||||
Emoji string `db:"emoji"`
|
||||
}
|
||||
|
||||
var db = &sql.Sqlite{}
|
||||
|
||||
func getPinyinByWord(word string) string {
|
||||
var p pinyin
|
||||
_ = db.Find("pinyin", &p, "where word = '"+word+"'")
|
||||
return p.Pronun
|
||||
}
|
||||
|
||||
func getPronunByDWord(w0, w1 rune) string {
|
||||
return getPinyinByWord(string(w0)) + getPinyinByWord(string(w1))
|
||||
}
|
||||
|
||||
func getEmojiByPronun(pronun string) string {
|
||||
var e emoji
|
||||
_ = db.Find("emoji", &e, "where pronunciation = '"+pronun+"'")
|
||||
return e.Emoji
|
||||
}
|
||||
56
plugin/coser/coser.go
Normal file
@@ -0,0 +1,56 @@
|
||||
// Package coser images
|
||||
package coser
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
)
|
||||
|
||||
var (
|
||||
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36"
|
||||
coserURL = "http://ovooa.com/API/cosplay/api.php"
|
||||
datestr = regexp.MustCompile(`/\d{4}-\d{2}-\d{2}/`)
|
||||
)
|
||||
|
||||
func init() {
|
||||
control.Register("coser", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "三次元小姐姐\n- coser",
|
||||
}).ApplySingle(ctxext.DefaultSingle).OnFullMatch("coser", zero.OnlyGroup).SetBlock(true).Limit(ctxext.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text("少女祈祷中......"))
|
||||
data, err := web.RequestDataWith(web.NewDefaultClient(), coserURL, "GET", "", ua)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
text := gjson.Get(helper.BytesToString(data), "data.Title").String()
|
||||
m := message.Message{ctxext.FakeSenderForwardNode(ctx, message.Text(text))}
|
||||
ds := ""
|
||||
gjson.Get(helper.BytesToString(data), "data.data").ForEach(func(_, value gjson.Result) bool {
|
||||
if ds == "" {
|
||||
ds = datestr.FindString(value.String())
|
||||
} else if ds != datestr.FindString(value.String()) {
|
||||
return false
|
||||
}
|
||||
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Image(value.String())))
|
||||
return true
|
||||
})
|
||||
|
||||
if id := ctx.SendGroupForwardMessage(
|
||||
ctx.Event.GroupID,
|
||||
m).Get("message_id").Int(); id == 0 {
|
||||
ctx.SendChain(message.Text("ERROR:可能被风控或下载图片用时过长,请耐心等待"))
|
||||
}
|
||||
})
|
||||
}
|
||||
73
plugin/cpstory/cpstory.go
Normal file
@@ -0,0 +1,73 @@
|
||||
// Package cpstory cp短打
|
||||
package cpstory
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/math"
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("cpstory", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "cp短打\n- 组cp[@xxx][@xxx]\n- 磕cp大老师 雪乃",
|
||||
PublicDataFolder: "CpStory",
|
||||
})
|
||||
|
||||
getdb := ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||
db.DBPath = engine.DataFolder() + "cp.db"
|
||||
// os.RemoveAll(dbpath)
|
||||
_, _ = engine.GetLazyData("cp.db", true)
|
||||
err := db.Open(time.Hour * 24)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
err = db.Create("cp_story", &cpstory{})
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
n, err := db.Count("cp_story")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
logrus.Printf("[cpstory]读取%d条故事", n)
|
||||
return true
|
||||
})
|
||||
|
||||
engine.OnRegex("^组cp.*?(\\d+).*?(\\d+)", zero.OnlyGroup, getdb).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
cs := getRandomCpStory()
|
||||
gong := ctx.CardOrNickName(math.Str2Int64(ctx.State["regex_matched"].([]string)[1]))
|
||||
shou := ctx.CardOrNickName(math.Str2Int64(ctx.State["regex_matched"].([]string)[2]))
|
||||
text := strings.ReplaceAll(cs.Story, "<攻>", gong)
|
||||
text = strings.ReplaceAll(text, "<受>", shou)
|
||||
text = strings.ReplaceAll(text, cs.Gong, gong)
|
||||
text = strings.ReplaceAll(text, cs.Shou, gong)
|
||||
ctx.SendChain(message.Text(text))
|
||||
})
|
||||
engine.OnPrefix("磕cp", getdb).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
cs := getRandomCpStory()
|
||||
params := strings.Split(ctx.State["args"].(string), " ")
|
||||
if len(params) < 2 {
|
||||
ctx.SendChain(message.Text(ctx.Event.MessageID), message.Text("请用空格分开两个人名"))
|
||||
} else {
|
||||
gong := params[0]
|
||||
shou := params[1]
|
||||
text := strings.ReplaceAll(cs.Story, "<攻>", gong)
|
||||
text = strings.ReplaceAll(text, "<受>", shou)
|
||||
text = strings.ReplaceAll(text, cs.Gong, gong)
|
||||
text = strings.ReplaceAll(text, cs.Shou, gong)
|
||||
ctx.SendChain(message.Text(text))
|
||||
}
|
||||
})
|
||||
}
|
||||
17
plugin/cpstory/model.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package cpstory
|
||||
|
||||
import sql "github.com/FloatTech/sqlite"
|
||||
|
||||
type cpstory struct {
|
||||
ID int64 `db:"id"`
|
||||
Gong string `db:"gong"`
|
||||
Shou string `db:"shou"`
|
||||
Story string `db:"story"`
|
||||
}
|
||||
|
||||
var db = &sql.Sqlite{}
|
||||
|
||||
func getRandomCpStory() (cs cpstory) {
|
||||
_ = db.Pick("cp_story", &cs)
|
||||
return
|
||||
}
|
||||
72
plugin/curse/curse.go
Normal file
@@ -0,0 +1,72 @@
|
||||
// Package curse 骂人插件(求骂,自卫)
|
||||
package curse
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/process"
|
||||
)
|
||||
|
||||
const (
|
||||
minLevel = "min"
|
||||
maxLevel = "max"
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("curse", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: true,
|
||||
Help: "骂人(求骂,自卫)\n- 骂我\n- 大力骂我",
|
||||
PublicDataFolder: "Curse",
|
||||
})
|
||||
|
||||
getdb := ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||
db.DBPath = engine.DataFolder() + "curse.db"
|
||||
_, err := engine.GetLazyData("curse.db", true)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
err = db.Open(time.Hour * 24)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
err = db.Create("curse", &curse{})
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
c, err := db.Count("curse")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
logrus.Infoln("[curse]加载", c, "条骂人语录")
|
||||
return true
|
||||
})
|
||||
|
||||
engine.OnFullMatch("骂我", getdb).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
text := getRandomCurseByLevel(minLevel).Text
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(text))
|
||||
})
|
||||
|
||||
engine.OnFullMatch("大力骂我", getdb).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
process.SleepAbout1sTo2s()
|
||||
text := getRandomCurseByLevel(maxLevel).Text
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(text))
|
||||
})
|
||||
|
||||
engine.OnKeywordGroup([]string{"他妈", "公交车", "你妈", "操", "屎", "去死", "快死", "我日", "逼", "尼玛", "艾滋", "癌症", "有病", "烦你", "你爹", "屮", "cnm"}, zero.OnlyToMe, getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
text := getRandomCurseByLevel(maxLevel).Text
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(text))
|
||||
})
|
||||
}
|
||||
16
plugin/curse/model.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package curse
|
||||
|
||||
import sql "github.com/FloatTech/sqlite"
|
||||
|
||||
type curse struct {
|
||||
ID uint32 `db:"id"`
|
||||
Text string `db:"text"`
|
||||
Level string `db:"level"`
|
||||
}
|
||||
|
||||
var db = &sql.Sqlite{}
|
||||
|
||||
func getRandomCurseByLevel(level string) (c curse) {
|
||||
_ = db.Find("curse", &c, "where level = '"+level+"' ORDER BY RANDOM() limit 1")
|
||||
return
|
||||
}
|
||||
46
plugin/danbooru/main.go
Normal file
@@ -0,0 +1,46 @@
|
||||
// Package deepdanbooru 二次元图片标签识别
|
||||
package deepdanbooru
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/danbooru"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/FloatTech/zbputils/img/writer"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("danbooru", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "二次元图片标签识别\n" +
|
||||
"- 鉴赏图片[图片]",
|
||||
PrivateDataFolder: "danbooru",
|
||||
})
|
||||
|
||||
cachefolder := engine.DataFolder()
|
||||
|
||||
// 上传一张图进行评价
|
||||
engine.OnKeywordGroup([]string{"鉴赏图片"}, zero.OnlyGroup, zero.MustProvidePicture).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text("少女祈祷中..."))
|
||||
for _, url := range ctx.State["image_url"].([]string) {
|
||||
t, err := danbooru.TagURL("", url)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
digest := md5.Sum(helper.StringToBytes(url))
|
||||
f := cachefolder + hex.EncodeToString(digest[:])
|
||||
if file.IsNotExist(f) {
|
||||
_ = writer.SavePNG2Path(f, t)
|
||||
}
|
||||
ctx.SendChain(message.Image("file:///" + file.BOTPATH + "/" + f))
|
||||
}
|
||||
})
|
||||
}
|
||||
57
plugin/diana/bing.go
Normal file
@@ -0,0 +1,57 @@
|
||||
// Package diana 虚拟偶像女团 A-SOUL 成员嘉然相关
|
||||
package diana
|
||||
|
||||
import (
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/plugin/diana/data"
|
||||
)
|
||||
|
||||
var engine = control.Register("diana", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "嘉然\n" +
|
||||
"- 小作文\n" +
|
||||
"- 发大病\n" +
|
||||
"- 教你一篇小作文[作文]\n" +
|
||||
"- [回复]查重",
|
||||
PublicDataFolder: "Diana",
|
||||
})
|
||||
|
||||
func init() {
|
||||
getdb := ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||
err := data.LoadText(engine.DataFolder() + "text.db")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
// 随机发送一篇上面的小作文
|
||||
engine.OnFullMatch("小作文", getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 绕过第一行发病
|
||||
ctx.SendChain(message.Text(data.RandText()))
|
||||
})
|
||||
// 逆天
|
||||
engine.OnFullMatch("发大病", getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 第一行是发病
|
||||
ctx.SendChain(message.Text(data.HentaiText()))
|
||||
})
|
||||
// 增加小作文
|
||||
engine.OnRegex(`^教你一篇小作文(.*)$`, zero.AdminPermission, getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
err := data.AddText(ctx.State["regex_matched"].([]string)[1])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("记住啦!"))
|
||||
}
|
||||
})
|
||||
}
|
||||
70
plugin/diana/data/text.go
Normal file
@@ -0,0 +1,70 @@
|
||||
// Package data 加载位于 datapath 的小作文
|
||||
package data
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/binary"
|
||||
"time"
|
||||
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
binutils "github.com/FloatTech/zbputils/binary"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var db = sql.Sqlite{}
|
||||
|
||||
type text struct {
|
||||
ID int64 `db:"id"`
|
||||
Data string `db:"data"`
|
||||
}
|
||||
|
||||
// LoadText 加载小作文
|
||||
func LoadText(dbfile string) error {
|
||||
_, err := file.GetLazyData(dbfile, false)
|
||||
db.DBPath = dbfile
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = db.Open(time.Hour * 24)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = db.Create("text", &text{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c, err := db.Count("text")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Printf("[Diana]读取%d条小作文", c)
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddText 添加小作文
|
||||
func AddText(txt string) error {
|
||||
s := md5.Sum(binutils.StringToBytes(txt))
|
||||
i := binary.LittleEndian.Uint64(s[:8])
|
||||
return db.Insert("text", &text{ID: int64(i), Data: txt})
|
||||
}
|
||||
|
||||
// RandText 随机小作文
|
||||
func RandText() string {
|
||||
var t text
|
||||
err := db.Pick("text", &t)
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
return t.Data
|
||||
}
|
||||
|
||||
// HentaiText 发大病
|
||||
func HentaiText() string {
|
||||
var t text
|
||||
err := db.Find("text", &t, "where id = -3802576048116006195")
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
return t.Data
|
||||
}
|
||||
89
plugin/diana/zhiwang.go
Normal file
@@ -0,0 +1,89 @@
|
||||
// Package diana 嘉然相关
|
||||
package diana
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/zbputils/binary"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
"github.com/tidwall/gjson"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
)
|
||||
|
||||
// 小作文查重: 回复要查的消息 查重
|
||||
func init() {
|
||||
engine.OnMessage(func(ctx *zero.Ctx) bool {
|
||||
msg := ctx.Event.Message
|
||||
if msg[0].Type != "reply" {
|
||||
return false
|
||||
}
|
||||
for _, elem := range msg {
|
||||
if elem.Type == "text" {
|
||||
text := elem.Data["text"]
|
||||
text = strings.ReplaceAll(text, " ", "")
|
||||
text = strings.ReplaceAll(text, "\r", "")
|
||||
text = strings.ReplaceAll(text, "\n", "")
|
||||
if text == "查重" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
msg := ctx.GetMessage(message.NewMessageIDFromString(ctx.Event.Message[0].Data["id"])).Elements[0].Data["text"]
|
||||
result, err := zhiwangapi(msg)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
if result.Get("code").Int() != 0 {
|
||||
ctx.SendChain(message.Text("api返回错误:", result.Get("code").Int()))
|
||||
return
|
||||
}
|
||||
if result.Get("data.related.#").Int() == 0 {
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("枝网没搜到,查重率为0%,鉴定为原创")))
|
||||
return
|
||||
}
|
||||
related := result.Get("data.related.0.reply").Map()
|
||||
rate := result.Get("data.related.0.rate").Float()
|
||||
relatedcontent := related["content"].String()
|
||||
if len(relatedcontent) > 102 {
|
||||
relatedcontent = relatedcontent[:102] + "....."
|
||||
}
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text(
|
||||
"枝网文本复制检测报告(简洁)", "\n",
|
||||
"查重时间: ", time.Now().Format("2006-01-02 15:04:05"), "\n",
|
||||
"总文字复制比: ", math.Floor(rate*100), "%", "\n",
|
||||
"相似小作文:", "\n", relatedcontent, "\n",
|
||||
"获赞数:", related["like_num"].String(), "\n",
|
||||
result.Get("data.related.0.reply_url").String(), "\n",
|
||||
"作者: ", related["m_name"].String(), "\n",
|
||||
"发表时间: ", time.Unix(int64(related["ctime"].Float()), 0).Format("2006-01-02 15:04:05"), "\n",
|
||||
"查重结果仅作参考,请注意辨别是否为原创", "\n",
|
||||
"数据来源: https://asoulcnki.asia/",
|
||||
)))
|
||||
})
|
||||
}
|
||||
|
||||
func zhiwangapi(text string) (*gjson.Result, error) {
|
||||
b, cl := binary.OpenWriterF(func(w *binary.Writer) {
|
||||
w.WriteString("{\n\"text\":\"")
|
||||
w.WriteString(text)
|
||||
w.WriteString("\"\n}")
|
||||
})
|
||||
|
||||
data, err := web.PostData("https://asoulcnki.asia/v1/api/check", "application/json", bytes.NewReader(b))
|
||||
cl()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := gjson.ParseBytes(data)
|
||||
return &result, nil
|
||||
}
|
||||
53
plugin/drift_bottle/data.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package driftbottle
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"hash/crc64"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
"github.com/FloatTech/zbputils/binary"
|
||||
)
|
||||
|
||||
type bottle struct {
|
||||
ID int64 `db:"id"` // ID qq_grp_name_msg 的 crc64
|
||||
QQ int64 `db:"qq"` // QQ 发送者 qq
|
||||
Grp int64 `db:"grp"` // Grp 限制抽出的群 / 人(负数)
|
||||
Name string `db:"name"` // Name 发送者 昵称
|
||||
Msg string `db:"msg"` // Msg 消息,纯文本
|
||||
}
|
||||
|
||||
var sea = &sql.Sqlite{}
|
||||
var seamu sync.RWMutex
|
||||
|
||||
func newBottle(qq, grp int64, name, msg string) *bottle {
|
||||
id := int64(crc64.Checksum(binary.StringToBytes(fmt.Sprintf("%d_%d_%s_%s", qq, grp, name, msg)), crc64.MakeTable(crc64.ISO)))
|
||||
return &bottle{ID: id, QQ: qq, Grp: grp, Name: name, Msg: msg}
|
||||
}
|
||||
|
||||
func (b *bottle) throw(db *sql.Sqlite, channel string) error {
|
||||
seamu.Lock()
|
||||
defer seamu.Unlock()
|
||||
return db.Insert(channel, b)
|
||||
}
|
||||
|
||||
func (b *bottle) destroy(db *sql.Sqlite, channel string) error {
|
||||
seamu.Lock()
|
||||
defer seamu.Unlock()
|
||||
return db.Del(channel, "WHERE id="+strconv.FormatInt(b.ID, 10))
|
||||
}
|
||||
|
||||
// fetchBottle grp != 0
|
||||
func fetchBottle(db *sql.Sqlite, channel string, grp int64) (*bottle, error) {
|
||||
seamu.RLock()
|
||||
defer seamu.RUnlock()
|
||||
b := new(bottle)
|
||||
return b, db.Find(channel, b, "WHERE grp=0 or grp="+strconv.FormatInt(grp, 10)+" ORDER BY RANDOM() limit 1")
|
||||
}
|
||||
|
||||
func createChannel(db *sql.Sqlite, channel string) error {
|
||||
seamu.Lock()
|
||||
defer seamu.Unlock()
|
||||
return db.Create(channel, &bottle{})
|
||||
}
|
||||
133
plugin/drift_bottle/main.go
Normal file
@@ -0,0 +1,133 @@
|
||||
// Package driftbottle 漂流瓶
|
||||
package driftbottle
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func init() {
|
||||
en := control.Register("driftbottle", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "漂流瓶\n- (在群xxx)丢漂流瓶(到频道xxx) [消息]\n- (从频道xxx)捡漂流瓶\n- @BOT 创建频道 xxx\n- 跳入(频道)海中\n- 注:不显式限制时,私聊发送可在所有群抽到,群聊发送仅可在本群抽到,默认频道为 global",
|
||||
PrivateDataFolder: "driftbottle",
|
||||
})
|
||||
sea.DBPath = en.DataFolder() + "sea.db"
|
||||
err := sea.Open(time.Hour * 24)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_ = createChannel(sea, "global")
|
||||
en.OnRegex(`^(在群\d+)?丢漂流瓶(到频道\w+)?\s+(.*)$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
msgs := ctx.State["regex_matched"].([]string)
|
||||
grp := ctx.Event.GroupID
|
||||
channel := "global"
|
||||
msg := msgs[3]
|
||||
var err error
|
||||
if msgs[1] != "" {
|
||||
grp, err = strconv.ParseInt(msgs[1][6:], 10, 64)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("群号非法!"))
|
||||
return
|
||||
}
|
||||
}
|
||||
if msgs[2] != "" {
|
||||
channel = msgs[2][9:]
|
||||
}
|
||||
if msg == "" {
|
||||
ctx.SendChain(message.Text("消息为空!"))
|
||||
return
|
||||
}
|
||||
logrus.Debugln("[driftbottle]", grp, channel, msg)
|
||||
err = newBottle(
|
||||
ctx.Event.UserID,
|
||||
grp,
|
||||
ctx.CardOrNickName(ctx.Event.UserID),
|
||||
msg,
|
||||
).throw(sea, channel)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("你将它扔进大海,希望有人捞到吧~")))
|
||||
})
|
||||
en.OnRegex(`^(从频道\w+)?捡漂流瓶$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
msgs := ctx.State["regex_matched"].([]string)
|
||||
grp := ctx.Event.GroupID
|
||||
if grp == 0 {
|
||||
grp = -ctx.Event.UserID
|
||||
}
|
||||
if grp == 0 {
|
||||
ctx.SendChain(message.Text("找不到对象!"))
|
||||
return
|
||||
}
|
||||
channel := "global"
|
||||
if msgs[1] != "" {
|
||||
channel = msgs[1][9:]
|
||||
}
|
||||
logrus.Debugln("[driftbottle]", grp, channel)
|
||||
b, err := fetchBottle(sea, channel, grp)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
err = b.destroy(sea, channel)
|
||||
wg.Done()
|
||||
}()
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(
|
||||
ctx.Event.MessageID,
|
||||
message.Text("你在海边捡到了一个来自 ", b.Name, " 的漂流瓶,打开瓶子,里面有一张纸条,写着:"),
|
||||
message.Text(b.Msg),
|
||||
),
|
||||
)
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
})
|
||||
en.OnPrefix("创建频道", zero.SuperUserPermission, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
channel := strings.TrimRight(ctx.State["args"].(string), " ")
|
||||
if channel == "" {
|
||||
ctx.SendChain(message.Text("频道名为空!"))
|
||||
return
|
||||
}
|
||||
err := createChannel(sea, channel)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("成功~")))
|
||||
})
|
||||
en.OnRegex(`^跳入(\w+)?海中$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
msgs := ctx.State["regex_matched"].([]string)
|
||||
channel := "global"
|
||||
if msgs[1] != "" {
|
||||
channel = msgs[1]
|
||||
}
|
||||
seamu.RLock()
|
||||
c, err := sea.Count(channel)
|
||||
seamu.RUnlock()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("你缓缓走入大海,感受着海浪轻柔地拍打着你的小腿,膝盖……\n波浪卷着你的腰腹,你感觉有些把握不住平衡了……\n……\n你沉入海中,", c, " 个物体与你一同沉浮。\n不知何处涌来一股暗流,你失去了意识。")))
|
||||
})
|
||||
}
|
||||
249
plugin/emojimix/emoji.go
Normal file
@@ -0,0 +1,249 @@
|
||||
// Package emojimix 合成emoji
|
||||
package emojimix
|
||||
|
||||
var emojis = map[rune]int64{
|
||||
128516: 20201001, // 😄 grinning face with smiling eyes
|
||||
128512: 20201001, // 😀 grinning face
|
||||
128578: 20201001, // 🙂 slightly smiling face
|
||||
128579: 20201001, // 🙃 upside-down face
|
||||
128521: 20201001, // 😉 winking face
|
||||
128522: 20201001, // 😊 smiling face with smiling eyes
|
||||
128518: 20201001, // 😆 grinning squinting face
|
||||
128515: 20201001, // 😃 grinning face with big eyes
|
||||
128513: 20201001, // 😁 beaming face with smiling eyes
|
||||
129315: 20201001, // 🤣 rolling on the floor laughing
|
||||
128517: 20201001, // 😅 grinning face with sweat
|
||||
128514: 20201001, // 😂 face with tears of joy
|
||||
128519: 20201001, // 😇 smiling face with halo
|
||||
129392: 20201001, // 🥰 smiling face with hearts
|
||||
128525: 20201001, // 😍 smiling face with heart-eyes
|
||||
128536: 20201001, // 😘 face blowing a kiss
|
||||
129321: 20201001, // 🤩 star-struck
|
||||
128535: 20201001, // 😗 kissing face
|
||||
128538: 20201001, // 😚 kissing face with closed eyes
|
||||
128537: 20201001, // 😙 kissing face with smiling eyes
|
||||
128539: 20201001, // 😛 face with tongue
|
||||
128541: 20201001, // 😝 squinting face with tongue
|
||||
128523: 20201001, // 😋 face savoring food
|
||||
129394: 20201001, // 🥲 smiling face with tear
|
||||
129297: 20201001, // 🤑 money-mouth face
|
||||
128540: 20201001, // 😜 winking face with tongue
|
||||
129303: 20201001, // 🤗 smiling face with open hands hugs
|
||||
129323: 20201001, // 🤫 shushing face quiet whisper
|
||||
129300: 20201001, // 🤔 thinking face question hmmm
|
||||
129325: 20201001, // 🤭 face with hand over mouth embarrassed
|
||||
129320: 20201001, // 🤨 face with raised eyebrow question
|
||||
129296: 20201001, // 🤐 zipper-mouth face
|
||||
128528: 20201001, // 😐 neutral face
|
||||
128529: 20201001, // 😑 expressionless face
|
||||
128566: 20201001, // 😶 face without mouth
|
||||
129322: 20201001, // 🤪 zany face
|
||||
128527: 20201001, // 😏 smirking face suspicious
|
||||
128530: 20201001, // 😒 unamused face
|
||||
128580: 20201001, // 🙄 face with rolling eyes
|
||||
128556: 20201001, // 😬 grimacing face
|
||||
128558: 20210218, // 😮 face exhaling
|
||||
129317: 20201001, // 🤥 lying face
|
||||
128524: 20201001, // 😌 relieved face
|
||||
128532: 20201001, // 😔 pensive face
|
||||
128554: 20201001, // 😪 sleepy face
|
||||
129316: 20201001, // 🤤 drooling face
|
||||
128564: 20201001, // 😴 sleeping face
|
||||
128567: 20201001, // 😷 face with medical mask
|
||||
129298: 20201001, // 🤒 face with thermometer
|
||||
129301: 20201001, // 🤕 face with head-bandage
|
||||
129314: 20201001, // 🤢 nauseated face
|
||||
129326: 20201001, // 🤮 face vomiting throw
|
||||
129319: 20201001, // 🤧 sneezing face
|
||||
129397: 20201001, // 🥵 hot face warm
|
||||
129398: 20201001, // 🥶 cold face freezing ice
|
||||
128565: 20201001, // 😵 face with crossed-out eyes
|
||||
129396: 20201001, // 🥴 woozy face drunk tipsy drug high
|
||||
129327: 20201001, // 🤯 exploding head mindblow
|
||||
129312: 20201001, // 🤠 cowboy hat face
|
||||
129395: 20201001, // 🥳 partying face
|
||||
129400: 20201001, // 🥸 disguised face
|
||||
129488: 20201001, // 🧐 face with monocle glasses
|
||||
128526: 20201001, // 😎 smiling face with sunglasses
|
||||
128533: 20201001, // 😕 confused face
|
||||
128543: 20201001, // 😟 worried face
|
||||
128577: 20201001, // 🙁 slightly frowning face
|
||||
128559: 20201001, // 😯 hushed face
|
||||
128562: 20201001, // 😲 astonished face
|
||||
129299: 20201001, // 🤓 nerd face glasses
|
||||
128563: 20201001, // 😳 flushed face
|
||||
129402: 20201001, // 🥺 pleading face
|
||||
128551: 20201001, // 😧 anguished face
|
||||
128552: 20201001, // 😨 fearful face
|
||||
128550: 20201001, // 😦 frowning face with open mouth
|
||||
128560: 20201001, // 😰 anxious face with sweat
|
||||
128549: 20201001, // 😥 sad but relieved face
|
||||
128557: 20201001, // 😭 loudly crying face
|
||||
128553: 20201001, // 😩 weary face
|
||||
128546: 20201001, // 😢 crying face
|
||||
128547: 20201001, // 😣 persevering face
|
||||
128544: 20201001, // 😠 angry face
|
||||
128531: 20201001, // 😓 downcast face with sweat
|
||||
128534: 20201001, // 😖 confounded face
|
||||
129324: 20201001, // 🤬 face with symbols on mouth
|
||||
128542: 20201001, // 😞 disappointed face
|
||||
128555: 20201001, // 😫 tired face
|
||||
128548: 20201001, // 😤 face with steam from nose
|
||||
129393: 20201001, // 🥱 yawning face
|
||||
128169: 20201001, // 💩 pile of poo
|
||||
128545: 20201001, // 😡 pouting face
|
||||
128561: 20201001, // 😱 face screaming in fear
|
||||
128127: 20201001, // 👿 angry face with horns
|
||||
128128: 20201001, // 💀 skull
|
||||
128125: 20201001, // 👽 alien
|
||||
128520: 20201001, // 😈 smiling face with horns devil
|
||||
129313: 20201001, // 🤡 clown face
|
||||
128123: 20201001, // 👻 ghost
|
||||
129302: 20201001, // 🤖 robot
|
||||
128175: 20201001, // 💯 hundred points percent
|
||||
128064: 20201001, // 👀 eyes
|
||||
127801: 20201001, // 🌹 rose flower
|
||||
127804: 20201001, // 🌼 blossom flower
|
||||
127799: 20201001, // 🌷 tulip flower
|
||||
127797: 20201001, // 🌵 cactus
|
||||
127821: 20201001, // 🍍 pineapple
|
||||
127874: 20201001, // 🎂 birthday cake
|
||||
127751: 20210831, // 🌇 sunset
|
||||
129473: 20201001, // 🧁 cupcake muffin
|
||||
127911: 20210521, // 🎧 headphone earphone
|
||||
127800: 20210218, // 🌸 cherry blossom flower
|
||||
129440: 20201001, // 🦠 microbe germ bacteria virus covid corona
|
||||
128144: 20201001, // 💐 bouquet flowers
|
||||
127789: 20201001, // 🌭 hot dog food
|
||||
128139: 20201001, // 💋 kiss mark lips
|
||||
127875: 20201001, // 🎃 jack-o-lantern pumpkin
|
||||
129472: 20201001, // 🧀 cheese wedge
|
||||
9749: 20201001, // ☕ hot beverage coffee cup tea
|
||||
127882: 20201001, // 🎊 confetti ball
|
||||
127880: 20201001, // 🎈 balloon
|
||||
9924: 20201001, // ⛄ snowman without snow
|
||||
128142: 20201001, // 💎 gem stone crystal diamond
|
||||
127794: 20201001, // 🌲 evergreen tree
|
||||
129410: 20210218, // 🦂 scorpion
|
||||
128584: 20201001, // 🙈 see-no-evil monkey
|
||||
128148: 20201001, // 💔 broken heart
|
||||
128140: 20201001, // 💌 love letter heart
|
||||
128152: 20201001, // 💘 heart with arrow
|
||||
128159: 20201001, // 💟 heart decoration
|
||||
128158: 20201001, // 💞 revolving hearts
|
||||
128147: 20201001, // 💓 beating heart
|
||||
128149: 20201001, // 💕 two hearts
|
||||
128151: 20201001, // 💗 growing heart
|
||||
129505: 20201001, // 🧡 orange heart
|
||||
128155: 20201001, // 💛 yellow heart
|
||||
10084: 20210218, // ❤ mending heart
|
||||
128156: 20201001, // 💜 purple heart
|
||||
128154: 20201001, // 💚 green heart
|
||||
128153: 20201001, // 💙 blue heart
|
||||
129294: 20201001, // 🤎 brown heart
|
||||
129293: 20201001, // 🤍 white heart
|
||||
128420: 20201001, // 🖤 black heart
|
||||
128150: 20201001, // 💖 sparkling heart
|
||||
128157: 20201001, // 💝 heart with ribbon
|
||||
127873: 20211115, // 🎁 wrapped-gift
|
||||
129717: 20211115, // 🪵 wood
|
||||
127942: 20211115, // 🏆 trophy
|
||||
127838: 20210831, // 🍞 bread
|
||||
128240: 20201001, // 📰 newspaper
|
||||
128302: 20201001, // 🔮 crystal ball
|
||||
128081: 20201001, // 👑 crown
|
||||
128055: 20201001, // 🐷 pig face
|
||||
129412: 20210831, // 🦄 unicorn
|
||||
127771: 20201001, // 🌛 first quarter moon face
|
||||
129420: 20201001, // 🦌 deer
|
||||
129668: 20210521, // 🪄 magic wand
|
||||
128171: 20201001, // 💫 dizzy
|
||||
128049: 20201001, // 🐱 meow cat face
|
||||
129409: 20201001, // 🦁 lion
|
||||
128293: 20201001, // 🔥 fire
|
||||
128038: 20210831, // 🐦 bird
|
||||
129415: 20201001, // 🦇 bat
|
||||
129417: 20210831, // 🦉 owl
|
||||
127752: 20201001, // 🌈 rainbow
|
||||
128053: 20201001, // 🐵 monkey face
|
||||
128029: 20201001, // 🐝 honeybee bumblebee wasp
|
||||
128034: 20201001, // 🐢 turtle
|
||||
128025: 20201001, // 🐙 octopus
|
||||
129433: 20201001, // 🦙 llama alpaca
|
||||
128016: 20210831, // 🐐 goat
|
||||
128060: 20201001, // 🐼 panda
|
||||
128040: 20201001, // 🐨 koala
|
||||
129445: 20201001, // 🦥 sloth
|
||||
128059: 20210831, // 🐻 bear
|
||||
128048: 20201001, // 🐰 rabbit face
|
||||
129428: 20201001, // 🦔 hedgehog
|
||||
128054: 20211115, // 🐶 dog puppy
|
||||
128041: 20211115, // 🐩 poodle dog
|
||||
129437: 20211115, // 🦝 raccoon
|
||||
128039: 20211115, // 🐧 penguin
|
||||
128012: 20210218, // 🐌 snail
|
||||
128045: 20201001, // 🐭 mouse face rat
|
||||
128031: 20210831, // 🐟 fish
|
||||
127757: 20201001, // 🌍 globe showing Europe-Africa
|
||||
127774: 20201001, // 🌞 sun with face
|
||||
127775: 20201001, // 🌟 glowing star
|
||||
11088: 20201001, // ⭐ star
|
||||
127772: 20201001, // 🌜 last quarter moon face
|
||||
129361: 20201001, // 🥑 avocado
|
||||
127820: 20211115, // 🍌 banana
|
||||
127827: 20210831, // 🍓 strawberry
|
||||
127819: 20210521, // 🍋 lemon
|
||||
127818: 20211115, // 🍊 tangerine orange
|
||||
}
|
||||
|
||||
var qqface = map[int]rune{
|
||||
0: 128558, // 😮 face exhaling
|
||||
1: 128556, // 😬 grimacing face
|
||||
2: 128525, // 😍 smiling face with heart-eyes
|
||||
4: 128526, // 😎 smiling face with sunglasses
|
||||
5: 128557, // 😭 loudly crying face
|
||||
6: 129402, // 🥺 pleading face
|
||||
7: 129296, // 🤐 zipper-mouth face
|
||||
8: 128554, // 😪 sleepy face
|
||||
11: 128545, // 😡 pouting face
|
||||
12: 128539, // 😛 face with tongue
|
||||
13: 128513, // 😁 beaming face with smiling eyes
|
||||
14: 128578, // 🙂 slightly smiling face
|
||||
15: 128577, // 🙁 slightly frowning face
|
||||
16: 128526, // 😎 smiling face with sunglasses
|
||||
19: 129326, // 🤮 face vomiting throw
|
||||
20: 129325, // 🤭 face with hand over mouth embarrassed
|
||||
21: 128522, // 😊 smiling face with smiling eyes
|
||||
23: 128533, // 😕 confused face
|
||||
24: 128523, // 😋 face savoring food
|
||||
27: 128531, // 😓 downcast face with sweat
|
||||
28: 128516, // 😄 grinning face with smiling eyes
|
||||
31: 129324, // 🤬 face with symbols on mouth
|
||||
32: 129300, // 🤔 thinking face question hmmm
|
||||
33: 129323, // 🤫 shushing face quiet whisper
|
||||
34: 128565, // 😵 face with crossed-out eyes
|
||||
35: 128547, // 😣 persevering face
|
||||
37: 128128, // 💀 skull
|
||||
46: 128055, // 🐷 pig face
|
||||
53: 127874, // 🎂 birthday cake
|
||||
59: 128169, // 💩 pile of poo
|
||||
60: 9749, // ☕ hot beverage coffee cup tea
|
||||
63: 127801, // 🌹 rose flower
|
||||
66: 10084, // ❤ mending heart
|
||||
67: 128148, // 💔 broken heart
|
||||
69: 127873, // 🎁 wrapped-gift
|
||||
74: 127774, // 🌞 sun with face
|
||||
75: 127772, // 🌜 last quarter moon face
|
||||
96: 128517, // 😅 grinning face with sweat
|
||||
104: 129393, // 🥱 yawning face
|
||||
109: 128535, // 😗 kissing face
|
||||
110: 128562, // 😲 astonished face
|
||||
111: 129402, // 🥺 pleading face
|
||||
172: 128539, // 😛 face with tongue
|
||||
182: 128514, // 😂 face with tears of joy
|
||||
187: 128123, // 👻 ghost
|
||||
247: 128567, // 😷 face with medical mask
|
||||
272: 128579, // 🙃 upside-down face
|
||||
320: 129395, // 🥳 partying face
|
||||
325: 128561, // 😱 face screaming in fear
|
||||
}
|
||||
101
plugin/emojimix/mix.go
Normal file
@@ -0,0 +1,101 @@
|
||||
// Package emojimix 合成emoji
|
||||
package emojimix
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
const bed = "https://www.gstatic.com/android/keyboard/emojikitchen/%d/u%x/u%x_u%x.png"
|
||||
|
||||
func init() {
|
||||
control.Register("emojimix", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "合成emoji\n" +
|
||||
"- [emoji][emoji]",
|
||||
}).OnMessage(match).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
r := ctx.State["emojimix"].([]rune)
|
||||
logrus.Debugln("[emojimix] match:", r)
|
||||
r1, r2 := r[0], r[1]
|
||||
u1 := fmt.Sprintf(bed, emojis[r1], r1, r1, r2)
|
||||
u2 := fmt.Sprintf(bed, emojis[r2], r2, r2, r1)
|
||||
logrus.Debugln("[emojimix] u1:", u1)
|
||||
logrus.Debugln("[emojimix] u2:", u2)
|
||||
resp1, err := http.Head(u1)
|
||||
if err == nil {
|
||||
resp1.Body.Close()
|
||||
if resp1.StatusCode == http.StatusOK {
|
||||
ctx.SendChain(message.Image(u1))
|
||||
return
|
||||
}
|
||||
}
|
||||
resp2, err := http.Head(u2)
|
||||
if err == nil {
|
||||
resp2.Body.Close()
|
||||
if resp2.StatusCode == http.StatusOK {
|
||||
ctx.SendChain(message.Image(u2))
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func match(ctx *zero.Ctx) bool {
|
||||
logrus.Debugln("[emojimix] msg:", ctx.Event.Message)
|
||||
if len(ctx.Event.Message) == 2 {
|
||||
r1 := face2emoji(ctx.Event.Message[0])
|
||||
if _, ok := emojis[r1]; !ok {
|
||||
return false
|
||||
}
|
||||
r2 := face2emoji(ctx.Event.Message[1])
|
||||
if _, ok := emojis[r2]; !ok {
|
||||
return false
|
||||
}
|
||||
ctx.State["emojimix"] = []rune{r1, r2}
|
||||
return true
|
||||
}
|
||||
|
||||
r := []rune(ctx.Event.RawMessage)
|
||||
logrus.Debugln("[emojimix] raw msg:", ctx.Event.RawMessage)
|
||||
if len(r) == 2 {
|
||||
if _, ok := emojis[r[0]]; !ok {
|
||||
return false
|
||||
}
|
||||
if _, ok := emojis[r[1]]; !ok {
|
||||
return false
|
||||
}
|
||||
ctx.State["emojimix"] = r
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func face2emoji(face message.MessageSegment) rune {
|
||||
if face.Type == "text" {
|
||||
r := []rune(face.Data["text"])
|
||||
if len(r) != 1 {
|
||||
return 0
|
||||
}
|
||||
return r[0]
|
||||
}
|
||||
if face.Type != "face" {
|
||||
return 0
|
||||
}
|
||||
id, err := strconv.Atoi(face.Data["id"])
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
if r, ok := qqface[id]; ok {
|
||||
return r
|
||||
}
|
||||
return 0
|
||||
}
|
||||
123
plugin/epidemic/epidemic.go
Normal file
@@ -0,0 +1,123 @@
|
||||
// Package epidemic 城市疫情查询
|
||||
package epidemic
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
)
|
||||
|
||||
const (
|
||||
servicename = "epidemic"
|
||||
txurl = "https://api.inews.qq.com/newsqa/v1/query/inner/publish/modules/list?modules=statisGradeCityDetail,diseaseh5Shelf"
|
||||
)
|
||||
|
||||
// result 疫情查询结果
|
||||
type result struct {
|
||||
Data struct {
|
||||
Epidemic epidemic `json:"diseaseh5Shelf"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// epidemic 疫情数据
|
||||
type epidemic struct {
|
||||
LastUpdateTime string `json:"lastUpdateTime"`
|
||||
AreaTree []*area `json:"areaTree"`
|
||||
}
|
||||
|
||||
// area 城市疫情数据
|
||||
type area struct {
|
||||
Name string `json:"name"`
|
||||
Today struct {
|
||||
Confirm int `json:"confirm"`
|
||||
Wzzadd interface{} `json:"wzz_add"`
|
||||
} `json:"today"`
|
||||
Total struct {
|
||||
NowConfirm int `json:"nowConfirm"`
|
||||
Confirm int `json:"confirm"`
|
||||
Dead int `json:"dead"`
|
||||
Heal int `json:"heal"`
|
||||
Grade string `json:"grade"`
|
||||
Wzz int `json:"wzz"`
|
||||
} `json:"total"`
|
||||
Children []*area `json:"children"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
engine := control.Register(servicename, &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "城市疫情查询\n" +
|
||||
"- xxx疫情\n",
|
||||
})
|
||||
engine.OnSuffix("疫情").SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
city := ctx.State["args"].(string)
|
||||
if city == "" {
|
||||
ctx.SendChain(message.Text("你还没有输入城市名字呢!"))
|
||||
return
|
||||
}
|
||||
data, time, err := queryEpidemic(city)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
if data == nil {
|
||||
ctx.SendChain(message.Text("没有找到【", city, "】城市的疫情数据."))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(
|
||||
message.Text(
|
||||
"【", data.Name, "】疫情数据\n",
|
||||
"新增人数:", data.Today.Confirm, "\n",
|
||||
"现有确诊:", data.Total.NowConfirm, "\n",
|
||||
"累计确诊:", data.Total.Confirm, "\n",
|
||||
"治愈人数:", data.Total.Heal, "\n",
|
||||
"死亡人数:", data.Total.Dead, "\n",
|
||||
"无症状人数:", data.Total.Wzz, "\n",
|
||||
"新增无症状:", data.Today.Wzzadd, "\n",
|
||||
"更新时间:\n『", time, "』",
|
||||
),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
// rcity 查找城市
|
||||
func rcity(a *area, cityName string) *area {
|
||||
if a == nil {
|
||||
return nil
|
||||
}
|
||||
if a.Name == cityName {
|
||||
return a
|
||||
}
|
||||
for _, v := range a.Children {
|
||||
if v.Name == cityName {
|
||||
return v
|
||||
}
|
||||
c := rcity(v, cityName)
|
||||
if c != nil {
|
||||
return c
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// queryEpidemic 查询城市疫情
|
||||
func queryEpidemic(findCityName string) (citydata *area, times string, err error) {
|
||||
data, err := web.GetData(txurl)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var r result
|
||||
err = json.Unmarshal(data, &r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
citydata = rcity(r.Data.Epidemic.AreaTree[0], findCityName)
|
||||
return citydata, r.Data.Epidemic.LastUpdateTime, nil
|
||||
}
|
||||
44
plugin/font/main.go
Normal file
@@ -0,0 +1,44 @@
|
||||
// Package font 渲染任意文字到图片
|
||||
package font
|
||||
|
||||
import (
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/binary"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func init() {
|
||||
control.Register("font", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "渲染任意文字到图片\n- (用[终末体|终末变体|紫罗兰体|樱酥体|Consolas体|苹方体])渲染文字xxx",
|
||||
}).OnRegex(`^(用.+)?渲染文字([\s\S]+)$`).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
fnt := ctx.State["regex_matched"].([]string)[1]
|
||||
txt := ctx.State["regex_matched"].([]string)[2]
|
||||
switch fnt {
|
||||
case "用终末体":
|
||||
fnt = text.SyumatuFontFile
|
||||
case "用终末变体":
|
||||
fnt = text.NisiFontFile
|
||||
case "用紫罗兰体":
|
||||
fnt = text.VioletEvergardenFontFile
|
||||
case "用樱酥体":
|
||||
fnt = text.SakuraFontFile
|
||||
case "用Consolas体":
|
||||
fnt = text.ConsolasFontFile
|
||||
case "用苹方体":
|
||||
fallthrough
|
||||
default:
|
||||
fnt = text.FontFile
|
||||
}
|
||||
b, err := text.RenderToBase64(txt, fnt, 400, 20)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Image("base64://" + binary.BytesToString(b)))
|
||||
})
|
||||
}
|
||||
248
plugin/fortune/fortune.go
Normal file
@@ -0,0 +1,248 @@
|
||||
// Package fortune 每日运势
|
||||
package fortune
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"image"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/fogleman/gg" // 注册了 jpg png gif
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/FloatTech/zbputils/img/pool"
|
||||
"github.com/FloatTech/zbputils/img/writer"
|
||||
"github.com/FloatTech/zbputils/math"
|
||||
)
|
||||
|
||||
const (
|
||||
// 底图缓存位置
|
||||
images = "data/Fortune/"
|
||||
// 基础文件位置
|
||||
omikujson = "data/Fortune/text.json"
|
||||
// 字体文件位置
|
||||
font = "data/Font/sakura.ttf"
|
||||
// 生成图缓存位置
|
||||
cache = images + "cache/"
|
||||
)
|
||||
|
||||
var (
|
||||
// 底图类型列表
|
||||
table = [...]string{"车万", "DC4", "爱因斯坦", "星空列车", "樱云之恋", "富婆妹", "李清歌", "公主连结", "原神", "明日方舟", "碧蓝航线", "碧蓝幻想", "战双", "阴阳师", "赛马娘", "东方归言录", "奇异恩典", "夏日口袋", "ASoul"}
|
||||
// 映射底图与 index
|
||||
index = make(map[string]uint8)
|
||||
// 签文
|
||||
omikujis []map[string]string
|
||||
)
|
||||
|
||||
func init() {
|
||||
// 插件主体
|
||||
en := control.Register("fortune", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "每日运势: \n" +
|
||||
"- 运势 | 抽签\n" +
|
||||
"- 设置底图[车万 | DC4 | 爱因斯坦 | 星空列车 | 樱云之恋 | 富婆妹 | 李清歌 | 公主连结 | 原神 | 明日方舟 | 碧蓝航线 | 碧蓝幻想 | 战双 | 阴阳师 | 赛马娘 | 东方归言录 | 奇异恩典 | 夏日口袋 | ASoul]",
|
||||
PublicDataFolder: "Fortune",
|
||||
})
|
||||
_ = os.RemoveAll(cache)
|
||||
err := os.MkdirAll(cache, 0755)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for i, s := range table {
|
||||
index[s] = uint8(i)
|
||||
}
|
||||
en.OnRegex(`^设置底图\s?(.*)`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid <= 0 {
|
||||
// 个人用户设为负数
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
i, ok := index[ctx.State["regex_matched"].([]string)[1]]
|
||||
if ok {
|
||||
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if ok {
|
||||
err := c.SetData(gid, int64(i)&0xff)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("设置失败:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("设置成功~"))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("设置失败: 找不到插件"))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("没有这个底图哦~"))
|
||||
})
|
||||
en.OnFullMatchGroup([]string{"运势", "抽签"}, ctxext.DoOnceOnSuccess(
|
||||
func(ctx *zero.Ctx) bool {
|
||||
data, err := file.GetLazyData(omikujson, false)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
err = json.Unmarshal(data, &omikujis)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
_, err = file.GetLazyData(font, true)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
)).Limit(ctxext.LimitByGroup).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 获取该群背景类型,默认车万
|
||||
kind := "车万"
|
||||
gid := ctx.Event.GroupID
|
||||
if gid <= 0 {
|
||||
// 个人用户设为负数
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
logrus.Debugln("[fortune]gid:", ctx.Event.GroupID, "uid:", ctx.Event.UserID)
|
||||
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if ok {
|
||||
v := uint8(c.GetData(gid) & 0xff)
|
||||
if int(v) < len(table) {
|
||||
kind = table[v]
|
||||
}
|
||||
}
|
||||
// 检查背景图片是否存在
|
||||
zipfile := images + kind + ".zip"
|
||||
_, err := file.GetLazyData(zipfile, false)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
|
||||
// 随机获取背景
|
||||
background, index, err := randimage(zipfile, ctx)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
|
||||
// 随机获取签文
|
||||
randtextindex := ctxext.RandSenderPerDayN(ctx.Event.UserID, len(omikujis))
|
||||
title, text := omikujis[randtextindex]["title"], omikujis[randtextindex]["content"]
|
||||
digest := md5.Sum(helper.StringToBytes(zipfile + strconv.Itoa(index) + title + text))
|
||||
cachefile := cache + hex.EncodeToString(digest[:])
|
||||
|
||||
err = pool.SendImageFromPool(cachefile, cachefile, func() error {
|
||||
f, err := os.Create(cachefile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = draw(background, title, text, f)
|
||||
_ = f.Close()
|
||||
return err
|
||||
}, ctxext.Send(ctx), ctxext.GetMessage(ctx))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// @function randimage 随机选取zip内的文件
|
||||
// @param path zip路径
|
||||
// @param ctx *zero.Ctx
|
||||
// @return 文件路径 & 错误信息
|
||||
func randimage(path string, ctx *zero.Ctx) (im image.Image, index int, err error) {
|
||||
reader, err := zip.OpenReader(path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
file := reader.File[ctxext.RandSenderPerDayN(ctx.Event.UserID, len(reader.File))]
|
||||
f, err := file.Open()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
im, _, err = image.Decode(f)
|
||||
return
|
||||
}
|
||||
|
||||
// @function draw 绘制运势图
|
||||
// @param background 背景图片路径
|
||||
// @param seed 随机数种子
|
||||
// @param title 签名
|
||||
// @param text 签文
|
||||
// @return 错误信息
|
||||
func draw(back image.Image, title, txt string, f io.Writer) (int64, error) {
|
||||
canvas := gg.NewContext(back.Bounds().Size().Y, back.Bounds().Size().X)
|
||||
canvas.DrawImage(back, 0, 0)
|
||||
// 写标题
|
||||
canvas.SetRGB(1, 1, 1)
|
||||
if err := canvas.LoadFontFace(font, 45); err != nil {
|
||||
return -1, err
|
||||
}
|
||||
sw, _ := canvas.MeasureString(title)
|
||||
canvas.DrawString(title, 140-sw/2, 112)
|
||||
// 写正文
|
||||
canvas.SetRGB(0, 0, 0)
|
||||
if err := canvas.LoadFontFace(font, 23); err != nil {
|
||||
return -1, err
|
||||
}
|
||||
tw, th := canvas.MeasureString("测")
|
||||
tw, th = tw+10, th+10
|
||||
r := []rune(txt)
|
||||
xsum := rowsnum(len(r), 9)
|
||||
switch xsum {
|
||||
default:
|
||||
for i, o := range r {
|
||||
xnow := rowsnum(i+1, 9)
|
||||
ysum := math.Min(len(r)-(xnow-1)*9, 9)
|
||||
ynow := i%9 + 1
|
||||
canvas.DrawString(string(o), -offest(xsum, xnow, tw)+115, offest(ysum, ynow, th)+320.0)
|
||||
}
|
||||
case 2:
|
||||
div := rowsnum(len(r), 2)
|
||||
for i, o := range r {
|
||||
xnow := rowsnum(i+1, div)
|
||||
ysum := math.Min(len(r)-(xnow-1)*div, div)
|
||||
ynow := i%div + 1
|
||||
switch xnow {
|
||||
case 1:
|
||||
canvas.DrawString(string(o), -offest(xsum, xnow, tw)+115, offest(9, ynow, th)+320.0)
|
||||
case 2:
|
||||
canvas.DrawString(string(o), -offest(xsum, xnow, tw)+115, offest(9, ynow+(9-ysum), th)+320.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
return writer.WriteTo(canvas.Image(), f)
|
||||
}
|
||||
|
||||
func offest(total, now int, distance float64) float64 {
|
||||
if total%2 == 0 {
|
||||
return (float64(now-total/2) - 1) * distance
|
||||
}
|
||||
return (float64(now-total/2) - 1.5) * distance
|
||||
}
|
||||
|
||||
func rowsnum(total, div int) int {
|
||||
temp := total / div
|
||||
if total%div != 0 {
|
||||
temp++
|
||||
}
|
||||
return temp
|
||||
}
|
||||
68
plugin/funny/laugh.go
Normal file
@@ -0,0 +1,68 @@
|
||||
// Package funny 冷笑话
|
||||
package funny
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
)
|
||||
|
||||
type joke struct {
|
||||
ID uint32 `db:"id"`
|
||||
Text string `db:"text"`
|
||||
}
|
||||
|
||||
var db = &sql.Sqlite{}
|
||||
|
||||
func init() {
|
||||
en := control.Register("funny", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "讲个笑话\n" +
|
||||
"- 讲个笑话[@xxx|qq号|人名] | 夸夸[@xxx|qq号|人名] ",
|
||||
PublicDataFolder: "Funny",
|
||||
})
|
||||
|
||||
en.OnPrefixGroup([]string{"讲个笑话", "夸夸"}, ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||
db.DBPath = en.DataFolder() + "jokes.db"
|
||||
_, err := en.GetLazyData("jokes.db", true)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
err = db.Open(time.Hour * 24)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
err = db.Create("jokes", &joke{})
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
c, err := db.Count("jokes")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
logrus.Infoln("[funny]加载", c, "个笑话")
|
||||
return true
|
||||
})).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
// 获取名字
|
||||
name := ctx.NickName()
|
||||
var j joke
|
||||
err := db.Pick("jokes", &j)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(strings.ReplaceAll(j.Text, "%name", name)))
|
||||
})
|
||||
}
|
||||
16
plugin/genshin/data.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package genshin
|
||||
|
||||
type storage uint64
|
||||
|
||||
func (s *storage) is5starsmode() bool {
|
||||
return *s&1 == 1
|
||||
}
|
||||
|
||||
func (s *storage) setmode(is5stars bool) bool {
|
||||
if is5stars {
|
||||
*s |= 1
|
||||
} else {
|
||||
*s &= 0xffffffff_fffffffe
|
||||
}
|
||||
return is5stars
|
||||
}
|
||||
375
plugin/genshin/ys.go
Normal file
@@ -0,0 +1,375 @@
|
||||
// Package genshin 原神抽卡
|
||||
package genshin
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/draw"
|
||||
"image/jpeg"
|
||||
"image/png"
|
||||
"math/rand"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/img/writer"
|
||||
"github.com/FloatTech/zbputils/process"
|
||||
"github.com/golang/freetype"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
type zipfilestructure map[string][]*zip.File
|
||||
|
||||
var (
|
||||
totl uint64 // 累计抽奖次数
|
||||
filetree = make(zipfilestructure, 32)
|
||||
starN3, starN4, starN5 *zip.File
|
||||
namereg = regexp.MustCompile(`_(.*)\.png`)
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("genshin", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "原神抽卡\n- 原神十连\n- 切换原神卡池",
|
||||
PublicDataFolder: "Genshin",
|
||||
}).ApplySingle(ctxext.DefaultSingle)
|
||||
|
||||
engine.OnFullMatch("切换原神卡池").SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if !ok {
|
||||
ctx.SendChain(message.Text("找不到服务!"))
|
||||
return
|
||||
}
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
store := (storage)(c.GetData(gid))
|
||||
if store.setmode(!store.is5starsmode()) {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(message.Text("切换到五星卡池~"))
|
||||
} else {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(message.Text("切换到普通卡池~"))
|
||||
}
|
||||
err := c.SetData(gid, int64(store))
|
||||
if err != nil {
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
}
|
||||
})
|
||||
|
||||
engine.OnFullMatch("原神十连", ctxext.DoOnceOnSuccess(
|
||||
func(ctx *zero.Ctx) bool {
|
||||
zipfile := engine.DataFolder() + "Genshin.zip"
|
||||
_, err := engine.GetLazyData("Genshin.zip", false)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
err = parsezip(zipfile)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
)).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
if !ok {
|
||||
ctx.SendChain(message.Text("找不到服务!"))
|
||||
return
|
||||
}
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
store := (storage)(c.GetData(gid))
|
||||
img, str, mode, err := randnums(10, store)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
b, cl := writer.ToBytes(img)
|
||||
if mode {
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("恭喜你抽到了: \n", str), message.ImageBytes(b)))
|
||||
} else {
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("十连成功~"), message.ImageBytes(b)))
|
||||
}
|
||||
cl()
|
||||
})
|
||||
}
|
||||
|
||||
func randnums(nums int, store storage) (rgba *image.RGBA, str string, replyMode bool, err error) {
|
||||
var (
|
||||
fours, fives = make([]*zip.File, 0, 10), make([]*zip.File, 0, 10) // 抽到 四, 五星角色
|
||||
threeArms, fourArms, fiveArms = make([]*zip.File, 0, 10), make([]*zip.File, 0, 10), make([]*zip.File, 0, 10) // 抽到 三 , 四, 五星武器
|
||||
fourN, fiveN = 0, 0 // 抽到 四, 五星角色的数量
|
||||
bgs = make([]*zip.File, 0, 10) // 背景图片名
|
||||
threeN2, fourN2, fiveN2 = 0, 0, 0 // 抽到 三 , 四, 五星武器的数量
|
||||
hero, stars = make([]*zip.File, 0, 10), make([]*zip.File, 0, 10) // 角色武器名, 储存星级图标
|
||||
|
||||
cicon = make([]*zip.File, 0, 10) // 元素图标
|
||||
fivebg, fourbg, threebg = filetree["five_bg.jpg"][0], filetree["four_bg.jpg"][0], filetree["three_bg.jpg"][0] // 背景图片名
|
||||
fivelen = len(filetree["five"])
|
||||
five2len = len(filetree["five2"])
|
||||
threelen = len(filetree["Three"])
|
||||
fourlen = len(filetree["four"])
|
||||
four2len = len(filetree["four2"])
|
||||
)
|
||||
|
||||
if totl%9 == 0 { // 累计9次加入一个五星
|
||||
switch rand.Intn(2) {
|
||||
case 0:
|
||||
fiveN++
|
||||
fives = append(fives, filetree["five"][rand.Intn(fivelen)])
|
||||
case 1:
|
||||
fiveN2++
|
||||
fiveArms = append(fiveArms, filetree["five2"][rand.Intn(five2len)])
|
||||
}
|
||||
nums--
|
||||
}
|
||||
|
||||
if store.is5starsmode() { // 5星模式
|
||||
for i := 0; i < nums; i++ {
|
||||
switch rand.Intn(2) {
|
||||
case 0:
|
||||
fiveN++
|
||||
fives = append(fives, filetree["five"][rand.Intn(fivelen)])
|
||||
case 1:
|
||||
fiveN2++
|
||||
fiveArms = append(fiveArms, filetree["five2"][rand.Intn(five2len)])
|
||||
}
|
||||
}
|
||||
} else { // 默认模式
|
||||
for i := 0; i < nums; i++ {
|
||||
a := rand.Intn(1000) // 抽卡几率 三星80% 四星17% 五星3%
|
||||
switch {
|
||||
case a >= 0 && a <= 800:
|
||||
threeN2++
|
||||
threeArms = append(threeArms, filetree["Three"][rand.Intn(threelen)])
|
||||
case a > 800 && a <= 885:
|
||||
fourN++
|
||||
fours = append(fours, filetree["four"][rand.Intn(fourlen)]) // 随机角色
|
||||
case a > 885 && a <= 970:
|
||||
fourN2++
|
||||
fourArms = append(fourArms, filetree["four2"][rand.Intn(four2len)]) // 随机武器
|
||||
case a > 970 && a <= 985:
|
||||
fiveN++
|
||||
fives = append(fives, filetree["five"][rand.Intn(fivelen)])
|
||||
default:
|
||||
fiveN2++
|
||||
fiveArms = append(fiveArms, filetree["five2"][rand.Intn(five2len)])
|
||||
}
|
||||
}
|
||||
if fourN+fourN2 == 0 && threeN2 > 0 { // 没有四星时自动加入
|
||||
threeN2--
|
||||
threeArms = threeArms[:len(threeArms)-1]
|
||||
switch rand.Intn(2) {
|
||||
case 0:
|
||||
fourN++
|
||||
fours = append(fours, filetree["four"][rand.Intn(fourlen)]) // 随机角色
|
||||
case 1:
|
||||
fourN2++
|
||||
fourArms = append(fourArms, filetree["four2"][rand.Intn(four2len)]) // 随机武器
|
||||
}
|
||||
}
|
||||
_ = atomic.AddUint64(&totl, 1)
|
||||
}
|
||||
|
||||
icon := func(f *zip.File) *zip.File {
|
||||
name := f.Name
|
||||
name = name[strings.LastIndex(name, "/")+1:strings.Index(name, "_")] + ".png"
|
||||
logrus.Debugln("[genshin]get named file", name)
|
||||
return filetree[name][0]
|
||||
}
|
||||
|
||||
he := func(cnt int, id int, f *zip.File, bg *zip.File) {
|
||||
var hen *[]*zip.File
|
||||
for i := 0; i < cnt; i++ {
|
||||
switch id {
|
||||
case 1:
|
||||
hen = &threeArms
|
||||
case 2:
|
||||
hen = &fourArms
|
||||
case 3:
|
||||
hen = &fours
|
||||
case 4:
|
||||
hen = &fiveArms
|
||||
case 5:
|
||||
hen = &fives
|
||||
}
|
||||
bgs = append(bgs, bg) // 加入颜色背景
|
||||
hero = append(hero, (*hen)[i])
|
||||
stars = append(stars, f) // 加入星级图标
|
||||
cicon = append(cicon, icon((*hen)[i])) // 加入元素图标
|
||||
}
|
||||
}
|
||||
|
||||
if fiveN > 0 { // 按顺序加入
|
||||
he(fiveN, 5, starN5, fivebg) // 五星角色
|
||||
str += reply(fives, 1, str)
|
||||
replyMode = true
|
||||
}
|
||||
if fourN > 0 {
|
||||
he(fourN, 3, starN4, fourbg) // 四星角色
|
||||
}
|
||||
if fiveN2 > 0 {
|
||||
he(fiveN2, 4, starN5, fivebg) // 五星武器
|
||||
str += reply(fiveArms, 2, str)
|
||||
replyMode = true
|
||||
}
|
||||
if fourN2 > 0 {
|
||||
he(fourN2, 2, starN4, fourbg) // 四星武器
|
||||
}
|
||||
if threeN2 > 0 {
|
||||
he(threeN2, 1, starN3, threebg) // 三星武器
|
||||
}
|
||||
|
||||
var c1, c2, c3 uint8 = 50, 50, 50 // 背景颜色
|
||||
|
||||
img00, err := filetree["bg0.jpg"][0].Open() // 打开背景图片
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
rectangle := image.Rect(0, 0, 1920, 1080) // 图片宽度, 图片高度
|
||||
rgba = image.NewRGBA(rectangle)
|
||||
draw.Draw(rgba, rgba.Bounds(), image.NewUniform(color.RGBA{c1, c2, c3, 255}), image.Point{}, draw.Over)
|
||||
context := freetype.NewContext() // 创建一个新的上下文
|
||||
context.SetDPI(72) // 每英寸 dpi
|
||||
context.SetClip(rgba.Bounds())
|
||||
context.SetDst(rgba)
|
||||
|
||||
defer img00.Close()
|
||||
img0, err := jpeg.Decode(img00) // 读取一个本地图像
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
offset := image.Pt(0, 0) // 图片在背景上的位置
|
||||
draw.Draw(rgba, img0.Bounds().Add(offset), img0, image.Point{}, draw.Over)
|
||||
|
||||
w1, h1 := 230, 0
|
||||
for i := 0; i < len(hero); i++ {
|
||||
if i > 0 {
|
||||
w1 += 146 // 图片宽度
|
||||
}
|
||||
|
||||
imgs, err := bgs[i].Open() // 取出背景图片
|
||||
if err != nil {
|
||||
return nil, "", false, err
|
||||
}
|
||||
defer imgs.Close()
|
||||
|
||||
img, _ := jpeg.Decode(imgs)
|
||||
offset := image.Pt(w1, h1)
|
||||
draw.Draw(rgba, img.Bounds().Add(offset), img, image.Point{}, draw.Over)
|
||||
|
||||
imgs1, err := hero[i].Open() // 取出图片名
|
||||
if err != nil {
|
||||
return nil, "", false, err
|
||||
}
|
||||
defer imgs1.Close()
|
||||
|
||||
img1, _ := png.Decode(imgs1)
|
||||
offset1 := image.Pt(w1, h1)
|
||||
draw.Draw(rgba, img1.Bounds().Add(offset1), img1, image.Point{}, draw.Over)
|
||||
|
||||
imgs2, err := stars[i].Open() // 取出星级图标
|
||||
if err != nil {
|
||||
return nil, "", false, err
|
||||
}
|
||||
defer imgs2.Close()
|
||||
|
||||
img2, _ := png.Decode(imgs2)
|
||||
offset2 := image.Pt(w1, h1)
|
||||
draw.Draw(rgba, img2.Bounds().Add(offset2), img2, image.Point{}, draw.Over)
|
||||
|
||||
imgs3, err := cicon[i].Open() // 取出类型图标
|
||||
if err != nil {
|
||||
return nil, "", false, err
|
||||
}
|
||||
defer imgs3.Close()
|
||||
|
||||
img3, _ := png.Decode(imgs3)
|
||||
offset3 := image.Pt(w1, h1)
|
||||
draw.Draw(rgba, img3.Bounds().Add(offset3), img3, image.Point{}, draw.Over)
|
||||
}
|
||||
imgs4, err := filetree["Reply.png"][0].Open() // "分享" 图标
|
||||
if err != nil {
|
||||
return nil, "", false, err
|
||||
}
|
||||
defer imgs4.Close()
|
||||
img4, err := png.Decode(imgs4)
|
||||
if err != nil {
|
||||
return nil, "", false, err
|
||||
}
|
||||
offset4 := image.Pt(1270, 945) // 宽, 高
|
||||
draw.Draw(rgba, img4.Bounds().Add(offset4), img4, image.Point{}, draw.Over)
|
||||
return
|
||||
}
|
||||
|
||||
func parsezip(zipFile string) error {
|
||||
zipReader, err := zip.OpenReader(zipFile) // will not close
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, f := range zipReader.File {
|
||||
if f.FileInfo().IsDir() {
|
||||
filetree[f.Name] = make([]*zip.File, 0, 32)
|
||||
continue
|
||||
}
|
||||
f.Name = f.Name[8:]
|
||||
i := strings.LastIndex(f.Name, "/")
|
||||
if i < 0 {
|
||||
filetree[f.Name] = []*zip.File{f}
|
||||
logrus.Debugln("[genshin]insert file", f.Name)
|
||||
continue
|
||||
}
|
||||
folder := f.Name[:i]
|
||||
if folder != "" {
|
||||
filetree[folder] = append(filetree[folder], f)
|
||||
logrus.Debugln("[genshin]insert file into", folder)
|
||||
if folder == "gacha" {
|
||||
switch f.Name[i+1:] {
|
||||
case "ThreeStar.png":
|
||||
starN3 = f
|
||||
case "FourStar.png":
|
||||
starN4 = f
|
||||
case "FiveStar.png":
|
||||
starN5 = f
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 取出角色武器名
|
||||
func reply(z []*zip.File, num int, nameStr string) string {
|
||||
var tmp strings.Builder
|
||||
tmp.Grow(128)
|
||||
switch {
|
||||
case num == 1:
|
||||
tmp.WriteString("★五星角色★\n")
|
||||
case num == 2 && len(nameStr) > 0:
|
||||
tmp.WriteString("\n★五星武器★\n")
|
||||
default:
|
||||
tmp.WriteString("★五星武器★\n")
|
||||
}
|
||||
for i := range z {
|
||||
tmp.WriteString(namereg.FindStringSubmatch(z[i].Name)[1] + " * ")
|
||||
}
|
||||
return tmp.String()
|
||||
}
|
||||
90
plugin/gif/README.md
Normal file
@@ -0,0 +1,90 @@
|
||||
# ZeroBot-Plugin-Gif
|
||||
[ZeroBot QQ机器人](https://github.com/wdvxdr1123/ZeroBot)插件,可以制作各种沙雕gif图
|
||||
> 素材包地址: https://gitcode.net/anto_july/imagematerials
|
||||
|
||||
## 触发方式
|
||||
1. [指令词]+[qq号] 如:爬123456
|
||||
2. [指令词]+[图片] 如:爬[图片]
|
||||
3. [指令词]+[艾特] 如:爬@小H
|
||||
|
||||
## 指令列表
|
||||
- [x] 爬
|
||||
- [x] 冲
|
||||
- [x] 摸
|
||||
- [x] 搓
|
||||
- [x] 拍
|
||||
- [x] 丢
|
||||
- [x] 敲
|
||||
- [x] 吃
|
||||
- [x] 啃
|
||||
- [x] 撕
|
||||
- [x] 蹭
|
||||
- [x] 灰度
|
||||
- [x] 上翻
|
||||
- [x] 下翻
|
||||
- [x] 左翻
|
||||
- [x] 右翻
|
||||
- [x] 反色
|
||||
- [x] 倒放
|
||||
- [x] 浮雕
|
||||
- [x] 打码
|
||||
- [x] 负片
|
||||
- [x] 旋转45
|
||||
- [x] 变形100 100
|
||||
- [x] 亲
|
||||
- [x] 娶|结婚申请|结婚登记
|
||||
- [x] 像只
|
||||
- [x] 阿尼亚喜欢
|
||||
- [x] 我永远喜欢|永远喜欢
|
||||
- [x] 像样的亲亲
|
||||
- [x] 国旗
|
||||
- [x] 不要靠近
|
||||
- [x] 万能表情|空白表情
|
||||
- [x] 采访
|
||||
- [x] 需要|你可能需要
|
||||
- [x] 这像画吗
|
||||
- [x] 小画家
|
||||
- [x] 完美
|
||||
- [x] 玩游戏 (应该使用透视变换)
|
||||
- [x] 出警
|
||||
- [x] 警察
|
||||
- [x] 舔|舔屏|prpr (应该使用透视变换)
|
||||
- [x] 安全感
|
||||
- [x] 精神支柱
|
||||
- [x] 想什么
|
||||
- [x] 墙纸
|
||||
- [x] 为什么at我
|
||||
- [x] 交个朋友
|
||||
- [x] 打工人|继续干活
|
||||
- [x] 兑换券
|
||||
- [ ] 捂脸 (使用了透视变换, 需要研究矩阵变换)
|
||||
- [x] 注意力涣散
|
||||
- [x] 垃圾桶|垃圾
|
||||
- [x] 锤
|
||||
- [x] 啾啾
|
||||
- [x] 2敲
|
||||
- [x] 听音乐
|
||||
- [ ] 群青 (需要mask)
|
||||
- [ ] 加载中 (需要mask)
|
||||
- [x] 永远爱你 (未加闪光)
|
||||
- [ ] 关注 (处理文字麻烦)
|
||||
- [x] 2拍
|
||||
- [x] 顶
|
||||
- [x] 捣
|
||||
- [x] 打拳 (未加闪光)
|
||||
- [ ] 复读 (处理文字麻烦)
|
||||
- [x] 滚
|
||||
- [x] 吸
|
||||
- [x] 扔
|
||||
- [x] 捶
|
||||
- [x] 紧贴
|
||||
- [ ] 膜拜 (使用了透视变换, 需要研究矩阵变换)
|
||||
- [ ] 小天使 (摆)
|
||||
- [ ] 一直 (摆)
|
||||
- [x] 转
|
||||
- [ ] 问问 (摆)
|
||||
- [ ] 典中典 (摆)
|
||||
- [ ] 震惊 (摆)
|
||||
- [ ] 哈哈镜 (摆)
|
||||
- [ ] 对称 (猎奇, 不整)
|
||||
- [ ] 远离 (摆)
|
||||
85
plugin/gif/context.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package gif
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/FloatTech/zbputils/img"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type context struct {
|
||||
usrdir string
|
||||
headimgsdir []string
|
||||
}
|
||||
|
||||
func dlchan(name string, s *string, wg *sync.WaitGroup, exit func(error)) {
|
||||
defer wg.Done()
|
||||
target := datapath + `materials/` + name
|
||||
var err error
|
||||
if file.IsNotExist(target) {
|
||||
err = file.DownloadTo(`https://gitcode.net/anto_july/imagematerials/-/raw/main/`+name, target, true)
|
||||
if err != nil {
|
||||
exit(err)
|
||||
return
|
||||
}
|
||||
logrus.Debugln("[gif] dl", name, "to", target, "succeeded")
|
||||
} else {
|
||||
logrus.Debugln("[gif] dl", name, "exists at", target)
|
||||
}
|
||||
*s = target
|
||||
}
|
||||
|
||||
func dlblock(name string) (string, error) {
|
||||
target := datapath + `materials/` + name
|
||||
if file.IsNotExist(target) {
|
||||
err := file.DownloadTo(`https://gitcode.net/u011570312/imagematerials/-/raw/main/`+name, target, true)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
logrus.Debugln("[gif] dl", name, "to", target, "succeeded")
|
||||
} else {
|
||||
logrus.Debugln("[gif] dl", name, "exists at", target)
|
||||
}
|
||||
return target, nil
|
||||
}
|
||||
|
||||
func dlrange(prefix string, end int, wg *sync.WaitGroup, exit func(error)) []string {
|
||||
if file.IsNotExist(datapath + `materials/` + prefix) {
|
||||
err := os.MkdirAll(datapath+`materials/`+prefix, 0755)
|
||||
if err != nil {
|
||||
exit(err)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
c := make([]string, end)
|
||||
for i := range c {
|
||||
wg.Add(1)
|
||||
go dlchan(prefix+"/"+strconv.Itoa(i)+".png", &c[i], wg, exit)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// 新的上下文
|
||||
func newContext(user int64) *context {
|
||||
c := new(context)
|
||||
c.usrdir = datapath + "users/" + strconv.FormatInt(user, 10) + `/`
|
||||
_ = os.MkdirAll(c.usrdir, 0755)
|
||||
c.headimgsdir = make([]string, 2)
|
||||
c.headimgsdir[0] = c.usrdir + "0.gif"
|
||||
c.headimgsdir[1] = c.usrdir + "1.gif"
|
||||
return c
|
||||
}
|
||||
|
||||
func loadFirstFrames(paths []string, size int) (imgs []*img.ImgFactory, err error) {
|
||||
imgs = make([]*img.ImgFactory, size)
|
||||
for i := range imgs {
|
||||
imgs[i], err = img.LoadFirstFrame(paths[i], 0, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return imgs, nil
|
||||
}
|
||||
893
plugin/gif/gif.go
Normal file
@@ -0,0 +1,893 @@
|
||||
package gif
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"sync"
|
||||
|
||||
"github.com/FloatTech/zbputils/img"
|
||||
"github.com/FloatTech/zbputils/img/writer"
|
||||
"github.com/fogleman/gg"
|
||||
)
|
||||
|
||||
// mo 摸
|
||||
func mo(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "摸.gif"
|
||||
c := dlrange("mo", 5, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 5)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
mo := []*image.NRGBA{
|
||||
imgs[0].InsertBottom(tou, 80, 80, 32, 32).Im,
|
||||
imgs[1].InsertBottom(tou, 70, 90, 42, 22).Im,
|
||||
imgs[2].InsertBottom(tou, 75, 85, 37, 27).Im,
|
||||
imgs[3].InsertBottom(tou, 85, 75, 27, 37).Im,
|
||||
imgs[4].InsertBottom(tou, 90, 70, 22, 42).Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(1, mo))
|
||||
}
|
||||
|
||||
// cuo 搓
|
||||
func cuo(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "搓.gif"
|
||||
c := dlrange("cuo", 5, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(110, 110)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
m1 := img.Rotate(tou, 72, 0, 0)
|
||||
m2 := img.Rotate(tou, 144, 0, 0)
|
||||
m3 := img.Rotate(tou, 216, 0, 0)
|
||||
m4 := img.Rotate(tou, 288, 0, 0)
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 5)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
cuo := []*image.NRGBA{
|
||||
imgs[0].InsertBottomC(tou, 0, 0, 75, 130).Im,
|
||||
imgs[1].InsertBottomC(m1.Im, 0, 0, 75, 130).Im,
|
||||
imgs[2].InsertBottomC(m2.Im, 0, 0, 75, 130).Im,
|
||||
imgs[3].InsertBottomC(m3.Im, 0, 0, 75, 130).Im,
|
||||
imgs[4].InsertBottomC(m4.Im, 0, 0, 75, 130).Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(5, cuo))
|
||||
}
|
||||
|
||||
// qiao 敲
|
||||
func qiao(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "敲.gif"
|
||||
c := dlrange("qiao", 2, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(40, 40)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 2)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
qiao := []*image.NRGBA{
|
||||
imgs[0].InsertUp(tou, 40, 33, 57, 52).Im,
|
||||
imgs[1].InsertUp(tou, 38, 36, 58, 50).Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(1, qiao))
|
||||
}
|
||||
|
||||
// chi 吃
|
||||
func chi(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "吃.gif"
|
||||
c := dlrange("chi", 3, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(32, 32)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 3)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
chi := []*image.NRGBA{
|
||||
imgs[0].InsertBottom(tou, 0, 0, 1, 38).Im,
|
||||
imgs[1].InsertBottom(tou, 0, 0, 1, 38).Im,
|
||||
imgs[2].InsertBottom(tou, 0, 0, 1, 38).Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(1, chi))
|
||||
}
|
||||
|
||||
// ceng 蹭
|
||||
func ceng(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "蹭.gif"
|
||||
c := dlrange("ceng", 6, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(100, 100)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou2, err := cc.getLogo2(100, 100)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 6)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
ceng := []*image.NRGBA{
|
||||
imgs[0].InsertUp(tou, 75, 77, 40, 88).InsertUp(tou2, 77, 103, 102, 81).Im,
|
||||
imgs[1].InsertUp(tou, 75, 77, 46, 100).InsertUp(img.Rotate(tou2, 10, 62, 127).Im, 0, 0, 92, 40).Im,
|
||||
imgs[2].InsertUp(tou, 75, 77, 67, 99).InsertUp(tou2, 76, 117, 90, 8).Im,
|
||||
imgs[3].InsertUp(tou, 75, 77, 52, 83).InsertUp(img.Rotate(tou2, -40, 94, 94).Im, 0, 0, 53, -20).Im,
|
||||
imgs[4].InsertUp(tou, 75, 77, 56, 110).InsertUp(img.Rotate(tou2, -66, 132, 80).Im, 0, 0, 78, 40).Im,
|
||||
imgs[5].InsertUp(tou, 75, 77, 62, 102).InsertUp(tou2, 71, 100, 110, 94).Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(8, ceng))
|
||||
}
|
||||
|
||||
// ken 啃
|
||||
func ken(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "啃.gif"
|
||||
c := dlrange("ken", 16, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(100, 100)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 16)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
ken := []*image.NRGBA{
|
||||
imgs[0].InsertBottom(tou, 90, 90, 105, 150).Im,
|
||||
imgs[1].InsertBottom(tou, 90, 83, 96, 172).Im,
|
||||
imgs[2].InsertBottom(tou, 90, 90, 106, 148).Im,
|
||||
imgs[3].InsertBottom(tou, 88, 88, 97, 167).Im,
|
||||
imgs[4].InsertBottom(tou, 90, 85, 89, 179).Im,
|
||||
imgs[5].InsertBottom(tou, 90, 90, 106, 151).Im,
|
||||
imgs[6].Im,
|
||||
imgs[7].Im,
|
||||
imgs[8].Im,
|
||||
imgs[9].Im,
|
||||
imgs[10].Im,
|
||||
imgs[11].Im,
|
||||
imgs[12].Im,
|
||||
imgs[13].Im,
|
||||
imgs[14].Im,
|
||||
imgs[15].Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, ken))
|
||||
}
|
||||
|
||||
// pai 拍
|
||||
func pai(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "拍.gif"
|
||||
c := dlrange("pai", 2, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(30, 30)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 2)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
pai := []*image.NRGBA{
|
||||
imgs[0].InsertUp(tou, 0, 0, 1, 47).Im,
|
||||
imgs[1].InsertUp(tou, 0, 0, 1, 67).Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(1, pai))
|
||||
}
|
||||
|
||||
// xqe 冲
|
||||
func xqe(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "冲.gif"
|
||||
c := dlrange("xqe", 2, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 2)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
chong := []*image.NRGBA{
|
||||
imgs[0].InsertUp(tou, 30, 30, 15, 53).Im,
|
||||
imgs[1].InsertUp(tou, 30, 30, 40, 53).Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(1, chong))
|
||||
}
|
||||
|
||||
// diu 丢
|
||||
func diu(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "丢.gif"
|
||||
c := dlrange("diu", 8, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou, err := cc.getLogo(0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, 8)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
diu := []*image.NRGBA{
|
||||
imgs[0].InsertUp(tou, 32, 32, 108, 36).Im,
|
||||
imgs[1].InsertUp(tou, 32, 32, 122, 36).Im,
|
||||
imgs[2].Im,
|
||||
imgs[3].InsertUp(tou, 123, 123, 19, 129).Im,
|
||||
imgs[4].InsertUp(tou, 185, 185, -50, 200).InsertUp(tou, 33, 33, 289, 70).Im,
|
||||
imgs[5].InsertUp(tou, 32, 32, 280, 73).Im,
|
||||
imgs[6].InsertUp(tou, 35, 35, 259, 31).Im,
|
||||
imgs[7].InsertUp(tou, 175, 175, -50, 220).Im,
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, diu))
|
||||
}
|
||||
|
||||
// kiss 亲
|
||||
func kiss(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 13
|
||||
name := cc.usrdir + "Kiss.gif"
|
||||
c := dlrange("kiss", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
tou, err := cc.getLogo(0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tou2, err := cc.getLogo2(0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
userLocs := [][]int{{58, 90}, {62, 95}, {42, 100}, {50, 100}, {56, 100}, {18, 120}, {28, 110}, {54, 100}, {46, 100}, {60, 100}, {35, 115}, {20, 120}, {40, 96}}
|
||||
selfLocs := [][]int{{92, 64}, {135, 40}, {84, 105}, {80, 110}, {155, 82}, {60, 96}, {50, 80}, {98, 55}, {35, 65}, {38, 100}, {70, 80}, {84, 65}, {75, 65}}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
kiss := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
kiss[i] = imgs[i].InsertUp(tou, 50, 50, userLocs[i][0], userLocs[i][1]).
|
||||
InsertUp(tou2, 40, 40, selfLocs[i][0], selfLocs[i][1]).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, kiss))
|
||||
}
|
||||
|
||||
// garbage 垃圾 垃圾桶
|
||||
func garbage(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 25
|
||||
name := cc.usrdir + "Garbage.gif"
|
||||
c := dlrange("garbage", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 79, 79)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
locs := [][]int{{39, 40}, {39, 40}, {39, 40}, {39, 30}, {39, 30}, {39, 32}, {39, 32}, {39, 32}, {39, 32}, {39, 32}, {39, 32}, {39, 32}, {39, 32}, {39, 32}, {39, 32}, {39, 30}, {39, 27}, {39, 32}, {37, 49}, {37, 64}, {37, 67}, {37, 67}, {39, 69}, {37, 70}, {37, 70}}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
garbage := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
garbage[i] = imgs[i].InsertBottom(im.Im, 0, 0, locs[i][0], locs[i][1]).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, garbage))
|
||||
}
|
||||
|
||||
// thump 捶
|
||||
func thump(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 4
|
||||
name := cc.usrdir + "Thump.gif"
|
||||
c := dlrange("thump", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
locs := [][]int{{65, 128, 77, 72}, {67, 128, 73, 72}, {54, 139, 94, 61}, {57, 135, 86, 65}}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
thump := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
thump[i] = imgs[i].InsertBottom(im.Im, locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, thump))
|
||||
}
|
||||
|
||||
// jiujiu 啾啾
|
||||
func jiujiu(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 8
|
||||
name := cc.usrdir + "Jiujiu.gif"
|
||||
c := dlrange("jiujiu", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 75, 51)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
jiujiu := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
jiujiu[i] = imgs[i].InsertBottom(im.Im, 0, 0, 0, 0).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, jiujiu))
|
||||
}
|
||||
|
||||
// knock 2敲
|
||||
func knock(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 8
|
||||
name := cc.usrdir + "Knock.gif"
|
||||
c := dlrange("knock", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
locs := [][]int{{60, 308, 210, 195}, {60, 308, 210, 198}, {45, 330, 250, 172}, {58, 320, 218, 180}, {60, 310, 215, 193}, {40, 320, 250, 285}, {48, 308, 226, 192}, {51, 301, 223, 200}}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
knock := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
knock[i] = imgs[i].InsertBottom(im.Im, locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, knock))
|
||||
}
|
||||
|
||||
// 听音乐 listenMusic
|
||||
func listenMusic(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 1
|
||||
name := cc.usrdir + "ListenMusic.gif"
|
||||
c := dlrange("listen_music", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
face, err := cc.getLogo(0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
listenmusic := make([]*image.NRGBA, 36)
|
||||
for i := 0; i < 36; i++ {
|
||||
listenmusic[i] = imgs[0].InsertBottomC(img.Rotate(face, float64(-i*10), 215, 215).Im, 0, 0, 207, 207).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, listenmusic))
|
||||
}
|
||||
|
||||
// loveYou 永远爱你
|
||||
func loveYou(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 2
|
||||
name := cc.usrdir + "LoveYou.gif"
|
||||
c := dlrange("love_you", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
locs := [][]int{{68, 65, 70, 70}, {63, 59, 80, 80}}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
loveyou := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
loveyou[i] = imgs[i].InsertBottom(im.Im, locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, loveyou))
|
||||
}
|
||||
|
||||
// pat 2拍
|
||||
func pat(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 10
|
||||
name := cc.usrdir + "Pat.gif"
|
||||
c := dlrange("pat", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
locs := [][]int{{11, 73, 106, 100}, {8, 79, 112, 96}}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
p := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
if i == 2 {
|
||||
p[i] = imgs[i].InsertBottom(im.Im, locs[1][2], locs[1][3], locs[1][0], locs[1][1]).Im
|
||||
} else {
|
||||
p[i] = imgs[i].InsertBottom(im.Im, locs[0][2], locs[0][3], locs[0][0], locs[0][1]).Im
|
||||
}
|
||||
}
|
||||
seq := []int{0, 1, 2, 3, 1, 2, 3, 0, 1, 2, 3, 0, 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 5, 5, 6, 7, 8, 9}
|
||||
pat := make([]*image.NRGBA, len(seq))
|
||||
for i := 0; i < len(pat); i++ {
|
||||
pat[i] = p[seq[i]]
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, pat))
|
||||
}
|
||||
|
||||
// jackUp 顶
|
||||
func jackUp(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 23
|
||||
name := cc.usrdir + "JackUp.gif"
|
||||
c := dlrange("play", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
locs := [][]int{{180, 60, 100, 100}, {184, 75, 100, 100}, {183, 98, 100, 100}, {179, 118, 110, 100}, {156, 194, 150, 48}, {178, 136, 122, 69}, {175, 66, 122, 85}, {170, 42, 130, 96}, {175, 34, 118, 95}, {179, 35, 110, 93}, {180, 54, 102, 93}, {183, 58, 97, 92}, {174, 35, 120, 94}, {179, 35, 109, 93}, {181, 54, 101, 92}, {182, 59, 98, 92}, {183, 71, 90, 96}, {180, 131, 92, 101}}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
p := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
if i < len(locs) {
|
||||
p[i] = imgs[i].InsertBottom(im.Im, locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Im
|
||||
} else {
|
||||
p[i] = imgs[i].Im
|
||||
}
|
||||
}
|
||||
play := make([]*image.NRGBA, 0, 16)
|
||||
play = append(play, p[0:12]...)
|
||||
play = append(play, p[0:12]...)
|
||||
play = append(play, p[0:8]...)
|
||||
play = append(play, p[12:18]...)
|
||||
play = append(play, p[18:23]...)
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, play))
|
||||
}
|
||||
|
||||
// pound 捣
|
||||
func pound(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 8
|
||||
name := cc.usrdir + "Pound.gif"
|
||||
c := dlrange("pound", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
locs := [][]int{{135, 240, 138, 47}, {135, 240, 138, 47}, {150, 190, 105, 95}, {150, 190, 105, 95}, {148, 188, 106, 98}, {146, 196, 110, 88}, {145, 223, 112, 61}, {145, 223, 112, 61}}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
pound := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
pound[i] = imgs[i].InsertBottom(im.Im, locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, pound))
|
||||
}
|
||||
|
||||
// punch 打拳
|
||||
func punch(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 13
|
||||
name := cc.usrdir + "Punch.gif"
|
||||
c := dlrange("punch", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 260, 260)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
locs := [][]int{{-50, 20}, {-40, 10}, {-30, 0}, {-20, -10}, {-10, -10}, {0, 0}, {10, 10}, {20, 20}, {10, 10}, {0, 0}, {-10, -10}, {10, 0}, {-30, 10}}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
punch := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
punch[i] = imgs[i].InsertBottom(im.Im, 0, 0, locs[i][0], locs[i][1]-15).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, punch))
|
||||
}
|
||||
|
||||
// roll 滚
|
||||
func roll(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 8
|
||||
name := cc.usrdir + "roll.gif"
|
||||
c := dlrange("roll", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 210, 210)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
locs := [][]int{{87, 77, 0}, {96, 85, -45}, {92, 79, -90}, {92, 78, -135}, {92, 75, -180}, {92, 75, -225}, {93, 76, -270}, {90, 80, -315}}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
roll := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
roll[i] = imgs[i].InsertBottomC(img.Rotate(im.Im, float64(locs[i][2]), 0, 0).Im, 0, 0, locs[i][0]+105, locs[i][1]+105).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, roll))
|
||||
}
|
||||
|
||||
// suck 吸 嗦
|
||||
func suck(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 12
|
||||
name := cc.usrdir + "Suck.gif"
|
||||
c := dlrange("suck", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
locs := [][]int{{82, 100, 130, 119}, {82, 94, 126, 125}, {82, 120, 128, 99}, {81, 164, 132, 55}, {79, 163, 132, 55}, {82, 140, 127, 79}, {83, 152, 125, 67}, {75, 157, 140, 62}, {72, 165, 144, 54}, {80, 132, 128, 87}, {81, 127, 127, 92}, {79, 111, 132, 108}}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
suck := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
suck[i] = imgs[i].InsertBottom(im.Im, locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, suck))
|
||||
}
|
||||
|
||||
// hammer 锤
|
||||
func hammer(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 7
|
||||
name := cc.usrdir + "Hammer.gif"
|
||||
c := dlrange("hammer", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
locs := [][]int{{62, 143, 158, 113}, {52, 177, 173, 105}, {42, 192, 192, 92}, {46, 182, 184, 100}, {54, 169, 174, 110}, {69, 128, 144, 135}, {65, 130, 152, 124}}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
hammer := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
hammer[i] = imgs[i].InsertBottom(im.Im, locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, hammer))
|
||||
}
|
||||
|
||||
// tightly 紧贴 紧紧贴着
|
||||
func tightly(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 20
|
||||
name := cc.usrdir + "Tightly.gif"
|
||||
c := dlrange("tightly", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
m.Unlock()
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wg.Wait()
|
||||
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
locs := [][]int{{39, 169, 267, 141}, {40, 167, 264, 143}, {38, 174, 270, 135}, {40, 167, 264, 143}, {38, 174, 270, 135}, {40, 167, 264, 143}, {38, 174, 270, 135}, {40, 167, 264, 143}, {38, 174, 270, 135}, {28, 176, 293, 134}, {5, 215, 333, 96}, {10, 210, 321, 102}, {3, 210, 330, 104}, {4, 210, 328, 102}, {4, 212, 328, 100}, {4, 212, 328, 100}, {4, 212, 328, 100}, {4, 212, 328, 100}, {4, 212, 328, 100}, {29, 195, 285, 120}}
|
||||
imgs, err := loadFirstFrames(c, piclen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tightly := make([]*image.NRGBA, piclen)
|
||||
for i := 0; i < piclen; i++ {
|
||||
tightly[i] = imgs[i].InsertBottom(im.Im, locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, tightly))
|
||||
}
|
||||
|
||||
// turn 转
|
||||
func turn(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
name := cc.usrdir + "Turn.gif"
|
||||
face, err := cc.getLogo(0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
canvas := gg.NewContext(250, 250)
|
||||
canvas.SetColor(color.White)
|
||||
canvas.DrawRectangle(0, 0, 250, 250)
|
||||
canvas.Fill()
|
||||
turn := make([]*image.NRGBA, 36)
|
||||
for i := 0; i < 36; i++ {
|
||||
turn[i] = img.Size(canvas.Image(), 0, 0).InsertUpC(img.Rotate(face, float64(10*i), 250, 250).Im, 0, 0, 125, 125).Im
|
||||
}
|
||||
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, turn))
|
||||
}
|
||||
41
plugin/gif/logo.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package gif
|
||||
|
||||
import (
|
||||
"image"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/FloatTech/zbputils/img"
|
||||
)
|
||||
|
||||
func (cc *context) prepareLogos(s ...string) error {
|
||||
for i, v := range s {
|
||||
_, err := strconv.Atoi(v)
|
||||
if err != nil {
|
||||
err = file.DownloadTo("https://gchat.qpic.cn/gchatpic_new//--"+strings.ToUpper(v)+"/0", cc.usrdir+strconv.Itoa(i)+".gif", true)
|
||||
} else {
|
||||
err = file.DownloadTo("http://q4.qlogo.cn/g?b=qq&nk="+v+"&s=640", cc.usrdir+strconv.Itoa(i)+".gif", true)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cc *context) getLogo(w int, h int) (*image.NRGBA, error) {
|
||||
frame, err := img.LoadFirstFrame(cc.headimgsdir[0], w, h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return frame.Circle(0).Im, nil
|
||||
}
|
||||
|
||||
func (cc *context) getLogo2(w int, h int) (*image.NRGBA, error) {
|
||||
frame, err := img.LoadFirstFrame(cc.headimgsdir[1], w, h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return frame.Circle(0).Im, nil
|
||||
}
|
||||
1085
plugin/gif/png.go
Normal file
130
plugin/gif/run.go
Normal file
@@ -0,0 +1,130 @@
|
||||
// Package gif 制图
|
||||
package gif
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
var (
|
||||
cmd = make([]string, 0)
|
||||
datapath string
|
||||
cmdMap = map[string]func(cc *context, args ...string) (string, error){
|
||||
"搓": cuo,
|
||||
"冲": xqe,
|
||||
"摸": mo,
|
||||
"拍": pai,
|
||||
"丢": diu,
|
||||
"吃": chi,
|
||||
"敲": qiao,
|
||||
"啃": ken,
|
||||
"蹭": ceng,
|
||||
"爬": pa,
|
||||
"撕": si,
|
||||
"灰度": grayscale,
|
||||
"上翻": flipV,
|
||||
"下翻": flipV,
|
||||
"左翻": flipH,
|
||||
"右翻": flipH,
|
||||
"反色": invert,
|
||||
"浮雕": convolve3x3,
|
||||
"打码": blur,
|
||||
"负片": invertAndGrayscale,
|
||||
"旋转": rotate,
|
||||
"变形": deformation,
|
||||
"亲": kiss,
|
||||
"结婚申请": marriage,
|
||||
"结婚登记": marriage,
|
||||
"阿尼亚喜欢": anyasuki,
|
||||
"像只": alike,
|
||||
"我永远喜欢": alwaysLike,
|
||||
"永远喜欢": alwaysLike,
|
||||
"像样的亲亲": decentKiss,
|
||||
"国旗": chinaFlag,
|
||||
"不要靠近": dontTouch,
|
||||
"万能表情": universal,
|
||||
"空白表情": universal,
|
||||
"采访": interview,
|
||||
"需要": need,
|
||||
"你可能需要": need,
|
||||
"这像画吗": paint,
|
||||
"小画家": painter,
|
||||
"完美": perfect,
|
||||
"玩游戏": playGame,
|
||||
"出警": police,
|
||||
"警察": police1,
|
||||
"舔": prpr,
|
||||
"舔屏": prpr,
|
||||
"prpr": prpr,
|
||||
"安全感": safeSense,
|
||||
"精神支柱": support,
|
||||
"想什么": thinkwhat,
|
||||
"墙纸": wallpaper,
|
||||
"为什么at我": whyatme,
|
||||
"交个朋友": makeFriend,
|
||||
"打工人": backToWork,
|
||||
"继续干活": backToWork,
|
||||
"兑换券": coupon,
|
||||
"注意力涣散": distracted,
|
||||
"垃圾桶": garbage,
|
||||
"垃圾": garbage,
|
||||
"捶": thump,
|
||||
"啾啾": jiujiu,
|
||||
"2敲": knock,
|
||||
"听音乐": listenMusic,
|
||||
"永远爱你": loveYou,
|
||||
"2拍": pat,
|
||||
"顶": jackUp,
|
||||
"捣": pound,
|
||||
"打拳": punch,
|
||||
"滚": roll,
|
||||
"吸": suck,
|
||||
"嗦": suck,
|
||||
"扔": throw,
|
||||
"锤": hammer,
|
||||
"紧贴": tightly,
|
||||
"紧紧贴着": tightly,
|
||||
"转": turn,
|
||||
}
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
for k := range cmdMap {
|
||||
cmd = append(cmd, k)
|
||||
}
|
||||
en := control.Register("gif", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "制图\n- 搓\n- 冲\n- 摸\n- 拍\n- 丢\n- 吃\n- 敲\n- 啃\n- 蹭\n- 爬\n- 撕\n- 灰度\n- 上翻|下翻\n" +
|
||||
"- 左翻|右翻\n- 反色\n- 浮雕\n- 打码\n- 负片\n- 旋转 45\n- 变形 100 100\n- 亲\n- 结婚申请|结婚登记\n- 阿尼亚喜欢\n- 像只\n" +
|
||||
"- 我永远喜欢|永远喜欢\n- 像样的亲亲\n- 国旗\n- 不要靠近\n- 万能表情|空白表情\n- 采访\n- 需要|你可能需要\n- 这像画吗\n- 小画家\n" +
|
||||
"- 完美\n- 玩游戏\n- 出警\n- 警察\n- 舔|舔屏|prpr\n- 安全感\n- 精神支柱\n- 想什么\n- 墙纸\n- 为什么at我\n- 交个朋友\n- 打工人|继续干活\n" +
|
||||
"- 兑换券\n- 注意力涣散\n- 垃圾桶|垃圾\n- 捶\n- 啾啾\n- 2敲\n- 听音乐\n- 永远爱你\n- 2拍\n- 顶\n- 捣\n- 打拳\n- 滚\n- 吸|嗦\n- 扔\n" +
|
||||
"- 锤\n- 紧贴|紧紧贴着\n- 转\n",
|
||||
PrivateDataFolder: "gif",
|
||||
}).ApplySingle(ctxext.DefaultSingle)
|
||||
datapath = file.BOTPATH + "/" + en.DataFolder()
|
||||
en.OnRegex(`^(` + strings.Join(cmd, "|") + `)[\s\S]*?(\[CQ:(image\,file=([0-9a-zA-Z]{32}).*|at.+?(\d{5,11}))\].*|(\d+))$`).
|
||||
SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
c := newContext(ctx.Event.UserID)
|
||||
list := ctx.State["regex_matched"].([]string)
|
||||
err := c.prepareLogos(list[4]+list[5]+list[6], strconv.FormatInt(ctx.Event.UserID, 10))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
argslist := strings.Split(strings.TrimSuffix(strings.TrimPrefix(list[0], list[1]), list[2]), " ")
|
||||
picurl, err := cmdMap[list[1]](c, argslist...)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Image(picurl))
|
||||
})
|
||||
}
|
||||
131
plugin/github/repo_searcher.go
Normal file
@@ -0,0 +1,131 @@
|
||||
// Package github GitHub 仓库搜索
|
||||
package github
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
control.Register("github", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "GitHub仓库搜索\n" +
|
||||
"- >github [xxx]\n" +
|
||||
"- >github -p [xxx]",
|
||||
}).OnRegex(`^>github\s(-.{1,10}? )?(.*)$`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 发送请求
|
||||
header := http.Header{
|
||||
"User-Agent": []string{"User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36"},
|
||||
}
|
||||
api, _ := url.Parse("https://api.github.com/search/repositories")
|
||||
api.RawQuery = url.Values{
|
||||
"q": []string{ctx.State["regex_matched"].([]string)[2]},
|
||||
}.Encode()
|
||||
body, err := netGet(api.String(), header)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
}
|
||||
// 解析请求
|
||||
info := gjson.ParseBytes(body)
|
||||
if info.Get("total_count").Int() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR:没有找到这样的仓库"))
|
||||
return
|
||||
}
|
||||
repo := info.Get("items.0")
|
||||
// 发送结果
|
||||
switch ctx.State["regex_matched"].([]string)[1] {
|
||||
case "-p ": // 图片模式
|
||||
ctx.SendChain(
|
||||
message.Image(
|
||||
"https://opengraph.githubassets.com/0/"+repo.Get("full_name").Str,
|
||||
).Add("cache", 0),
|
||||
)
|
||||
case "-t ": // 文字模式
|
||||
ctx.SendChain(
|
||||
message.Text(
|
||||
repo.Get("full_name").Str, "\n",
|
||||
"Description: ",
|
||||
repo.Get("description").Str, "\n",
|
||||
"Star/Fork/Issue: ",
|
||||
repo.Get("watchers").Int(), "/", repo.Get("forks").Int(), "/", repo.Get("open_issues").Int(), "\n",
|
||||
"Language: ",
|
||||
notnull(repo.Get("language").Str), "\n",
|
||||
"License: ",
|
||||
notnull(strings.ToUpper(repo.Get("license.key").Str)), "\n",
|
||||
"Last pushed: ",
|
||||
repo.Get("pushed_at").Str, "\n",
|
||||
"Jump: ",
|
||||
repo.Get("html_url").Str, "\n",
|
||||
),
|
||||
)
|
||||
default: // 文字模式
|
||||
ctx.SendChain(
|
||||
message.Text(
|
||||
repo.Get("full_name").Str, "\n",
|
||||
"Description: ",
|
||||
repo.Get("description").Str, "\n",
|
||||
"Star/Fork/Issue: ",
|
||||
repo.Get("watchers").Int(), "/", repo.Get("forks").Int(), "/", repo.Get("open_issues").Int(), "\n",
|
||||
"Language: ",
|
||||
notnull(repo.Get("language").Str), "\n",
|
||||
"License: ",
|
||||
notnull(strings.ToUpper(repo.Get("license.key").Str)), "\n",
|
||||
"Last pushed: ",
|
||||
repo.Get("pushed_at").Str, "\n",
|
||||
"Jump: ",
|
||||
repo.Get("html_url").Str, "\n",
|
||||
),
|
||||
message.Image(
|
||||
"https://opengraph.githubassets.com/0/"+repo.Get("full_name").Str,
|
||||
).Add("cache", 0),
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// notnull 如果传入文本为空,则返回默认值
|
||||
|
||||
func notnull(text string) string {
|
||||
if text == "" {
|
||||
return "None"
|
||||
}
|
||||
return text
|
||||
}
|
||||
|
||||
// netGet 返回请求结果
|
||||
func netGet(dest string, header http.Header) ([]byte, error) {
|
||||
client := &http.Client{}
|
||||
|
||||
req, err := http.NewRequest("GET", dest, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header = header
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if code := resp.StatusCode; code != 200 {
|
||||
// 如果返回不是200则立刻抛出错误
|
||||
errmsg := fmt.Sprintf("code %d", code)
|
||||
return nil, errors.New(errmsg)
|
||||
}
|
||||
return body, nil
|
||||
}
|
||||
755
plugin/guessmusic/main.go
Normal file
@@ -0,0 +1,755 @@
|
||||
// Package guessmusic 基于zbp的猜歌插件
|
||||
package guessmusic
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
"github.com/wdvxdr1123/ZeroBot/extension/single"
|
||||
|
||||
// 图片输出
|
||||
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
)
|
||||
|
||||
const (
|
||||
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.66"
|
||||
)
|
||||
|
||||
var (
|
||||
catlist = make(map[string]int64, 100)
|
||||
filelist []string
|
||||
cuttime = [...]string{"00:00:05", "00:00:30", "00:01:00"} // 音乐切割时间点,可自行调节时间(时:分:秒)
|
||||
cfg config
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("guessmusic", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "猜歌插件(该插件依赖ffmpeg)\n" +
|
||||
"------bot主人指令------\n" +
|
||||
"- 设置猜歌缓存歌库路径 [绝对路径]\n" +
|
||||
"- 设置猜歌[本地/Api] [true/false]\n" +
|
||||
"- 登录网易云\n" +
|
||||
"- 添加歌单 [网易云歌单ID] [歌单名称]\n" +
|
||||
"- 删除歌单 [网易云歌单ID/API歌单名称]\n" +
|
||||
"注:\n1.不登陆也能用,API有几率返回400\n" +
|
||||
"2.[歌单名称]可为空,默认原标题\n" +
|
||||
"------公 用 指 令------\n" +
|
||||
"- 获取歌单列表\n" +
|
||||
"- [网易云歌单ID/API歌单名称]歌单信息\n" +
|
||||
"- [个人/团队]猜歌\n" +
|
||||
"注:默认歌库为网易云ACG动画榜\n" +
|
||||
"可在后面添加[-歌单名称]进行指定歌单猜歌\n" +
|
||||
"歌单的歌曲命名规则为:\n歌名 - 歌手 - 其他(歌曲出处之类)",
|
||||
PrivateDataFolder: "guessmusic",
|
||||
}).ApplySingle(single.New(
|
||||
single.WithKeyFn(func(ctx *zero.Ctx) int64 { return ctx.Event.GroupID }),
|
||||
single.WithPostFn[int64](func(ctx *zero.Ctx) {
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("已经有正在进行的游戏..."),
|
||||
),
|
||||
)
|
||||
}),
|
||||
))
|
||||
cachePath := engine.DataFolder() + "cache/"
|
||||
err := os.MkdirAll(cachePath, 0755)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
cfgFile := engine.DataFolder() + "config.json"
|
||||
if file.IsExist(cfgFile) {
|
||||
reader, err := os.Open(cfgFile)
|
||||
if err == nil {
|
||||
err = json.NewDecoder(reader).Decode(&cfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
err = reader.Close()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
var plist = []listRaw{
|
||||
{
|
||||
Name: "动画榜",
|
||||
ID: 3001835560,
|
||||
},
|
||||
}
|
||||
cfg = config{ // 默认 config
|
||||
MusicPath: file.BOTPATH + "/data/guessmusic/music/", // 绝对路径,歌库根目录,通过指令进行更改
|
||||
Local: true, // 是否使用本地音乐库
|
||||
API: true, // 是否使用 Api
|
||||
Cookie: "",
|
||||
Playlist: plist,
|
||||
}
|
||||
err = saveConfig(cfgFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
err = getcatlist(cfg.MusicPath)
|
||||
if err != nil {
|
||||
logrus.Infof("[guessmusic2]无法获取歌单列表,[error]:%s", err)
|
||||
}
|
||||
engine.OnRegex(`^设置猜歌(缓存歌库路径|本地|Api)\s*(.*)$`, func(ctx *zero.Ctx) bool {
|
||||
if !zero.SuperUserPermission(ctx) {
|
||||
ctx.SendChain(message.Text("只有bot主人可以设置!"))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
option := ctx.State["regex_matched"].([]string)[1]
|
||||
value := ctx.State["regex_matched"].([]string)[2]
|
||||
switch option {
|
||||
case "缓存歌库路径":
|
||||
if value == "" {
|
||||
ctx.SendChain(message.Text("请输入正确的路径!"))
|
||||
return
|
||||
}
|
||||
musicPath := strings.ReplaceAll(value, "\\", "/")
|
||||
if !strings.HasSuffix(musicPath, "/") {
|
||||
musicPath += "/"
|
||||
}
|
||||
cfg.MusicPath = musicPath
|
||||
case "本地":
|
||||
choice, err := strconv.ParseBool(value)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
cfg.Local = choice
|
||||
case "Api":
|
||||
choice, err := strconv.ParseBool(value)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
cfg.API = choice
|
||||
}
|
||||
err = saveConfig(cfgFile)
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
}
|
||||
})
|
||||
engine.OnFullMatch("登录网易云", zero.SuperUserPermission, func(ctx *zero.Ctx) bool {
|
||||
if !zero.OnlyPrivate(ctx) {
|
||||
ctx.SendChain(message.Text("为了保护登录过程,请bot主人私聊。"))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
keyURL := "https://music.cyrilstudio.top/login/qr/key"
|
||||
data, err := web.GetData(keyURL)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("获取网易云key失败, ERROR:", err))
|
||||
return
|
||||
}
|
||||
var keyInfo keyInfo
|
||||
err = json.Unmarshal(data, &keyInfo)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("解析网易云key失败, ERROR:", err))
|
||||
return
|
||||
}
|
||||
qrURL := "https://music.cyrilstudio.top/login/qr/create?key=" + keyInfo.Data.Unikey + "&qrimg=1"
|
||||
data, err = web.GetData(qrURL)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("获取网易云二维码失败, ERROR:", err))
|
||||
return
|
||||
}
|
||||
var qrInfo qrInfo
|
||||
err = json.Unmarshal(data, &qrInfo)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("解析网易云二维码失败, ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("[请使用手机APP扫描二维码或者进入网页扫码登录]\n", qrInfo.Data.Qrurl), message.Image("base64://"+strings.ReplaceAll(qrInfo.Data.Qrimg, "data:image/png;base64,", "")), message.Text("二维码有效时间为6分钟"))
|
||||
i := 0
|
||||
for range time.NewTicker(10 * time.Second).C {
|
||||
apiURL := "https://music.cyrilstudio.top/login/qr/check?key=" + url.QueryEscape(keyInfo.Data.Unikey)
|
||||
referer := "https://music.cyrilstudio.top"
|
||||
data, err := web.RequestDataWith(web.NewDefaultClient(), apiURL, "GET", referer, ua)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("无法获取登录状态, ERROR:", err))
|
||||
return
|
||||
}
|
||||
var cookiesInfo cookyInfo
|
||||
err = json.Unmarshal(data, &cookiesInfo)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("解析登录状态失败, ERROR:", err))
|
||||
return
|
||||
}
|
||||
switch cookiesInfo.Code {
|
||||
case 803:
|
||||
cfg.Cookie = cookiesInfo.Cookie
|
||||
err = saveConfig(cfgFile)
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
}
|
||||
return
|
||||
case 801:
|
||||
i++
|
||||
if i%6 == 0 { // 每1分钟才提醒一次,减少提示(380/60=6次)
|
||||
ctx.SendChain(message.Text("状态:", cookiesInfo.Message))
|
||||
}
|
||||
continue
|
||||
case 800:
|
||||
ctx.SendChain(message.Text("状态:", cookiesInfo.Message))
|
||||
return
|
||||
default:
|
||||
ctx.SendChain(message.Text("状态:", cookiesInfo.Message))
|
||||
continue
|
||||
}
|
||||
}
|
||||
})
|
||||
engine.OnRegex(`^添加歌单\s?(\d*)(\s(.*))?$`, zero.SuperUserPermission).SetBlock(true).Limit(ctxext.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
listID := ctx.State["regex_matched"].([]string)[1]
|
||||
listName := ctx.State["regex_matched"].([]string)[3]
|
||||
apiURL := "https://music.cyrilstudio.top/playlist/detail?id=" + listID + "&cookie=" + url.QueryEscape(cfg.Cookie)
|
||||
referer := "https://music.cyrilstudio.top"
|
||||
data, err := web.RequestDataWith(web.NewDefaultClient(), apiURL, "GET", referer, ua)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("无法连接歌单,[error]", err))
|
||||
return
|
||||
}
|
||||
var parsed topList
|
||||
err = json.Unmarshal(data, &parsed)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("无法解析歌单ID内容,[error]", err))
|
||||
return
|
||||
}
|
||||
if listName == "" {
|
||||
listName = parsed.Playlist.Name
|
||||
}
|
||||
playID, _ := strconv.ParseInt(listID, 10, 64)
|
||||
catlist[listName] = playID
|
||||
cfg.Playlist = append(cfg.Playlist, listRaw{
|
||||
Name: listName,
|
||||
ID: playID,
|
||||
})
|
||||
err = saveConfig(cfgFile)
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
}
|
||||
})
|
||||
engine.OnRegex(`^删除歌单\s?(.*)$`, zero.SuperUserPermission).SetBlock(true).Limit(ctxext.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
delList := ctx.State["regex_matched"].([]string)[1]
|
||||
var playlist []listRaw
|
||||
var newCatList = make(map[string]int64)
|
||||
var ok = false
|
||||
for name, musicID := range catlist {
|
||||
if delList == name || delList == strconv.FormatInt(musicID, 10) {
|
||||
ok = true
|
||||
continue
|
||||
}
|
||||
newCatList[name] = musicID
|
||||
playlist = append(playlist, listRaw{
|
||||
Name: name,
|
||||
ID: musicID,
|
||||
})
|
||||
}
|
||||
if !ok {
|
||||
ctx.SendChain(message.Text("目标歌单未找到,请确认是否正确"))
|
||||
return
|
||||
}
|
||||
catlist = newCatList
|
||||
cfg.Playlist = playlist
|
||||
err = saveConfig(cfgFile)
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
}
|
||||
})
|
||||
engine.OnFullMatch("获取歌单列表").SetBlock(true).Limit(ctxext.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
var msg []string
|
||||
// 获取网易云歌单列表
|
||||
if cfg.API {
|
||||
catlist = make(map[string]int64, 100)
|
||||
msg = append(msg, "\n当前添加的API歌单含有以下:\n")
|
||||
for i, listInfo := range cfg.Playlist {
|
||||
catlist[listInfo.Name] = listInfo.ID
|
||||
msg = append(msg, strconv.Itoa(i)+":"+listInfo.Name)
|
||||
if i%3 == 2 {
|
||||
msg = append(msg, "\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
// 获取本地歌单列表*/
|
||||
if cfg.Local {
|
||||
err = os.MkdirAll(cfg.MusicPath, 0755)
|
||||
if err == nil {
|
||||
files, err := ioutil.ReadDir(cfg.MusicPath)
|
||||
if err == nil {
|
||||
msg = append(msg, "\n当前本地歌单含有以下:\n")
|
||||
i := 0
|
||||
for _, name := range files {
|
||||
if !name.IsDir() {
|
||||
continue
|
||||
}
|
||||
filelist[i] = strconv.Itoa(i) + ":" + name.Name()
|
||||
msg = append(msg, filelist[i])
|
||||
if i%3 == 2 {
|
||||
msg = append(msg, "\n")
|
||||
}
|
||||
i++
|
||||
}
|
||||
} else {
|
||||
ctx.SendChain(message.Text("[读取本地列表错误]ERROR:", err))
|
||||
}
|
||||
} else {
|
||||
ctx.SendChain(message.Text("[生成文件夹错误]ERROR:", err))
|
||||
}
|
||||
}
|
||||
if msg == nil {
|
||||
ctx.SendChain(message.Text("本地和API均未开启!"))
|
||||
return
|
||||
}
|
||||
msgs, err := text.RenderToBase64(strings.Join(msg, " "), text.FontFile, 400, 20)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("生成列表图片失败,请重试"))
|
||||
return
|
||||
}
|
||||
if id := ctx.SendChain(message.Image("base64://" + helper.BytesToString(msgs))); id.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
|
||||
}
|
||||
})
|
||||
engine.OnSuffix("歌单信息").SetBlock(true).Limit(ctxext.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
list := ctx.State["args"].(string)
|
||||
var listIDStr string
|
||||
for listName, listID := range catlist {
|
||||
if list == listName || list == strconv.FormatInt(listID, 10) {
|
||||
listIDStr = strconv.FormatInt(listID, 10)
|
||||
break
|
||||
}
|
||||
}
|
||||
if listIDStr == "" {
|
||||
_, err := strconv.ParseInt(list, 10, 64)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("仅支持歌单ID查询"))
|
||||
return
|
||||
}
|
||||
listIDStr = list
|
||||
}
|
||||
apiURL := "https://music.cyrilstudio.top/playlist/detail?id=" + listIDStr + "&cookie=" + url.QueryEscape(cfg.Cookie)
|
||||
referer := "https://music.cyrilstudio.top"
|
||||
data, err := web.RequestDataWith(web.NewDefaultClient(), apiURL, "GET", referer, ua)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("无法连接歌单,[error]", err))
|
||||
return
|
||||
}
|
||||
var parsed topList
|
||||
err = json.Unmarshal(data, &parsed)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("无法解析歌单ID内容,[error]", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(
|
||||
message.Image(parsed.Playlist.CoverImgURL),
|
||||
message.Text(
|
||||
"歌单名称:", parsed.Playlist.Name,
|
||||
"\n歌单ID:", parsed.Playlist.ID,
|
||||
"\n创建人:", parsed.Playlist.Creator.Nickname,
|
||||
"\n创建时间:", time.Unix(parsed.Playlist.CreateTime/1000, 0).Format("2006-01-02"),
|
||||
"\n标签:", strings.Join(parsed.Playlist.Tags, ";"),
|
||||
"\n歌曲数量:", parsed.Playlist.TrackCount,
|
||||
"\n歌单简介:\n", parsed.Playlist.Description,
|
||||
"\n更新时间:", time.Unix(parsed.Playlist.UpdateTime/1000, 0).Format("2006-01-02"),
|
||||
))
|
||||
})
|
||||
engine.OnRegex(`^(个人|团队)猜歌(-(.*))?$`, zero.OnlyGroup).SetBlock(true).Limit(ctxext.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
mode := ctx.State["regex_matched"].([]string)[3]
|
||||
if mode == "" {
|
||||
mode = "动画榜"
|
||||
}
|
||||
_, ok := catlist[mode]
|
||||
switch {
|
||||
// 如果API没有开,本地也不存在这个歌单
|
||||
case !cfg.API && !strings.Contains(strings.Join(filelist, " "), mode):
|
||||
ctx.SendChain(message.Text("歌单名称错误,可以发送“获取歌单列表”获取歌单名称"))
|
||||
return
|
||||
// 如果本地没有开,网易云也不存在这个歌单
|
||||
case !cfg.Local && !ok:
|
||||
ctx.SendChain(message.Text("歌单名称错误,可以发送“获取歌单列表”获取歌单名称"))
|
||||
return
|
||||
}
|
||||
gid := strconv.FormatInt(ctx.Event.GroupID, 10)
|
||||
ctx.SendChain(message.Text("正在准备歌曲,请稍等\n回答“-[歌曲信息(歌名歌手等)|提示|取消]”\n一共3段语音,6次机会"))
|
||||
// 随机抽歌
|
||||
musicName, pathOfMusic, err := musicLottery(mode, cfg.MusicPath)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text(err))
|
||||
return
|
||||
}
|
||||
// 切割音频,生成3个10秒的音频
|
||||
outputPath := cachePath + gid + "/"
|
||||
err = cutMusic(musicName, pathOfMusic, outputPath)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text(err))
|
||||
return
|
||||
}
|
||||
// 解析歌曲信息
|
||||
musicInfo := strings.Split(musicName, " - ")
|
||||
infoNum := len(musicInfo)
|
||||
answerString := "歌名:" + musicInfo[0] + "\n歌手:" + musicInfo[1]
|
||||
musicAlia := ""
|
||||
if infoNum > 2 {
|
||||
musicAlia = musicInfo[2]
|
||||
answerString += "\n其他信息:\n" + strings.ReplaceAll(musicAlia, "&", "\n")
|
||||
}
|
||||
// 进行猜歌环节
|
||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + outputPath + "0.wav"))
|
||||
var next *zero.FutureEvent
|
||||
if ctx.State["regex_matched"].([]string)[1] == "个人" {
|
||||
next = zero.NewFutureEvent("message", 999, false, zero.OnlyGroup, zero.RegexRule(`^-\S{1,}`), ctx.CheckSession())
|
||||
} else {
|
||||
next = zero.NewFutureEvent("message", 999, false, zero.OnlyGroup, zero.RegexRule(`^-\S{1,}`), zero.CheckGroup(ctx.Event.GroupID))
|
||||
}
|
||||
var musicCount = 0 // 音频数量
|
||||
var answerCount = 0 // 问答次数
|
||||
recv, cancel := next.Repeat()
|
||||
defer cancel()
|
||||
wait := time.NewTimer(40 * time.Second)
|
||||
tick := time.NewTimer(105 * time.Second)
|
||||
after := time.NewTimer(120 * time.Second)
|
||||
for {
|
||||
select {
|
||||
case <-tick.C:
|
||||
ctx.SendChain(message.Text("猜歌游戏,你还有15s作答时间"))
|
||||
case <-after.C:
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("时间超时,猜歌结束,公布答案:\n", answerString)))
|
||||
return
|
||||
case <-wait.C:
|
||||
wait.Reset(40 * time.Second)
|
||||
musicCount++
|
||||
if musicCount > 2 {
|
||||
wait.Stop()
|
||||
continue
|
||||
}
|
||||
ctx.SendChain(
|
||||
message.Text("好像有些难度呢,再听这段音频,要仔细听哦"),
|
||||
)
|
||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + outputPath + strconv.Itoa(musicCount) + ".wav"))
|
||||
case c := <-recv:
|
||||
wait.Reset(40 * time.Second)
|
||||
tick.Reset(105 * time.Second)
|
||||
after.Reset(120 * time.Second)
|
||||
answer := strings.Replace(c.Event.Message.String(), "-", "", 1)
|
||||
switch {
|
||||
case answer == "取消":
|
||||
if c.Event.UserID == ctx.Event.UserID {
|
||||
wait.Stop()
|
||||
tick.Stop()
|
||||
after.Stop()
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("游戏已取消,猜歌答案是\n", answerString)))
|
||||
return
|
||||
}
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(c.Event.MessageID,
|
||||
message.Text("你无权限取消"),
|
||||
),
|
||||
)
|
||||
case answer == "提示":
|
||||
musicCount++
|
||||
if musicCount > 2 {
|
||||
wait.Stop()
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(c.Event.MessageID,
|
||||
message.Text("已经没有提示了哦"),
|
||||
),
|
||||
)
|
||||
continue
|
||||
}
|
||||
wait.Reset(40 * time.Second)
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(c.Event.MessageID,
|
||||
message.Text("再听这段音频,要仔细听哦"),
|
||||
),
|
||||
)
|
||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + outputPath + strconv.Itoa(musicCount) + ".wav"))
|
||||
case strings.Contains(musicInfo[0], answer) || strings.EqualFold(musicInfo[0], answer):
|
||||
wait.Stop()
|
||||
tick.Stop()
|
||||
after.Stop()
|
||||
ctx.Send(message.ReplyWithMessage(c.Event.MessageID,
|
||||
message.Text("太棒了,你猜对歌曲名了!答案是\n", answerString)))
|
||||
return
|
||||
case strings.Contains(musicInfo[1], answer) || strings.EqualFold(musicInfo[1], answer):
|
||||
wait.Stop()
|
||||
tick.Stop()
|
||||
after.Stop()
|
||||
ctx.Send(message.ReplyWithMessage(c.Event.MessageID,
|
||||
message.Text("太棒了,你猜对歌手名了!答案是\n", answerString)))
|
||||
return
|
||||
case strings.Contains(musicAlia, answer) || strings.EqualFold(musicAlia, answer):
|
||||
wait.Stop()
|
||||
tick.Stop()
|
||||
after.Stop()
|
||||
ctx.Send(message.ReplyWithMessage(c.Event.MessageID,
|
||||
message.Text("太棒了,你猜对出处了!答案是\n", answerString)))
|
||||
return
|
||||
default:
|
||||
musicCount++
|
||||
switch {
|
||||
case musicCount > 2 && answerCount < 6:
|
||||
wait.Stop()
|
||||
answerCount++
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(c.Event.MessageID,
|
||||
message.Text("答案不对哦,加油啊~"),
|
||||
),
|
||||
)
|
||||
case musicCount > 2:
|
||||
wait.Stop()
|
||||
tick.Stop()
|
||||
after.Stop()
|
||||
ctx.Send(message.ReplyWithMessage(c.Event.MessageID,
|
||||
message.Text("次数到了,没能猜出来。答案是\n", answerString)))
|
||||
return
|
||||
default:
|
||||
wait.Reset(40 * time.Second)
|
||||
answerCount++
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(c.Event.MessageID,
|
||||
message.Text("答案不对,再听这段音频,要仔细听哦"),
|
||||
),
|
||||
)
|
||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + outputPath + strconv.Itoa(musicCount) + ".wav"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func saveConfig(cfgFile string) (err error) {
|
||||
if reader, err := os.Create(cfgFile); err == nil {
|
||||
err = json.NewEncoder(reader).Encode(&cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getcatlist(pathOfMusic string) error {
|
||||
catlist = make(map[string]int64, 100)
|
||||
for _, listInfo := range cfg.Playlist {
|
||||
catlist[listInfo.Name] = listInfo.ID
|
||||
}
|
||||
err := os.MkdirAll(pathOfMusic, 0755)
|
||||
if err != nil {
|
||||
err = errors.Errorf("[生成文件夹错误]ERROR:%s", err)
|
||||
return err
|
||||
}
|
||||
files, err := ioutil.ReadDir(pathOfMusic)
|
||||
if err != nil {
|
||||
err = errors.Errorf("[读取本地列表错误]ERROR:%s", err)
|
||||
return err
|
||||
}
|
||||
for i, name := range files {
|
||||
filelist = append(filelist, strconv.Itoa(i)+":"+name.Name())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 随机抽取音乐
|
||||
func musicLottery(mode, musicPath string) (musicName, pathOfMusic string, err error) {
|
||||
pathOfMusic = musicPath + mode + "/"
|
||||
err = os.MkdirAll(pathOfMusic, 0755)
|
||||
if err != nil {
|
||||
err = errors.Errorf("[生成文件夹错误]ERROR:%s", err)
|
||||
return
|
||||
}
|
||||
files, err := ioutil.ReadDir(pathOfMusic)
|
||||
if err != nil {
|
||||
err = errors.Errorf("[读取本地列表错误]ERROR:%s", err)
|
||||
return
|
||||
}
|
||||
listID, ok := catlist[mode]
|
||||
listIDstr := strconv.FormatInt(listID, 10)
|
||||
if cfg.Local && cfg.API {
|
||||
switch {
|
||||
case len(files) == 0:
|
||||
if !ok {
|
||||
// 如果歌单是本地歌单
|
||||
err = errors.New("本地歌单数据为0")
|
||||
return
|
||||
}
|
||||
// 如果没有任何本地就下载歌曲
|
||||
musicName, err = getListMusic(listIDstr, pathOfMusic)
|
||||
if err != nil {
|
||||
err = errors.Errorf("[本地数据为0,歌曲下载错误]ERROR:%s", err)
|
||||
return
|
||||
}
|
||||
case rand.Intn(2) == 0 || !ok:
|
||||
// 1/2概率抽本地或者歌单只有本地有时
|
||||
musicName = getLocalMusic(files)
|
||||
default:
|
||||
musicName, err = getListMusic(listIDstr, pathOfMusic)
|
||||
if err != nil {
|
||||
// 如果下载失败就从本地抽一个歌曲
|
||||
musicName = getLocalMusic(files)
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
if cfg.Local {
|
||||
if len(files) == 0 {
|
||||
err = errors.New("[本地数据为0,未开启API数据]")
|
||||
return
|
||||
}
|
||||
musicName = getLocalMusic(files)
|
||||
return
|
||||
}
|
||||
if cfg.API && ok {
|
||||
musicName, err = getListMusic(listIDstr, pathOfMusic)
|
||||
if err != nil {
|
||||
err = errors.Errorf("[获取API失败,未开启本地数据] ERROR:%s", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
err = errors.New("[请确认本地和API设置已开启或歌单存在]")
|
||||
return
|
||||
}
|
||||
|
||||
func getLocalMusic(files []fs.FileInfo) (musicName string) {
|
||||
if len(files) > 1 {
|
||||
musicName = strings.Replace(files[rand.Intn(len(files))].Name(), ".mp3", "", 1)
|
||||
} else {
|
||||
musicName = strings.Replace(files[0].Name(), ".mp3", "", 1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 下载网易云歌单音乐
|
||||
func getListMusic(listID, pathOfMusic string) (musicName string, err error) {
|
||||
apiURL := "https://music.cyrilstudio.top/playlist/track/all?id=" + listID + "&cookie=" + url.QueryEscape(cfg.Cookie)
|
||||
referer := "https://music.cyrilstudio.top"
|
||||
data, err := web.RequestDataWith(web.NewDefaultClient(), apiURL, "GET", referer, ua)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var parsed topMusicInfo
|
||||
err = json.Unmarshal(data, &parsed)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
listlen := len(parsed.Songs)
|
||||
randidx := rand.Intn(listlen)
|
||||
// 将"/"符号去除,不然无法生成文件
|
||||
name := strings.ReplaceAll(parsed.Songs[randidx].Name, "/", "·")
|
||||
musicID := parsed.Songs[randidx].ID
|
||||
artistName := ""
|
||||
for i, ARInfo := range parsed.Songs[randidx].Ar {
|
||||
if i != 0 {
|
||||
artistName += "&" + ARInfo.Name
|
||||
} else {
|
||||
artistName += ARInfo.Name
|
||||
}
|
||||
}
|
||||
cource := ""
|
||||
if parsed.Songs[randidx].Alia != nil {
|
||||
cource = strings.Join(parsed.Songs[randidx].Alia, "&")
|
||||
// 将"/"符号去除,不然无法下载
|
||||
cource = strings.ReplaceAll(cource, "/", "&")
|
||||
}
|
||||
if name == "" || musicID == 0 {
|
||||
err = errors.New("无法获API取歌曲信息")
|
||||
return
|
||||
}
|
||||
musicURL := "http://music.163.com/song/media/outer/url?id=" + strconv.Itoa(musicID)
|
||||
response, err := http.Head(musicURL)
|
||||
if err != nil {
|
||||
err = errors.Errorf("下载音乐失败, ERROR: %s", err)
|
||||
return
|
||||
}
|
||||
if response.StatusCode != 200 {
|
||||
err = errors.Errorf("下载音乐失败, Status Code: %d", response.StatusCode)
|
||||
return
|
||||
}
|
||||
if cource != "" {
|
||||
musicName = name + " - " + artistName + " - " + cource
|
||||
} else {
|
||||
musicName = name + " - " + artistName
|
||||
}
|
||||
downMusic := pathOfMusic + musicName + ".mp3"
|
||||
if file.IsNotExist(downMusic) {
|
||||
data, err = web.GetData(musicURL)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = os.WriteFile(downMusic, data, 0666)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 切割音乐成三个10s音频
|
||||
func cutMusic(musicName, pathOfMusic, outputPath string) (err error) {
|
||||
err = os.MkdirAll(outputPath, 0755)
|
||||
if err != nil {
|
||||
err = errors.Errorf("[生成歌曲目录错误]ERROR:%s", err)
|
||||
return
|
||||
}
|
||||
var stderr bytes.Buffer
|
||||
cmdArguments := []string{"-y", "-i", pathOfMusic + musicName + ".mp3",
|
||||
"-ss", cuttime[0], "-t", "10", file.BOTPATH + "/" + outputPath + "0.wav",
|
||||
"-ss", cuttime[1], "-t", "10", file.BOTPATH + "/" + outputPath + "1.wav",
|
||||
"-ss", cuttime[2], "-t", "10", file.BOTPATH + "/" + outputPath + "2.wav", "-hide_banner"}
|
||||
cmd := exec.Command("ffmpeg", cmdArguments...)
|
||||
cmd.Stderr = &stderr
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
err = errors.Errorf("[生成歌曲错误]ERROR:%s", stderr.String())
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
406
plugin/guessmusic/struct.go
Normal file
@@ -0,0 +1,406 @@
|
||||
package guessmusic
|
||||
|
||||
type listRaw struct {
|
||||
Name string `json:"name"`
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
|
||||
type config struct {
|
||||
MusicPath string `json:"musicPath"`
|
||||
Local bool `json:"local"`
|
||||
API bool `json:"api"`
|
||||
Cookie string `json:"cookie"`
|
||||
Playlist []listRaw `json:"playlist"`
|
||||
}
|
||||
|
||||
type keyInfo struct {
|
||||
Data struct {
|
||||
Code int `json:"code"`
|
||||
Unikey string `json:"unikey"`
|
||||
} `json:"data"`
|
||||
Code int `json:"code"`
|
||||
}
|
||||
type cookyInfo struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Cookie string `json:"cookie"`
|
||||
}
|
||||
type qrInfo struct {
|
||||
Code int `json:"code"`
|
||||
Data struct {
|
||||
Qrurl string `json:"qrurl"`
|
||||
Qrimg string `json:"qrimg"`
|
||||
} `json:"data"`
|
||||
}
|
||||
type topList struct {
|
||||
Code int `json:"code"`
|
||||
RelatedVideos interface{} `json:"relatedVideos"`
|
||||
Playlist struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
CoverImgID int64 `json:"coverImgId"`
|
||||
CoverImgURL string `json:"coverImgUrl"`
|
||||
CoverImgIDStr string `json:"coverImgId_str"`
|
||||
AdType int `json:"adType"`
|
||||
UserID int `json:"userId"`
|
||||
CreateTime int64 `json:"createTime"`
|
||||
Status int `json:"status"`
|
||||
OpRecommend bool `json:"opRecommend"`
|
||||
HighQuality bool `json:"highQuality"`
|
||||
NewImported bool `json:"newImported"`
|
||||
UpdateTime int64 `json:"updateTime"`
|
||||
TrackCount int `json:"trackCount"`
|
||||
SpecialType int `json:"specialType"`
|
||||
Privacy int `json:"privacy"`
|
||||
TrackUpdateTime int64 `json:"trackUpdateTime"`
|
||||
CommentThreadID string `json:"commentThreadId"`
|
||||
PlayCount int `json:"playCount"`
|
||||
TrackNumberUpdateTime int64 `json:"trackNumberUpdateTime"`
|
||||
SubscribedCount int `json:"subscribedCount"`
|
||||
CloudTrackCount int `json:"cloudTrackCount"`
|
||||
Ordered bool `json:"ordered"`
|
||||
Description string `json:"description"`
|
||||
Tags []string `json:"tags"`
|
||||
UpdateFrequency interface{} `json:"updateFrequency"`
|
||||
BackgroundCoverID int `json:"backgroundCoverId"`
|
||||
BackgroundCoverURL interface{} `json:"backgroundCoverUrl"`
|
||||
TitleImage int `json:"titleImage"`
|
||||
TitleImageURL interface{} `json:"titleImageUrl"`
|
||||
EnglishTitle interface{} `json:"englishTitle"`
|
||||
OfficialPlaylistType interface{} `json:"officialPlaylistType"`
|
||||
Subscribers []struct {
|
||||
DefaultAvatar bool `json:"defaultAvatar"`
|
||||
Province int `json:"province"`
|
||||
AuthStatus int `json:"authStatus"`
|
||||
Followed bool `json:"followed"`
|
||||
AvatarURL string `json:"avatarUrl"`
|
||||
AccountStatus int `json:"accountStatus"`
|
||||
Gender int `json:"gender"`
|
||||
City int `json:"city"`
|
||||
Birthday int `json:"birthday"`
|
||||
UserID int `json:"userId"`
|
||||
UserType int `json:"userType"`
|
||||
Nickname string `json:"nickname"`
|
||||
Signature string `json:"signature"`
|
||||
Description string `json:"description"`
|
||||
DetailDescription string `json:"detailDescription"`
|
||||
AvatarImgID int64 `json:"avatarImgId"`
|
||||
BackgroundImgID int64 `json:"backgroundImgId"`
|
||||
BackgroundURL string `json:"backgroundUrl"`
|
||||
Authority int `json:"authority"`
|
||||
Mutual bool `json:"mutual"`
|
||||
ExpertTags interface{} `json:"expertTags"`
|
||||
Experts interface{} `json:"experts"`
|
||||
DjStatus int `json:"djStatus"`
|
||||
VipType int `json:"vipType"`
|
||||
RemarkName interface{} `json:"remarkName"`
|
||||
AuthenticationTypes int `json:"authenticationTypes"`
|
||||
AvatarDetail interface{} `json:"avatarDetail"`
|
||||
Anchor bool `json:"anchor"`
|
||||
BackgroundImgIDStr string `json:"backgroundImgIdStr"`
|
||||
AvatarImgIDStr string `json:"avatarImgIdStr"`
|
||||
AvatarImgIDString string `json:"AvatarImgIDString"`
|
||||
} `json:"subscribers"`
|
||||
Subscribed interface{} `json:"subscribed"`
|
||||
Creator struct {
|
||||
DefaultAvatar bool `json:"defaultAvatar"`
|
||||
Province int `json:"province"`
|
||||
AuthStatus int `json:"authStatus"`
|
||||
Followed bool `json:"followed"`
|
||||
AvatarURL string `json:"avatarUrl"`
|
||||
AccountStatus int `json:"accountStatus"`
|
||||
Gender int `json:"gender"`
|
||||
City int `json:"city"`
|
||||
Birthday int `json:"birthday"`
|
||||
UserID int `json:"userId"`
|
||||
UserType int `json:"userType"`
|
||||
Nickname string `json:"nickname"`
|
||||
Signature string `json:"signature"`
|
||||
Description string `json:"description"`
|
||||
DetailDescription string `json:"detailDescription"`
|
||||
AvatarImgID int64 `json:"avatarImgId"`
|
||||
BackgroundImgID int64 `json:"backgroundImgId"`
|
||||
BackgroundURL string `json:"backgroundUrl"`
|
||||
Authority int `json:"authority"`
|
||||
Mutual bool `json:"mutual"`
|
||||
ExpertTags interface{} `json:"expertTags"`
|
||||
Experts interface{} `json:"experts"`
|
||||
DjStatus int `json:"djStatus"`
|
||||
VipType int `json:"vipType"`
|
||||
RemarkName interface{} `json:"remarkName"`
|
||||
AuthenticationTypes int `json:"authenticationTypes"`
|
||||
AvatarDetail struct {
|
||||
UserType int `json:"userType"`
|
||||
IdentityLevel int `json:"identityLevel"`
|
||||
IdentityIconURL string `json:"identityIconUrl"`
|
||||
} `json:"avatarDetail"`
|
||||
Anchor bool `json:"anchor"`
|
||||
BackgroundImgIDStr string `json:"backgroundImgIdStr"`
|
||||
AvatarImgIDStr string `json:"avatarImgIdStr"`
|
||||
AvatarImgIDString string `json:"AvatarImgIDString"`
|
||||
} `json:"creator"`
|
||||
Tracks []struct {
|
||||
Name string `json:"name"`
|
||||
ID int `json:"id"`
|
||||
Pst int `json:"pst"`
|
||||
T int `json:"t"`
|
||||
Ar []struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Tns []interface{} `json:"tns"`
|
||||
Alias []interface{} `json:"alias"`
|
||||
} `json:"ar"`
|
||||
Alia []string `json:"alia"`
|
||||
Pop int `json:"pop"`
|
||||
St int `json:"st"`
|
||||
Rt string `json:"rt"`
|
||||
Fee int `json:"fee"`
|
||||
V int `json:"v"`
|
||||
Crbt interface{} `json:"crbt"`
|
||||
Cf string `json:"cf"`
|
||||
Al struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
PicURL string `json:"picUrl"`
|
||||
Tns []interface{} `json:"tns"`
|
||||
PicStr string `json:"pic_str"`
|
||||
Pic int64 `json:"pic"`
|
||||
} `json:"al"`
|
||||
Dt int `json:"dt"`
|
||||
H struct {
|
||||
Br int `json:"br"`
|
||||
Fid int `json:"fid"`
|
||||
Size int `json:"size"`
|
||||
Vd int `json:"vd"`
|
||||
Sr int `json:"sr"`
|
||||
} `json:"h"`
|
||||
M struct {
|
||||
Br int `json:"br"`
|
||||
Fid int `json:"fid"`
|
||||
Size int `json:"size"`
|
||||
Vd int `json:"vd"`
|
||||
Sr int `json:"sr"`
|
||||
} `json:"m"`
|
||||
L struct {
|
||||
Br int `json:"br"`
|
||||
Fid int `json:"fid"`
|
||||
Size int `json:"size"`
|
||||
Vd int `json:"vd"`
|
||||
Sr int `json:"sr"`
|
||||
} `json:"l"`
|
||||
Sq interface{} `json:"sq"`
|
||||
Hr interface{} `json:"hr"`
|
||||
A interface{} `json:"a"`
|
||||
Cd string `json:"cd"`
|
||||
No int `json:"no"`
|
||||
RtURL interface{} `json:"rtUrl"`
|
||||
Ftype int `json:"ftype"`
|
||||
RtUrls []interface{} `json:"rtUrls"`
|
||||
DjID int `json:"djId"`
|
||||
Copyright int `json:"copyright"`
|
||||
SID int `json:"s_id"`
|
||||
Mark int `json:"mark"`
|
||||
OriginCoverType int `json:"originCoverType"`
|
||||
OriginSongSimpleData interface{} `json:"originSongSimpleData"`
|
||||
TagPicList interface{} `json:"tagPicList"`
|
||||
ResourceState bool `json:"resourceState"`
|
||||
Version int `json:"version"`
|
||||
SongJumpInfo interface{} `json:"songJumpInfo"`
|
||||
EntertainmentTags interface{} `json:"entertainmentTags"`
|
||||
Single int `json:"single"`
|
||||
NoCopyrightRcmd interface{} `json:"noCopyrightRcmd"`
|
||||
Alg interface{} `json:"alg"`
|
||||
Rtype int `json:"rtype"`
|
||||
Rurl interface{} `json:"rurl"`
|
||||
Mst int `json:"mst"`
|
||||
Cp int `json:"cp"`
|
||||
Mv int `json:"mv"`
|
||||
PublishTime int64 `json:"publishTime"`
|
||||
Tns []string `json:"tns,omitempty"`
|
||||
} `json:"tracks"`
|
||||
VideoIds interface{} `json:"videoIds"`
|
||||
Videos interface{} `json:"videos"`
|
||||
TrackIds []struct {
|
||||
ID int `json:"id"`
|
||||
V int `json:"v"`
|
||||
T int `json:"t"`
|
||||
At int64 `json:"at"`
|
||||
Alg interface{} `json:"alg"`
|
||||
UID int `json:"uid"`
|
||||
RcmdReason string `json:"rcmdReason"`
|
||||
Sc interface{} `json:"sc"`
|
||||
Lr int `json:"lr,omitempty"`
|
||||
} `json:"trackIds"`
|
||||
ShareCount int `json:"shareCount"`
|
||||
CommentCount int `json:"commentCount"`
|
||||
RemixVideo interface{} `json:"remixVideo"`
|
||||
SharedUsers interface{} `json:"sharedUsers"`
|
||||
HistorySharedUsers interface{} `json:"historySharedUsers"`
|
||||
GradeStatus string `json:"gradeStatus"`
|
||||
Score interface{} `json:"score"`
|
||||
AlgTags interface{} `json:"algTags"`
|
||||
} `json:"playlist"`
|
||||
Urls interface{} `json:"urls"`
|
||||
Privileges []struct {
|
||||
ID int `json:"id"`
|
||||
Fee int `json:"fee"`
|
||||
Payed int `json:"payed"`
|
||||
RealPayed int `json:"realPayed"`
|
||||
St int `json:"st"`
|
||||
Pl int `json:"pl"`
|
||||
Dl int `json:"dl"`
|
||||
Sp int `json:"sp"`
|
||||
Cp int `json:"cp"`
|
||||
Subp int `json:"subp"`
|
||||
Cs bool `json:"cs"`
|
||||
Maxbr int `json:"maxbr"`
|
||||
Fl int `json:"fl"`
|
||||
Pc interface{} `json:"pc"`
|
||||
Toast bool `json:"toast"`
|
||||
Flag int `json:"flag"`
|
||||
PaidBigBang bool `json:"paidBigBang"`
|
||||
PreSell bool `json:"preSell"`
|
||||
PlayMaxbr int `json:"playMaxbr"`
|
||||
DownloadMaxbr int `json:"downloadMaxbr"`
|
||||
MaxBrLevel string `json:"maxBrLevel"`
|
||||
PlayMaxBrLevel string `json:"playMaxBrLevel"`
|
||||
DownloadMaxBrLevel string `json:"downloadMaxBrLevel"`
|
||||
PlLevel string `json:"plLevel"`
|
||||
DlLevel string `json:"dlLevel"`
|
||||
FlLevel string `json:"flLevel"`
|
||||
Rscl int `json:"rscl"`
|
||||
FreeTrialPrivilege struct {
|
||||
ResConsumable bool `json:"resConsumable"`
|
||||
UserConsumable bool `json:"userConsumable"`
|
||||
ListenType interface{} `json:"listenType"`
|
||||
} `json:"freeTrialPrivilege"`
|
||||
ChargeInfoList []struct {
|
||||
Rate int `json:"rate"`
|
||||
ChargeURL interface{} `json:"chargeUrl"`
|
||||
ChargeMessage interface{} `json:"chargeMessage"`
|
||||
ChargeType int `json:"chargeType"`
|
||||
} `json:"chargeInfoList"`
|
||||
} `json:"privileges"`
|
||||
SharedPrivilege interface{} `json:"sharedPrivilege"`
|
||||
ResEntrance interface{} `json:"resEntrance"`
|
||||
}
|
||||
|
||||
type topMusicInfo struct {
|
||||
Songs []struct {
|
||||
Name string `json:"name"`
|
||||
ID int `json:"id"`
|
||||
Pst int `json:"pst"`
|
||||
T int `json:"t"`
|
||||
Ar []struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Tns []interface{} `json:"tns"`
|
||||
Alias []interface{} `json:"alias"`
|
||||
} `json:"ar"`
|
||||
Alia []string `json:"alia"`
|
||||
Pop int `json:"pop"`
|
||||
St int `json:"st"`
|
||||
Rt string `json:"rt"`
|
||||
Fee int `json:"fee"`
|
||||
V int `json:"v"`
|
||||
Crbt interface{} `json:"crbt"`
|
||||
Cf string `json:"cf"`
|
||||
Al struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
PicURL string `json:"picUrl"`
|
||||
Tns []interface{} `json:"tns"`
|
||||
PicStr string `json:"pic_str"`
|
||||
Pic int64 `json:"pic"`
|
||||
} `json:"al"`
|
||||
Dt int `json:"dt"`
|
||||
H struct {
|
||||
Br int `json:"br"`
|
||||
Fid int `json:"fid"`
|
||||
Size int `json:"size"`
|
||||
Vd float32 `json:"vd"`
|
||||
Sr int `json:"sr"`
|
||||
} `json:"h"`
|
||||
M struct {
|
||||
Br int `json:"br"`
|
||||
Fid int `json:"fid"`
|
||||
Size int `json:"size"`
|
||||
Vd float32 `json:"vd"`
|
||||
Sr int `json:"sr"`
|
||||
} `json:"m"`
|
||||
L struct {
|
||||
Br int `json:"br"`
|
||||
Fid int `json:"fid"`
|
||||
Size int `json:"size"`
|
||||
Vd float32 `json:"vd"`
|
||||
Sr int `json:"sr"`
|
||||
} `json:"l"`
|
||||
Sq interface{} `json:"sq"`
|
||||
Hr interface{} `json:"hr"`
|
||||
A interface{} `json:"a"`
|
||||
Cd string `json:"cd"`
|
||||
No int `json:"no"`
|
||||
RtURL interface{} `json:"rtUrl"`
|
||||
Ftype int `json:"ftype"`
|
||||
RtUrls []interface{} `json:"rtUrls"`
|
||||
DjID int `json:"djId"`
|
||||
Copyright int `json:"copyright"`
|
||||
SID int `json:"s_id"`
|
||||
Mark int `json:"mark"`
|
||||
OriginCoverType int `json:"originCoverType"`
|
||||
OriginSongSimpleData interface{} `json:"originSongSimpleData"`
|
||||
TagPicList interface{} `json:"tagPicList"`
|
||||
ResourceState bool `json:"resourceState"`
|
||||
Version int `json:"version"`
|
||||
SongJumpInfo interface{} `json:"songJumpInfo"`
|
||||
EntertainmentTags interface{} `json:"entertainmentTags"`
|
||||
AwardTags interface{} `json:"awardTags"`
|
||||
Single int `json:"single"`
|
||||
NoCopyrightRcmd interface{} `json:"noCopyrightRcmd"`
|
||||
Rtype int `json:"rtype"`
|
||||
Rurl interface{} `json:"rurl"`
|
||||
Mst int `json:"mst"`
|
||||
Cp int `json:"cp"`
|
||||
Mv int `json:"mv"`
|
||||
PublishTime int64 `json:"publishTime"`
|
||||
Tns []string `json:"tns,omitempty"`
|
||||
} `json:"songs"`
|
||||
Privileges []struct {
|
||||
ID int `json:"id"`
|
||||
Fee int `json:"fee"`
|
||||
Payed int `json:"payed"`
|
||||
St int `json:"st"`
|
||||
Pl int `json:"pl"`
|
||||
Dl int `json:"dl"`
|
||||
Sp int `json:"sp"`
|
||||
Cp int `json:"cp"`
|
||||
Subp int `json:"subp"`
|
||||
Cs bool `json:"cs"`
|
||||
Maxbr int `json:"maxbr"`
|
||||
Fl int `json:"fl"`
|
||||
Toast bool `json:"toast"`
|
||||
Flag int `json:"flag"`
|
||||
PreSell bool `json:"preSell"`
|
||||
PlayMaxbr int `json:"playMaxbr"`
|
||||
DownloadMaxbr int `json:"downloadMaxbr"`
|
||||
MaxBrLevel string `json:"maxBrLevel"`
|
||||
PlayMaxBrLevel string `json:"playMaxBrLevel"`
|
||||
DownloadMaxBrLevel string `json:"downloadMaxBrLevel"`
|
||||
PlLevel string `json:"plLevel"`
|
||||
DlLevel string `json:"dlLevel"`
|
||||
FlLevel string `json:"flLevel"`
|
||||
Rscl int `json:"rscl"`
|
||||
FreeTrialPrivilege struct {
|
||||
ResConsumable bool `json:"resConsumable"`
|
||||
UserConsumable bool `json:"userConsumable"`
|
||||
ListenType interface{} `json:"listenType"`
|
||||
} `json:"freeTrialPrivilege"`
|
||||
ChargeInfoList []struct {
|
||||
Rate int `json:"rate"`
|
||||
ChargeURL interface{} `json:"chargeUrl"`
|
||||
ChargeMessage interface{} `json:"chargeMessage"`
|
||||
ChargeType int `json:"chargeType"`
|
||||
} `json:"chargeInfoList"`
|
||||
} `json:"privileges"`
|
||||
Code int `json:"code"`
|
||||
}
|
||||
119
plugin/hs/run.go
Normal file
@@ -0,0 +1,119 @@
|
||||
// Package hs 炉石
|
||||
package hs
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
)
|
||||
|
||||
var reqconf = [...]string{"GET", "https://hs.fbigame.com",
|
||||
"Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Mobile Safari/537.36"}
|
||||
|
||||
const (
|
||||
hs = `https://hs.fbigame.com/ajax.php?`
|
||||
para = "mod=get_cards_list&" +
|
||||
"mode=-1&" +
|
||||
"extend=-1&" +
|
||||
"mutil_extend=&" +
|
||||
"hero=-1&" +
|
||||
"rarity=-1&" +
|
||||
"cost=-1&" +
|
||||
"mutil_cost=&" +
|
||||
"techlevel=-1&" +
|
||||
"type=-1&" +
|
||||
"collectible=-1&" +
|
||||
"isbacon=-1&" +
|
||||
"page=1&" +
|
||||
"search_type=1&" +
|
||||
"deckmode=normal"
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("hs", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "炉石\n" +
|
||||
"- 搜卡[xxxx]\n" +
|
||||
"- [卡组代码xxx]\n" +
|
||||
"- 更多搜卡指令参数:https://hs.fbigame.com/misc/searchhelp",
|
||||
PrivateDataFolder: "hs",
|
||||
}).ApplySingle(ctxext.DefaultSingle)
|
||||
cachedir := file.BOTPATH + "/" + engine.DataFolder()
|
||||
engine.OnRegex(`^搜卡(.+)$`).
|
||||
SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
List := ctx.State["regex_matched"].([]string)[1]
|
||||
g := sh(List)
|
||||
t := int(gjson.Get(g, `list.#`).Int())
|
||||
if t == 0 {
|
||||
ctx.SendChain(message.Text("查询为空!"))
|
||||
return
|
||||
}
|
||||
var sk message.Message
|
||||
for i := 0; i < t && i < 5; i++ {
|
||||
cid := gjson.Get(g, `list.`+strconv.Itoa(i)+`.CardID`).String()
|
||||
cachefile := cachedir + cid
|
||||
if file.IsNotExist(cachefile) {
|
||||
data, err := web.RequestDataWith(web.NewDefaultClient(),
|
||||
`https://res.fbigame.com/hs/v13/`+cid+`.png?auth_key=`+
|
||||
gjson.Get(g, `list.`+strconv.Itoa(i)+`.auth_key`).String(),
|
||||
reqconf[0], reqconf[1], reqconf[2])
|
||||
if err == nil {
|
||||
err = os.WriteFile(cachefile, data, 0644)
|
||||
}
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
sk = append(sk, ctxext.FakeSenderForwardNode(ctx, message.Image("file:///"+cachefile)))
|
||||
}
|
||||
if id := ctx.SendGroupForwardMessage(
|
||||
ctx.Event.GroupID,
|
||||
sk,
|
||||
).Get("message_id").Int(); id == 0 {
|
||||
ctx.SendChain(message.Text("ERROR:可能被风控了"))
|
||||
}
|
||||
})
|
||||
// 卡组
|
||||
engine.OnRegex(`^[\s\S]*?(AAE[a-zA-Z0-9/\+=]{70,})[\s\S]*$`).
|
||||
SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
List := ctx.State["regex_matched"].([]string)[1]
|
||||
ctx.SendChain(
|
||||
message.Image(kz(List)),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
func sh(s string) string {
|
||||
data, err := web.RequestDataWith(web.NewDefaultClient(), "https://hs.fbigame.com", reqconf[0], reqconf[1], reqconf[2])
|
||||
if err == nil {
|
||||
url := hs + para + "&hash=" + strings.SplitN(strings.SplitN(helper.BytesToString(data), `var hash = "`, 2)[1], `"`, 2)[0] + "&search=" + s
|
||||
r, err := web.RequestDataWith(web.NewDefaultClient(), url, reqconf[0], reqconf[1], reqconf[2])
|
||||
if err == nil {
|
||||
return helper.BytesToString(r)
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func kz(s string) string {
|
||||
data, err := web.RequestDataWith(web.NewDefaultClient(), "https://hs.fbigame.com", reqconf[0], reqconf[1], reqconf[2])
|
||||
if err == nil {
|
||||
url := hs + para + "mod=general_deck_image&deck_code=" + s + "&deck_text=&hash=" + strings.SplitN(strings.SplitN(helper.BytesToString(data), `var hash = "`, 2)[1], `"`, 2)[0] + "&search=" + s
|
||||
r, err := web.RequestDataWith(web.NewDefaultClient(), url, reqconf[0], reqconf[1], reqconf[2])
|
||||
if err == nil {
|
||||
return "base64://" + gjson.Get(helper.BytesToString(r), "img").String()
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
123
plugin/hyaku/main.go
Normal file
@@ -0,0 +1,123 @@
|
||||
// Package hyaku 百人一首
|
||||
package hyaku
|
||||
|
||||
import (
|
||||
"encoding/csv"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"unsafe"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/binary"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/file"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
const bed = "https://gitcode.net/u011570312/OguraHyakuninIsshu/-/raw/master/"
|
||||
|
||||
//nolint: asciicheck
|
||||
type line struct {
|
||||
番号, 歌人, 上の句, 下の句, 上の句ひらがな, 下の句ひらがな string
|
||||
}
|
||||
|
||||
func (l *line) String() string {
|
||||
b := binary.NewWriterF(func(w *binary.Writer) {
|
||||
r := reflect.ValueOf(l).Elem().Type()
|
||||
for i := 0; i < r.NumField(); i++ {
|
||||
switch i {
|
||||
case 0:
|
||||
w.WriteString("●")
|
||||
case 1:
|
||||
w.WriteString("◉")
|
||||
case 2, 3:
|
||||
w.WriteString("○")
|
||||
case 4, 5:
|
||||
w.WriteString("◎")
|
||||
}
|
||||
w.WriteString(r.Field(i).Name)
|
||||
w.WriteString(":")
|
||||
w.WriteString((*[6]string)(unsafe.Pointer(l))[i])
|
||||
w.WriteString("\n")
|
||||
}
|
||||
})
|
||||
return binary.BytesToString(b)
|
||||
}
|
||||
|
||||
var lines [100]*line
|
||||
|
||||
func init() {
|
||||
engine := control.Register("hyaku", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "百人一首\n" +
|
||||
"- 百人一首(随机发一首)\n" +
|
||||
"- 百人一首之n",
|
||||
PrivateDataFolder: "hyaku",
|
||||
})
|
||||
csvfile := engine.DataFolder() + "hyaku.csv"
|
||||
go func() {
|
||||
if file.IsNotExist(csvfile) {
|
||||
err := file.DownloadTo(bed+"小倉百人一首.csv", csvfile, true)
|
||||
if err != nil {
|
||||
_ = os.Remove(csvfile)
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
f, err := os.Open(csvfile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
records, err := csv.NewReader(f).ReadAll()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_ = f.Close()
|
||||
records = records[1:] // skip title
|
||||
if len(records) != 100 {
|
||||
panic("invalid csvfile")
|
||||
}
|
||||
for j, r := range records {
|
||||
if len(r) != 6 {
|
||||
panic("invalid csvfile")
|
||||
}
|
||||
i, err := strconv.Atoi(r[0])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
i--
|
||||
if j != i {
|
||||
panic("invalid csvfile")
|
||||
}
|
||||
lines[i] = (*line)(*(*unsafe.Pointer)(unsafe.Pointer(&r)))
|
||||
}
|
||||
}()
|
||||
engine.OnFullMatch("百人一首").SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
i := rand.Intn(100)
|
||||
ctx.SendChain(
|
||||
message.Image(fmt.Sprintf(bed+"img/%03d.jpg", i+1)),
|
||||
message.Text("\n", lines[i]),
|
||||
message.Image(fmt.Sprintf(bed+"img/%03d.png", i+1)),
|
||||
)
|
||||
})
|
||||
engine.OnRegex(`^百人一首之\s?(\d+)$`).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
i, err := strconv.Atoi(ctx.State["regex_matched"].([]string)[1])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
if i > 100 || i < 1 {
|
||||
ctx.SendChain(message.Text("ERROR:超出范围"))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(
|
||||
message.Image(fmt.Sprintf(bed+"img/%03d.jpg", i)),
|
||||
message.Text("\n", lines[i-1]),
|
||||
message.Image(fmt.Sprintf(bed+"img/%03d.png", i)),
|
||||
)
|
||||
})
|
||||
}
|
||||
145
plugin/image_finder/keyword.go
Normal file
@@ -0,0 +1,145 @@
|
||||
// Package imagefinder 关键字搜图
|
||||
package imagefinder
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/http3"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/pixiv"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/binary"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/img/pool"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
)
|
||||
|
||||
type resultjson struct {
|
||||
Error bool `json:"error"`
|
||||
Message string `json:"message"`
|
||||
Data struct {
|
||||
Illusts []struct {
|
||||
ID int64 `json:"id"`
|
||||
Title string `json:"title"`
|
||||
AltTitle string `json:"altTitle"`
|
||||
Description string `json:"description"`
|
||||
Type int64 `json:"type"`
|
||||
CreateDate string `json:"createDate"`
|
||||
UploadDate string `json:"uploadDate"`
|
||||
Sanity int64 `json:"sanity"`
|
||||
Width int64 `json:"width"`
|
||||
Height int64 `json:"height"`
|
||||
PageCount int64 `json:"pageCount"`
|
||||
Tags []struct {
|
||||
Name string `json:"name"`
|
||||
Translation string `json:"translation"`
|
||||
} `json:"tags"`
|
||||
Statistic struct {
|
||||
Bookmarks int64 `json:"bookmarks"`
|
||||
Likes int64 `json:"likes"`
|
||||
Comments int64 `json:"comments"`
|
||||
Views int64 `json:"views"`
|
||||
} `json:"statistic"`
|
||||
Image string `json:"image"`
|
||||
} `json:"illusts"`
|
||||
Scores []float64 `json:"scores"`
|
||||
HasNext bool `json:"has_next"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
var hrefre = regexp.MustCompile(`<a href=".*">`)
|
||||
|
||||
func init() {
|
||||
control.Register("imgfinder", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "关键字搜图\n" +
|
||||
"- 来张 [xxx]",
|
||||
}).OnRegex(`^来张\s?(.*)$`, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
keyword := ctx.State["regex_matched"].([]string)[1]
|
||||
soutujson, err := soutuapi(keyword)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
rannum := rand.Intn(len(soutujson.Data.Illusts))
|
||||
il := soutujson.Data.Illusts[rannum]
|
||||
illust, err := pixiv.Works(il.ID)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
u := illust.ImageUrls[0]
|
||||
n := u[strings.LastIndex(u, "/")+1 : len(u)-4]
|
||||
f := illust.Path(0)
|
||||
|
||||
err = pool.SendImageFromPool(n, f, func() error {
|
||||
// 下载图片
|
||||
return illust.DownloadToCache(0)
|
||||
}, ctxext.SendFakeForwardToGroup(ctx,
|
||||
message.Text(
|
||||
il.Width, "x", il.Height, "\n",
|
||||
"标题: ", il.Title, "\n",
|
||||
"副标题: ", il.AltTitle, "\n",
|
||||
"ID: ", il.ID, "\n",
|
||||
"画师: ", illust.UserName, " (", illust.UserId, ")", "\n",
|
||||
"分级:", il.Sanity, "\n",
|
||||
hrefre.ReplaceAllString(strings.ReplaceAll(strings.ReplaceAll(il.Description, "<br />", "\n"), "</a>", ""), ""),
|
||||
printtags(reflect.ValueOf(&il.Tags)),
|
||||
),
|
||||
), ctxext.GetFirstMessageInForward(ctx))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// soutuapi 请求api
|
||||
func soutuapi(keyword string) (r resultjson, err error) {
|
||||
var data []byte
|
||||
data, err = web.RequestDataWith(&http.Client{Transport: &http3.RoundTripper{}},
|
||||
"https://api.pixivel.moe/v2/pixiv/illust/search/"+url.QueryEscape(keyword)+"?page=0",
|
||||
"GET",
|
||||
"https://pixivel.moe/",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36",
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(data, &r)
|
||||
if err == nil && r.Error {
|
||||
err = errors.New(r.Message)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func printtags(r reflect.Value) string {
|
||||
tags := r.Elem()
|
||||
s := binary.BytesToString(binary.NewWriterF(func(w *binary.Writer) {
|
||||
for i := 0; i < tags.Len(); i++ {
|
||||
_ = w.WriteByte('\n')
|
||||
tag := tags.Index(i)
|
||||
_ = w.WriteByte('#')
|
||||
w.WriteString(tag.Field(0).String())
|
||||
if !tag.Field(1).IsZero() {
|
||||
w.WriteString(" (")
|
||||
w.WriteString(tag.Field(1).String())
|
||||
w.WriteString(")")
|
||||
}
|
||||
}
|
||||
}))
|
||||
return s
|
||||
}
|
||||
23
plugin/inject/main.go
Normal file
@@ -0,0 +1,23 @@
|
||||
// Package inject 注入指令
|
||||
package inject
|
||||
|
||||
import (
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func init() {
|
||||
en := control.Register("inject", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "注入指令\n" +
|
||||
"- run[CQ码]",
|
||||
})
|
||||
// 运行 CQ 码
|
||||
en.OnPrefix("run", zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 可注入,权限为主人
|
||||
ctx.Send(message.UnescapeCQCodeText(ctx.State["args"].(string)))
|
||||
})
|
||||
}
|
||||
24
plugin/jandan/data.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package jandan
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
)
|
||||
|
||||
var db = &sql.Sqlite{}
|
||||
var mu sync.RWMutex
|
||||
|
||||
type picture struct {
|
||||
ID uint64 `db:"id"`
|
||||
URL string `db:"url"`
|
||||
}
|
||||
|
||||
func getRandomPicture() (u string, err error) {
|
||||
var p picture
|
||||
mu.RLock()
|
||||
err = db.Pick("picture", &p)
|
||||
mu.RUnlock()
|
||||
u = p.URL
|
||||
return
|
||||
}
|
||||
115
plugin/jandan/jandan.go
Normal file
@@ -0,0 +1,115 @@
|
||||
// Package jandan 煎蛋网无聊图
|
||||
package jandan
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"hash/crc64"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/binary"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/antchfx/htmlquery"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
const (
|
||||
api = "http://jandan.net/pic"
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("jandan", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "煎蛋网无聊图\n- 来份[屌|弔|吊]图\n- 更新[屌|弔|吊]图\n",
|
||||
PublicDataFolder: "Jandan",
|
||||
})
|
||||
|
||||
getdb := ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||
db.DBPath = engine.DataFolder() + "pics.db"
|
||||
_, _ = engine.GetLazyData("pics.db", false)
|
||||
err := db.Open(time.Hour * 24)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
err = db.Create("picture", &picture{})
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
n, err := db.Count("picture")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
logrus.Printf("[jandan]读取%d张图片", n)
|
||||
return true
|
||||
})
|
||||
|
||||
engine.OnRegex(`来份[屌|弔|吊]图`, getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
u, err := getRandomPicture()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Image(u))
|
||||
})
|
||||
|
||||
engine.OnRegex(`更新[屌|弔|吊]图`, zero.SuperUserPermission, getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.Send("少女更新中...")
|
||||
webpageURL := api
|
||||
doc, err := htmlquery.LoadURL(webpageURL)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
re := regexp.MustCompile(`\d+`)
|
||||
pageTotal, err := strconv.Atoi(re.FindString(htmlquery.FindOne(doc, "//*[@id='comments']/div[2]/div/span[@class='current-comment-page']/text()").Data))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
LOOP:
|
||||
for i := 0; i < pageTotal; i++ {
|
||||
logrus.Debugln("[jandan]", fmt.Sprintf("处理第%d/%d页...", i, pageTotal))
|
||||
doc, err = htmlquery.LoadURL(webpageURL)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
picList, err := htmlquery.QueryAll(doc, "//*[@class='view_img_link']")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
if len(picList) != 0 {
|
||||
for _, v := range picList {
|
||||
u := "https:" + v.Attr[0].Val
|
||||
i := crc64.Checksum(binary.StringToBytes(u), crc64.MakeTable(crc64.ISO))
|
||||
mu.RLock()
|
||||
ok := db.CanFind("picture", "where id="+strconv.FormatUint(i, 10))
|
||||
mu.RUnlock()
|
||||
if !ok {
|
||||
mu.Lock()
|
||||
_ = db.Insert("picture", &picture{ID: i, URL: u})
|
||||
mu.Unlock()
|
||||
} else {
|
||||
// 开始重复,说明之后都是重复
|
||||
break LOOP
|
||||
}
|
||||
}
|
||||
}
|
||||
if i != pageTotal-1 {
|
||||
webpageURL = "https:" + htmlquery.FindOne(doc, "//*[@id='comments']/div[@class='comments']/div[@class='cp-pagenavi']/a[@class='previous-comment-page']").Attr[1].Val
|
||||
}
|
||||
}
|
||||
ctx.Send("更新完成!")
|
||||
})
|
||||
}
|
||||
71
plugin/juejuezi/juejuezi.go
Normal file
@@ -0,0 +1,71 @@
|
||||
// Package juejuezi 绝绝子
|
||||
package juejuezi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
)
|
||||
|
||||
const (
|
||||
juejueziURL = "https://www.offjuan.com/api/juejuezi/text"
|
||||
referer = "https://juejuezi.offjuan.com/"
|
||||
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"
|
||||
)
|
||||
|
||||
func init() {
|
||||
control.Register("juejuezi", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "绝绝子生成器\n" +
|
||||
"- 喝奶茶绝绝子 | 绝绝子吃饭",
|
||||
}).OnRegex("[\u4E00-\u9FA5]{0,10}绝绝子[\u4E00-\u9FA5]{0,10}").SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
toDealStr := []rune(strings.ReplaceAll(ctx.ExtractPlainText(), "绝绝子", ""))
|
||||
switch len(toDealStr) {
|
||||
case 0, 1:
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("不要只输入绝绝子"))
|
||||
case 2:
|
||||
data, err := juejuezi(string(toDealStr[0]), string(toDealStr[1]))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(gjson.Get(helper.BytesToString(data), "text").String()))
|
||||
default:
|
||||
params := ctx.GetWordSlices(string(toDealStr)).Get("slices").Array()
|
||||
data, err := juejuezi(params[0].String(), params[1].String())
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(gjson.Get(helper.BytesToString(data), "text").String()))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func juejuezi(verb, noun string) (data []byte, err error) {
|
||||
juejueziStr := fmt.Sprintf("{\"verb\":\"%s\",\"noun\":\"%s\"}", verb, noun)
|
||||
client := &http.Client{}
|
||||
// 提交请求
|
||||
request, err := http.NewRequest("POST", juejueziURL, strings.NewReader(juejueziStr))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
request.Header.Add("Referer", referer)
|
||||
request.Header.Add("User-Agent", ua)
|
||||
response, err := client.Do(request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data, err = io.ReadAll(response.Body)
|
||||
response.Body.Close()
|
||||
return
|
||||
}
|
||||
101
plugin/lolicon/lolicon.go
Normal file
@@ -0,0 +1,101 @@
|
||||
// Package lolicon 基于 https://api.lolicon.app 随机图片
|
||||
package lolicon
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/img/pool"
|
||||
"github.com/FloatTech/zbputils/math"
|
||||
"github.com/FloatTech/zbputils/process"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
)
|
||||
|
||||
const (
|
||||
api = "https://api.lolicon.app/setu/v2"
|
||||
capacity = 10
|
||||
)
|
||||
|
||||
var (
|
||||
queue = make(chan string, capacity)
|
||||
custapi = ""
|
||||
)
|
||||
|
||||
func init() {
|
||||
en := control.Register("lolicon", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "lolicon\n" +
|
||||
"- 来份萝莉\n" +
|
||||
"- 设置随机图片地址[http...]",
|
||||
}).ApplySingle(ctxext.DefaultSingle)
|
||||
en.OnFullMatch("来份萝莉").Limit(ctxext.LimitByGroup).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
go func() {
|
||||
for i := 0; i < math.Min(cap(queue)-len(queue), 2); i++ {
|
||||
if custapi != "" {
|
||||
data, err := web.GetData(custapi)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
continue
|
||||
}
|
||||
queue <- "base64://" + base64.StdEncoding.EncodeToString(data)
|
||||
continue
|
||||
}
|
||||
data, err := web.GetData(api)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
continue
|
||||
}
|
||||
json := gjson.ParseBytes(data)
|
||||
if e := json.Get("error").Str; e != "" {
|
||||
ctx.SendChain(message.Text("ERROR:", e))
|
||||
continue
|
||||
}
|
||||
url := json.Get("data.0.urls.original").Str
|
||||
url = strings.ReplaceAll(url, "i.pixiv.cat", "i.pixiv.re")
|
||||
name := url[strings.LastIndex(url, "/")+1 : len(url)-4]
|
||||
m, err := pool.GetImage(name)
|
||||
if err != nil {
|
||||
m.SetFile(url)
|
||||
_, err = m.Push(ctxext.SendToSelf(ctx), ctxext.GetMessage(ctx))
|
||||
process.SleepAbout1sTo2s()
|
||||
}
|
||||
if err == nil {
|
||||
queue <- m.String()
|
||||
} else {
|
||||
queue <- url
|
||||
}
|
||||
}
|
||||
}()
|
||||
select {
|
||||
case <-time.After(time.Minute):
|
||||
ctx.SendChain(message.Text("ERROR:等待填充,请稍后再试......"))
|
||||
case img := <-queue:
|
||||
id := ctx.SendChain(message.Image(img))
|
||||
if id.ID() == 0 {
|
||||
process.SleepAbout1sTo2s()
|
||||
id = ctx.SendChain(message.Image(img).Add("cache", "0"))
|
||||
if id.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR:图片发送失败,可能被风控了~"))
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
en.OnPrefix("设置随机图片地址", zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
u := strings.TrimSpace(ctx.State["args"].(string))
|
||||
if !strings.HasPrefix(u, "http") {
|
||||
ctx.SendChain(message.Text("ERROR:url非法!"))
|
||||
return
|
||||
}
|
||||
custapi = u
|
||||
})
|
||||
}
|
||||