mirror of
https://github.com/nonebot/nonebot2.git
synced 2025-10-07 11:16:43 +00:00
Compare commits
1496 Commits
v2.0.0a3
...
v2.0.0-bet
Author | SHA1 | Date | |
---|---|---|---|
|
95415659ce | ||
|
304118c98e | ||
|
3fe3c1351f | ||
|
b0536edab3 | ||
|
ff330e1536 | ||
|
6c00432c10 | ||
|
1c37024699 | ||
|
ad2ebc3818 | ||
|
92fd6fb669 | ||
|
a904becfe0 | ||
|
7a8b38bd07 | ||
|
cd94672999 | ||
|
3e66bc73a6 | ||
|
f01694dfe7 | ||
|
d13ca9aee6 | ||
|
0a10a3c18b | ||
|
6b2d8d2674 | ||
|
cf1333f8a8 | ||
|
0cbcc04396 | ||
|
f396f76425 | ||
|
89ae275793 | ||
|
381e5e4a76 | ||
|
ac6eed9217 | ||
|
abf4d57987 | ||
|
1393318bce | ||
|
1ee1ed80c0 | ||
|
20751e8ee5 | ||
|
1030b73555 | ||
|
e39539a3be | ||
|
159fc12fb9 | ||
|
93b76894bb | ||
|
2b5f3268c8 | ||
|
87f9ccd058 | ||
|
402de4bb8a | ||
|
1af67b4431 | ||
|
493a4e5880 | ||
|
ef386af2bc | ||
|
896f1d6596 | ||
|
69b4c29dcb | ||
|
dd5112ff99 | ||
|
3bede1581f | ||
|
e54b80f739 | ||
|
bd7ee0a1ba | ||
|
aaed95cae1 | ||
|
7f54468868 | ||
|
07cb96864c | ||
|
96749bde83 | ||
|
bbbb5bbecd | ||
|
7053f0ee72 | ||
|
6950e5b34d | ||
|
5fe5273f8f | ||
|
479952777b | ||
|
0541008fb5 | ||
|
be1915381e | ||
|
43938a004e | ||
|
983e5aefdb | ||
|
620938c26c | ||
|
338c41abd5 | ||
|
2bb365c70e | ||
|
574d4366a6 | ||
|
feadffebcd | ||
|
78d0ec847e | ||
|
ec35f292bd | ||
|
c48231454e | ||
|
56677616b4 | ||
|
ab2c73856d | ||
|
21a958ffd9 | ||
|
e4691f0525 | ||
|
2beed6bf16 | ||
|
d1706e438b | ||
|
23d0b2509e | ||
|
80c0ac5456 | ||
|
af03188f88 | ||
|
4bd2156929 | ||
|
c7f428795b | ||
|
39fd8b2dcd | ||
|
0aea7f13e3 | ||
|
f06b78054c | ||
|
3323393261 | ||
|
5cfeb4e79d | ||
|
86c859fec2 | ||
|
9379182f04 | ||
|
db826caff4 | ||
|
0f5a4473ab | ||
|
7690f0e640 | ||
|
3b1dd6d5db | ||
|
7e9dabfd5f | ||
|
c815ac7ca3 | ||
|
91262d68bc | ||
|
717fbd1b95 | ||
|
2ec04e5a4c | ||
|
c1e06c2ec0 | ||
|
fd9ec5e6fa | ||
|
8093c5d154 | ||
|
e64f399370 | ||
|
7b204d72e6 | ||
|
00c2ee8490 | ||
|
d773fea709 | ||
|
7ebae277d1 | ||
|
9b9941e6c5 | ||
|
188eb110c5 | ||
|
e62ce93011 | ||
|
2f5e523b5a | ||
|
495053f83b | ||
|
5c67290f00 | ||
|
80258fe2d4 | ||
|
75e2ca77df | ||
|
6ed87f1910 | ||
|
6643f951ef | ||
|
e968b71239 | ||
|
a51158cfc0 | ||
|
17f3c8fd09 | ||
|
76104d3237 | ||
|
e3aba26080 | ||
|
8fb394e4c3 | ||
|
b9f1890d80 | ||
|
0839d6d062 | ||
|
e870fcceab | ||
|
ee7f4daef7 | ||
|
cda49551a8 | ||
|
b984f99643 | ||
|
71caa4a0ae | ||
|
fecdb5367a | ||
|
9e316bff77 | ||
|
9b2fa46921 | ||
|
b900133ab4 | ||
|
cf8670c167 | ||
|
e9b8515cf1 | ||
|
d549cdf26a | ||
|
1a602b68e3 | ||
|
883ea18224 | ||
|
e5fdb1e07a | ||
|
ea8f7717b9 | ||
|
c49059f9d3 | ||
|
0d24a79840 | ||
|
6968d34fc2 | ||
|
008c6fd036 | ||
|
44e5182322 | ||
|
c2c3d5ef4b | ||
|
ca045b2f73 | ||
|
ec9e159ef6 | ||
|
c0f321116a | ||
|
3d762fcbab | ||
|
fe69735ca0 | ||
|
acbb886942 | ||
|
3dac49f271 | ||
|
14f88d4062 | ||
|
de7c51a518 | ||
|
329a1fd226 | ||
|
9613e47682 | ||
|
ec1249f5fb | ||
|
0316033a57 | ||
|
baabf2a83a | ||
|
85ee0ce420 | ||
|
27f8d6aa28 | ||
|
e942f4076c | ||
|
8f3978f2b2 | ||
|
3b8ba6ee3a | ||
|
60461c767e | ||
|
66ba25494a | ||
|
6b5a5e53eb | ||
|
344c3576b1 | ||
|
5efdc71d9f | ||
|
f160310aea | ||
|
5aedc52537 | ||
|
a0d13822c0 | ||
|
6963047af2 | ||
|
4de01d7d4f | ||
|
61e17d0de7 | ||
|
b64b02bb45 | ||
|
47d4909b31 | ||
|
d80c02ae46 | ||
|
180aaadda9 | ||
|
a85ee6555f | ||
|
bbaf156826 | ||
|
5b75b72720 | ||
|
ca4d7397f8 | ||
|
02ef337bc4 | ||
|
d82ab12948 | ||
|
c25ee1cb56 | ||
|
59e139724b | ||
|
b52954a240 | ||
|
aea961b346 | ||
|
a148ef7bfe | ||
|
3c428d98c4 | ||
|
2ce305da2a | ||
|
226fc0feb3 | ||
|
534119eaf0 | ||
|
c037c7a196 | ||
|
b4e49d8b8d | ||
|
b47869198d | ||
|
dcb6f69f21 | ||
|
7d8a60b033 | ||
|
0236746e65 | ||
|
2dc5a7e1b1 | ||
|
a414406039 | ||
|
5a7af6d6e2 | ||
|
f2b15d4efa | ||
|
4570baa57b | ||
|
b92c1a0b33 | ||
|
319b03acd8 | ||
|
44356154fa | ||
|
a6112fdf64 | ||
|
d0821cd12f | ||
|
ebdc8c7004 | ||
|
37f55652d9 | ||
|
bd55cd19e3 | ||
|
a369d7dcbc | ||
|
030237fe22 | ||
|
6cf7f1f1fc | ||
|
f9b244b0d6 | ||
|
29f14a20ce | ||
|
286729f703 | ||
|
db5d4d7acf | ||
|
a98d98cd12 | ||
|
602185a34e | ||
|
3120abacb3 | ||
|
225e48d420 | ||
|
91bd5aa708 | ||
|
23c237cb2a | ||
|
9a29966e2d | ||
|
760ac693c0 | ||
|
a864b36e9f | ||
|
75d4cd9565 | ||
|
d22630e768 | ||
|
b4d12d905d | ||
|
d1c03208e4 | ||
|
8ee9697cc0 | ||
|
a5948fb5e3 | ||
|
471d306e13 | ||
|
81e1cf23c7 | ||
|
203e1c1897 | ||
|
646eedb2ad | ||
|
4150e4d771 | ||
|
c1163bed8d | ||
|
1b9a6cb2ca | ||
|
ee619a33a9 | ||
|
36d93b8a3a | ||
|
dc31afbd18 | ||
|
4cbdd726e5 | ||
|
ea502c1fff | ||
|
d1c6eeb6c2 | ||
|
cafe5c9af0 | ||
|
0a1ae75b70 | ||
|
7495fee2a2 | ||
|
9d708a6723 | ||
|
f7eadb48b5 | ||
|
c454cf0874 | ||
|
57e826a835 | ||
|
ecb9d6bc28 | ||
|
512d77de0d | ||
|
618753bd3a | ||
|
fdffaf4e85 | ||
|
7c27fbe1d5 | ||
|
554ad156c0 | ||
|
8be2de4cfc | ||
|
2ccbc93e48 | ||
|
b796f3cabc | ||
|
4e482685ae | ||
|
08f56db385 | ||
|
72f5aeea54 | ||
|
1236abe507 | ||
|
06c1978260 | ||
|
f1b204f421 | ||
|
2b26f519af | ||
|
069e7024ec | ||
|
2d7d5f73c2 | ||
|
75774d34bc | ||
|
0c2c2717ac | ||
|
d10f557212 | ||
|
32e3c17552 | ||
|
e632e99feb | ||
|
e38772435d | ||
|
d9093a20e0 | ||
|
130f11ac68 | ||
|
9a44a2ff2f | ||
|
c81c0578e3 | ||
|
b01db74e0b | ||
|
4c40acb09d | ||
|
3722547f1c | ||
|
e12e18022b | ||
|
9a84bd175c | ||
|
ac87107556 | ||
|
33f605a947 | ||
|
2a08f6bdf6 | ||
|
b9c91dc5c3 | ||
|
6b79106cd1 | ||
|
0fa85be0e4 | ||
|
69f8821acb | ||
|
ff96a11dc5 | ||
|
042f7faa71 | ||
|
0d5849759f | ||
|
391a899045 | ||
|
b72583b8c8 | ||
|
cbb3ec1fb8 | ||
|
9f70daca59 | ||
|
cfd992b6b1 | ||
|
6ec1159f95 | ||
|
38ac45f687 | ||
|
1331cbf8a3 | ||
|
a6fc0e408c | ||
|
66b2153493 | ||
|
94b98b74b9 | ||
|
f3abd2f1a3 | ||
|
1280cf9ba3 | ||
|
bac56635c0 | ||
|
6d9caadffc | ||
|
4a7c07a7ac | ||
|
910d18e79f | ||
|
5cff80812e | ||
|
c8a8ff28ec | ||
|
292b8e6366 | ||
|
9e9608abd8 | ||
|
3452880b16 | ||
|
ef2c98c6af | ||
|
246b8ccbe7 | ||
|
2355c6385d | ||
|
75811c0b64 | ||
|
3a510e3888 | ||
|
161cfbe1b8 | ||
|
0b08d23e34 | ||
|
2ebf7fc096 | ||
|
041b59011b | ||
|
92a411e3b4 | ||
|
81cbf84dca | ||
|
4364685b30 | ||
|
cfdebb30b7 | ||
|
049d14295e | ||
|
3dc93f7997 | ||
|
b19c2e4191 | ||
|
d121a2080b | ||
|
919e3ebf8c | ||
|
b0f4b8ffa1 | ||
|
b3bf9470cf | ||
|
16029a33e8 | ||
|
b31d04dc5d | ||
|
e0f73ba193 | ||
|
0b35d5e724 | ||
|
c747342709 | ||
|
244df12069 | ||
|
368afe6d63 | ||
|
5cd61c09a8 | ||
|
1e55fbf6b1 | ||
|
463ff260c4 | ||
|
89e32a3241 | ||
|
4f8771acbd | ||
|
a212baf90b | ||
|
5db8b124ab | ||
|
a273d75b07 | ||
|
55a402203e | ||
|
64967e8807 | ||
|
43917b5aad | ||
|
b97133fb59 | ||
|
855f61d837 | ||
|
e2003e27df | ||
|
d82749c48e | ||
|
0a802f9b13 | ||
|
e0610fdcc0 | ||
|
20d0ecfc7f | ||
|
fa15e5b0ee | ||
|
d9cc912ccb | ||
|
09d9f414ce | ||
|
ca09fb8372 | ||
|
b25a0387ba | ||
|
9931563d80 | ||
|
53a576dae5 | ||
|
44d13acc81 | ||
|
59f567004f | ||
|
956e581d72 | ||
|
b635d01519 | ||
|
12c1f6d764 | ||
|
b66a4df4c5 | ||
|
46c61df081 | ||
|
b6ec81c21d | ||
|
f9f2f1b0bd | ||
|
45396e3163 | ||
|
7ced508f9d | ||
|
ed1f1c27e2 | ||
|
3fa75b1c78 | ||
|
258ef670e2 | ||
|
5cf665fa21 | ||
|
116f16b470 | ||
|
9518e3c568 | ||
|
57827ea4bb | ||
|
8e41422055 | ||
|
fcd168fd3e | ||
|
fe1bd87ff8 | ||
|
efe1615d16 | ||
|
ca26609308 | ||
|
01e818f6a4 | ||
|
1c73a9adfa | ||
|
a739b93561 | ||
|
7cfdc2dd37 | ||
|
a6ff3711bb | ||
|
58d10abd32 | ||
|
f0bc47ec5e | ||
|
b5f2b1a76d | ||
|
4f4a072dd7 | ||
|
fff7d3bff6 | ||
|
474fd10613 | ||
|
9bea710e45 | ||
|
3c76c6ff8b | ||
|
a8a61623d2 | ||
|
24ce531598 | ||
|
a6be0c370f | ||
|
22c7371f2e | ||
|
bfb77e9cdf | ||
|
9aa346fb1f | ||
|
1dfe5d49fc | ||
|
e48788e41f | ||
|
802c39da32 | ||
|
0d23a9ab8d | ||
|
109cae6dac | ||
|
f63ef8d23b | ||
|
3d4d3b0f24 | ||
|
a3fa1a36c9 | ||
|
45cec05bbc | ||
|
e4d1462585 | ||
|
18c6bea451 | ||
|
c4e3309026 | ||
|
57a60ae45b | ||
|
e7f5097e17 | ||
|
e437c13bb3 | ||
|
edd7f3ccc8 | ||
|
26f0d66017 | ||
|
5791018af1 | ||
|
2c6b41f62c | ||
|
f2b23f1b44 | ||
|
a534f7b58c | ||
|
81398bb803 | ||
|
3a0265b0f6 | ||
|
59db66ef27 | ||
|
a04957a354 | ||
|
371cfd4a0e | ||
|
037a5ccce0 | ||
|
879767df01 | ||
|
31b18e36e7 | ||
|
eb3e20abfb | ||
|
b96823b5bd | ||
|
b098c8477b | ||
|
02b2589eeb | ||
|
05ea21becd | ||
|
2836f50e74 | ||
|
7b3d66cd2a | ||
|
ceebe0e95d | ||
|
2fe01f33e0 | ||
|
410266acb1 | ||
|
02924d56cd | ||
|
0bd8d4fbbc | ||
|
547bebebd9 | ||
|
f8703557a0 | ||
|
8e97a84ad8 | ||
|
3564228183 | ||
|
bb93757f51 | ||
|
e18b3d04fb | ||
|
458085b317 | ||
|
832875e7cf | ||
|
73762e65bb | ||
|
26e627c36c | ||
|
8b93dc7769 | ||
|
6cfd44224d | ||
|
dc8b7887d7 | ||
|
18f98e4cbc | ||
|
db73d2b621 | ||
|
7a3cd8c395 | ||
|
358528b495 | ||
|
cda1ad093f | ||
|
f48c61c2e0 | ||
|
571cdef826 | ||
|
0ce3ee6c20 | ||
|
600fc4fffd | ||
|
c1b10a0e48 | ||
|
904f285f62 | ||
|
8680695586 | ||
|
a1803553fb | ||
|
9c647682e7 | ||
|
fb6e5a69f2 | ||
|
cf85cbecb3 | ||
|
948ea93599 | ||
|
de48ed99a7 | ||
|
8a6c26440c | ||
|
cf747f954c | ||
|
54a7e4808c | ||
|
03f5683d52 | ||
|
58c922f042 | ||
|
98e65ebdec | ||
|
e4a4a8127e | ||
|
72b0ee0130 | ||
|
679ec94020 | ||
|
1f0be1e1e3 | ||
|
bcc55a9143 | ||
|
749d33478a | ||
|
cb68e0ee1b | ||
|
ecc613f6c5 | ||
|
04b3fda40c | ||
|
32787fdc1e | ||
|
637c48aea7 | ||
|
5768b5bdd6 | ||
|
96d05cb521 | ||
|
92e5b8ea88 | ||
|
59ed869ed0 | ||
|
a14d475de2 | ||
|
8ea4561f1c | ||
|
5ac43eb459 | ||
|
c22d97fe47 | ||
|
bb964213f1 | ||
|
ef1547cbfe | ||
|
f2295318a9 | ||
|
66b54de869 | ||
|
d802fad111 | ||
|
8acd561de6 | ||
|
b4e20e00e4 | ||
|
3230dfc14a | ||
|
607f338934 | ||
|
758108229a | ||
|
aac4571d43 | ||
|
0436c1b7b8 | ||
|
a740a9cfea | ||
|
57ff73269b | ||
|
625c12fc12 | ||
|
4fc655323d | ||
|
f0482bb636 | ||
|
df6486f926 | ||
|
141cd10651 | ||
|
711fffe3b0 | ||
|
2c056364c1 | ||
|
c6921c731c | ||
|
8c7498eeb5 | ||
|
30cb6be104 | ||
|
fbd60e30fc | ||
|
2908cb3ce2 | ||
|
b1c5013088 | ||
|
70e424b58f | ||
|
730186cfd4 | ||
|
d2ae2e2982 | ||
|
67770ffa6f | ||
|
15ab958a70 | ||
|
af6f63dc44 | ||
|
7c7994e2e2 | ||
|
f597303698 | ||
|
1222972b73 | ||
|
7df407056b | ||
|
79b6601d12 | ||
|
53d98f3d2e | ||
|
fe43c8d69a | ||
|
e490be9eb0 | ||
|
3af8b55985 | ||
|
aaed345a20 | ||
|
f42d578765 | ||
|
f5843dd3ad | ||
|
840580334f | ||
|
5a8b5b5696 | ||
|
dc5aa3d4bf | ||
|
b9befc8350 | ||
|
e3c3e370cb | ||
|
603a63a629 | ||
|
276d09bb54 | ||
|
5635c83bfb | ||
|
0ec7cdc3aa | ||
|
932963e71c | ||
|
322ac98c50 | ||
|
811e94e186 | ||
|
0c39300f4b | ||
|
33bd7582be | ||
|
b6979594a7 | ||
|
150ef30b73 | ||
|
1042759d60 | ||
|
866149902c | ||
|
136b13b4cc | ||
|
cc11e2e885 | ||
|
f9f1e33262 | ||
|
7a8f881b04 | ||
|
20c3c24a6d | ||
|
f80ba8451f | ||
|
b1fa2bbb80 | ||
|
406511496d | ||
|
24144a9474 | ||
|
3571a5fdc0 | ||
|
4afd681ca9 | ||
|
48816308f8 | ||
|
3e66eb2fdb | ||
|
d669fed5e9 | ||
|
8e915f808b | ||
|
46ace83106 | ||
|
da16bdbb96 | ||
|
c1b7b78929 | ||
|
b9de8baac4 | ||
|
b3718c3042 | ||
|
69cee3844e | ||
|
1db462e4ad | ||
|
23cfa5564a | ||
|
7879346ca1 | ||
|
ef5a49933f | ||
|
e0bd7e11d5 | ||
|
0c5bbdaabe | ||
|
d8e29a81aa | ||
|
9f15b69724 | ||
|
cd12718dcb | ||
|
94c3c47523 | ||
|
fde6181d3c | ||
|
a4c6d834ff | ||
|
c8e494ca83 | ||
|
f87c23c9a7 | ||
|
b2f21ab974 | ||
|
6749afe75e | ||
|
8849cb73bb | ||
|
ad2060e651 | ||
|
c76dae584e | ||
|
edb7c79acf | ||
|
76c830739c | ||
|
8e6f8fada8 | ||
|
ddd96271b0 | ||
|
e9bc98e74d | ||
|
af6e9217c7 | ||
|
c0d78449be | ||
|
d7f2837efe | ||
|
cf9b5fd980 | ||
|
b42cafafd6 | ||
|
136c9a2687 | ||
|
cf45572211 | ||
|
c9d80255ae | ||
|
393be3baa4 | ||
|
fd01213697 | ||
|
2f5eb1a0f9 | ||
|
ca31ec5fe3 | ||
|
2003dfd703 | ||
|
f3342722f5 | ||
|
b2f5f93603 | ||
|
830276d110 | ||
|
9342d03f4d | ||
|
fe588caebb | ||
|
b0026831d0 | ||
|
46d7804c98 | ||
|
accbf57776 | ||
|
62c0dd6e74 | ||
|
916bb5b0e6 | ||
|
45e1126f37 | ||
|
57cf8e9bd8 | ||
|
f609a9fe0e | ||
|
4795f01583 | ||
|
06f9f795aa | ||
|
2d7d8992c0 | ||
|
15007feea7 | ||
|
8095be9ab9 | ||
|
ea48b86310 | ||
|
6402d8a4de | ||
|
5ec30c5122 | ||
|
c4b83a60f1 | ||
|
0fec4c8592 | ||
|
a09e09b942 | ||
|
7e8296b36e | ||
|
322477638a | ||
|
e659b4b2b6 | ||
|
27fe6e4fcb | ||
|
7d8b0843a0 | ||
|
e44b427b7a | ||
|
2ff6f87842 | ||
|
84dfe18f39 | ||
|
918b375ece | ||
|
c82a4820f7 | ||
|
c6e62957ab | ||
|
8a14177219 | ||
|
24268072fc | ||
|
3c65f2dd19 | ||
|
3f14a92a3e | ||
|
adf2016f4e | ||
|
81bb8be7f3 | ||
|
744f9e9f5d | ||
|
e2de13e122 | ||
|
3939dfa024 | ||
|
8680a954f8 | ||
|
20001764bf | ||
|
61512ff01f | ||
|
2488c6295e | ||
|
100f560558 | ||
|
01678005f0 | ||
|
00dc72b6c4 | ||
|
ca21fb8202 | ||
|
5989c3fecd | ||
|
7376933c31 | ||
|
a573266cab | ||
|
8374f86fde | ||
|
4a18772d2c | ||
|
5d0ac94bfe | ||
|
a636ddfab4 | ||
|
5c2840ca27 | ||
|
44850a279d | ||
|
17f3258207 | ||
|
b95fed69b0 | ||
|
059935aedb | ||
|
c99e1880d3 | ||
|
faf7a3b500 | ||
|
41c5ac0ac7 | ||
|
f8ad9ef278 | ||
|
5146a30836 | ||
|
db59cd9578 | ||
|
4b38afdcd7 | ||
|
b87971247a | ||
|
dcf4838fda | ||
|
6f40365407 | ||
|
315fdb97d3 | ||
|
9a3e974063 | ||
|
6b3183cdfa | ||
|
5189a182b5 | ||
|
884a7b966f | ||
|
fa73c13800 | ||
|
593d593a62 | ||
|
c2c8906b7d | ||
|
71f68fc1ce | ||
|
add2bda2c1 | ||
|
beef2ad8cf | ||
|
554865f97f | ||
|
d3e7ed4a71 | ||
|
56e489b458 | ||
|
5f3bd91321 | ||
|
4655bf1df8 | ||
|
9052214e6d | ||
|
59405bbe7a | ||
|
260d119711 | ||
|
5abc0d9614 | ||
|
4ba6ff106c | ||
|
9e51df9116 | ||
|
64d51448b8 | ||
|
79d3bbcdfe | ||
|
c24d0def09 | ||
|
e08843dd5c | ||
|
ec35ef041a | ||
|
efe8dd98b5 | ||
|
3fb9b25284 | ||
|
06deb13826 | ||
|
7d189392d2 | ||
|
2a07b49cb7 | ||
|
0be145491d | ||
|
58dd4a2183 | ||
|
810477749b | ||
|
92b035bea8 | ||
|
9801a8cebd | ||
|
f5a22b3d4b | ||
|
abbcb36131 | ||
|
d4860af85f | ||
|
50a4cbdb80 | ||
|
dff9a74f35 | ||
|
a5c2b06493 | ||
|
7bb49f0b3c | ||
|
00b4b880e9 | ||
|
87d93def62 | ||
|
0315aa7d8f | ||
|
b9812ea11b | ||
|
207750774d | ||
|
176dbd5830 | ||
|
1c6711355e | ||
|
20e1bf9624 | ||
|
d1a438a287 | ||
|
0d467d9275 | ||
|
c402b7599f | ||
|
916d620012 | ||
|
0fd82d4f54 | ||
|
e425571b08 | ||
|
85f0023350 | ||
|
0eadf5f4e9 | ||
|
b09a7518f5 | ||
|
0235af770f | ||
|
e03e3f6130 | ||
|
f0a6ff4627 | ||
|
6b763e20d0 | ||
|
fcb1c5d316 | ||
|
953328903c | ||
|
afba90838f | ||
|
f1ed783776 | ||
|
59ec5bacde | ||
|
ca08c56df7 | ||
|
d1e8925fe0 | ||
|
68ba1c1af2 | ||
|
03ac119313 | ||
|
8f99b01fb5 | ||
|
4e7592de98 | ||
|
5db819738e | ||
|
ade5d923ab | ||
|
43b185a3b8 | ||
|
65ec4828a9 | ||
|
1f585d8bcb | ||
|
b861149e0b | ||
|
534b51bc73 | ||
|
430b3467cc | ||
|
2dc7107990 | ||
|
81edb535a4 | ||
|
f00ce8b4f6 | ||
|
696ae2da6b | ||
|
b7e5ce88ea | ||
|
8fc8cb6112 | ||
|
48fae782d7 | ||
|
f3e78cc82e | ||
|
45199a247b | ||
|
f0a8b47c06 | ||
|
6371cd6bfe | ||
|
d738f8674d | ||
|
abfda3113b | ||
|
a941b32dd5 | ||
|
1527fb55f5 | ||
|
ffc1cd7d8d | ||
|
7f27957164 | ||
|
f8c057b135 | ||
|
2166595e50 | ||
|
22033e1cfb | ||
|
fc334ec7b9 | ||
|
e7dc4e1eec | ||
|
6bd12b7f2c | ||
|
5d48a92d1d | ||
|
4bc87ca747 | ||
|
62135dc117 | ||
|
1e294b8fbe | ||
|
9258bb09b4 | ||
|
b31317720b | ||
|
211c571508 | ||
|
785eac1345 | ||
|
bb64c6fb71 | ||
|
782232fb1a | ||
|
0fec9915de | ||
|
efacff698d | ||
|
36d0628e4f | ||
|
46c65b919f | ||
|
0b9aad09cf | ||
|
717e74f01d | ||
|
ef4f8df5a7 | ||
|
dce1187750 | ||
|
5ee6beb4b8 | ||
|
3af8cc45ea | ||
|
89ff2dd3c5 | ||
|
e7101a1f39 | ||
|
2af7f2bedb | ||
|
ad70fac377 | ||
|
2885e6053c | ||
|
4661adc564 | ||
|
edc6da9e61 | ||
|
d49749e5a1 | ||
|
8544fb2f69 | ||
|
80e41d26e2 | ||
|
8d6bb3768b | ||
|
c54007d7a4 | ||
|
35bf3ef772 | ||
|
06e1459667 | ||
|
da97a18497 | ||
|
61e33e24e9 | ||
|
f49a581193 | ||
|
f30b9e4fb9 | ||
|
c3a8dc709f | ||
|
63d6f173d6 | ||
|
8d80b610d1 | ||
|
80a54914e2 | ||
|
ac613b5839 | ||
|
33412f9bd2 | ||
|
51304fdd8e | ||
|
e139c883a3 | ||
|
662c5c09a6 | ||
|
a99d33198f | ||
|
e6ac07e608 | ||
|
d476c7e999 | ||
|
22655005f9 | ||
|
f7dd898379 | ||
|
d568a31684 | ||
|
46795ecd4b | ||
|
f1f510604e | ||
|
611049681a | ||
|
15c6f30fc3 | ||
|
59a855f2ed | ||
|
db61a93de8 | ||
|
4ed5b06db0 | ||
|
9e04e497b7 | ||
|
464f0d4a89 | ||
|
1df24a683e | ||
|
873aa62825 | ||
|
cb6c1cccca | ||
|
f6289ff1b3 | ||
|
7b61cd370e | ||
|
7f4ee24f87 | ||
|
3c8dca67fa | ||
|
b962bc43e6 | ||
|
e70b29bb9e | ||
|
94a55fead5 | ||
|
b23e845726 | ||
|
dc17d514b4 | ||
|
5e24300619 | ||
|
dc38a98180 | ||
|
af27e8f3f5 | ||
|
01af05742c | ||
|
11052dbcd1 | ||
|
f9e4d077d4 | ||
|
3477c0d8b4 | ||
|
8c9e096a84 | ||
|
19a780eabb | ||
|
3c312d9759 | ||
|
bb37d757da | ||
|
9ea80abf8c | ||
|
117758658e | ||
|
da290dad07 | ||
|
00daaed074 | ||
|
6f2b9a1d13 | ||
|
04e11c3b3e | ||
|
eb8e5aa39d | ||
|
93ffc93a80 | ||
|
d3091cdb3e | ||
|
869df38238 | ||
|
507000b63b | ||
|
6ab18f2d14 | ||
|
80714c9b61 | ||
|
42157f3dd1 | ||
|
854c2ae499 | ||
|
f397789516 | ||
|
fe8d711108 | ||
|
f31318b7f4 | ||
|
74ce56817c | ||
|
31682f5f28 | ||
|
7d3b397ff4 | ||
|
352f9f85c1 | ||
|
f9d4bcba3d | ||
|
2c85b2aa19 | ||
|
9bbadddfa9 | ||
|
247456df56 | ||
|
be674c0efc | ||
|
f26fb9d6fb | ||
|
6cd6750729 | ||
|
19c4602354 | ||
|
60ef01b66f | ||
|
f40f1788df | ||
|
c855ebcfb1 | ||
|
24f3900c69 | ||
|
70581abcef | ||
|
f2c732722f | ||
|
e76430a43b | ||
|
20e19d34b8 | ||
|
f58eb61f2d | ||
|
35e9321feb | ||
|
631743171f | ||
|
fc2694497e | ||
|
31b8a5ff77 | ||
|
6ce034ca20 | ||
|
3cc738c205 | ||
|
7b2af1b2f3 | ||
|
eeec690e71 | ||
|
aba18a2f68 | ||
|
17c7903bee | ||
|
ad47c24b60 | ||
|
6eab05d57f | ||
|
f4d623be25 | ||
|
4a961d8584 | ||
|
36e6f5b5c1 | ||
|
332a3a4f93 | ||
|
145caee37a | ||
|
2fa7b7ca00 | ||
|
d60fca90f6 | ||
|
4abfa2cf2b | ||
|
ada964e5aa | ||
|
16cf694a77 | ||
|
362b8724fc | ||
|
d06a927085 | ||
|
031faa5923 | ||
|
a2c1e5fd26 | ||
|
ac35c13727 | ||
|
f7b8c7ab8d | ||
|
802250eb71 | ||
|
3fb002c977 | ||
|
98d1d407c3 | ||
|
8821218bfd | ||
|
27b9b413df | ||
|
2b67b0f12e | ||
|
d26d7bba55 | ||
|
0761a60443 | ||
|
217b1a5fac | ||
|
ef98a6f23c | ||
|
c6a6dc6e21 | ||
|
f3b77a7f60 | ||
|
f625c34269 | ||
|
ac5c4acf09 | ||
|
9a3464744f | ||
|
91bdfc4704 | ||
|
6f8aa49d0e | ||
|
be57798eac | ||
|
4855e65b1a | ||
|
a3fe3a1ad8 | ||
|
382a9b6e12 | ||
|
24349953e3 | ||
|
85aba9e36f | ||
|
49010bf5b7 | ||
|
b1c7f309f8 | ||
|
458ddaa167 | ||
|
ab97334cf8 | ||
|
112fdf7ed3 | ||
|
b59ff03abf | ||
|
bdd9f5ae30 | ||
|
abcdbc4de9 | ||
|
1715139494 | ||
|
b862c506e4 | ||
|
4fd4fbfb08 | ||
|
6cb9fda53a | ||
|
4f7a033b9c | ||
|
c537841bc1 | ||
|
7d9a8eaf19 | ||
|
86965ee06d | ||
|
496f64f103 | ||
|
9e0862bc97 | ||
|
6b43ad5575 | ||
|
bf7b2a8cbe | ||
|
7232c89292 | ||
|
bc164ca2f2 | ||
|
ad8429e7fa | ||
|
c268e0105d | ||
|
050137fb3f | ||
|
f2d04c598c | ||
|
49307a3df2 | ||
|
ff9f0bc74a | ||
|
f929f25abd | ||
|
6af0a2574d | ||
|
c61a159eff | ||
|
59bdd03b1e | ||
|
35ea1e78ec | ||
|
7db386b752 | ||
|
e6a68feb0c | ||
|
78b0450d66 | ||
|
bd5fb46e0a | ||
|
cc3ed735f1 | ||
|
3f0c3f1f37 | ||
|
e1ff0a7221 | ||
|
2bf8b4d313 | ||
|
188aa8a50a | ||
|
1538d2094a | ||
|
16eb74e88b | ||
|
3460d445b8 | ||
|
461b65700f | ||
|
e809c7c500 | ||
|
8e0572d5d3 | ||
|
7555051df6 | ||
|
d913be5c0d | ||
|
98b67ad829 | ||
|
0d8e51ff3f | ||
|
223b9bc887 | ||
|
a54fd2f235 | ||
|
88bbb57c66 | ||
|
c9a8e7ff0d | ||
|
9e4e9f29d1 | ||
|
c8ebaf38b6 | ||
|
f8fb36a1f7 | ||
|
bbeeb11502 | ||
|
27c6457c20 | ||
|
02a780f3b0 | ||
|
00858416f9 | ||
|
9b79c83c3d | ||
|
d6ae1ca01c | ||
|
f446411f08 | ||
|
ad3a08f514 | ||
|
f2ab618083 | ||
|
da1218221c | ||
|
c0fa137fed | ||
|
5a63827f22 | ||
|
a739e71df6 | ||
|
6c0b20e5b7 | ||
|
d2a62ebd3d | ||
|
b67d2ebce6 | ||
|
6a273a8eea | ||
|
35d34a787b | ||
|
8fe562e864 | ||
|
34c2ba8faa | ||
|
616e07cd2d | ||
|
f6c24ec92f | ||
|
68945d2f20 | ||
|
977c10524e | ||
|
923cbd3b8c | ||
|
56592fc413 | ||
|
7fdfd89525 | ||
|
7c9cbe7b58 | ||
|
ceeb37f8ec | ||
|
858639bebe | ||
|
a39785d6d9 | ||
|
7b04854b43 | ||
|
20b299c758 | ||
|
3f56da9245 | ||
|
0428b1dd81 | ||
|
95aad49fb4 | ||
|
73be9151b0 | ||
|
95f27824ee | ||
|
c82ceefc8b | ||
|
ea615946f6 | ||
|
84504c9daf | ||
|
6137c1f341 | ||
|
5b3ef53301 | ||
|
8b3eb4e076 | ||
|
9cbe182ff4 | ||
|
b140ebd149 | ||
|
e2f837055e | ||
|
5de41a18f9 | ||
|
02af1c1227 | ||
|
0bb0d16d93 | ||
|
5a9798121c | ||
|
8574b2ec72 | ||
|
5f6a2fffc5 | ||
|
27e06dd4e8 | ||
|
06837d4a56 | ||
|
62cb63aa1d | ||
|
d43dcdf03f | ||
|
a6fcc1ea2a | ||
|
3047214676 | ||
|
115132a188 | ||
|
5e3f1b5435 | ||
|
2e75671d56 | ||
|
f8304406c5 | ||
|
e8d892ebc8 | ||
|
9f37fb23d6 | ||
|
853b797cd9 | ||
|
eb330c3260 | ||
|
109125b583 | ||
|
c06e9bd432 | ||
|
30132e21e8 | ||
|
fbf2eb638e | ||
|
a729b8fa3c | ||
|
de0bca5c51 | ||
|
a028766cf8 | ||
|
8973e66ec5 | ||
|
b0a71b461f | ||
|
9685a4b1bf | ||
|
7c3b2b514a | ||
|
fcac6f8a0f | ||
|
27189ebfbe | ||
|
a1d801ba14 | ||
|
9d047daef5 | ||
|
719858168e | ||
|
01fa2ece6e | ||
|
e7993a4485 | ||
|
b6bf477551 | ||
|
a211f09a99 | ||
|
fe3122adbd | ||
|
0c517acee2 | ||
|
9d31fcce2e | ||
|
5abac36647 | ||
|
60fd092410 | ||
|
877fa1a75a | ||
|
2218fa2b33 | ||
|
6b26cecd17 | ||
|
bc5391d711 | ||
|
3ea2c27e17 | ||
|
17960b2868 | ||
|
22416bf512 | ||
|
a4cb7f13be | ||
|
822709ceeb | ||
|
4dffc879d9 | ||
|
f036057b2b | ||
|
38ab392b91 | ||
|
a45d88ef29 | ||
|
996c57df62 | ||
|
8f69b2449d | ||
|
db7e10cb4d | ||
|
b446fcc929 | ||
|
5cc5375cb5 | ||
|
ebf3766cfb | ||
|
fbaf19e454 | ||
|
a966f82192 | ||
|
210496f760 | ||
|
13adfa5b55 | ||
|
d7e4b52d10 | ||
|
53c8028646 | ||
|
49201f5346 | ||
|
938b5bf275 | ||
|
a98417a878 | ||
|
1bd223eab2 | ||
|
55f1bd1f2d | ||
|
380977bc67 | ||
|
086a998b20 | ||
|
d4f344d247 | ||
|
3cb2b44130 | ||
|
c8cd6de2f2 | ||
|
0221d02ca7 | ||
|
a5947922b6 | ||
|
13f6a692a7 | ||
|
f13befc4d8 | ||
|
f4ba97ebab | ||
|
1bdbbca12f | ||
|
5028f6408a | ||
|
f53cf80221 | ||
|
e052692a57 | ||
|
ab61be26a9 | ||
|
e02b5f1de8 | ||
|
de5ca44d6b | ||
|
9de421b2d2 | ||
|
82abd2e6ce | ||
|
13fb2de964 | ||
|
53de7eab96 | ||
|
e14d3d8d73 | ||
|
c23a777a9f | ||
|
1c9df5ac02 | ||
|
0c43d83494 | ||
|
299c259d50 | ||
|
c993f15bca | ||
|
2d63eb32e1 | ||
|
2ae76ff78b | ||
|
41663e1b08 | ||
|
c3df90c541 | ||
|
ab256e57b1 | ||
|
054df580eb | ||
|
5fecb5f506 | ||
|
44a15d684b | ||
|
f3243f8989 | ||
|
bc459b5ff4 | ||
|
338d5e6f17 | ||
|
340e8c3760 | ||
|
e44cde0600 | ||
|
1b00fe7921 | ||
|
168cc3801a | ||
|
4ec4adf003 | ||
|
a88a2f4a4f | ||
|
a539fd0062 | ||
|
83addf045f | ||
|
00305a8436 | ||
|
799144e64d | ||
|
6bd69e6708 | ||
|
784bc7b0cf | ||
|
ca8f764b8b | ||
|
a63a5fea3c | ||
|
a068040cbf | ||
|
f5d3ae9efb | ||
|
e4377faa67 | ||
|
12ef3e7bf1 | ||
|
3d4adaa444 | ||
|
7d2a87b73e | ||
|
6c08982ca7 | ||
|
f4cea065d8 | ||
|
b651f89865 | ||
|
ae73facd89 | ||
|
72653c6116 | ||
|
a57cd396fa | ||
|
783efeaf0e | ||
|
2c97902f4e | ||
|
2bc05b2576 | ||
|
73bda494d9 | ||
|
e7b44710cc | ||
|
2d76209c8a | ||
|
ddf044d6d3 | ||
|
f220a01a30 | ||
|
8443c01303 | ||
|
f8d0b691ec | ||
|
e0d44f3fa7 | ||
|
a420af75fc | ||
|
6b3f6a46e6 | ||
|
629eed08b6 | ||
|
9ab7176eaf | ||
|
3345142db2 | ||
|
b1ab5d91a4 | ||
|
3ba59da0ab | ||
|
308acff19a | ||
|
de64e38a07 | ||
|
4a22a50f19 | ||
|
997114477c | ||
|
700407ba98 | ||
|
d42d975d9e | ||
|
b6bbc7d228 | ||
|
621f93f75a | ||
|
5ebe7ff1cb | ||
|
d7a4593fcf | ||
|
dc70f9a9cd | ||
|
f6806c1d55 | ||
|
5b42454a55 | ||
|
b24649b6af | ||
|
0838cdfbe7 | ||
|
71c5cdc445 | ||
|
be244f4538 | ||
|
afd01796aa | ||
|
dc691889e3 | ||
|
4b764ccba3 | ||
|
9658e446e5 | ||
|
8f89e0f26e | ||
|
7116532081 | ||
|
b47bef3ef6 | ||
|
3638da7f2d | ||
|
da62e012c2 | ||
|
e718f25c3f | ||
|
f1a0ac099b | ||
|
8c5c02f040 | ||
|
33bd9d0fb8 | ||
|
edb4458031 | ||
|
f332199baa | ||
|
8cda1b5417 | ||
|
45ceba47f3 | ||
|
8a9a77656f | ||
|
064ed81758 | ||
|
0d5930fc3a | ||
|
8601c61cd8 | ||
|
0738b275a5 | ||
|
6a25e42571 | ||
|
81d96888bd | ||
|
c9d7b63f23 | ||
|
4c179d9910 | ||
|
a085b47eac | ||
|
ad994f04fc | ||
|
301e9093bd | ||
|
39a2658a25 | ||
|
d624f13f96 | ||
|
6ac04d6507 | ||
|
cc7ebe2f73 | ||
|
bdb4d584e4 | ||
|
38d502f7f5 | ||
|
e931b535f1 | ||
|
0775a232ce | ||
|
e5463cc564 | ||
|
5554c6e62d | ||
|
96cdb9c23e | ||
|
b75343d3e7 | ||
|
62b93c1ba7 | ||
|
146134a1a7 | ||
|
da5d63ae29 | ||
|
9cfcbc5b32 | ||
|
ee80a4ea60 | ||
|
dc0c634eab | ||
|
168f366efc | ||
|
39d96d9667 | ||
|
47d1fab4bd | ||
|
84756f3092 | ||
|
309c6d1ed0 | ||
|
2bf63ce8aa | ||
|
b2902407d7 | ||
|
1fe38afa95 | ||
|
0200167ce2 | ||
|
0dddbedd70 | ||
|
458728ffdd | ||
|
df71a1e6ee | ||
|
7e35f591d7 | ||
|
b7642394f4 | ||
|
bdd7e9514a | ||
|
f214c0b2cb | ||
|
5ff638f9e7 | ||
|
e92cbf2f50 | ||
|
9d30f2dff3 | ||
|
f01295d936 | ||
|
343a345ed2 | ||
|
2965867516 | ||
|
68887086a6 | ||
|
47b015a2d0 | ||
|
1affeb8e20 | ||
|
b5b8ff165c | ||
|
389211f740 | ||
|
68ed443fa3 | ||
|
9a819fc12c | ||
|
2b10f81326 | ||
|
689180ebe8 | ||
|
1aba139136 | ||
|
e5213eb95a | ||
|
5fb9799807 | ||
|
9241f4df79 | ||
|
d55459cfcd | ||
|
17747f94c8 | ||
|
829f47c5e7 | ||
|
557054cb8b | ||
|
d726b75721 | ||
|
47aede8f67 | ||
|
1557158cd9 | ||
|
de07a6594d | ||
|
07b72f87d7 | ||
|
8f4961613d | ||
|
339e6cd665 | ||
|
1c87c83c45 | ||
|
d70f622a24 | ||
|
9373bd09ed | ||
|
b36f95862a | ||
|
71fad44d23 | ||
|
cfbfeec69b | ||
|
318aa98c98 | ||
|
009cca3c9d | ||
|
f53644ef26 | ||
|
7b15d0d01f | ||
|
7fdddf4d8f | ||
|
a734790bcf | ||
|
9e598cfa70 | ||
|
aca37736c4 | ||
|
a5935e77c9 | ||
|
93ee9a3b58 | ||
|
0b6a1ca1a4 | ||
|
e9127f505a | ||
|
30b839d736 | ||
|
49ad65f449 | ||
|
8b3af9fb47 | ||
|
0c39b06355 | ||
|
73ce79472e | ||
|
9e1eee166b | ||
|
03c7b59df5 | ||
|
1654dffa4d | ||
|
26a4daad33 | ||
|
c666366673 | ||
|
d5eb110626 | ||
|
04a3712bc7 | ||
|
39f508bbdf | ||
|
0a6008ddc0 | ||
|
9ba1dc614c | ||
|
31123b0573 | ||
|
aaa860de33 | ||
|
5efe1907ad | ||
|
d0c19d09a3 | ||
|
e6268f319d | ||
|
42e714ee7d | ||
|
4bee48e9e5 | ||
|
c71c182834 | ||
|
9fc354af43 | ||
|
bc8833ce8e | ||
|
8524c32b93 | ||
|
872df975f5 | ||
|
36c0d995af | ||
|
1c31453ba0 | ||
|
2e2f3eee04 | ||
|
b3e6d1c803 | ||
|
829f085340 | ||
|
6986232290 | ||
|
b5ea66359c | ||
|
730cb82eb7 | ||
|
c4f99d8c77 | ||
|
218c8ea398 | ||
|
47869ccad5 | ||
|
bde256608b | ||
|
bc00c1be82 | ||
|
781ec1ef67 | ||
|
c79a6df400 | ||
|
28e3177e60 | ||
|
5c29abd724 | ||
|
9803925bbb | ||
|
47b1affc56 | ||
|
b2a2234d5c | ||
|
1f1f9cd7e6 | ||
|
3903b718cb | ||
|
c3c2c7935d | ||
|
09a511acf8 | ||
|
b3f7aaa580 | ||
|
286036a936 | ||
|
11889b57fe | ||
|
9b3dffaab9 | ||
|
bb869b5263 | ||
|
3528d38be1 | ||
|
17ad11212e | ||
|
50056228b6 | ||
|
946750a189 | ||
|
7ce69fb6f8 | ||
|
b87df479a2 | ||
|
5458248403 | ||
|
9b4121053c | ||
|
746b608d10 | ||
|
9d7da873c4 | ||
|
70c400da7f | ||
|
2a5cfe712f | ||
|
533a045622 | ||
|
93aa1791c9 | ||
|
06c76cc096 | ||
|
04df0e5f51 | ||
|
f99e029567 | ||
|
71ee9aee21 | ||
|
d9ea95c67e | ||
|
af7f42ac60 | ||
|
15e59a1778 | ||
|
22962d55e1 | ||
|
70c7927006 | ||
|
89c3aa38a6 | ||
|
2eb330b8a8 | ||
|
383c0031a5 | ||
|
06f20281a5 | ||
|
a40f1a453c | ||
|
5d9f354209 | ||
|
c3bd8ebf57 | ||
|
c9c615c8cb | ||
|
47f491039c | ||
|
dc5c35a9ed | ||
|
c636186321 | ||
|
aafc3dd060 | ||
|
38469611a4 | ||
|
59a8bd8c97 | ||
|
50cfd3c9b5 | ||
|
5d08d53c27 | ||
|
4f6f99146c | ||
|
32388d070d | ||
|
d9f8bf38c6 | ||
|
4e2b74af75 | ||
|
c2c28cebf5 | ||
|
24141b1a4b | ||
|
c85e50d73d | ||
|
444156766a | ||
|
308824d0b1 | ||
|
c3ed962837 | ||
|
2c13303d89 | ||
|
1304b94b61 | ||
|
8ca677c271 | ||
|
7c17412106 | ||
|
26207f762b | ||
|
8db70dbb0c | ||
|
1b6924a104 | ||
|
c5a30a8a79 | ||
|
56c9c24dc6 | ||
|
9ad629841b | ||
|
78433bdae9 | ||
|
5f44212faa | ||
|
df517b6b36 | ||
|
6afe9b6f4f | ||
|
1d79ac232f | ||
|
0a64959973 | ||
|
1e4b058681 | ||
|
3c5d06a2de |
2
.github/FUNDING.yml
vendored
Normal file
2
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
open_collective: nonebot
|
||||
custom: ["https://afdian.net/@nonebot"]
|
38
.github/ISSUE_TEMPLATE/bug-report.md
vendored
Normal file
38
.github/ISSUE_TEMPLATE/bug-report.md
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a bug report to help us improve
|
||||
title: 'Bug: Something went wrong'
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**描述问题:**
|
||||
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**如何复现?**
|
||||
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**期望的结果**
|
||||
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**环境信息:**
|
||||
|
||||
- OS: [e.g. Linux]
|
||||
- Python Version: [e.g. 3.8]
|
||||
- Nonebot Version: [e.g. 2.0.0]
|
||||
|
||||
**协议端信息:**
|
||||
|
||||
- 协议端: [e.g. go-cqhttp]
|
||||
- 协议端版本: [e.g. 1.0.0]
|
||||
|
||||
**截图或日志**
|
||||
|
||||
If applicable, add screenshots to help explain your problem.
|
14
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
14
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Question
|
||||
url: https://discussions.nonebot.dev/
|
||||
about: Ask questions about nonebot
|
||||
- name: Plugin Publish
|
||||
url: https://v2.nonebot.dev/store.html
|
||||
about: Publish your plugin to nonebot homepage and nb-cli
|
||||
- name: Adapter Publish
|
||||
url: https://v2.nonebot.dev/store.html
|
||||
about: Publish your adapter to nonebot homepage and nb-cli
|
||||
- name: Bot Publish
|
||||
url: https://v2.nonebot.dev/store.html
|
||||
about: Publish your bot to nonebot homepage and nb-cli
|
17
.github/ISSUE_TEMPLATE/document.md
vendored
Normal file
17
.github/ISSUE_TEMPLATE/document.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
name: Document improvement
|
||||
about: Feedback on documentation, including errors and ideas
|
||||
title: 'Docs: some description'
|
||||
labels: documentation
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**描述问题或主题:**
|
||||
|
||||
|
||||
**需做出的修改:**
|
||||
|
||||
* [ ] 一些修改
|
||||
* [ ] 一些修改
|
||||
* [ ] 一些修改
|
16
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
16
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: 'Feature: Something you want'
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**是否在使用中遇到某些问题而需要新的特性?请描述:**
|
||||
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**描述你所需要的特性:**
|
||||
|
||||
A clear and concise description of what you want to happen.
|
42
.github/release-drafter.yml
vendored
Normal file
42
.github/release-drafter.yml
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
name-template: 'Release v$RESOLVED_VERSION 🌈'
|
||||
tag-template: 'v$RESOLVED_VERSION'
|
||||
categories:
|
||||
- title: '💥 Breaking Changes'
|
||||
labels:
|
||||
- 'Breaking'
|
||||
- title: '🚀 Features'
|
||||
labels:
|
||||
- 'feature'
|
||||
- 'enhancement'
|
||||
- title: '🐛 Bug Fixes'
|
||||
labels:
|
||||
- 'fix'
|
||||
- 'bugfix'
|
||||
- 'bug'
|
||||
- title: '🍻 Plugin Publish'
|
||||
label: 'Plugin'
|
||||
- title: '🍻 Bot Publish'
|
||||
label: 'Bot'
|
||||
- title: '🍻 Adapter Publish'
|
||||
label: 'Adapter'
|
||||
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
|
||||
change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks.
|
||||
version-resolver:
|
||||
major:
|
||||
labels:
|
||||
- 'major'
|
||||
minor:
|
||||
labels:
|
||||
- 'minor'
|
||||
patch:
|
||||
labels:
|
||||
- 'patch'
|
||||
default: patch
|
||||
template: |
|
||||
## Documentation
|
||||
|
||||
See: https://v2.nonebot.dev
|
||||
|
||||
## 💫 Changes
|
||||
|
||||
$CHANGES
|
41
.github/workflows/api_docs.yml
vendored
41
.github/workflows/api_docs.yml
vendored
@@ -1,41 +0,0 @@
|
||||
name: Build API Doc
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [ opened, synchronize, reopened ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.8
|
||||
architecture: "x64"
|
||||
|
||||
- name: Install Dependences
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install poetry
|
||||
poetry install
|
||||
|
||||
- name: Build Doc
|
||||
run: poetry run sphinx-build -M markdown ./docs_build ./build
|
||||
|
||||
- name: Copy Files
|
||||
run: cp -r ./build/markdown/* ./docs/api/
|
||||
|
||||
- run: |
|
||||
git config user.name nonebot
|
||||
git config user.email nonebot@nonebot.dev
|
||||
git add .
|
||||
git diff-index --quiet HEAD || git commit -m ":memo: update api docs"
|
||||
git remote -vv
|
||||
git remote add target ${{github.event.pull_request.head.repo.clone_url}}
|
||||
git push target HEAD:${{github.event.pull_request.head.ref}}
|
39
.github/workflows/codecov.yml
vendored
Normal file
39
.github/workflows/codecov.yml
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
name: Code Coverage
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
name: Run Pytest and Upload Coverage
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set up Python environment
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: "3.9"
|
||||
architecture: "x64"
|
||||
|
||||
- uses: Gr1N/setup-poetry@v7
|
||||
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cache/pypoetry/virtualenvs
|
||||
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: poetry install -E all
|
||||
|
||||
- name: Run Pytest
|
||||
run: |
|
||||
cd tests/
|
||||
poetry run pytest --cov-report xml
|
||||
|
||||
- name: Upload coverage report
|
||||
uses: codecov/codecov-action@v2
|
||||
with:
|
||||
files: ./tests/coverage.xml
|
||||
flags: unittests
|
30
.github/workflows/publish-bot.yml
vendored
Normal file
30
.github/workflows/publish-bot.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
name: NoneBot2 Publish Bot
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
issues:
|
||||
types: [opened, reopened, edited]
|
||||
pull_request:
|
||||
types: [closed]
|
||||
|
||||
jobs:
|
||||
publish_bot:
|
||||
runs-on: ubuntu-latest
|
||||
name: nonebot2 publish bot
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: NoneBot2 Publish Bot
|
||||
uses: nonebot/nonebot2-publish-bot@main
|
||||
with:
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
config: >
|
||||
{
|
||||
"base": "master",
|
||||
"plugin_path": "website/static/plugins.json",
|
||||
"bot_path": "website/static/bots.json",
|
||||
"adapter_path": "website/static/adapters.json"
|
||||
}
|
36
.github/workflows/release-github.yml
vendored
Normal file
36
.github/workflows/release-github.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
name: Release Drafter
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
tags:
|
||||
- v*
|
||||
|
||||
jobs:
|
||||
update-release-draft:
|
||||
if: github.ref == 'refs/heads/master'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: release-drafter/release-drafter@v5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
release:
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- run: |
|
||||
echo "TAG_NAME=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
|
||||
|
||||
- uses: release-drafter/release-drafter@v5
|
||||
with:
|
||||
name: Release ${{ env.TAG_NAME }} 🌈
|
||||
tag: ${{ env.TAG_NAME }}
|
||||
publish: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
58
.github/workflows/release-plugin-docs.yml
vendored
Normal file
58
.github/workflows/release-plugin-docs.yml
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
name: Release Nonebot Plugin Docs
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- v*
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: "3.9"
|
||||
architecture: "x64"
|
||||
|
||||
- uses: Gr1N/setup-poetry@v7
|
||||
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cache/pypoetry/virtualenvs
|
||||
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: "16"
|
||||
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
|
||||
- name: Cache Packages
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
|
||||
- name: Install and build
|
||||
run: |
|
||||
poetry install -E all
|
||||
poetry run sphinx-build -M markdown ./docs_build ./build
|
||||
cp -r ./build/markdown/* ./website/docs/api/
|
||||
yarn install
|
||||
yarn prettier
|
||||
yarn build:plugin --out-dir ../packages/nonebot-plugin-docs/nonebot_plugin_docs/dist
|
||||
|
||||
- name: Publish Package
|
||||
run: |
|
||||
export NONEBOT_VERSION=`poetry version -s`
|
||||
cd packages/nonebot-plugin-docs/
|
||||
poetry version $NONEBOT_VERSION
|
||||
poetry build
|
||||
poetry publish -u ${{secrets.PYPI_USERNAME}} -p ${{secrets.PYPI_PASSWORD}}
|
69
.github/workflows/release.yml
vendored
Normal file
69
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: master
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: "3.9"
|
||||
architecture: "x64"
|
||||
|
||||
- uses: Gr1N/setup-poetry@v7
|
||||
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cache/pypoetry/virtualenvs
|
||||
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: "16"
|
||||
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
|
||||
- name: Cache Packages
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
|
||||
- name: Set up dependencies
|
||||
run: |
|
||||
poetry install -E all
|
||||
|
||||
- name: Build Doc
|
||||
run: poetry run sphinx-build -M markdown ./docs_build ./build
|
||||
|
||||
- name: Copy Files
|
||||
run: cp -r ./build/markdown/* ./website/docs/api/
|
||||
|
||||
- name: Archive Files
|
||||
run: |
|
||||
yarn install
|
||||
yarn prettier
|
||||
yarn archive $(poetry version -s)
|
||||
|
||||
- name: Push Tag and Release to PyPI
|
||||
run: |
|
||||
git config user.name github-actions
|
||||
git config user.email github-actions@github.com
|
||||
git add .
|
||||
git commit -m ":bookmark: Release $(poetry version -s)"
|
||||
git tag v$(poetry version -s)
|
||||
git push && git push --tags
|
||||
poetry build
|
||||
poetry publish -u ${{secrets.PYPI_USERNAME}} -p ${{secrets.PYPI_PASSWORD}}
|
83
.github/workflows/website-deploy.yml
vendored
Normal file
83
.github/workflows/website-deploy.yml
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
name: Build Upload Site
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request_target:
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
if: github.event_name == 'push'
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
if: github.event_name != 'push'
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.8
|
||||
architecture: "x64"
|
||||
|
||||
- uses: Gr1N/setup-poetry@v7
|
||||
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cache/pypoetry/virtualenvs
|
||||
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: "16"
|
||||
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
|
||||
- name: Cache Packages
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
|
||||
- name: Install and build
|
||||
run: |
|
||||
poetry install -E all
|
||||
poetry run sphinx-build -M markdown ./docs_build ./build
|
||||
cp -r ./build/markdown/* ./website/docs/api/
|
||||
yarn install
|
||||
yarn prettier
|
||||
yarn build
|
||||
|
||||
- name: Get Branch Name
|
||||
run: echo "BRANCH_NAME=$(echo ${GITHUB_REF#refs/heads/})" >> $GITHUB_ENV
|
||||
|
||||
- name: Get Deploy Name
|
||||
if: github.event_name == 'push'
|
||||
run: |
|
||||
echo "DEPLOY_NAME=${{ env.BRANCH_NAME }}" >> $GITHUB_ENV
|
||||
echo "PRODUCTION=${{ env.BRANCH_NAME == 'master' }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Get Deploy Name
|
||||
if: github.event_name != 'push'
|
||||
run: |
|
||||
echo "DEPLOY_NAME=deploy-preview-${{ github.event.number }}" >> $GITHUB_ENV
|
||||
echo "PRODUCTION=false" >> $GITHUB_ENV
|
||||
|
||||
- name: Deploy to Netlify
|
||||
uses: nwtgck/actions-netlify@v1
|
||||
with:
|
||||
publish-dir: './website/build'
|
||||
production-deploy: ${{ env.PRODUCTION }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
deploy-message: 'Deploy ${{ env.DEPLOY_NAME }}@${{ github.sha }}'
|
||||
enable-commit-comment: false
|
||||
alias: ${{ env.DEPLOY_NAME }}
|
||||
env:
|
||||
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
||||
NETLIFY_SITE_ID: ${{ secrets.SITE_ID }}
|
439
.gitignore
vendored
439
.gitignore
vendored
@@ -1,5 +1,296 @@
|
||||
# ----- Python -----
|
||||
# ----- Project -----
|
||||
|
||||
.idea
|
||||
.vscode
|
||||
dev
|
||||
docs_build/_build
|
||||
!tests/.env
|
||||
.docusaurus
|
||||
website/docs/api/**/*.md
|
||||
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/python,node,visualstudiocode,jetbrains,macos,windows,linux
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=python,node,visualstudiocode,jetbrains,macos,windows,linux
|
||||
|
||||
### JetBrains ###
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
|
||||
# AWS User-specific
|
||||
.idea/**/aws.xml
|
||||
|
||||
# Generated files
|
||||
.idea/**/contentModel.xml
|
||||
|
||||
# Sensitive or high-churn files
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
|
||||
# Gradle
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
# .idea/artifacts
|
||||
# .idea/compiler.xml
|
||||
# .idea/jarRepositories.xml
|
||||
# .idea/modules.xml
|
||||
# .idea/*.iml
|
||||
# .idea/modules
|
||||
# *.iml
|
||||
# *.ipr
|
||||
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
# File-based project format
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
### JetBrains Patch ###
|
||||
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
|
||||
|
||||
# *.iml
|
||||
# modules.xml
|
||||
# .idea/misc.xml
|
||||
# *.ipr
|
||||
|
||||
# Sonarlint plugin
|
||||
# https://plugins.jetbrains.com/plugin/7973-sonarlint
|
||||
.idea/**/sonarlint/
|
||||
|
||||
# SonarQube Plugin
|
||||
# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
|
||||
.idea/**/sonarIssues.xml
|
||||
|
||||
# Markdown Navigator plugin
|
||||
# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
|
||||
.idea/**/markdown-navigator.xml
|
||||
.idea/**/markdown-navigator-enh.xml
|
||||
.idea/**/markdown-navigator/
|
||||
|
||||
# Cache file creation bug
|
||||
# See https://youtrack.jetbrains.com/issue/JBR-2257
|
||||
.idea/$CACHE_FILE$
|
||||
|
||||
# CodeStream plugin
|
||||
# https://plugins.jetbrains.com/plugin/12206-codestream
|
||||
.idea/codestream.xml
|
||||
|
||||
### Linux ###
|
||||
*~
|
||||
|
||||
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||
.fuse_hidden*
|
||||
|
||||
# KDE directory preferences
|
||||
.directory
|
||||
|
||||
# Linux trash folder which might appear on any partition or disk
|
||||
.Trash-*
|
||||
|
||||
# .nfs files are created when an open file is removed but is still being accessed
|
||||
.nfs*
|
||||
|
||||
### macOS ###
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
### Node ###
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
.env.production
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
### Node Patch ###
|
||||
# Serverless Webpack directories
|
||||
.webpack/
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# SvelteKit build / generate output
|
||||
.svelte-kit
|
||||
|
||||
### Python ###
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
@@ -22,6 +313,7 @@ parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
@@ -40,23 +332,25 @@ pip-delete-this-directory.txt
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
@@ -69,22 +363,39 @@ instance/
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# celery beat schedule file
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
@@ -104,87 +415,61 @@ venv.bak/
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# ----- Node -----
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
### VisualStudioCode ###
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
*.code-workspace
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
### VisualStudioCode Patch ###
|
||||
# Ignore all local history of files
|
||||
.history
|
||||
.ionide
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
# Support for Project snippet scope
|
||||
!.vscode/*.code-snippets
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
### Windows ###
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
Thumbs.db:encryptable
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
# Dump file
|
||||
*.stackdump
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
# Folder config file
|
||||
[Dd]esktop.ini
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# next.js build output
|
||||
.next
|
||||
|
||||
# nuxt.js build output
|
||||
.nuxt
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless
|
||||
|
||||
# ----- Project -----
|
||||
|
||||
.idea
|
||||
.vscode
|
||||
dev
|
||||
docs_build/_build
|
||||
!tests/.env
|
||||
# End of https://www.toptal.com/developers/gitignore/api/python,node,visualstudiocode,jetbrains,macos,windows,linux
|
||||
|
1
.prettierignore
Normal file
1
.prettierignore
Normal file
@@ -0,0 +1 @@
|
||||
.github/**/*.md
|
9
.prettierrc
Normal file
9
.prettierrc
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"endOfLine": "lf",
|
||||
"arrowParens": "always",
|
||||
"singleQuote": false,
|
||||
"trailingComma": "es5",
|
||||
"semi": true
|
||||
}
|
@@ -1,2 +0,0 @@
|
||||
[style]
|
||||
based_on_style = google
|
3
CHANGELOG.md
Normal file
3
CHANGELOG.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Changelog
|
||||
|
||||
See [changelog.md](./website/src/pages/changelog.md) or <https://v2.nonebot.dev/changelog>
|
4
LICENSE
4
LICENSE
@@ -1,5 +1,5 @@
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2018 Richard Chien
|
||||
Copyright (c) 2020 NoneBot Team
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
@@ -16,4 +16,4 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
181
README.md
181
README.md
@@ -1,37 +1,180 @@
|
||||
<div align=center>
|
||||
<img src="./docs/.vuepress/public/logo.png" width="200" height="200">
|
||||
<!-- markdownlint-disable MD033 MD041 -->
|
||||
<p align="center">
|
||||
<a href="https://v2.nonebot.dev/"><img src="https://v2.nonebot.dev/logo.png" width="200" height="200" alt="nonebot"></a>
|
||||
</p>
|
||||
|
||||
<div align="center">
|
||||
|
||||
# NoneBot
|
||||
|
||||
[](LICENSE)
|
||||
[](https://pypi.python.org/pypi/nonebot2)
|
||||

|
||||

|
||||
[](https://jq.qq.com/?_wv=1027&k=5OFifDh)
|
||||
[](https://t.me/cqhttp)
|
||||
[](https://jq.qq.com/?_wv=1027&k=5Nl0zhE)
|
||||
[](https://t.me/cqhttp_release)
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- markdownlint-disable-next-line MD036 -->
|
||||
_✨ 跨平台 Python 异步机器人框架 ✨_
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
</div>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://raw.githubusercontent.com/nonebot/nonebot2/master/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/nonebot/nonebot2" alt="license">
|
||||
</a>
|
||||
<a href="https://pypi.python.org/pypi/nonebot2">
|
||||
<img src="https://img.shields.io/pypi/v/nonebot2" alt="pypi">
|
||||
</a>
|
||||
<img src="https://img.shields.io/badge/python-3.7.3+-blue" alt="python">
|
||||
<a href="https://codecov.io/gh/nonebot/nonebot2">
|
||||
<img src="https://codecov.io/gh/nonebot/nonebot2/branch/master/graph/badge.svg?token=2P0G0VS7N4"/>
|
||||
</a>
|
||||
<br />
|
||||
<a href="https://onebot.dev/">
|
||||
<img src="https://img.shields.io/badge/OneBot-v11-black?style=social&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABABAMAAABYR2ztAAAAIVBMVEUAAAAAAAADAwMHBwceHh4UFBQNDQ0ZGRkoKCgvLy8iIiLWSdWYAAAAAXRSTlMAQObYZgAAAQVJREFUSMftlM0RgjAQhV+0ATYK6i1Xb+iMd0qgBEqgBEuwBOxU2QDKsjvojQPvkJ/ZL5sXkgWrFirK4MibYUdE3OR2nEpuKz1/q8CdNxNQgthZCXYVLjyoDQftaKuniHHWRnPh2GCUetR2/9HsMAXyUT4/3UHwtQT2AggSCGKeSAsFnxBIOuAggdh3AKTL7pDuCyABcMb0aQP7aM4AnAbc/wHwA5D2wDHTTe56gIIOUA/4YYV2e1sg713PXdZJAuncdZMAGkAukU9OAn40O849+0ornPwT93rphWF0mgAbauUrEOthlX8Zu7P5A6kZyKCJy75hhw1Mgr9RAUvX7A3csGqZegEdniCx30c3agAAAABJRU5ErkJggg==" alt="cqhttp">
|
||||
</a>
|
||||
<a href="http://github.com/mamoe/mirai">
|
||||
<img src="https://img.shields.io/badge/mirai-HTTP-lightgrey?style=social">
|
||||
</a>
|
||||
<a href="https://ding-doc.dingtalk.com/document#/org-dev-guide/elzz1p">
|
||||
<img src="https://img.shields.io/badge/%E9%92%89%E9%92%89-Bot-lightgrey?style=social&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAnFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4jUzeAAAAM3RSTlMAQKSRaA+/f0YyFevh29R3cyklIfrlyrGsn41tVUs48c/HqJm9uZdhX1otGwkF9IN8V1CX0Q+IAAABY0lEQVRYw+3V2W7CMBAF0JuNQAhhX9OEfYdu9///rUVWpagE27Ef2gfO+0zGozsKnv6bMGzAhkNytIe5gDdzrwtTCwrbI8x4/NF668NAxgI3Q3UtFi3TyPwNQtPLUUmDd8YfqGLNe4v22XwEYb5zoOuF5baHq2UHtsKe5ivWfGAwrWu2mC34QM0PoCAuqZdOmiwV+5BLyMRtZ7dTSEcs48rzWfzwptMLyzpApka1SJ5FtR4kfCqNIBPEVDmqoqgwUYY5plQOlf6UEjNoOPnuKB6wzDyCrks///TDza8+PnR109WQdxLo8RKWq0PPnuXG0OXKQ6wWLFnCg75uYYbhmMIVVdQ709q33aHbGIj6Duz+2k1HQFX9VwqmY8xYsEJll2ahvhWgsjYLHFRXvIi2Qb0jzMQCzC3FAoydxCma88UCzE3JCWwkjCNYyMUCzHX4DiuTMawEwwhW6hnshPhjZzzJfAH0YacpbmRd7QAAAABJRU5ErkJggg==" alt="ding">
|
||||
</a>
|
||||
<a href="https://core.telegram.org/bots/api">
|
||||
<img src="https://img.shields.io/badge/telegram-Bot-lightgrey?style=social&logo=telegram">
|
||||
</a>
|
||||
<a href="https://open.feishu.cn/document/home/index">
|
||||
<img src="https://img.shields.io/badge/%E9%A3%9E%E4%B9%A6-Bot-lightgrey?style=social&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAk1BMVEX///8zMzNJSUlSUlJcXFxtbW0zMzNLS0szMzMzMzNBQUGVlZUzMzM1NTU0NDQzMzMzMzM0NDQ0NDQ0NDQ3NzdDQ0M0NDQ2NjY4ODg9PT0zMzM0NDQ5OTk7OzszMzM0NDQ3NzczMzM0NDQ0NDQ0NDQ0NDQ3Nzc2NjY4ODg2NjY7Ozs0NDQ6Ojo6Ojo3Nzc4ODgzMzNGdMWJAAAAMHRSTlMD6h0TDgr8GNf0KQbvhLT45KKTmm4jwHVJLdLFQzbcjFTgzsq7rl58T2kyqD46Y1riMDRhAAAFr0lEQVR42uzZWXKiUACF4YMyqKAQhyjOc7STmLP/1bVlLukESIJ3sLGKbwFU/Q8HuIBKpVKpVCqVSqVSqVQqlUqlUvmNM10Mcfda/U6TPdw3e9lb8ayLO+bPniYu+amjNcPd8U7PFhML0RE5uCvnaY/5SVt0WFvckcu0vxjiYmDxbu5cl2mn9UVHRMa4B2LaP3RYKD1vL6adccRFLSLL/izxxbRz7UXHimdLlFdq2mlvnztYRznZh96cP3G/dkxQRrOnR5c/c5eiQ+S2UTbe/sHir9zD1w6+okz8aXvMItyRqE46ApSHmHYRYdLRoPCMcrAP3TkLC6fpDp5QAn/EtItqij3UG/zgQZH5aWc7ZqJjzA9jKFGf9ppXC3I6uMB/Mzh2mpQQ/Mnp4BSy1Kctx4pFx5qfhA4kqE87pCyrldfBDm6sLqat2mGnttXHDfkvYtryooHo2PCrFm5lcNw1qWr1XUeEm7BH3QYVRJNGcOmoietNmNKDWeKFnCo6b3Wc1drW/NsOLpFRqmmT4xgfPFw42Q7XhkFi2kq2DtKcR2Y8wpTacRdQ3aZYB59ggiOmrS6sFevgDNr9GW6pzRAZdsQsC3rV3x4i6uQha8+sB2h9am9c6rVBDj9ixr5k007rIs+CGV65pl3wXjRi2hrKYjFtM/rI02JaW3XaPYtGtZHHY9qL0lN7QuO2yBMzpenLTvtkZNos+AY1ZcpObtoLtWmrj6TNlCOuJqZ9M3PkaDBlIBHCmwpHyHpjSgMS2ryhcIqsmsWULmR0eTPhK7LsMdMOKHdJM+nw8E+8ZoYDOT3eRDDDuz6HNt7VeszaQtYDJch+38WRZ51TDO+0Y54hylzy0XHib2JI83c0zIoLd1hAeUus1jenQe2HQ79Dg6wB3i1d/uoNpS2JrulgHWqcRxqySjoObrFjfUlLVrVrOtiGMmdCA+ZJx8hlEa9QZ2+oXcNLOkIWEUAHe22sYxqykGdoUV//5w6eoKlkTI3Gdbx7CVmQB10lDWqzSTpemyyoAW28ubYO++oOLqBPbUUtJknHrMnCRihdyaOTdAQsLHSgtSTS2BEHLK4DvQYWFW2lOtiHZi3Fko6fXCjgNVooV0nHl7tMBP1aAaXtJDvYgwGxdMmzLzu1JUyYNSU7IAwiiZ8OJrxKlTzI38QnMORFoqSn8Fh9gikvIa/UVejgDMZMQ9mOOa8WwKCRyysslF6hn2HSwZX4+ew1KGEPCSZKhoqHMw9mLd1rO8aUMYZpexbRV/2AsYBxy7/t3NtuglAQheFR6wEPVEQtaq1WxQNqnfd/urY08QJFYHZS15D9vcHckMzOz/QWA9/3jqHrbmbr1bT10a90ncQcoiclgKY/Vq81q6P2JJqfI+NHPqdDSMRzsEtIXmYGcQcQk2fwKgHxTCIVJGMWwTu6sWGxPSFx+QpkOfz3QcYEJWQhtGsbR5aKCIrHInjXNsSDeITFZ6ELYZEMAnltY8AyawKz4KJAr21IBzkRmB6LOIRGOEhIaHYsciA0uxIshwa/DLQIzrAEy2HswBIBwck9yNOvbWT4YgHEU4zbEiyHsQsXhnmKccmxp2cbxvb8CyDbMBXwD4hsw1BQguUw9s4Mk20YOTFQtmHiDJVtGJhjZRtyEVi2ITbhnLBOMd5qOvqXwz9RFy3bkJpU0LINeTCsJdvIztHVZhsJo77SbOPG6FNltpFQqMxsE7hmS+9ymJxE7XKYUGupyzZS1Kbaso00tbWybONBTadyObyjPlaVbTycRFO28Uh9oyjbEJ/E2JImnVDXy1y6zpHvW5E2npJsI5unI9vIwVe3HKYZaMg2clkoyDby6Wl5mcv0Bp9t5DVEzzZyG4JnG/kdsLONArbQ2UYRlwZwtlHIsoGbbRSdRNtymGbf0LYcpgleQbMNwdUCbcthmrP2j++VjqdSy7Isy7Isy4LxDTcBnqEPd5jdAAAAAElFTkSuQmCC" alt="feishu">
|
||||
</a>
|
||||
<a href="https://bot.q.qq.com/wiki/">
|
||||
<img src="https://img.shields.io/badge/QQ%E9%A2%91%E9%81%93-Bot-lightgrey?style=social&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAC+lBMVEUAAAApRHRAbvYyVI4dMlsNGjcvTH5anN0/a5xdo+Vdpvpms/dMfvdcoPZjr/hJfu5krvA9Z+8/a+M9adxQjNdYmdVAbdU4XtRRjcxFd8wyVbM+aZowUJwpRJlZneRIevU5YORWl+1fqOZVle9ZnOpEdOk/aelepus/a+NQiuVKgeQ6YeRQi905X91EdtxAbthZnNlRjdk5YdpQjuhLgehhquc7Y+c6Y8k3XctWlcs0V8tJfMMzVsM9aMJVksdHebVKgLQyVJknP5REdKD///9irv9Ccf5EdP9GfP9jsf7+/f5SkP9mtf9GeP/+/vxJfv5Ukv9Ng/9boP9Gef1ls/9Ulf9Wl//+//5KgP9Nhv9dpP9Oiv9Tk/5Abv9Lg/9Fdv9NiP7///5Qj/7+/fxfpv9Nh/xhq/9QjP9Wm/79//1co/9ir/5fqf5bov9Qi//8/f1XmP1Wl/1ksv/7/v38/vv9/vlgqv9Znf9IfPzZ5fdeqP9nt/5anv5Xmf9Uk/1anvxpuf73/P34+/tot/9hrf1anvpMhvpSjv1pt/9ZnP1aofxTkfxNivza5/dOhPf+//1Ri/z+//vz+fvw9/tIf/v6/fpdofrI2PlYmfnF3Pe0y/Pm7/jW4/e0zvRapPxXlfpTkvpGevri7ffS3vVMiP5XnvxXnPtQivn3/Ph0r/dgpPZ1qfXi6/S9z/NYmf/z+v5Yn/7L2vlfmflUk/hXi/dRgvSw0fGnu+1dqP3t9Pthq/vA1vjc6vfU4vd4sfdepPdsn/dam/fU5fawzfRjjfRhi/NJhP0/a/y80fhTjfhrrfeXvvZuk/WyyPR9rvSqz/OcwfOmv/OSuPO0yfKguPCWr/BPi+9MheRKgv1gsPzq9PpgpvpVjvrN2/jG1vdonvbA0PSrx/OtxPCkxPDp8PvN4ftnuPuCufloqPiex/a3z/WPuvWQqvR2mfRplvReivSOqvOKufKGufKCrPKBoPJzlfFjr+88Ze6ftux8nOxxq/SGr/CFr/Cvx+3R19+QAAAARHRSTlMAEP4ZEwUEvC3S/v7+/Pv08PDXvJqampqSgEtJLS3f/Pz4+O/n5+bl4tTU1Lq6ure2trGdnZ2dlI6Afl5eXldMS0lJLRAR2gcAAAewSURBVFjDlZcFfBJRHMdvdnd3d3cn1qk3h4Et7EQ965h3KKgTQUGdOgYMHII6a5vO2d3d3d3d3X4+/t974A51xvfDu7vfP348HsdxR6VAulaN6lUu8SHVgQOpPpSoXK9Rq3TUf5CmSdWcB/oFcCBn1SZp/rG9aP6c/X5LzvxF/6W9Vqq2KZKq1t8sgvKT9pQt8gf9qb9QOVLWjux+K8oVSrE9bYNU7f6BVA3SpjD93O3+kdy//Ripcw34QefOnaViwM8iV+rf9Ffo7Kdr166du87vSgQGZGcIJocq/OIQlAv1EbAHDL/0hXzOhFxBP61f7vbJdJ0PFfN1RBB0MIPAUO7Alazvz+l0WY4+Pbthw4az66QG63Do6dEsuh+W9QO+//moVRet071L8phomUzBGPcGBwe3hxdmn5FVyGS0yZP0TodpHzy/kGQBygYjonUvbtpFraDwGUjYZ2JRVNSKK26+0EXjWNnkZciH26OjPy3gOZ5nVVCq+p0BzfK8wC/4FB2MLfL5+4sU7wkER7/dhN6aYxia0zKmvT0l7DUxHE1zHMcoVLJNb6ODUbB4EYpQHddcPHpXK5OpWNHp8CxbtmzmPqnBvpnLAIeTQdPT3j16EUer+yaQpT8i8pqAVi9h4cu1kZGR69bt7y9h/7p1EFz7cmEC+iTiwkgczUKmkC8ECkIs54wiI4j2j5EXQwj9QyCBNgCRIZbIj3ZRYET+nCVkP4TwKqTJHoJTXlbFscZzlv6WXr1CkpGKXhb0PozVynoj1SiTHV3lmvYC1JZnCQzNOG9a1BY1aAlKqbBYLEm8jWYSnpGypmBQTQ0sUp9iVCqr/bl60SK1UqlchIIzYCABB/BCIRR/breqVMwp9SIlUA2u39mVCPUWBlZQHz8DiT591t5euPD2WiUR6rXfiAKhnBHvhXVkrs9AGWX2dFTLGX0AZfxCTiaTHYwChTjl1LL8HZ+YccvJa52nfCL+IHyT3Lb4kVi1pAqOBPqMjPfSYHBmZBQSI6Nm0TTDXicCFCsy9HWfiDqGDPTxIzEFqTqDMVF6BTIYHEXUKhDMrMGEKddstIr2qajQYzT6sIeIrENVCsVc1VuRQeiU0FAYU4gBEkhfY5CBT4TCDJABkZWoCx0xxGB26BSspqyiFSowwAKUSNvoWUQQA1p/NRTLC9R5El+jZ5BBR9Qzffr0VbTICrNiQSC9yskKrN9g+hkoVOljp2N5njrUBdExlhj07UI4qGVZ7ePpREw/KLJa5xxfqu9sBRjMjCXJQ5SvaI3ehg0mELlz94oVu3ei3IQJE2J3eu0rdt/AAvAZoEMwp2L7Iias0aOlAYO+hHmrV89De5KVqAndicEaUhlLremOCJuHDeZ0D+v+V4jBPFK5hjrfA+E3CAvr8RfCwvwGWJ6nLmgQYTF6Gr4cZACCELN6Z+Kbr1/eJO5cHaOBBAyNpkeYZg86kWbGgAAuUBXDw8OXh4fH6BlkoNGgY43mxumkbR6HySiIomBKcHi2JZ2+odHELIdSzR5YbevMmHBMRar2EEyMXgXxOcvD4Viza88mnuNYhmNpDMMwIr9pzy4NJMOXIwMGDHBfbaog3k+LQzNgHscNmTZkSNwut0mgaQH6OK0NtmDG8yb3rrghY8YMiZuD5jozbhoSQwpShaeNAaYt3obWYIt58TQkzKe3JYisKCoUNKegwUFI8J7257agSi8SIAtT6UqPRxjc+De2axocLzYbzObjSVtX8Dyj1TICv2Jr0nEzsHLMmPFxZvS75d2GMSDGl4bbxypyuXy8wXBLUMloe6JBvtJgGB8BjitdiUfmuO/dc885kuhaaRg/fiVUwUi00zKVcAuqoLEKRVGN5UCE4bhJRdPiFrPZJZcQESEPwOUybxFpWmU6bsCZxuiyXnKEfIQ8wjWTZxSs6WRExNwRfiCByn4IOSRPwr+kit/qikChkvjmNc/Qob2HznWd5G1WgXbc2TF36A9GkI0fqLrj4AWrjT/pmju0d++heShEhqy9EUt3CwKso9F75OHSHTuWLp3bW8LcpSj28IjXCCsoCLuv4GjWDBSm5sCBSG6/zMNJDldjh2fBggVbEwdicOXAz1sh5HHwrBbON3bTdpKoCc1kCrg00xMHzICzwanD0VrTkoESlpi06L/dZuMUMoXjSaaNKIgmQMgzFti48corj1aEk88KJwpjXDJWwhIjSysUVi0HJ4bn1ZWNG1EwT/ItTpnhhCVuO8sKCjDgjNuHSwAD9M8lsJzdvcQXKyO502ueaTQwaNDmza/dl50+g9EStsMMwMB52f168+bho4dDKFNzSkKBQX4mH37w6MT69etPHCaacBiHHj04PHnQoNGkrkDgjWb6NslMJrSRhjZPHhQYSp+WCiCoWHJu2LBhl2BIDSASGMoY9MvNdjFfKUA2RCRHpQbFfne7nrHDqA4dOozCG/Qie6mAQURG6P+VoPS4DED7wONAkT4ohUeeAtm6/QPZCqSlUqJF+U6dOnVDA23Q/ldRvsUfH/vyZuv0R7LlDaL+TOsamSdNmjTuBwEic43W1N/JkDfH1EmIqT78xznyZvjXh+9m6XNM/Ikc6Zulof6DdIUb1s1Y6n3m+/czvy+VsW7Dwik9/n8HzjZEy9x05tIAAAAASUVORK5CYII=" alt="QQ频道">
|
||||
</a>
|
||||
<br />
|
||||
<a href="https://jq.qq.com/?_wv=1027&k=5OFifDh">
|
||||
<img src="https://img.shields.io/badge/qq%E7%BE%A4-768887710-orange?style=flat-square" alt="QQ Chat">
|
||||
</a>
|
||||
<a href="https://t.me/botuniverse">
|
||||
<img src="https://img.shields.io/badge/telegram-botuniverse-blue?style=flat-square" alt="Telegram Channel">
|
||||
</a>
|
||||
<a href="https://discord.gg/VKtE6Gdc4h">
|
||||
<img src="https://discordapp.com/api/guilds/847819937858584596/widget.png?style=shield" alt="Discord Server">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://v2.nonebot.dev/">文档</a>
|
||||
·
|
||||
<a href="https://v2.nonebot.dev/guide/installation.html">安装</a>
|
||||
·
|
||||
<a href="https://v2.nonebot.dev/guide/getting-started.html">开始使用</a>
|
||||
·
|
||||
<a href="#插件">文档打不开?</a>
|
||||
</p>
|
||||
|
||||
<!-- TODO: asciinema for install -->
|
||||
|
||||
## 简介
|
||||
|
||||
NoneBot2 是一个可扩展的 Python 异步机器人框架,它会对机器人收到的消息进行解析和处理,并以插件化的形式,分发给消息所对应的命令处理器和自然语言处理器,来完成具体的功能。
|
||||
NoneBot2 是一个现代、跨平台、可扩展的 Python 聊天机器人框架,它基于 Python 的类型注解和异步特性,能够为你的需求实现提供便捷灵活的支持。
|
||||
|
||||
除了起到解析消息的作用,NoneBot 还为插件提供了大量实用的预设操作和权限控制机制,尤其对于命令处理器,它更是提供了完善且易用的会话机制和内部调用机制,以分别适应命令的连续交互和插件内部功能复用等需求。
|
||||
## 特色
|
||||
|
||||
目前 NoneBot2 在 [FastAPI](https://fastapi.tiangolo.com/) 的基础上封装了与 [CQHTTP(OneBot) 协议](http://cqhttp.cc/)插件的网络交互。
|
||||
- 异步优先:基于 Python 的异步特性,即使是~~非常~~大量的消息,也能吞吐自如
|
||||
- 易于开发:配合 NB-CLI 脚手架,代码编写上手简单,没有过多的冗余代码,可以让开发者专注于业务逻辑
|
||||
- 生而可靠:100% 类型注解覆盖,配合编辑器的类型推导功能,能将绝大多数的 Bug 杜绝在编辑器中 ([编辑器支持](https://v2.nonebot.dev/docs/start/editor-support))
|
||||
- 社区丰富:社区用户众多,直接和间接用户超过十万人,每天都有大量的活跃用户 ([社区资源](#社区资源))
|
||||
- 海纳百川:一个框架,支持多个聊天软件平台,可自定义通信协议
|
||||
- [OneBot 协议](https://onebot.dev/) (QQ 等)
|
||||
- [Mirai-API-HTTP 协议](https://github.com/project-mirai/mirai-api-http)
|
||||
- [钉钉](https://ding-doc.dingtalk.com/document#/org-dev-guide/elzz1p)
|
||||
- [Telegram](https://core.telegram.org/bots/api)
|
||||
- [飞书](https://open.feishu.cn/document/home/index)
|
||||
- [QQ 频道](https://bot.q.qq.com/wiki/)
|
||||
- 坚实后盾:支持多种 web 框架,可自定义替换
|
||||
- [FastAPI](https://fastapi.tiangolo.com/)
|
||||
- [Quart](https://pgjones.gitlab.io/quart/) (异步 Flask)
|
||||
- [aiohttp](https://docs.aiohttp.org/en/stable/)
|
||||
- [httpx](https://www.python-httpx.org/)
|
||||
- [websockets](https://websockets.readthedocs.io/en/stable/)
|
||||
|
||||
得益于 Python 的 [asyncio](https://docs.python.org/3/library/asyncio.html) 机制,NoneBot 处理消息的吞吐量有了很大的保障,再配合 WebSocket 通信方式(也是最建议的通信方式),NoneBot 的性能可以达到 HTTP 通信方式的两倍以上,相较于传统同步 I/O 的 HTTP 通信,更是有质的飞跃。
|
||||
更多:[概览](https://v2.nonebot.dev/docs/)
|
||||
|
||||
需要注意的是,NoneBot 仅支持 Python 3.7+ 及 CQHTTP(OneBot) 插件 v11+。
|
||||
## 什么不是 NoneBot2
|
||||
|
||||
## 文档
|
||||
NoneBot2 不是某个平台或者协议的具体实现,它只负责和已有协议适配器通信,并处理接收到的事件。所以,“NoneBot 有 blabla 平台的 blabla 功能吗?”这种问题是与 NoneBot2 无关的。请在相应平台的功能文档中确认,或与相应平台的协议适配开发者联系。
|
||||
|
||||
文档目前尚未完成,「API」部分由 sphinx 自动生成,你可以在 [这里](https://v2.nonebot.dev/) 查看。
|
||||
NoneBot2 不是 NoneBot1 的替代品。事实上,它们都在被积极的维护着。但是,如果你想尝试一些新功能,或者想要支持更多的平台,可以考虑使用 NoneBot2。
|
||||
|
||||
> ~~NoneBot2 和 NoneBot1 的区别,就像是 VisualStudio Code 和 VisualStudio 一样~~
|
||||
|
||||
## 即刻开始
|
||||
|
||||
~~完整~~文档可以在 [这里](https://v2.nonebot.dev/) 查看。
|
||||
|
||||
懒得看文档?下面是快速安装指南:
|
||||
|
||||
1. (**强烈建议**)使用你喜欢的 Python 环境管理工具创建新的虚拟环境。
|
||||
|
||||
2. 使用 `pip` (或其他) 安装 NoneBot 脚手架。
|
||||
|
||||
```bash
|
||||
pip install nb-cli
|
||||
```
|
||||
|
||||
3. 使用脚手架创建项目
|
||||
|
||||
```bash
|
||||
nb create
|
||||
```
|
||||
|
||||
## 社区资源
|
||||
|
||||
### 常见问题
|
||||
|
||||
- [常见问题解答(FAQ)](https://faq.nonebot.dev/)
|
||||
- [论坛(Discussion)](https://discussions.nonebot.dev/)
|
||||
|
||||
### 教程/实际项目/经验分享
|
||||
|
||||
- [awesome-nonebot](https://github.com/nonebot/awesome-nonebot)
|
||||
|
||||
### 插件
|
||||
|
||||
此外,NoneBot2 还有丰富的官方以及第三方现成的插件供大家使用:
|
||||
|
||||
- [NoneBot-Plugin-Docs](https://github.com/nonebot/nonebot2/tree/master/packages/nonebot-plugin-docs):离线文档至本地项目使用 (别再说文档打不开了!)
|
||||
|
||||
在项目目录下执行:
|
||||
|
||||
```bash
|
||||
nb plugin install nonebot_plugin_docs
|
||||
```
|
||||
|
||||
或者尝试以下镜像:
|
||||
|
||||
- [文档镜像(中国境内)](https://nb2.baka.icu)
|
||||
- [文档镜像(Vercel)](https://nonebot2-vercel-mirror.vercel.app)
|
||||
|
||||
- 其他插件请查看 [商店](https://v2.nonebot.dev/store.html)
|
||||
|
||||
## 许可证
|
||||
|
||||
`NoneBot` 采用 `MIT` 许可证进行开源
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
## 贡献
|
||||
|
||||
如果你在使用过程中发现任何问题,可以 [提交 issue](https://github.com/nonebot/nonebot2/issues/new) 或自行 fork 修改后提交 pull request。
|
||||
如果你在使用过程中发现任何问题,可以 [提交 Issue](https://github.com/nonebot/nonebot2/issues/new) 或自行 Fork 修改后提交 Pull Request。
|
||||
|
||||
如果你要提交 pull request,请确保你的代码风格和项目已有的代码保持一致,遵循 [PEP 8](https://www.python.org/dev/peps/pep-0008/),变量命名清晰,有适当的注释。
|
||||
如果你要提交 Pull Request,请确保你的代码风格和项目已有的代码保持一致,遵循 [PEP 8](https://www.python.org/dev/peps/pep-0008/) 与 [PEP 484](https://www.python.org/dev/peps/pep-0484/),变量命名清晰,有适当的注释与测试代码,**并且请以 `dev` 分支作为 Pull Request 目标分支**。
|
||||
|
||||
<!--TODO: Add a CONTRIBUTING.md-->
|
||||
|
||||
### 鸣谢
|
||||
|
||||
感谢以下开发者对 NoneBot2 作出的贡献:
|
||||
|
||||
<a href="https://github.com/nonebot/nonebot2/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=nonebot/nonebot2" />
|
||||
</a>
|
||||
|
@@ -1,15 +0,0 @@
|
||||
---
|
||||
home: true
|
||||
heroImage: /logo.png
|
||||
tagline: An asynchronous QQ bot framework.
|
||||
actionText: 开始使用
|
||||
actionLink: /guide/
|
||||
features:
|
||||
- title: 简洁
|
||||
details: 提供极其简洁易懂的 API,使你可以毫无压力地开始验证你的绝佳创意,只需编写最少量的代码,即可实现丰富的功能。
|
||||
- title: 易于扩展
|
||||
details: 精心设计的消息处理流程使得你可以很方便地将原型扩充为具有大量实用功能的完整聊天机器人,并持续保证扩展性。
|
||||
- title: 高性能
|
||||
details: 采用异步 I/O,利用 WebSocket 进行通信,以获得极高的性能;同时,支持使用多账号同时接入,减少业务宕机的可能。
|
||||
footer: MIT Licensed | Copyright © 2020 NoneBot Team
|
||||
---
|
@@ -1,46 +0,0 @@
|
||||
# NoneBot Api Reference
|
||||
|
||||
|
||||
* **模块索引**
|
||||
|
||||
|
||||
* [nonebot](nonebot.html)
|
||||
|
||||
|
||||
* [nonebot.config](config.html)
|
||||
|
||||
|
||||
* [nonebot.matcher](matcher.html)
|
||||
|
||||
|
||||
* [nonebot.rule](rule.html)
|
||||
|
||||
|
||||
* [nonebot.permission](permission.html)
|
||||
|
||||
|
||||
* [nonebot.sched](sched.html)
|
||||
|
||||
|
||||
* [nonebot.log](log.html)
|
||||
|
||||
|
||||
* [nonebot.utils](utils.html)
|
||||
|
||||
|
||||
* [nonebot.typing](typing.html)
|
||||
|
||||
|
||||
* [nonebot.exception](exception.html)
|
||||
|
||||
|
||||
* [nonebot.drivers](drivers/)
|
||||
|
||||
|
||||
* [nonebot.drivers.fastapi](drivers/fastapi.html)
|
||||
|
||||
|
||||
* [nonebot.adapters](adapters/)
|
||||
|
||||
|
||||
* [nonebot.adapters.cqhttp](adapters/cqhttp.html)
|
@@ -1,323 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.adapters 模块
|
||||
|
||||
## 协议适配基类
|
||||
|
||||
各协议请继承以下基类,并使用 `driver.register_adapter` 注册适配器
|
||||
|
||||
|
||||
## _class_ `BaseBot`
|
||||
|
||||
基类:`abc.ABC`
|
||||
|
||||
Bot 基类。用于处理上报消息,并提供 API 调用接口。
|
||||
|
||||
|
||||
### _abstract_ `__init__(driver, connection_type, config, self_id, *, websocket=None)`
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `driver: Driver`: Driver 对象
|
||||
|
||||
|
||||
* `connection_type: str`: http 或者 websocket
|
||||
|
||||
|
||||
* `config: Config`: Config 对象
|
||||
|
||||
|
||||
* `self_id: str`: 机器人 ID
|
||||
|
||||
|
||||
* `websocket: Optional[WebSocket]`: Websocket 连接对象
|
||||
|
||||
|
||||
|
||||
### `driver`
|
||||
|
||||
Driver 对象
|
||||
|
||||
|
||||
### `connection_type`
|
||||
|
||||
连接类型
|
||||
|
||||
|
||||
### `config`
|
||||
|
||||
Config 配置对象
|
||||
|
||||
|
||||
### `self_id`
|
||||
|
||||
机器人 ID
|
||||
|
||||
|
||||
### `websocket`
|
||||
|
||||
Websocket 连接对象
|
||||
|
||||
|
||||
### _abstract property_ `type`
|
||||
|
||||
Adapter 类型
|
||||
|
||||
|
||||
### _abstract async_ `handle_message(message)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
处理上报消息的函数,转换为 `Event` 事件后调用 `nonebot.message.handle_event` 进一步处理事件。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `message: dict`: 收到的上报消息
|
||||
|
||||
|
||||
|
||||
### _abstract async_ `call_api(api, **data)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
调用机器人 API 接口,可以通过该函数或直接通过 bot 属性进行调用
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `api: str`: API 名称
|
||||
|
||||
|
||||
* `**data`: API 数据
|
||||
|
||||
|
||||
|
||||
* **示例**
|
||||
|
||||
|
||||
```python
|
||||
await bot.call_api("send_msg", data={"message": "hello world"})
|
||||
await bot.send_msg(message="hello world")
|
||||
```
|
||||
|
||||
|
||||
### _abstract async_ `send(event, message, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
调用机器人基础发送消息接口
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `event: Event`: 上报事件
|
||||
|
||||
|
||||
* `message: Union[str, Message, MessageSegment]`: 要发送的消息
|
||||
|
||||
|
||||
* `**kwargs`
|
||||
|
||||
|
||||
|
||||
## _class_ `BaseEvent`
|
||||
|
||||
基类:`abc.ABC`
|
||||
|
||||
Event 基类。提供上报信息的关键信息,其余信息可从原始上报消息获取。
|
||||
|
||||
|
||||
### `__init__(raw_event)`
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `raw_event: dict`: 原始上报消息
|
||||
|
||||
|
||||
|
||||
### _property_ `raw_event`
|
||||
|
||||
原始上报消息
|
||||
|
||||
|
||||
### _abstract property_ `id`
|
||||
|
||||
事件 ID
|
||||
|
||||
|
||||
### _abstract property_ `name`
|
||||
|
||||
事件名称
|
||||
|
||||
|
||||
### _abstract property_ `self_id`
|
||||
|
||||
机器人 ID
|
||||
|
||||
|
||||
### _abstract property_ `time`
|
||||
|
||||
事件发生时间
|
||||
|
||||
|
||||
### _abstract property_ `type`
|
||||
|
||||
事件主类型
|
||||
|
||||
|
||||
### _abstract property_ `detail_type`
|
||||
|
||||
事件详细类型
|
||||
|
||||
|
||||
### _abstract property_ `sub_type`
|
||||
|
||||
事件子类型
|
||||
|
||||
|
||||
### _abstract property_ `user_id`
|
||||
|
||||
触发事件的主体 ID
|
||||
|
||||
|
||||
### _abstract property_ `group_id`
|
||||
|
||||
触发事件的主体群 ID
|
||||
|
||||
|
||||
### _abstract property_ `to_me`
|
||||
|
||||
事件是否为发送给机器人的消息
|
||||
|
||||
|
||||
### _abstract property_ `message`
|
||||
|
||||
消息内容
|
||||
|
||||
|
||||
### _abstract property_ `reply`
|
||||
|
||||
回复的消息
|
||||
|
||||
|
||||
### _abstract property_ `raw_message`
|
||||
|
||||
原始消息
|
||||
|
||||
|
||||
### _abstract property_ `plain_text`
|
||||
|
||||
纯文本消息
|
||||
|
||||
|
||||
### _abstract property_ `sender`
|
||||
|
||||
消息发送者信息
|
||||
|
||||
|
||||
## _class_ `BaseMessageSegment`
|
||||
|
||||
基类:`abc.ABC`
|
||||
|
||||
消息段基类
|
||||
|
||||
|
||||
### `type`
|
||||
|
||||
|
||||
* 类型: `str`
|
||||
|
||||
|
||||
* 说明: 消息段类型
|
||||
|
||||
|
||||
### `data`
|
||||
|
||||
|
||||
* 类型: `Dict[str, Union[str, list]]`
|
||||
|
||||
|
||||
* 说明: 消息段数据
|
||||
|
||||
|
||||
## _class_ `BaseMessage`
|
||||
|
||||
基类:`list`, `abc.ABC`
|
||||
|
||||
消息数组
|
||||
|
||||
|
||||
### `__init__(message=None, *args, **kwargs)`
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `message: Union[str, dict, list, MessageSegment, Message]`: 消息内容
|
||||
|
||||
|
||||
|
||||
### `append(obj)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
添加一个消息段到消息数组末尾
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `obj: Union[str, MessageSegment]`: 要添加的消息段
|
||||
|
||||
|
||||
|
||||
### `extend(obj)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
拼接一个消息数组或多个消息段到消息数组末尾
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `obj: Union[Message, Iterable[MessageSegment]]`: 要添加的消息数组
|
||||
|
||||
|
||||
|
||||
### `reduce()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
缩减消息数组,即拼接相邻纯文本消息段
|
||||
|
||||
|
||||
|
||||
### `extract_plain_text()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
提取消息内纯文本消息
|
@@ -1,411 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.adapters.cqhttp 模块
|
||||
|
||||
## CQHTTP (OneBot) v11 协议适配
|
||||
|
||||
协议详情请看: [CQHTTP](http://cqhttp.cc/) | [OneBot](https://github.com/howmanybots/onebot)
|
||||
|
||||
|
||||
## `log(level, message)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
用于打印 CQHTTP 日志。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `level: str`: 日志等级
|
||||
|
||||
|
||||
* `message: str`: 日志信息
|
||||
|
||||
|
||||
|
||||
## `escape(s, *, escape_comma=True)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
对字符串进行 CQ 码转义。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `s: str`: 需要转义的字符串
|
||||
|
||||
|
||||
* `escape_comma: bool`: 是否转义逗号(`,`)。
|
||||
|
||||
|
||||
|
||||
## `unescape(s)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
对字符串进行 CQ 码去转义。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `s: str`: 需要转义的字符串
|
||||
|
||||
|
||||
|
||||
## `_b2s(b)`
|
||||
|
||||
转换布尔值为字符串。
|
||||
|
||||
|
||||
## _async_ `_check_reply(bot, event)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
检查消息中存在的回复,去除并赋值 `event.reply`, `event.to_me`
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `bot: Bot`: Bot 对象
|
||||
|
||||
|
||||
* `event: Event`: Event 对象
|
||||
|
||||
|
||||
|
||||
## `_check_at_me(bot, event)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
检查消息开头或结尾是否存在 @机器人,去除并赋值 `event.to_me`
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `bot: Bot`: Bot 对象
|
||||
|
||||
|
||||
* `event: Event`: Event 对象
|
||||
|
||||
|
||||
|
||||
## `_check_nickname(bot, event)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
检查消息开头是否存在,去除并赋值 `event.to_me`
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `bot: Bot`: Bot 对象
|
||||
|
||||
|
||||
* `event: Event`: Event 对象
|
||||
|
||||
|
||||
|
||||
## `_handle_api_result(result)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
处理 API 请求返回值。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `result: Optional[Dict[str, Any]]`: API 返回数据
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Any`: API 调用返回数据
|
||||
|
||||
|
||||
|
||||
* **异常**
|
||||
|
||||
|
||||
* `ActionFailed`: API 调用失败
|
||||
|
||||
|
||||
|
||||
## _class_ `Bot`
|
||||
|
||||
基类:[`nonebot.adapters.BaseBot`](#None)
|
||||
|
||||
CQHTTP 协议 Bot 适配。继承属性参考 [BaseBot](./#class-basebot) 。
|
||||
|
||||
|
||||
### _property_ `type`
|
||||
|
||||
|
||||
* 返回: `"cqhttp"`
|
||||
|
||||
|
||||
### _async_ `handle_message(message)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
调用 [_check_reply](#async-check-reply-bot-event), [_check_at_me](#check-at-me-bot-event), [_check_nickname](#check-nickname-bot-event) 处理事件并转换为 [Event](#class-event)
|
||||
|
||||
|
||||
|
||||
### _async_ `call_api(api, **data)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
调用 CQHTTP 协议 API
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `api: str`: API 名称
|
||||
|
||||
|
||||
* `**data: Any`: API 参数
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Any`: API 调用返回数据
|
||||
|
||||
|
||||
|
||||
* **异常**
|
||||
|
||||
|
||||
* `NetworkError`: 网络错误
|
||||
|
||||
|
||||
* `ActionFailed`: API 调用失败
|
||||
|
||||
|
||||
|
||||
### _async_ `send(event, message, at_sender=False, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
根据 `event` 向触发事件的主体发送消息。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `event: Event`: Event 对象
|
||||
|
||||
|
||||
* `message: Union[str, Message, MessageSegment]`: 要发送的消息
|
||||
|
||||
|
||||
* `at_sender: bool`: 是否 @ 事件主体
|
||||
|
||||
|
||||
* `**kwargs`: 覆盖默认参数
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Any`: API 调用返回数据
|
||||
|
||||
|
||||
|
||||
* **异常**
|
||||
|
||||
|
||||
* `ValueError`: 缺少 `user_id`, `group_id`
|
||||
|
||||
|
||||
* `NetworkError`: 网络错误
|
||||
|
||||
|
||||
* `ActionFailed`: API 调用失败
|
||||
|
||||
|
||||
|
||||
## _class_ `Event`
|
||||
|
||||
基类:[`nonebot.adapters.BaseEvent`](#None)
|
||||
|
||||
CQHTTP 协议 Event 适配。继承属性参考 [BaseEvent](./#class-baseevent) 。
|
||||
|
||||
|
||||
### _property_ `id`
|
||||
|
||||
|
||||
* 类型: `Optional[int]`
|
||||
|
||||
|
||||
* 说明: 事件/消息 ID
|
||||
|
||||
|
||||
### _property_ `name`
|
||||
|
||||
|
||||
* 类型: `str`
|
||||
|
||||
|
||||
* 说明: 事件名称,由类型与 `.` 组合而成
|
||||
|
||||
|
||||
### _property_ `self_id`
|
||||
|
||||
|
||||
* 类型: `str`
|
||||
|
||||
|
||||
* 说明: 机器人自身 ID
|
||||
|
||||
|
||||
### _property_ `time`
|
||||
|
||||
|
||||
* 类型: `int`
|
||||
|
||||
|
||||
* 说明: 事件发生时间
|
||||
|
||||
|
||||
### _property_ `type`
|
||||
|
||||
|
||||
* 类型: `str`
|
||||
|
||||
|
||||
* 说明: 事件类型
|
||||
|
||||
|
||||
### _property_ `detail_type`
|
||||
|
||||
|
||||
* 类型: `str`
|
||||
|
||||
|
||||
* 说明: 事件详细类型
|
||||
|
||||
|
||||
### _property_ `sub_type`
|
||||
|
||||
|
||||
* 类型: `Optional[str]`
|
||||
|
||||
|
||||
* 说明: 事件子类型
|
||||
|
||||
|
||||
### _property_ `user_id`
|
||||
|
||||
|
||||
* 类型: `Optional[int]`
|
||||
|
||||
|
||||
* 说明: 事件主体 ID
|
||||
|
||||
|
||||
### _property_ `group_id`
|
||||
|
||||
|
||||
* 类型: `Optional[int]`
|
||||
|
||||
|
||||
* 说明: 事件主体群 ID
|
||||
|
||||
|
||||
### _property_ `to_me`
|
||||
|
||||
|
||||
* 类型: `Optional[bool]`
|
||||
|
||||
|
||||
* 说明: 消息是否与机器人相关
|
||||
|
||||
|
||||
### _property_ `message`
|
||||
|
||||
|
||||
* 类型: `Optional[Message]`
|
||||
|
||||
|
||||
* 说明: 消息内容
|
||||
|
||||
|
||||
### _property_ `reply`
|
||||
|
||||
|
||||
* 类型: `Optional[dict]`
|
||||
|
||||
|
||||
* 说明: 回复消息详情
|
||||
|
||||
|
||||
### _property_ `raw_message`
|
||||
|
||||
|
||||
* 类型: `Optional[str]`
|
||||
|
||||
|
||||
* 说明: 原始消息
|
||||
|
||||
|
||||
### _property_ `plain_text`
|
||||
|
||||
|
||||
* 类型: `Optional[str]`
|
||||
|
||||
|
||||
* 说明: 纯文本消息内容
|
||||
|
||||
|
||||
### _property_ `sender`
|
||||
|
||||
|
||||
* 类型: `Optional[dict]`
|
||||
|
||||
|
||||
* 说明: 消息发送者信息
|
||||
|
||||
|
||||
## _class_ `MessageSegment`
|
||||
|
||||
基类:[`nonebot.adapters.BaseMessageSegment`](#None)
|
||||
|
||||
|
||||
## _class_ `Message`
|
||||
|
||||
基类:[`nonebot.adapters.BaseMessage`](#None)
|
@@ -1,265 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.config 模块
|
||||
|
||||
## 配置
|
||||
|
||||
NoneBot 使用 [pydantic](https://pydantic-docs.helpmanual.io/) 以及 [python-dotenv](https://saurabh-kumar.com/python-dotenv/) 来读取配置。
|
||||
|
||||
配置项需符合特殊格式或 json 序列化格式。详情见 [pydantic Field Type](https://pydantic-docs.helpmanual.io/usage/types/) 文档。
|
||||
|
||||
|
||||
## _class_ `Env`
|
||||
|
||||
基类:`pydantic.env_settings.BaseSettings`
|
||||
|
||||
运行环境配置。大小写不敏感。
|
||||
|
||||
将会从 `nonebot.init 参数` > `环境变量` > `.env 环境配置文件` 的优先级读取配置。
|
||||
|
||||
|
||||
### `environment`
|
||||
|
||||
|
||||
* 类型: `str`
|
||||
|
||||
|
||||
* 默认值: `"prod"`
|
||||
|
||||
|
||||
* 说明:
|
||||
当前环境名。 NoneBot 将从 `.env.{environment}` 文件中加载配置。
|
||||
|
||||
|
||||
## _class_ `Config`
|
||||
|
||||
基类:`nonebot.config.BaseConfig`
|
||||
|
||||
NoneBot 主要配置。大小写不敏感。
|
||||
|
||||
除了 NoneBot 的配置项外,还可以自行添加配置项到 `.env.{environment}` 文件中。
|
||||
这些配置将会在 json 反序列化后一起带入 `Config` 类中。
|
||||
|
||||
|
||||
### `driver`
|
||||
|
||||
|
||||
* 类型: `str`
|
||||
|
||||
|
||||
* 默认值: `"nonebot.drivers.fastapi"`
|
||||
|
||||
|
||||
* 说明:
|
||||
NoneBot 运行所使用的 `Driver` 。继承自 `nonebot.driver.BaseDriver` 。
|
||||
|
||||
|
||||
### `host`
|
||||
|
||||
|
||||
* 类型: `IPvAnyAddress`
|
||||
|
||||
|
||||
* 默认值: `127.0.0.1`
|
||||
|
||||
|
||||
* 说明:
|
||||
NoneBot 的 HTTP 和 WebSocket 服务端监听的 IP/主机名。
|
||||
|
||||
|
||||
### `port`
|
||||
|
||||
|
||||
* 类型: `int`
|
||||
|
||||
|
||||
* 默认值: `8080`
|
||||
|
||||
|
||||
* 说明:
|
||||
NoneBot 的 HTTP 和 WebSocket 服务端监听的端口。
|
||||
|
||||
|
||||
### `debug`
|
||||
|
||||
|
||||
* 类型: `bool`
|
||||
|
||||
|
||||
* 默认值: `False`
|
||||
|
||||
|
||||
* 说明:
|
||||
是否以调试模式运行 NoneBot。
|
||||
|
||||
|
||||
### `api_root`
|
||||
|
||||
|
||||
* 类型: `Dict[str, str]`
|
||||
|
||||
|
||||
* 默认值: `{}`
|
||||
|
||||
|
||||
* 说明:
|
||||
以机器人 ID 为键,上报地址为值的字典,环境变量或文件中应使用 json 序列化。
|
||||
|
||||
|
||||
* 示例:
|
||||
|
||||
```default
|
||||
API_ROOT={"123456": "http://127.0.0.1:5700"}
|
||||
```
|
||||
|
||||
|
||||
### `api_timeout`
|
||||
|
||||
|
||||
* 类型: `Optional[float]`
|
||||
|
||||
|
||||
* 默认值: `30.`
|
||||
|
||||
|
||||
* 说明:
|
||||
API 请求超时时间,单位: 秒。
|
||||
|
||||
|
||||
### `access_token`
|
||||
|
||||
|
||||
* 类型: `Optional[str]`
|
||||
|
||||
|
||||
* 默认值: `None`
|
||||
|
||||
|
||||
* 说明:
|
||||
API 请求以及上报所需密钥,在请求头中携带。
|
||||
|
||||
|
||||
* 示例:
|
||||
|
||||
```http
|
||||
POST /cqhttp/ HTTP/1.1
|
||||
Authorization: Bearer kSLuTF2GC2Q4q4ugm3
|
||||
```
|
||||
|
||||
|
||||
### `secret`
|
||||
|
||||
|
||||
* 类型: `Optional[str]`
|
||||
|
||||
|
||||
* 默认值: `None`
|
||||
|
||||
|
||||
* 说明:
|
||||
HTTP POST 形式上报所需签名,在请求头中携带。
|
||||
|
||||
|
||||
* 示例:
|
||||
|
||||
```http
|
||||
POST /cqhttp/ HTTP/1.1
|
||||
X-Signature: sha1=f9ddd4863ace61e64f462d41ca311e3d2c1176e2
|
||||
```
|
||||
|
||||
|
||||
### `superusers`
|
||||
|
||||
|
||||
* 类型: `Set[int]`
|
||||
|
||||
|
||||
* 默认值: `set()`
|
||||
|
||||
|
||||
* 说明:
|
||||
机器人超级用户。
|
||||
|
||||
|
||||
* 示例:
|
||||
|
||||
```default
|
||||
SUPER_USERS=[12345789]
|
||||
```
|
||||
|
||||
|
||||
### `nickname`
|
||||
|
||||
|
||||
* 类型: `Set[str]`
|
||||
|
||||
|
||||
* 默认值: `set()`
|
||||
|
||||
|
||||
* 说明:
|
||||
机器人昵称。
|
||||
|
||||
|
||||
### `command_start`
|
||||
|
||||
|
||||
* 类型: `Set[str]`
|
||||
|
||||
|
||||
* 默认值: `{"/"}`
|
||||
|
||||
|
||||
* 说明:
|
||||
命令的起始标记,用于判断一条消息是不是命令。
|
||||
|
||||
|
||||
### `command_sep`
|
||||
|
||||
|
||||
* 类型: `Set[str]`
|
||||
|
||||
|
||||
* 默认值: `{"."}`
|
||||
|
||||
|
||||
* 说明:
|
||||
命令的分隔标记,用于将文本形式的命令切分为元组(实际的命令名)。
|
||||
|
||||
|
||||
### `session_expire_timeout`
|
||||
|
||||
|
||||
* 类型: `timedelta`
|
||||
|
||||
|
||||
* 默认值: `timedelta(minutes=2)`
|
||||
|
||||
|
||||
* 说明:
|
||||
等待用户回复的超时时间。
|
||||
|
||||
|
||||
* 示例:
|
||||
|
||||
```default
|
||||
SESSION_EXPIRE_TIMEOUT=120 # 单位: 秒
|
||||
SESSION_EXPIRE_TIMEOUT=[DD ][HH:MM]SS[.ffffff]
|
||||
SESSION_EXPIRE_TIMEOUT=P[DD]DT[HH]H[MM]M[SS]S # ISO 8601
|
||||
```
|
||||
|
||||
|
||||
### `apscheduler_config`
|
||||
|
||||
|
||||
* 类型: `dict`
|
||||
|
||||
|
||||
* 默认值: `{"apscheduler.timezone": "Asia/Shanghai"}`
|
||||
|
||||
|
||||
* 说明:
|
||||
APScheduler 的配置对象,见 [Configuring the Scheduler](https://apscheduler.readthedocs.io/en/latest/userguide.html#configuring-the-scheduler)
|
@@ -1,37 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.drivers 模块
|
||||
|
||||
## 后端驱动适配基类
|
||||
|
||||
各驱动请继承以下基类
|
||||
|
||||
|
||||
## _class_ `BaseDriver`
|
||||
|
||||
基类:`abc.ABC`
|
||||
|
||||
Driver 基类。将后端框架封装,以满足适配器使用。
|
||||
|
||||
|
||||
### `_adapters`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Dict[str, Type[Bot]]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
已注册的适配器列表
|
||||
|
||||
|
||||
|
||||
### _abstract_ `__init__(env, config)`
|
||||
|
||||
Initialize self. See help(type(self)) for accurate signature.
|
@@ -1,16 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.drivers.fastapi 模块
|
||||
|
||||
|
||||
## _class_ `Driver`
|
||||
|
||||
基类:[`nonebot.drivers.BaseDriver`](#None)
|
||||
|
||||
|
||||
### `__init__(env, config)`
|
||||
|
||||
Initialize self. See help(type(self)) for accurate signature.
|
@@ -1,156 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.exception 模块
|
||||
|
||||
## 异常
|
||||
|
||||
下列文档中的异常是所有 NoneBot 运行时可能会抛出的。
|
||||
这些异常并非所有需要用户处理,在 NoneBot 内部运行时被捕获,并进行对应操作。
|
||||
|
||||
|
||||
## _exception_ `IgnoredException`
|
||||
|
||||
基类:`Exception`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
指示 NoneBot 应该忽略该事件。可由 PreProcessor 抛出。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `reason`: 忽略事件的原因
|
||||
|
||||
|
||||
|
||||
## _exception_ `PausedException`
|
||||
|
||||
基类:`Exception`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
指示 NoneBot 结束当前 `Handler` 并等待下一条消息后继续下一个 `Handler`。
|
||||
可用于用户输入新信息。
|
||||
|
||||
|
||||
|
||||
* **用法**
|
||||
|
||||
可以在 `Handler` 中通过 `Matcher.pause()` 抛出。
|
||||
|
||||
|
||||
|
||||
## _exception_ `RejectedException`
|
||||
|
||||
基类:`Exception`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
指示 NoneBot 结束当前 `Handler` 并等待下一条消息后重新运行当前 `Handler`。
|
||||
可用于用户重新输入。
|
||||
|
||||
|
||||
|
||||
* **用法**
|
||||
|
||||
可以在 `Handler` 中通过 `Matcher.reject()` 抛出。
|
||||
|
||||
|
||||
|
||||
## _exception_ `FinishedException`
|
||||
|
||||
基类:`Exception`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
指示 NoneBot 结束当前 `Handler` 且后续 `Handler` 不再被运行。
|
||||
可用于结束用户会话。
|
||||
|
||||
|
||||
|
||||
* **用法**
|
||||
|
||||
可以在 `Handler` 中通过 `Matcher.finish()` 抛出。
|
||||
|
||||
|
||||
|
||||
## _exception_ `ExpiredException`
|
||||
|
||||
基类:`Exception`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
指示 NoneBot 当前 `Matcher` 已失效。
|
||||
|
||||
|
||||
|
||||
* **用法**
|
||||
|
||||
当 `Matcher` 运行前检查时抛出。
|
||||
|
||||
|
||||
|
||||
## _exception_ `StopPropagation`
|
||||
|
||||
基类:`Exception`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
指示 NoneBot 终止事件向下层传播。
|
||||
|
||||
|
||||
|
||||
* **用法**
|
||||
|
||||
在 `Matcher.block == True` 时抛出。
|
||||
|
||||
|
||||
|
||||
## _exception_ `ApiNotAvailable`
|
||||
|
||||
基类:`Exception`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
在 API 连接不可用时抛出。
|
||||
|
||||
|
||||
|
||||
## _exception_ `NetworkError`
|
||||
|
||||
基类:`Exception`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
在网络出现问题时抛出,如: API 请求地址不正确, API 请求无返回或返回状态非正常等。
|
||||
|
||||
|
||||
|
||||
## _exception_ `ActionFailed`
|
||||
|
||||
基类:`Exception`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
API 请求成功返回数据,但 API 操作失败。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `retcode`: 错误代码
|
@@ -1,55 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.log 模块
|
||||
|
||||
## 日志
|
||||
|
||||
NoneBot 使用 [loguru](https://github.com/Delgan/loguru) 来记录日志信息。
|
||||
|
||||
自定义 logger 请参考 [loguru](https://github.com/Delgan/loguru) 文档。
|
||||
|
||||
|
||||
## `logger`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
NoneBot 日志记录器对象。
|
||||
|
||||
|
||||
|
||||
* **默认信息**
|
||||
|
||||
|
||||
* 格式: `[%(asctime)s %(name)s] %(levelname)s: %(message)s`
|
||||
|
||||
|
||||
* 等级: `DEBUG` / `INFO` ,根据 config 配置改变
|
||||
|
||||
|
||||
* 输出: 输出至 stdout
|
||||
|
||||
|
||||
|
||||
* **用法**
|
||||
|
||||
|
||||
```python
|
||||
from nonebot.log import logger
|
||||
```
|
||||
|
||||
|
||||
## _class_ `LoguruHandler`
|
||||
|
||||
基类:`logging.Handler`
|
||||
|
||||
|
||||
### `emit(record)`
|
||||
|
||||
Do whatever it takes to actually log the specified logging record.
|
||||
|
||||
This version is intended to be implemented by subclasses and so
|
||||
raises a NotImplementedError.
|
@@ -1,485 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.matcher 模块
|
||||
|
||||
## 事件响应器
|
||||
|
||||
该模块实现事件响应器的创建与运行,并提供一些快捷方法来帮助用户更好的与机器人进行 对话 。
|
||||
|
||||
|
||||
## `matchers`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Dict[int, List[Type[Matcher]]]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
用于存储当前所有的事件响应器
|
||||
|
||||
|
||||
|
||||
## _class_ `Matcher`
|
||||
|
||||
基类:`object`
|
||||
|
||||
事件响应器类
|
||||
|
||||
|
||||
### `module`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Optional[str]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器所在模块名称
|
||||
|
||||
|
||||
|
||||
### `type`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`str`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器类型
|
||||
|
||||
|
||||
|
||||
### `rule`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Rule`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器匹配规则
|
||||
|
||||
|
||||
|
||||
### `permission`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Permission`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器触发权限
|
||||
|
||||
|
||||
|
||||
### `priority`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`int`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器优先级
|
||||
|
||||
|
||||
|
||||
### `block`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`bool`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器是否阻止事件传播
|
||||
|
||||
|
||||
|
||||
### `temp`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`bool`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器是否为临时
|
||||
|
||||
|
||||
|
||||
### `expire_time`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Optional[datetime]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器过期时间点
|
||||
|
||||
|
||||
|
||||
### `_default_state`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`dict`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器默认状态
|
||||
|
||||
|
||||
|
||||
### `_default_parser`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Optional[ArgsParser]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器默认参数解析函数
|
||||
|
||||
|
||||
|
||||
### `__init__()`
|
||||
|
||||
实例化 Matcher 以便运行
|
||||
|
||||
|
||||
### `handlers`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`List[Handler]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器拥有的事件处理函数列表
|
||||
|
||||
|
||||
|
||||
### _classmethod_ `new(type_='', rule=None, permission=None, handlers=None, temp=False, priority=1, block=False, *, module=None, default_state=None, expire_time=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
创建一个新的事件响应器,并存储至 [matchers](#matchers)
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `type_: str`: 事件响应器类型,与 `event.type` 一致时触发,空字符串表示任意
|
||||
|
||||
|
||||
* `rule: Optional[Rule]`: 匹配规则
|
||||
|
||||
|
||||
* `permission: Optional[Permission]`: 权限
|
||||
|
||||
|
||||
* `handlers: Optional[List[Handler]]`: 事件处理函数列表
|
||||
|
||||
|
||||
* `temp: bool`: 是否为临时事件响应器,即触发一次后删除
|
||||
|
||||
|
||||
* `priority: int`: 响应优先级
|
||||
|
||||
|
||||
* `block: bool`: 是否阻止事件向更低优先级的响应器传播
|
||||
|
||||
|
||||
* `module: Optional[str]`: 事件响应器所在模块名称
|
||||
|
||||
|
||||
* `default_state: Optional[dict]`: 默认状态 `state`
|
||||
|
||||
|
||||
* `expire_time: Optional[datetime]`: 事件响应器最终有效时间点,过时即被删除
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Type[Matcher]`: 新的事件响应器类
|
||||
|
||||
|
||||
|
||||
### _async classmethod_ `check_perm(bot, event)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
检查是否满足触发权限
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `bot: Bot`: Bot 对象
|
||||
|
||||
|
||||
* `event: Event`: 上报事件
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `bool`: 是否满足权限
|
||||
|
||||
|
||||
|
||||
### _async classmethod_ `check_rule(bot, event, state)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
检查是否满足匹配规则
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `bot: Bot`: Bot 对象
|
||||
|
||||
|
||||
* `event: Event`: 上报事件
|
||||
|
||||
|
||||
* `state: dict`: 当前状态
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `bool`: 是否满足匹配规则
|
||||
|
||||
|
||||
|
||||
### _classmethod_ `args_parser(func)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
装饰一个函数来更改当前事件响应器的默认参数解析函数
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `func: ArgsParser`: 参数解析函数
|
||||
|
||||
|
||||
|
||||
### _classmethod_ `handle()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
装饰一个函数来向事件响应器直接添加一个处理函数
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* 无
|
||||
|
||||
|
||||
|
||||
### _classmethod_ `receive()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
装饰一个函数来指示 NoneBot 在接收用户新的一条消息后继续运行该函数
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* 无
|
||||
|
||||
|
||||
|
||||
### _classmethod_ `got(key, prompt=None, args_parser=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
装饰一个函数来指示 NoneBot 当要获取的 `key` 不存在时接收用户新的一条消息并经过 `ArgsParser` 处理后再运行该函数,如果 `key` 已存在则直接继续运行
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `key: str`: 参数名
|
||||
|
||||
|
||||
* `prompt: Optional[Union[str, Message, MessageSegment]]`: 在参数不存在时向用户发送的消息
|
||||
|
||||
|
||||
* `args_parser: Optional[ArgsParser]`: 可选参数解析函数,空则使用默认解析函数
|
||||
|
||||
|
||||
|
||||
### _async classmethod_ `send(message)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
发送一条消息给当前交互用户
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `message: Union[str, Message, MessageSegment]`: 消息内容
|
||||
|
||||
|
||||
|
||||
### _async classmethod_ `finish(message=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
发送一条消息给当前交互用户并结束当前事件响应器
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `message: Union[str, Message, MessageSegment]`: 消息内容
|
||||
|
||||
|
||||
|
||||
### _async classmethod_ `pause(prompt=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
发送一条消息给当前交互用户并暂停事件响应器,在接收用户新的一条消息后继续下一个处理函数
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `prompt: Union[str, Message, MessageSegment]`: 消息内容
|
||||
|
||||
|
||||
|
||||
### _async classmethod_ `reject(prompt=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
发送一条消息给当前交互用户并暂停事件响应器,在接收用户新的一条消息后重新运行当前处理函数
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `prompt: Union[str, Message, MessageSegment]`: 消息内容
|
||||
|
||||
|
||||
|
||||
## _class_ `MatcherGroup`
|
||||
|
||||
基类:`object`
|
||||
|
||||
事件响应器组合,统一管理。用法同 `Matcher`
|
||||
|
||||
|
||||
### `__init__(type_='', rule=None, permission=None, handlers=None, temp=False, priority=1, block=False, *, module=None, default_state=None, expire_time=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
创建一个事件响应器组合,参数为默认值,与 `Matcher.new` 一致
|
||||
|
||||
|
||||
|
||||
### `matchers`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`List[Type[Matcher]]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
组内事件响应器列表
|
||||
|
||||
|
||||
|
||||
### `new(type_='', rule=None, permission=None, handlers=None, temp=False, priority=1, block=False, *, module=None, default_state=None, expire_time=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
在组中创建一个新的事件响应器,参数留空则使用组合默认值
|
||||
|
||||
|
||||
:::danger 警告
|
||||
如果使用 handlers 参数覆盖组合默认值则该事件响应器不会随组合一起添加新的事件处理函数
|
||||
:::
|
@@ -1,257 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot 模块
|
||||
|
||||
## 快捷导入
|
||||
|
||||
为方便使用,`nonebot` 模块从子模块导入了部分内容
|
||||
|
||||
|
||||
* `on_message` => `nonebot.plugin.on_message`
|
||||
|
||||
|
||||
* `on_notice` => `nonebot.plugin.on_notice`
|
||||
|
||||
|
||||
* `on_request` => `nonebot.plugin.on_request`
|
||||
|
||||
|
||||
* `on_metaevent` => `nonebot.plugin.on_metaevent`
|
||||
|
||||
|
||||
* `on_startswith` => `nonebot.plugin.on_startswith`
|
||||
|
||||
|
||||
* `on_endswith` => `nonebot.plugin.on_endswith`
|
||||
|
||||
|
||||
* `on_command` => `nonebot.plugin.on_command`
|
||||
|
||||
|
||||
* `on_regex` => `nonebot.plugin.on_regex`
|
||||
|
||||
|
||||
* `on_regex` => `nonebot.plugin.on_regex`
|
||||
|
||||
|
||||
* `on_regex` => `nonebot.plugin.on_regex`
|
||||
|
||||
|
||||
* `CommandGroup` => `nonebot.plugin.CommandGroup`
|
||||
|
||||
|
||||
* `load_plugin` => `nonebot.plugin.load_plugin`
|
||||
|
||||
|
||||
* `load_plugins` => `nonebot.plugin.load_plugins`
|
||||
|
||||
|
||||
* `load_builtin_plugins` => `nonebot.plugin.load_builtin_plugins`
|
||||
|
||||
|
||||
* `get_loaded_plugins` => `nonebot.plugin.get_loaded_plugins`
|
||||
|
||||
|
||||
## `get_driver()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
获取全局 Driver 对象。可用于在计划任务的回调中获取当前 Driver 对象。
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Driver`: 全局 Driver 对象
|
||||
|
||||
|
||||
|
||||
* **异常**
|
||||
|
||||
|
||||
* `ValueError`: 全局 Driver 对象尚未初始化 (nonebot.init 尚未调用)
|
||||
|
||||
|
||||
|
||||
* **用法**
|
||||
|
||||
|
||||
```python
|
||||
driver = nonebot.get_driver()
|
||||
```
|
||||
|
||||
|
||||
## `get_app()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
获取全局 Driver 对应 Server App 对象。
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Any`: Server App 对象
|
||||
|
||||
|
||||
|
||||
* **异常**
|
||||
|
||||
|
||||
* `ValueError`: 全局 Driver 对象尚未初始化 (nonebot.init 尚未调用)
|
||||
|
||||
|
||||
|
||||
* **用法**
|
||||
|
||||
|
||||
```python
|
||||
app = nonebot.get_app()
|
||||
```
|
||||
|
||||
|
||||
## `get_asgi()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
获取全局 Driver 对应 Asgi 对象。
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Any`: Asgi 对象
|
||||
|
||||
|
||||
|
||||
* **异常**
|
||||
|
||||
|
||||
* `ValueError`: 全局 Driver 对象尚未初始化 (nonebot.init 尚未调用)
|
||||
|
||||
|
||||
|
||||
* **用法**
|
||||
|
||||
|
||||
```python
|
||||
asgi = nonebot.get_asgi()
|
||||
```
|
||||
|
||||
|
||||
## `get_bots()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
获取所有通过 ws 连接 NoneBot 的 Bot 对象。
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Dict[str, Bot]`: 一个以字符串 ID 为键,Bot 对象为值的字典
|
||||
|
||||
|
||||
|
||||
* **异常**
|
||||
|
||||
|
||||
* `ValueError`: 全局 Driver 对象尚未初始化 (nonebot.init 尚未调用)
|
||||
|
||||
|
||||
|
||||
* **用法**
|
||||
|
||||
|
||||
```python
|
||||
bots = nonebot.get_bots()
|
||||
```
|
||||
|
||||
|
||||
## `init(*, _env_file=None, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
初始化 NoneBot 以及 全局 Driver 对象。
|
||||
|
||||
NoneBot 将会从 .env 文件中读取环境信息,并使用相应的 env 文件配置。
|
||||
|
||||
你也可以传入自定义的 _env_file 来指定 NoneBot 从该文件读取配置。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `_env_file: Optional[str]`: 配置文件名,默认从 .env.{env_name} 中读取配置
|
||||
|
||||
|
||||
* `**kwargs`: 任意变量,将会存储到 Config 对象里
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `None`
|
||||
|
||||
|
||||
|
||||
* **用法**
|
||||
|
||||
|
||||
```python
|
||||
nonebot.init(database=Database(...))
|
||||
```
|
||||
|
||||
|
||||
## `run(host=None, port=None, *args, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
启动 NoneBot,即运行全局 Driver 对象。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `host: Optional[str]`: 主机名/IP,若不传入则使用配置文件中指定的值
|
||||
|
||||
|
||||
* `port: Optional[int]`: 端口,若不传入则使用配置文件中指定的值
|
||||
|
||||
|
||||
* `*args`: 传入 Driver.run 的位置参数
|
||||
|
||||
|
||||
* `**kwargs`: 传入 Driver.run 的命名参数
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `None`
|
||||
|
||||
|
||||
|
||||
* **用法**
|
||||
|
||||
|
||||
```python
|
||||
nonebot.run(host="127.0.0.1", port=8080)
|
||||
```
|
@@ -1,121 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.permission 模块
|
||||
|
||||
## 权限
|
||||
|
||||
每个 `Matcher` 拥有一个 `Permission` ,其中是 **异步** `PermissionChecker` 的集合,只要有一个 `PermissionChecker` 检查结果为 `True` 时就会继续运行。
|
||||
|
||||
:::tip 提示
|
||||
`PermissionChecker` 既可以是 async function 也可以是 sync function
|
||||
:::
|
||||
|
||||
|
||||
## `MESSAGE`
|
||||
|
||||
|
||||
* **说明**: 匹配任意 `message` 类型事件,仅在需要同时捕获不同类型事件时使用。优先使用 message type 的 Matcher。
|
||||
|
||||
|
||||
## `NOTICE`
|
||||
|
||||
|
||||
* **说明**: 匹配任意 `notice` 类型事件,仅在需要同时捕获不同类型事件时使用。优先使用 notice type 的 Matcher。
|
||||
|
||||
|
||||
## `REQUEST`
|
||||
|
||||
|
||||
* **说明**: 匹配任意 `request` 类型事件,仅在需要同时捕获不同类型事件时使用。优先使用 request type 的 Matcher。
|
||||
|
||||
|
||||
## `METAEVENT`
|
||||
|
||||
|
||||
* **说明**: 匹配任意 `meta_event` 类型事件,仅在需要同时捕获不同类型事件时使用。优先使用 meta_event type 的 Matcher。
|
||||
|
||||
|
||||
## `USER(*user, perm=<nonebot.permission.Permission object>)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
在白名单内且满足 perm
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `*user: int`: 白名单
|
||||
|
||||
|
||||
* `perm: Permission`: 需要同时满足的权限
|
||||
|
||||
|
||||
|
||||
## `PRIVATE`
|
||||
|
||||
|
||||
* **说明**: 匹配任意私聊消息类型事件
|
||||
|
||||
|
||||
## `PRIVATE_FRIEND`
|
||||
|
||||
|
||||
* **说明**: 匹配任意好友私聊消息类型事件
|
||||
|
||||
|
||||
## `PRIVATE_GROUP`
|
||||
|
||||
|
||||
* **说明**: 匹配任意群临时私聊消息类型事件
|
||||
|
||||
|
||||
## `PRIVATE_OTHER`
|
||||
|
||||
|
||||
* **说明**: 匹配任意其他私聊消息类型事件
|
||||
|
||||
|
||||
## `GROUP`
|
||||
|
||||
|
||||
* **说明**: 匹配任意群聊消息类型事件
|
||||
|
||||
|
||||
## `GROUP_MEMBER`
|
||||
|
||||
|
||||
* **说明**: 匹配任意群员群聊消息类型事件
|
||||
|
||||
:::warning 警告
|
||||
该权限通过 event.sender 进行判断且不包含管理员以及群主!
|
||||
:::
|
||||
|
||||
|
||||
## `GROUP_ADMIN`
|
||||
|
||||
|
||||
* **说明**: 匹配任意群管理员群聊消息类型事件
|
||||
|
||||
|
||||
## `GROUP_OWNER`
|
||||
|
||||
|
||||
* **说明**: 匹配任意群主群聊消息类型事件
|
||||
|
||||
|
||||
## `SUPERUSER`
|
||||
|
||||
|
||||
* **说明**: 匹配任意超级用户消息类型事件
|
||||
|
||||
|
||||
## `EVERYBODY`
|
||||
|
||||
|
||||
* **说明**: 匹配任意消息类型事件
|
@@ -1,202 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.rule 模块
|
||||
|
||||
## 规则
|
||||
|
||||
每个事件响应器 `Matcher` 拥有一个匹配规则 `Rule` ,其中是 **异步** `RuleChecker` 的集合,只有当所有 `RuleChecker` 检查结果为 `True` 时继续运行。
|
||||
|
||||
:::tip 提示
|
||||
`RuleChecker` 既可以是 async function 也可以是 sync function,但在最终会被 `nonebot.utils.run_sync` 转换为 async function
|
||||
:::
|
||||
|
||||
|
||||
## _class_ `Rule`
|
||||
|
||||
基类:`object`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
`Matcher` 规则类,当事件传递时,在 `Matcher` 运行前进行检查。
|
||||
|
||||
|
||||
|
||||
* **示例**
|
||||
|
||||
|
||||
```python
|
||||
Rule(async_function) & sync_function
|
||||
# 等价于
|
||||
from nonebot.utils import run_sync
|
||||
Rule(async_function, run_sync(sync_function))
|
||||
```
|
||||
|
||||
|
||||
### `__init__(*checkers)`
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `*checkers: Callable[[Bot, Event, dict], Awaitable[bool]]`: **异步** RuleChecker
|
||||
|
||||
|
||||
|
||||
### `checkers`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
存储 `RuleChecker`
|
||||
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
|
||||
* `Set[Callable[[Bot, Event, dict], Awaitable[bool]]]`
|
||||
|
||||
|
||||
|
||||
### _async_ `__call__(bot, event, state)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
检查是否符合所有规则
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `bot: Bot`: Bot 对象
|
||||
|
||||
|
||||
* `event: Event`: Event 对象
|
||||
|
||||
|
||||
* `state: dict`: 当前 State
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `bool`
|
||||
|
||||
|
||||
|
||||
## `startswith(msg)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
匹配消息开头
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `msg: str`: 消息开头字符串
|
||||
|
||||
|
||||
|
||||
## `endswith(msg)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
匹配消息结尾
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `msg: str`: 消息结尾字符串
|
||||
|
||||
|
||||
|
||||
## `keyword(msg)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
匹配消息关键词
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `msg: str`: 关键词
|
||||
|
||||
|
||||
|
||||
## `command(command)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
命令形式匹配,根据配置里提供的 `command_start`, `command_sep` 判断消息是否为命令。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `command: Tuples[str, ...]`: 命令内容
|
||||
|
||||
|
||||
|
||||
* **示例**
|
||||
|
||||
使用默认 `command_start`, `command_sep` 配置
|
||||
|
||||
命令 `("test",)` 可以匹配:`/test` 开头的消息
|
||||
命令 `("test", "sub")` 可以匹配”`/test.sub` 开头的消息
|
||||
|
||||
|
||||
:::tip 提示
|
||||
命令内容与后续消息间无需空格!
|
||||
:::
|
||||
|
||||
|
||||
## `regex(regex, flags=0)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
根据正则表达式进行匹配
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `regex: str`: 正则表达式
|
||||
|
||||
|
||||
* `flags: Union[int, re.RegexFlag]`: 正则标志
|
||||
|
||||
|
||||
|
||||
## `to_me()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
通过 `event.to_me` 判断消息是否是发送给机器人
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* 无
|
@@ -1,41 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.sched 模块
|
||||
|
||||
## 计划任务
|
||||
|
||||
计划任务使用第三方库 [APScheduler](https://github.com/agronholm/apscheduler) ,使用文档请参考 [APScheduler使用文档](https://apscheduler.readthedocs.io/en/latest/) 。
|
||||
|
||||
|
||||
## `scheduler`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Optional[apscheduler.schedulers.asyncio.AsyncIOScheduler]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
当可选依赖 `APScheduler` 未安装时,`scheduler` 为 None
|
||||
|
||||
使用 `pip install nonebot[scheduler]` 安装可选依赖
|
||||
|
||||
|
||||
|
||||
* **常用示例**
|
||||
|
||||
|
||||
```python
|
||||
from nonebot import scheduler
|
||||
|
||||
@scheduler.scheduled_job("cron", hour="*/2", id="xxx", args=[1], kwargs={arg2: 2})
|
||||
async def run_every_2_hour(arg1, arg2):
|
||||
pass
|
||||
|
||||
scheduler.add_job(run_every_day_from_program_start, "interval", days=1, id="xxx")
|
||||
```
|
@@ -1,252 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.typing 模块
|
||||
|
||||
## 类型
|
||||
|
||||
下面的文档中,「类型」部分使用 Python 的 Type Hint 语法,见 [PEP 484](https://www.python.org/dev/peps/pep-0484/)、[PEP 526](https://www.python.org/dev/peps/pep-0526/) 和 [typing](https://docs.python.org/3/library/typing.html)。
|
||||
|
||||
除了 Python 内置的类型,下面还出现了如下 NoneBot 自定类型,实际上它们是 Python 内置类型的别名。
|
||||
|
||||
以下类型均可从 nonebot.typing 模块导入。
|
||||
|
||||
|
||||
## `Driver`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`BaseDriver`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
所有 Driver 的基类。
|
||||
|
||||
|
||||
|
||||
|
||||
## `WebSocket`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`BaseWebSocket`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
所有 WebSocket 的基类。
|
||||
|
||||
|
||||
|
||||
|
||||
## `Bot`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`BaseBot`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
所有 Bot 的基类。
|
||||
|
||||
|
||||
|
||||
|
||||
## `Event`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`BaseEvent`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
所有 Event 的基类。
|
||||
|
||||
|
||||
|
||||
|
||||
## `Message`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`BaseMessage`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
所有 Message 的基类。
|
||||
|
||||
|
||||
|
||||
|
||||
## `MessageSegment`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`BaseMessageSegment`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
所有 MessageSegment 的基类。
|
||||
|
||||
|
||||
|
||||
|
||||
## `PreProcessor`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Callable[[Bot, Event, dict], Union[Awaitable[None], Awaitable[NoReturn]]]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
消息预处理函数 PreProcessor 类型
|
||||
|
||||
|
||||
|
||||
|
||||
## `Matcher`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Matcher`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
Matcher 即响应事件的处理类。通过 Rule 判断是否响应事件,运行 Handler。
|
||||
|
||||
|
||||
|
||||
|
||||
## `MatcherGroup`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`MatcherGroup`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
MatcherGroup 为 Matcher 的集合。可以共享 Handler。
|
||||
|
||||
|
||||
|
||||
|
||||
## `Rule`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Rule`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
Rule 即判断是否响应事件的处理类。内部存储 RuleChecker ,返回全为 True 则响应事件。
|
||||
|
||||
|
||||
|
||||
|
||||
## `RuleChecker`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Callable[[Bot, Event, dict], Union[bool, Awaitable[bool]]]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
RuleChecker 即判断是否响应事件的处理函数。
|
||||
|
||||
|
||||
|
||||
|
||||
## `Permission`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Permission`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
Permission 即判断是否响应消息的处理类。内部存储 PermissionChecker ,返回只要有一个 True 则响应消息。
|
||||
|
||||
|
||||
|
||||
|
||||
## `PermissionChecker`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Callable[[Bot, Event], Union[bool, Awaitable[bool]]]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
RuleChecker 即判断是否响应消息的处理函数。
|
||||
|
||||
|
||||
|
||||
|
||||
## `Handler`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Callable[[Bot, Event, dict], Union[Awaitable[None], Awaitable[NoReturn]]]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
Handler 即事件的处理函数。
|
||||
|
||||
|
||||
|
||||
|
||||
## `ArgsParser`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Callable[[Bot, Event, dict], Union[Awaitable[None], Awaitable[NoReturn]]]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
ArgsParser 即消息参数解析函数,在 Matcher.got 获取参数时被运行。
|
@@ -1,62 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.utils 模块
|
||||
|
||||
|
||||
## `escape_tag(s)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
用于记录带颜色日志时转义 `<tag>` 类型特殊标签
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `s: str`: 需要转义的字符串
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `str`
|
||||
|
||||
|
||||
|
||||
## `run_sync(func)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
一个用于包装 sync function 为 async function 的装饰器
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `func: Callable[..., Any]`: 被装饰的同步函数
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Callable[..., Awaitable[Any]]`
|
||||
|
||||
|
||||
|
||||
## _class_ `DataclassEncoder`
|
||||
|
||||
基类:`json.encoder.JSONEncoder`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
在JSON序列化 `Message` (List[Dataclass]) 时使用的 `JSONEncoder`
|
@@ -1,34 +0,0 @@
|
||||
# 概览
|
||||
|
||||
:::tip 提示
|
||||
如果在阅读本文档时遇到难以理解的词汇,请随时查阅 [术语表](../glossary.md) 或使用 [Google 搜索](https://www.google.com/)。
|
||||
:::
|
||||
|
||||
:::tip 提示
|
||||
初次使用时可能会觉得这里的概览过于枯燥,可以先简单略读之后直接前往 [安装](./installation.md) 查看安装方法,并进行后续的基础使用教程。
|
||||
:::
|
||||
|
||||
NoneBot2 是一个可扩展的 Python 异步机器人框架,它会对机器人收到的消息进行解析和处理,并以插件化的形式,分发给消息所对应的命令处理器和自然语言处理器,来完成具体的功能。
|
||||
|
||||
除了起到解析消息的作用,NoneBot 还为插件提供了大量实用的预设操作和权限控制机制,尤其对于命令处理器,它更是提供了完善且易用的会话机制和内部调用机制,以分别适应命令的连续交互和插件内部功能复用等需求。
|
||||
|
||||
目前 NoneBot2 在 [FastAPI](https://fastapi.tiangolo.com/) 的基础上封装了与 [CQHTTP(OneBot) 协议](http://cqhttp.cc/)插件的网络交互。
|
||||
|
||||
得益于 Python 的 [asyncio](https://docs.python.org/3/library/asyncio.html) 机制,NoneBot 处理消息的吞吐量有了很大的保障,再配合 WebSocket 通信方式(也是最建议的通信方式),NoneBot 的性能可以达到 HTTP 通信方式的两倍以上,相较于传统同步 I/O 的 HTTP 通信,更是有质的飞跃。
|
||||
|
||||
需要注意的是,NoneBot 仅支持 Python 3.7+ 及 CQHTTP(OneBot) 插件 v11+。
|
||||
|
||||
## 它如何工作?
|
||||
|
||||
~~未填坑~~
|
||||
|
||||
## 特色
|
||||
|
||||
- 提供直观的测试前端
|
||||
- 提供使用简易的脚手架
|
||||
- 基于异步 I/O
|
||||
- 同时支持 HTTP 和反向 WebSocket 通信方式
|
||||
- 支持多个机器人账号负载均衡
|
||||
- 提供直观的交互式会话接口
|
||||
- 提供可自定义的权限控制机制
|
||||
- 多种方式渲染要发送的消息内容,使对话足够自然
|
@@ -1,68 +0,0 @@
|
||||
# 基本配置
|
||||
|
||||
到目前为止我们还在使用 NoneBot 的默认行为,在开始编写自己的插件之前,我们先尝试在配置文件上动动手脚,让 NoneBot 表现出不同的行为。
|
||||
|
||||
在上一章节中,我们创建了默认的项目结构,其中 `.env`, `.env.*` 均为项目的配置文件,下面将介绍几种 NoneBot 配置方式。
|
||||
|
||||
:::danger 警告
|
||||
请勿将敏感信息写入配置文件并提交至开源仓库!
|
||||
:::
|
||||
|
||||
## .env 文件
|
||||
|
||||
NoneBot 在启动时将会从系统环境变量或者 `.env` 文件中寻找变量 `ENVIRONMENT` (大小写不敏感),默认值为 `prod`。
|
||||
这将引导 NoneBot 从系统环境变量或者 `.env.{ENVIRONMENT}` 文件中进一步加载具体配置。
|
||||
|
||||
现在,我们在 `.env` 文件中写入当前环境信息
|
||||
|
||||
```bash
|
||||
# .env
|
||||
ENVIRONMENT=dev
|
||||
```
|
||||
|
||||
## .env.\* 文件
|
||||
|
||||
详细配置文件,使用 [pydantic](https://pydantic-docs.helpmanual.io/) 加载配置。在 NoneBot 初始化时可以指定忽略 `.env` 中的环境信息转而加载某个配置文件: `nonebot.init(_env_file=".env.dev")`。
|
||||
|
||||
:::warning 提示
|
||||
由于 `pydantic` 使用 JSON 加载配置项,请确保配置项值为 JSON 能够解析的数据。如果 JSON 解析失败将作为字符串处理。
|
||||
:::
|
||||
|
||||
示例及说明:
|
||||
|
||||
```bash
|
||||
HOST=0.0.0.0 # 配置 NoneBot 监听的 IP/主机名
|
||||
PORT=8080 # 配置 NoneBot 监听的端口
|
||||
DEBUG=true # 开启 debug 模式 **请勿在生产环境开启**
|
||||
SUPERUSERS=["123456789", "987654321"] # 配置 NoneBot 超级用户
|
||||
NICKNAME=["awesome", "bot"] # 配置机器人的昵称
|
||||
COMMAND_START=["/", ""] # 配置命令起始字符
|
||||
COMMAND_SEP=["."] # 配置命令分割字符
|
||||
|
||||
# Custom Configs
|
||||
CUSTOM_CONFIG1="config in env file"
|
||||
CUSTOM_CONFIG2= # 留空则从系统环境变量读取,如不存在则为空字符串
|
||||
```
|
||||
|
||||
详细的配置项参考 [Config Reference](../api/config.md) 。
|
||||
|
||||
## bot.py 文件
|
||||
|
||||
配置项也可以在 NoneBot 初始化时传入。此处可以传入任意合法 Python 变量。当然也可以在初始化完成后修改或新增。
|
||||
|
||||
示例:
|
||||
|
||||
```python
|
||||
# bot.py
|
||||
import nonebot
|
||||
|
||||
nonebot.init(custom_config3="config on init")
|
||||
|
||||
config = nonebot.get_driver().config
|
||||
config.custom_config3 = "changed after init"
|
||||
config.custom_config4 = "new config after init"
|
||||
```
|
||||
|
||||
## 优先级
|
||||
|
||||
`bot.py init` > `env file` > `system env`
|
@@ -1,55 +0,0 @@
|
||||
# 创建一个完整的项目
|
||||
|
||||
上一章中我们已经运行了一个最小的 NoneBot 实例,在这一章,我们将从零开始一个完整的项目。
|
||||
|
||||
## 目录结构
|
||||
|
||||
首先,我们可以使用 `nb-cli` 或者自行创建项目目录:
|
||||
|
||||
```bash
|
||||
pip install nonebot2[cli]
|
||||
# pip install nb-cli
|
||||
nb create
|
||||
```
|
||||
|
||||
这将创建默认的目录结构
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
:::vue
|
||||
AweSome-Bot
|
||||
├── `awesome_bot` _(**或是 src**)_
|
||||
│ └── `plugins`
|
||||
├── `.env` _(**可选的**)_
|
||||
├── `.env.dev` _(**可选的**)_
|
||||
├── `.env.prod` _(**可选的**)_
|
||||
├── .gitignore
|
||||
├── `bot.py`
|
||||
├── docker-compose.yml
|
||||
├── Dockerfile
|
||||
├── `pyproject.toml`
|
||||
└── README.md
|
||||
:::
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
- `awesome_bot/plugins` 或 `src/plugins`: 用于存放编写的 bot 插件
|
||||
- `.env`, `.env.dev`, `.env.prod`: 各环境配置文件
|
||||
- `bot.py`: bot 入口文件
|
||||
- `pyproject.toml`: 项目依赖管理文件,默认使用 [poetry](https://python-poetry.org/)
|
||||
|
||||
## 启动 Bot
|
||||
|
||||
如果你使用 `nb-cli`
|
||||
|
||||
```bash
|
||||
nb run [--file=bot.py] [--app=app]
|
||||
```
|
||||
|
||||
或者使用
|
||||
|
||||
```bash
|
||||
python bot.py
|
||||
```
|
||||
|
||||
:::tip 提示
|
||||
如果在 bot 入口文件内定义了 asgi server, `nb-cli` 将会为你启动**冷重载模式**
|
||||
:::
|
@@ -1,146 +0,0 @@
|
||||
# 开始使用
|
||||
|
||||
一切都安装成功后,你就已经做好了进行简单配置以运行一个最小的 NoneBot 实例的准备。
|
||||
|
||||
## 最小实例
|
||||
|
||||
使用你最熟悉的编辑器或 IDE,创建一个名为 `bot.py` 的文件,内容如下:
|
||||
|
||||
```python{3,4,7}
|
||||
import nonebot
|
||||
|
||||
nonebot.init()
|
||||
nonebot.load_builtin_plugins()
|
||||
|
||||
if __name__ == "__main__":
|
||||
nonebot.run()
|
||||
```
|
||||
|
||||
这几行高亮代码将依次:
|
||||
|
||||
1. 使用默认配置初始化 NoneBot 包
|
||||
2. 加载 NoneBot 内置的插件
|
||||
3. 在地址 `127.0.0.1:8080` 运行 NoneBot
|
||||
|
||||
在命令行使用如下命令即可运行这个 NoneBot 实例:
|
||||
|
||||
```bash
|
||||
python bot.py
|
||||
```
|
||||
|
||||
运行后会产生如下日志:
|
||||
|
||||
```default
|
||||
09-14 21:02:00 [INFO] nonebot | Succeeded to import "nonebot.plugins.base"
|
||||
09-14 21:02:00 [INFO] nonebot | Running NoneBot...
|
||||
09-14 21:02:00 [INFO] uvicorn | Started server process [1234]
|
||||
09-14 21:02:00 [INFO] uvicorn | Waiting for application startup.
|
||||
09-14 21:02:00 [INFO] nonebot | Scheduler Started
|
||||
09-14 21:02:00 [INFO] uvicorn | Application startup complete.
|
||||
09-14 21:02:00 [INFO] uvicorn | Uvicorn running on http://127.0.0.1:8080 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
## 配置 QQ 协议端
|
||||
|
||||
单纯运行 NoneBot 实例并不会产生任何效果,因为此刻 QQ 这边还不知道 NoneBot 的存在,也就无法把消息发送给它,因此现在需要使用一个无头 QQ 来把消息等事件上报给 NoneBot。
|
||||
|
||||
目前支持的协议有:
|
||||
|
||||
- [OneBot(CQHTTP)](https://github.com/howmanybots/onebot)
|
||||
|
||||
QQ 协议端举例:
|
||||
|
||||
- [Mirai](https://github.com/mamoe/mirai) + [cqhttp-mirai](https://github.com/yyuueexxiinngg/cqhttp-mirai)
|
||||
- [cqhttp-mirai-embedded](https://github.com/yyuueexxiinngg/cqhttp-mirai/tree/embedded)
|
||||
- [Mirai](https://github.com/mamoe/mirai) + [Mirai Native](https://github.com/iTXTech/mirai-native) + [CQHTTP](https://github.com/richardchien/coolq-http-api)
|
||||
- [go-cqhttp](https://github.com/Mrs4s/go-cqhttp) (基于 [MiraiGo](https://github.com/Mrs4s/MiraiGo))
|
||||
- [OICQ-http-api](https://github.com/takayama-lily/onebot) (基于 [OICQ](https://github.com/takayama-lily/oicq))
|
||||
|
||||
这里以 [go-cqhttp](https://github.com/Mrs4s/go-cqhttp) 为例
|
||||
|
||||
1. 下载 go-cqhttp 对应平台的 release 文件
|
||||
2. 双击 exe 文件或者使用 `./go-cqhttp` 启动
|
||||
3. 生成默认配置文件并修改默认配置
|
||||
|
||||
```json{2,3,30-31}
|
||||
{
|
||||
"uin": 你的QQ号,
|
||||
"password": "你的密码",
|
||||
"encrypt_password": false,
|
||||
"password_encrypted": "",
|
||||
"enable_db": true,
|
||||
"access_token": "",
|
||||
"relogin": {
|
||||
"enabled": true,
|
||||
"relogin_delay": 3,
|
||||
"max_relogin_times": 0
|
||||
},
|
||||
"ignore_invalid_cqcode": false,
|
||||
"force_fragmented": true,
|
||||
"heartbeat_interval": 0,
|
||||
"http_config": {
|
||||
"enabled": false,
|
||||
"host": "0.0.0.0",
|
||||
"port": 5700,
|
||||
"timeout": 0,
|
||||
"post_urls": {}
|
||||
},
|
||||
"ws_config": {
|
||||
"enabled": false,
|
||||
"host": "0.0.0.0",
|
||||
"port": 6700
|
||||
},
|
||||
"ws_reverse_servers": [
|
||||
{
|
||||
"enabled": true,
|
||||
"reverse_url": "ws://127.0.0.1:8080/cqhttp/ws",
|
||||
"reverse_api_url": "",
|
||||
"reverse_event_url": "",
|
||||
"reverse_reconnect_interval": 3000
|
||||
}
|
||||
],
|
||||
"post_message_format": "string",
|
||||
"debug": false,
|
||||
"log_level": ""
|
||||
}
|
||||
```
|
||||
|
||||
其中 `ws://127.0.0.1:8080/cqhttp/ws` 中的 `127.0.0.1` 和 `8080` 应分别对应 nonebot 配置的 HOST 和 PORT
|
||||
|
||||
## 历史性的第一次对话
|
||||
|
||||
一旦新的配置文件正确生效之后,NoneBot 所在的控制台(如果正在运行的话)应该会输出类似下面的内容(两条访问日志):
|
||||
|
||||
```default
|
||||
09-14 21:31:16 [INFO] uvicorn | ('127.0.0.1', 12345) - "WebSocket /cqhttp/ws" [accepted]
|
||||
09-14 21:31:16 [INFO] nonebot | WebSocket Connection from CQHTTP Bot 你的QQ号 Accepted!
|
||||
```
|
||||
|
||||
这表示 QQ 协议端已经成功地使用 CQHTTP 协议连接上了 NoneBot。
|
||||
|
||||
:::warning 注意
|
||||
如果到这一步你没有看到上面这样的成功日志,CQHTTP 的日志中在不断地重连或无反应,请注意检查配置中的 IP 和端口是否确实可以访问。比较常见的出错点包括:
|
||||
|
||||
- NoneBot 监听 `0.0.0.0`,然后在 CQHTTP 配置中填了 `ws://0.0.0.0:8080/cqhttp/ws`
|
||||
- 在 Docker 容器内运行 CQHTTP,并通过 `127.0.0.1` 访问宿主机上的 NoneBot
|
||||
- 想从公网访问,但没有修改云服务商的安全组策略或系统防火墙
|
||||
- NoneBot 所监听的端口存在冲突,已被其它程序占用
|
||||
- 弄混了 NoneBot 的 `host`、`port` 参数与 CQHTTP 配置中的 `host`、`port` 参数
|
||||
- 使用了 `ws_reverse_api_url` 和 `ws_reverse_event_url` 而非 universal client
|
||||
- `ws://` 错填为 `http://`
|
||||
- CQHTTP 或 NoneBot 启动时遭到外星武器干扰
|
||||
|
||||
请尝试重启 CQHTTP、重启 NoneBot、更换端口、修改防火墙、重启系统、仔细阅读前面的文档及提示、更新 CQHTTP 和 NoneBot 到最新版本等方式来解决。
|
||||
:::
|
||||
|
||||
现在,尝试向你的 QQ 机器人账号发送如下内容:
|
||||
|
||||
```default
|
||||
/say 你好,世界
|
||||
```
|
||||
|
||||
到这里如果一切 OK,你应该会收到机器人给你回复了 `你好,世界`。这一历史性的对话标志着你已经成功地运行了一个 NoneBot 的最小实例,开始了编写更强大的 QQ 机器人的创意之旅!
|
||||
|
||||
<ClientOnly>
|
||||
<Messenger :messages="[{ position: 'right', msg: '/say 你好,世界' }, { position: 'left', msg: '你好,世界' }]"/>
|
||||
</ClientOnly>
|
@@ -1,73 +0,0 @@
|
||||
# 安装
|
||||
|
||||
## NoneBot
|
||||
|
||||
:::warning 注意
|
||||
请确保你的 Python 版本 >= 3.7。
|
||||
:::
|
||||
|
||||
```bash
|
||||
pip install nonebot2
|
||||
```
|
||||
|
||||
如果你需要使用最新的(可能尚未发布的)特性,可以克隆 Git 仓库后手动安装:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/nonebot/nonebot2.git
|
||||
cd nonebot2
|
||||
poetry install --no-dev # 推荐
|
||||
pip install . # 不推荐
|
||||
```
|
||||
|
||||
## 额外依赖
|
||||
|
||||
### APScheduler
|
||||
|
||||
A task scheduling library for Python.
|
||||
|
||||
可用于计划任务,后台执行任务等
|
||||
|
||||
```bash
|
||||
pip install nonebot2[scheduler]
|
||||
poetry add nonebot2[scheduler]
|
||||
```
|
||||
|
||||
[View On GitHub](https://github.com/agronholm/apscheduler)
|
||||
|
||||
### NoneBot-Test
|
||||
|
||||
A test frontend for nonebot2.
|
||||
|
||||
通过前端展示 nonebot 已加载的插件以及运行状态,同时可以用于模拟发送事件测试机器人
|
||||
|
||||
```bash
|
||||
pip install nonebot2[test]
|
||||
poetry add nonebot2[test]
|
||||
```
|
||||
|
||||
[View On GitHub](https://github.com/nonebot/nonebot-test)
|
||||
|
||||
### CLI
|
||||
|
||||
CLI for nonebot2.
|
||||
|
||||
一个多功能脚手架
|
||||
|
||||
```bash
|
||||
pip install nonebot2[cli]
|
||||
poetry add nonebot2[cli]
|
||||
```
|
||||
|
||||
[View On GitHub](https://github.com/yanyongyu/nb-cli)
|
||||
|
||||
### 我全都要
|
||||
|
||||
```bash
|
||||
pip install nonebot2[full]
|
||||
poetry add nonebot2[full]
|
||||
```
|
||||
|
||||
```bash
|
||||
pip install nonebot2[cli,scheduler]
|
||||
poetry add nonebot2[cli,scheduler]
|
||||
```
|
@@ -1,290 +0,0 @@
|
||||
# 编写插件
|
||||
|
||||
本章将以一个天气查询插件为例,教学如何编写自己的命令。
|
||||
|
||||
## 加载插件
|
||||
|
||||
在 [创建一个完整的项目](creating-a-project) 一章节中,我们已经创建了插件目录 `awesome_bot/plugins`,现在我们在机器人入口文件中加载它。当然,你也可以单独加载一个插件。
|
||||
|
||||
:::tip 提示
|
||||
加载插件目录时,目录下以 `_` 下划线开头的插件将不会被加载!
|
||||
:::
|
||||
|
||||
在 `bot.py` 文件中添加以下行:
|
||||
|
||||
```python{5,7}
|
||||
import nonebot
|
||||
|
||||
nonebot.init()
|
||||
# 加载单独的一个插件,参数为合法的python包名
|
||||
nonebot.load_plugin("nonebot.plugins.base")
|
||||
# 加载插件目录,该目录下为各插件,以下划线开头的插件将不会被加载
|
||||
nonebot.load_plugins("awesome_bot/plugins")
|
||||
|
||||
app = nonebot.get_asgi()
|
||||
|
||||
if __name__ == "__main__":
|
||||
nonebot.run()
|
||||
```
|
||||
|
||||
尝试运行 `nb run` 或者 `python bot.py`,可以看到日志输出了类似如下内容:
|
||||
|
||||
```plain
|
||||
09-19 21:51:59 [INFO] nonebot | Succeeded to import "nonebot.plugins.base"
|
||||
09-19 21:51:59 [INFO] nonebot | Succeeded to import "plugin_in_folder"
|
||||
```
|
||||
|
||||
## 创建插件
|
||||
|
||||
现在我们已经有了一个空的插件目录,我们可以开始创建插件了!插件有两种形式
|
||||
|
||||
### 单文件形式
|
||||
|
||||
在插件目录下创建名为 `weather.py` 的 Python 文件,暂时留空,此时目录结构如下:
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
:::vue
|
||||
AweSome-Bot
|
||||
├── awesome_bot
|
||||
│ └── plugins
|
||||
│ └── `weather.py`
|
||||
├── .env
|
||||
├── .env.dev
|
||||
├── .env.prod
|
||||
├── .gitignore
|
||||
├── bot.py
|
||||
├── docker-compose.yml
|
||||
├── Dockerfile
|
||||
├── pyproject.toml
|
||||
└── README.md
|
||||
:::
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
这个时候它已经可以被称为一个插件了,尽管它还什么都没做。
|
||||
|
||||
### 包形式
|
||||
|
||||
在插件目录下创建文件夹 `weather`,并在该文件夹下创建文件 `__init__.py`,此时目录结构如下:
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
:::vue
|
||||
AweSome-Bot
|
||||
├── awesome_bot
|
||||
│ └── plugins
|
||||
│ └── `weather`
|
||||
│ └── `__init__.py`
|
||||
├── .env
|
||||
├── .env.dev
|
||||
├── .env.prod
|
||||
├── .gitignore
|
||||
├── bot.py
|
||||
├── docker-compose.yml
|
||||
├── Dockerfile
|
||||
├── pyproject.toml
|
||||
└── README.md
|
||||
:::
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
这个时候 `weather` 就是一个合法的 Python 包了,同时也是合法的 NoneBot 插件,插件内容可以在 `__init__.py` 中编写。
|
||||
|
||||
## 编写真正的内容
|
||||
|
||||
好了,现在插件已经可以正确加载,我们可以开始编写命令的实际代码了。在 `weather.py` 中添加如下代码:
|
||||
|
||||
```python
|
||||
from nonebot import on_command
|
||||
from nonebot.rule import to_me
|
||||
from nonebot.adapters.cqhttp import Bot, Event
|
||||
|
||||
weather = on_command("天气", rule=to_me(), priority=5)
|
||||
|
||||
|
||||
@weather.handle()
|
||||
async def handle_first_receive(bot: Bot, event: Event, state: dict):
|
||||
args = str(event.message).strip() # 首次发送命令时跟随的参数,例:/天气 上海,则args为上海
|
||||
if args:
|
||||
state["city"] = args # 如果用户发送了参数则直接赋值
|
||||
|
||||
|
||||
@weather.got("city", prompt="你想查询哪个城市的天气呢?")
|
||||
async def handle_city(bot: Bot, event: Event, state: dict):
|
||||
city = state["city"]
|
||||
if city not in ["上海", "北京"]:
|
||||
await weather.reject("你想查询的城市暂不支持,请重新输入!")
|
||||
city_weather = await get_weather(city)
|
||||
await weather.finish(city_weather)
|
||||
|
||||
|
||||
async def get_weather(city: str):
|
||||
return f"{city}的天气是..."
|
||||
```
|
||||
|
||||
为了简单起见,我们在这里的例子中没有接入真实的天气数据,但要接入也非常简单,你可以使用中国天气网、和风天气等网站提供的 API。
|
||||
|
||||
下面我们来说明这段代码是如何工作的。
|
||||
|
||||
:::tip 提示
|
||||
从这里开始,你需要对 Python 的 asyncio 编程有所了解,因为 NoneBot 是完全基于 asyncio 的,具体可以参考 [廖雪峰的 Python 教程](https://www.liaoxuefeng.com/wiki/1016959663602400/1017959540289152)
|
||||
:::
|
||||
|
||||
### 注册一个 [事件响应器](../api/matcher.md)
|
||||
|
||||
```python{4}
|
||||
from nonebot import on_command
|
||||
from nonebot.rule import to_me
|
||||
from nonebot.permission import Permission
|
||||
|
||||
weather = on_command("天气", rule=to_me(), permission=Permission(), priority=5)
|
||||
```
|
||||
|
||||
在上方代码中,我们注册了一个事件响应器 `Matcher`,它由几个部分组成:
|
||||
|
||||
1. `on_command` 注册一个消息类型的命令处理器
|
||||
2. `"天气"` 指定 command 参数 - 命令名
|
||||
3. `rule` 补充事件响应器的匹配规则
|
||||
4. `priority` 事件响应器优先级
|
||||
5. `block` 是否阻止事件传递
|
||||
|
||||
其他详细配置可以参考 API 文档,下面我们详细说明各个部分:
|
||||
|
||||
#### 事件响应器类型 type
|
||||
|
||||
事件响应器类型其实就是对应 `Event.type` ,NoneBot 提供了一个基础类型事件响应器 `on()` 以及一些内置的事件响应器。
|
||||
|
||||
- `on("事件类型")`: 基础事件响应器,第一个参数为事件类型,空字符串表示不限
|
||||
- `on_metaevent()` ~ `on("meta_event")`: 元事件响应器
|
||||
- `on_message()` ~ `on("message")`: 消息事件响应器
|
||||
- `on_request()` ~ `on("request")`: 请求事件响应器
|
||||
- `on_notice()` ~ `on("notice")`: 通知事件响应器
|
||||
- `on_startswith(str)` ~ `on("message", startswith(str))`: 消息开头匹配处理器
|
||||
- `on_endswith(str)` ~ `on("message", endswith(str))`: 消息结尾匹配处理器
|
||||
- `on_command(str|tuple)` ~ `on("message", command(str|tuple))`: 命令处理器
|
||||
- `on_regex(pattern_str)` ~ `on("message", regex(pattern_str))`: 正则匹配处理器
|
||||
|
||||
#### 匹配规则 rule
|
||||
|
||||
事件响应器的匹配规则即 `Rule`,由非负个 `RuleChecker` 组成,当所有 `RuleChecker` 返回 `True` 时匹配成功。这些 `RuleChecker` 的形式如下:
|
||||
|
||||
```python
|
||||
async def check(bot: Bot, event: Event, state: dict) -> bool:
|
||||
return True
|
||||
|
||||
def check(bot: Bot, event: Event, state: dict) -> bool:
|
||||
return True
|
||||
```
|
||||
|
||||
`Rule` 和 `RuleChecker` 之间可以使用 `与 &` 互相组合:
|
||||
|
||||
```python
|
||||
from nonebot.rule import Rule
|
||||
|
||||
Rule(async_checker1) & sync_checker & async_checker2
|
||||
```
|
||||
|
||||
:::danger 警告
|
||||
`Rule(*checkers)` 只接受 async function,或使用 `nonebot.utils.run_sync` 自行包裹 sync function。在使用 `与 &` 时,NoneBot 会自动包裹 sync function
|
||||
:::
|
||||
|
||||
#### 优先级 priority
|
||||
|
||||
事件响应器的优先级代表事件响应器的执行顺序,同一优先级的事件响应器会 **同时执行!**
|
||||
|
||||
:::tip 提示
|
||||
使用 `nonebot-test` 可以看到当前所有事件响应器的执行流程,有助理解事件响应流程!
|
||||
|
||||
```bash
|
||||
pip install nonebot2[test]
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
#### 阻断 block
|
||||
|
||||
当有任意事件响应器发出了阻止事件传递信号时,该事件将不再会传递给下一优先级,直接结束处理。
|
||||
|
||||
NoneBot 内置的事件响应器中,所有 `message` 类的事件响应器默认会阻断事件传递,其他则不会。
|
||||
|
||||
### 编写事件处理函数 [Handler](../api/typing.md#handler)
|
||||
|
||||
```python{1,2,8,9}
|
||||
@weather.handle()
|
||||
async def handle_first_receive(bot: Bot, event: Event, state: dict):
|
||||
args = str(event.message).strip() # 首次发送命令时跟随的参数,例:/天气 上海,则args为上海
|
||||
if args:
|
||||
state["city"] = args # 如果用户发送了参数则直接赋值
|
||||
|
||||
|
||||
@weather.got("city", prompt="你想查询哪个城市的天气呢?")
|
||||
async def handle_city(bot: Bot, event: Event, state: dict):
|
||||
city = state["city"]
|
||||
if city not in ["上海", "北京"]:
|
||||
await weather.reject("你想查询的城市暂不支持,请重新输入!")
|
||||
city_weather = await get_weather(city)
|
||||
await weather.finish(city_weather)
|
||||
```
|
||||
|
||||
在上面的代码中,我们给 `weather` 事件响应器添加了两个事件处理函数:`handle_first_receive`, `handle_city`
|
||||
|
||||
其中有几个要点,我们一一解释:
|
||||
|
||||
#### 添加一个事件处理函数
|
||||
|
||||
在事件响应器响应事件时,事件处理函数会依次顺序执行,也就是说,与添加顺序一致。
|
||||
|
||||
我们可以使用 `@matcher.handle()` 装饰器来简单地为该事件响应器添加一个处理函数。
|
||||
|
||||
同时,NoneBot 内置了几种添加事件处理函数方式以方便处理:
|
||||
|
||||
- `@matcher.receive()`: 指示 NoneBot 接收一条新的用户消息以继续执行后续处理函数。
|
||||
- `@matcher.got(key, [prompt="请输入key"], [args_parser=function])`: 指示 NoneBot 当 `state` 中不存在 `key` 时向用户发送 `prompt` 等待用户回复并赋值给 `state[key]`
|
||||
|
||||
这些装饰器可以套娃使用!例如:
|
||||
|
||||
```python
|
||||
@matcher.got("key1")
|
||||
@matcher.got("key2")
|
||||
async def handle(bot: Bot, event: Event, state: dict):
|
||||
pass
|
||||
```
|
||||
|
||||
#### 事件处理函数参数
|
||||
|
||||
事件处理函数类型为 `Callable[[Bot, Event, dict], Union[Awaitable[None], Awaitable[NoReturn]]]` 。
|
||||
|
||||
参数分别为:
|
||||
|
||||
1. [nonebot.typing.Bot](../api/typing.md#bot): 即事件上报连接对应的 Bot 对象,为 BaseBot 的子类。特别注意,此处的类型注释可以替换为指定的 Bot 类型,例如:`nonebot.adapters.cqhttp.Bot`,只有在上报事件的 Bot 类型与类型注释相符时才会执行该处理函数!可用于多平台进行不同的处理。
|
||||
2. [nonebot.typing.Event](../api/typing.md#event): 即上报事件对象,可以获取到上报的所有信息。
|
||||
3. `state`: 状态字典,可以存储任意的信息
|
||||
|
||||
#### 处理事件
|
||||
|
||||
在事件处理函数中,我们只需要对 `event` 做出相应的处理,存入状态字典 `state` 中,或者向用户发送消息、调用某个机器人 API 等等。
|
||||
|
||||
在 NoneBot 中,提供了几种特殊的处理函数:
|
||||
|
||||
##### `@matcher.args_parser`
|
||||
|
||||
这是一个装饰器,装饰一个函数来使它成为参数的默认解析函数,当使用 `matcher.got(xxx, [args_parser])` 获取到一条消息时,会运行 `matcher.got` 的 `args_parser` ,如果不存在则运行 `@matcher.args_parser`。
|
||||
|
||||
##### `matcher.pause`
|
||||
|
||||
这个函数用于结束当前事件处理函数,强制接收一条新的消息再运行**下一个消息处理函数**。
|
||||
|
||||
##### `matcher.reject`
|
||||
|
||||
这个函数用于结束当前事件处理函数,强制接收一条新的消息再**再次运行当前消息处理函数**。
|
||||
|
||||
##### `matcher.finish`
|
||||
|
||||
这个函数用于直接结束当前事件处理。
|
||||
|
||||
以上三个函数都拥有一个参数 `prompt`,用于向用户发送一条消息。
|
||||
|
||||
## 结语
|
||||
|
||||
至此,相信你已经能够写出一个基础的插件了,更多的用法将会在 进阶 部分进行介绍,这里给出几个小提示:
|
||||
|
||||
- 请千万注意事件处理器的优先级设定
|
||||
- 在匹配规则中请勿使用耗时极长的函数
|
||||
- 同一个用户可以跨群(私聊)继续他的事件处理(除非做出权限限制,将在后续介绍)
|
@@ -1,108 +0,0 @@
|
||||
{
|
||||
"locales": {
|
||||
"/": {
|
||||
"label": "简体中文",
|
||||
"selectText": "Languages",
|
||||
"editLinkText": "在 GitHub 上编辑此页",
|
||||
"lastUpdated": "上次更新",
|
||||
"nav": [
|
||||
{
|
||||
"text": "主页",
|
||||
"link": "/"
|
||||
},
|
||||
{
|
||||
"text": "指南",
|
||||
"link": "/guide/"
|
||||
},
|
||||
{
|
||||
"text": "API",
|
||||
"link": "/api/"
|
||||
}
|
||||
],
|
||||
"sidebarDepth": 2,
|
||||
"sidebar": {
|
||||
"/guide/": [
|
||||
{
|
||||
"title": "指南",
|
||||
"path": "",
|
||||
"collapsable": false,
|
||||
"sidebar": "auto",
|
||||
"children": [
|
||||
"",
|
||||
"installation",
|
||||
"getting-started",
|
||||
"creating-a-project",
|
||||
"basic-configuration",
|
||||
"writing-a-plugin"
|
||||
]
|
||||
}
|
||||
],
|
||||
"/api/": [
|
||||
{
|
||||
"title": "NoneBot Api Reference",
|
||||
"path": "",
|
||||
"collapsable": false,
|
||||
"children": [
|
||||
{
|
||||
"title": "nonebot 模块",
|
||||
"path": "nonebot"
|
||||
},
|
||||
{
|
||||
"title": "nonebot.config 模块",
|
||||
"path": "config"
|
||||
},
|
||||
{
|
||||
"title": "nonebot.matcher 模块",
|
||||
"path": "matcher"
|
||||
},
|
||||
{
|
||||
"title": "nonebot.rule 模块",
|
||||
"path": "rule"
|
||||
},
|
||||
{
|
||||
"title": "nonebot.permission 模块",
|
||||
"path": "permission"
|
||||
},
|
||||
{
|
||||
"title": "nonebot.sched 模块",
|
||||
"path": "sched"
|
||||
},
|
||||
{
|
||||
"title": "nonebot.log 模块",
|
||||
"path": "log"
|
||||
},
|
||||
{
|
||||
"title": "nonebot.utils 模块",
|
||||
"path": "utils"
|
||||
},
|
||||
{
|
||||
"title": "nonebot.typing 模块",
|
||||
"path": "typing"
|
||||
},
|
||||
{
|
||||
"title": "nonebot.exception 模块",
|
||||
"path": "exception"
|
||||
},
|
||||
{
|
||||
"title": "nonebot.drivers 模块",
|
||||
"path": "drivers/"
|
||||
},
|
||||
{
|
||||
"title": "nonebot.drivers.fastapi 模块",
|
||||
"path": "drivers/fastapi"
|
||||
},
|
||||
{
|
||||
"title": "nonebot.adapters 模块",
|
||||
"path": "adapters/"
|
||||
},
|
||||
{
|
||||
"title": "nonebot.adapters.cqhttp 模块",
|
||||
"path": "adapters/cqhttp"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,219 +0,0 @@
|
||||
<template>
|
||||
<div class="qq-chat">
|
||||
<v-app>
|
||||
<v-main>
|
||||
<v-card class="elevation-6">
|
||||
<v-toolbar color="primary" dark dense flat>
|
||||
<v-row no-gutters>
|
||||
<v-col>
|
||||
<v-row no-gutters justify="space-between">
|
||||
<v-col cols="auto">
|
||||
<v-icon small>fa-chevron-left</v-icon>
|
||||
</v-col>
|
||||
<v-col cols="auto">
|
||||
<h3>🔥</h3>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-col>
|
||||
<v-col cols="auto">
|
||||
<h3 class="white--text">NoneBot</h3>
|
||||
</v-col>
|
||||
<v-col class="text-right">
|
||||
<v-icon small>fa-user</v-icon>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-toolbar>
|
||||
<v-container fluid ref="chat" class="chat chat-bg">
|
||||
<template v-for="(item, index) in messages">
|
||||
<v-row
|
||||
v-if="item.position === 'right'"
|
||||
justify="end"
|
||||
:key="index"
|
||||
class="message wow animate__fadeInRight"
|
||||
data-wow-duration="0.7s"
|
||||
>
|
||||
<div
|
||||
class="message-box"
|
||||
v-html="
|
||||
item.msg.replace(/\n/g, '<br/>').replace(/ /g, ' ')
|
||||
"
|
||||
></div>
|
||||
<v-avatar color="blue lighten-2" size="36">
|
||||
<v-icon small>fa-user</v-icon>
|
||||
</v-avatar>
|
||||
</v-row>
|
||||
<v-row
|
||||
v-else-if="item.position === 'left'"
|
||||
justify="start"
|
||||
:key="index"
|
||||
class="message wow animate__fadeInLeft"
|
||||
data-wow-duration="0.7s"
|
||||
>
|
||||
<v-avatar color="transparent" size="36">
|
||||
<v-img src="/logo.png"></v-img>
|
||||
</v-avatar>
|
||||
<div
|
||||
class="message-box"
|
||||
v-html="
|
||||
item.msg.replace(/\n/g, '<br/>').replace(/ /g, ' ')
|
||||
"
|
||||
></div>
|
||||
</v-row>
|
||||
<v-row
|
||||
v-else
|
||||
justify="center"
|
||||
:key="index"
|
||||
class="notify mt-1 wow animate__fadeIn"
|
||||
data-wow-duration="0.7s"
|
||||
>
|
||||
<div class="notify-box">
|
||||
<span style="display: inline; white-space: nowrap">
|
||||
<v-icon x-small color="blue" left>fa-info-circle</v-icon>
|
||||
</span>
|
||||
<span
|
||||
v-html="
|
||||
item.msg.replace(/\n/g, '<br/>').replace(/ /g, ' ')
|
||||
"
|
||||
></span>
|
||||
</div>
|
||||
</v-row>
|
||||
</template>
|
||||
</v-container>
|
||||
<v-container fluid class="chat-bg py-0">
|
||||
<v-row dense class="mx-0">
|
||||
<v-col>
|
||||
<v-text-field
|
||||
dense
|
||||
solo
|
||||
hide-details
|
||||
height="28px"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="auto">
|
||||
<v-btn
|
||||
style="font-size: 0.8rem"
|
||||
color="primary"
|
||||
small
|
||||
rounded
|
||||
depressed
|
||||
>发送</v-btn
|
||||
>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row class="text-center" no-gutters>
|
||||
<v-col class="pa-1" cols="2">
|
||||
<v-icon small>fa-microphone</v-icon>
|
||||
</v-col>
|
||||
<v-col class="pa-1" cols="2">
|
||||
<v-icon small>fa-image</v-icon>
|
||||
</v-col>
|
||||
<v-col class="pa-1" cols="2">
|
||||
<v-icon small>fa-camera</v-icon>
|
||||
</v-col>
|
||||
<v-col class="pa-1" cols="2">
|
||||
<v-icon small>fa-wallet</v-icon>
|
||||
</v-col>
|
||||
<v-col class="pa-1" cols="2">
|
||||
<v-icon small>fa-smile-wink</v-icon>
|
||||
</v-col>
|
||||
<v-col class="pa-1" cols="2">
|
||||
<v-icon small>fa-plus-circle</v-icon>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</v-card>
|
||||
</v-main>
|
||||
</v-app>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { WOW } from "wowjs";
|
||||
import "animate.css/animate.min.css";
|
||||
|
||||
export default {
|
||||
name: "Messenger",
|
||||
props: {
|
||||
messages: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initWOW: function() {
|
||||
new WOW({
|
||||
noxClass: "wow",
|
||||
animateClass: "animate__animated",
|
||||
offset: 0,
|
||||
mobile: true,
|
||||
live: true
|
||||
}).init();
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initWOW();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.wow {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.chat {
|
||||
min-height: 150px;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.chat-bg {
|
||||
background-color: #f3f6f9;
|
||||
}
|
||||
|
||||
.message {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
}
|
||||
.message .message-box {
|
||||
position: relative;
|
||||
width: fit-content;
|
||||
max-width: 55%;
|
||||
border-radius: 0.5rem;
|
||||
padding: 0.6rem 0.8rem;
|
||||
margin: 0.4rem 0.8rem;
|
||||
background-color: #fff;
|
||||
}
|
||||
.message .message-box::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
right: 100%;
|
||||
top: 0;
|
||||
width: 8px;
|
||||
height: 12px;
|
||||
color: #fff;
|
||||
border: 0 solid transparent;
|
||||
border-bottom: 7px solid;
|
||||
border-radius: 0 0 0 8px;
|
||||
}
|
||||
.message.justify-end .message-box::after {
|
||||
left: 100%;
|
||||
right: auto;
|
||||
border-radius: 0 0 8px 0;
|
||||
}
|
||||
|
||||
.notify {
|
||||
position: relative;
|
||||
}
|
||||
.notify .notify-box {
|
||||
max-width: 70%;
|
||||
background: #e0e0e0;
|
||||
border-radius: 10px;
|
||||
padding: 5px 12px;
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
.v-application--wrap {
|
||||
min-height: 0 !important;
|
||||
}
|
||||
</style>
|
@@ -1,173 +0,0 @@
|
||||
const path = require("path");
|
||||
|
||||
module.exports = context => ({
|
||||
title: "NoneBot",
|
||||
description: "基于 酷Q 的 Python 异步 QQ 机器人框架",
|
||||
markdown: {
|
||||
lineNumbers: true
|
||||
},
|
||||
/**
|
||||
* Extra tags to be injected to the page HTML `<head>`
|
||||
*
|
||||
* ref:https://v1.vuepress.vuejs.org/config/#head
|
||||
*/
|
||||
head: [
|
||||
["link", { rel: "icon", href: "/logo.png" }],
|
||||
["meta", { name: "theme-color", content: "#d32f2f" }],
|
||||
["meta", { name: "application-name", content: "NoneBot" }],
|
||||
["meta", { name: "apple-mobile-web-app-title", content: "NoneBot" }],
|
||||
["meta", { name: "apple-mobile-web-app-capable", content: "yes" }],
|
||||
[
|
||||
"meta",
|
||||
{ name: "apple-mobile-web-app-status-bar-style", content: "black" }
|
||||
],
|
||||
[
|
||||
"link",
|
||||
{
|
||||
rel: "stylesheet",
|
||||
href:
|
||||
"https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5/css/all.min.css"
|
||||
}
|
||||
]
|
||||
],
|
||||
locales: {
|
||||
"/": {
|
||||
lang: "zh-CN",
|
||||
title: "NoneBot",
|
||||
description: "基于 酷Q 的 Python 异步 QQ 机器人框架"
|
||||
}
|
||||
},
|
||||
|
||||
theme: "titanium",
|
||||
themeConfig: {
|
||||
logo: "/logo.png",
|
||||
repo: "nonebot/nonebot",
|
||||
docsDir: "docs",
|
||||
docsBranch: "dev2",
|
||||
docsDirVersioned: "archive",
|
||||
docsDirPages: "pages",
|
||||
editLinks: true,
|
||||
smoothScroll: true,
|
||||
|
||||
locales: {
|
||||
"/": {
|
||||
label: "简体中文",
|
||||
selectText: "Languages",
|
||||
editLinkText: "在 GitHub 上编辑此页",
|
||||
lastUpdated: "上次更新",
|
||||
nav: [
|
||||
{ text: "主页", link: "/" },
|
||||
{ text: "指南", link: "/guide/" },
|
||||
{ text: "API", link: "/api/" }
|
||||
],
|
||||
sidebarDepth: 2,
|
||||
sidebar: {
|
||||
"/guide/": [
|
||||
{
|
||||
title: "指南",
|
||||
path: "",
|
||||
collapsable: false,
|
||||
sidebar: "auto",
|
||||
children: [
|
||||
"",
|
||||
"installation",
|
||||
"getting-started",
|
||||
"creating-a-project",
|
||||
"basic-configuration",
|
||||
"writing-a-plugin"
|
||||
]
|
||||
}
|
||||
],
|
||||
"/api/": [
|
||||
{
|
||||
title: "NoneBot Api Reference",
|
||||
path: "",
|
||||
collapsable: false,
|
||||
children: [
|
||||
{
|
||||
title: "nonebot 模块",
|
||||
path: "nonebot"
|
||||
},
|
||||
{
|
||||
title: "nonebot.config 模块",
|
||||
path: "config"
|
||||
},
|
||||
{
|
||||
title: "nonebot.matcher 模块",
|
||||
path: "matcher"
|
||||
},
|
||||
{
|
||||
title: "nonebot.rule 模块",
|
||||
path: "rule"
|
||||
},
|
||||
{
|
||||
title: "nonebot.permission 模块",
|
||||
path: "permission"
|
||||
},
|
||||
{
|
||||
title: "nonebot.sched 模块",
|
||||
path: "sched"
|
||||
},
|
||||
{
|
||||
title: "nonebot.log 模块",
|
||||
path: "log"
|
||||
},
|
||||
{
|
||||
title: "nonebot.utils 模块",
|
||||
path: "utils"
|
||||
},
|
||||
{
|
||||
title: "nonebot.typing 模块",
|
||||
path: "typing"
|
||||
},
|
||||
{
|
||||
title: "nonebot.exception 模块",
|
||||
path: "exception"
|
||||
},
|
||||
{
|
||||
title: "nonebot.drivers 模块",
|
||||
path: "drivers/"
|
||||
},
|
||||
{
|
||||
title: "nonebot.drivers.fastapi 模块",
|
||||
path: "drivers/fastapi"
|
||||
},
|
||||
{
|
||||
title: "nonebot.adapters 模块",
|
||||
path: "adapters/"
|
||||
},
|
||||
{
|
||||
title: "nonebot.adapters.cqhttp 模块",
|
||||
path: "adapters/cqhttp"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
plugins: [
|
||||
"@vuepress/plugin-back-to-top",
|
||||
"@vuepress/plugin-medium-zoom",
|
||||
[
|
||||
"versioning",
|
||||
{
|
||||
versionedSourceDir: path.resolve(context.sourceDir, "..", "archive"),
|
||||
pagesSourceDir: path.resolve(context.sourceDir, "..", "pages"),
|
||||
onNewVersion(version, versionDestPath) {
|
||||
console.log(`Created version ${version} in ${versionDestPath}`);
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
"container",
|
||||
{
|
||||
type: "vue",
|
||||
before: '<pre class="vue-container"><code>',
|
||||
after: "</code></pre>"
|
||||
}
|
||||
]
|
||||
]
|
||||
});
|
@@ -1,42 +0,0 @@
|
||||
/**
|
||||
* Client app enhancement file.
|
||||
*
|
||||
* https://v1.vuepress.vuejs.org/guide/basic-config.html#app-level-enhancements
|
||||
*/
|
||||
|
||||
import Vuetify from "vuetify";
|
||||
import "vuetify/dist/vuetify.min.css";
|
||||
|
||||
export default ({
|
||||
Vue, // the version of Vue being used in the VuePress app
|
||||
options, // the options for the root Vue instance
|
||||
router, // the router instance for the app
|
||||
siteData // site metadata
|
||||
}) => {
|
||||
Vue.use(Vuetify);
|
||||
options.vuetify = new Vuetify({
|
||||
icons: {
|
||||
iconfont: "fa",
|
||||
values: {
|
||||
//
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (typeof process === "undefined" || process.env.VUE_ENV !== "server") {
|
||||
router.onReady(() => {
|
||||
const { app } = router;
|
||||
app.$once("hook:mounted", () => {
|
||||
// temporary fix for https://github.com/vuejs/vuepress/issues/2428
|
||||
setTimeout(() => {
|
||||
const { hash } = document.location;
|
||||
if (hash.length > 1) {
|
||||
const id = decodeURI(hash.substring(1));
|
||||
const element = document.getElementById(id);
|
||||
if (element) element.scrollIntoView();
|
||||
}
|
||||
}, 500);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
@@ -1,8 +0,0 @@
|
||||
/**
|
||||
* Custom Styles here.
|
||||
*
|
||||
* ref:https://v1.vuepress.vuejs.org/config/#index-styl
|
||||
*/
|
||||
|
||||
.home .hero img
|
||||
max-width 450px!important
|
@@ -1,10 +0,0 @@
|
||||
/**
|
||||
* Custom palette here.
|
||||
*
|
||||
* ref:https://v1.vuepress.vuejs.org/zh/config/#palette-styl
|
||||
*/
|
||||
|
||||
$accentColor = #ea5252
|
||||
$textColor = #2c3e50
|
||||
$borderColor = #eaecef
|
||||
$codeBgColor = #282c34
|
@@ -1,3 +0,0 @@
|
||||
[
|
||||
"2.0.0a3"
|
||||
]
|
@@ -1,15 +0,0 @@
|
||||
---
|
||||
home: true
|
||||
heroImage: /logo.png
|
||||
tagline: An asynchronous QQ bot framework.
|
||||
actionText: 开始使用
|
||||
actionLink: /guide/
|
||||
features:
|
||||
- title: 简洁
|
||||
details: 提供极其简洁易懂的 API,使你可以毫无压力地开始验证你的绝佳创意,只需编写最少量的代码,即可实现丰富的功能。
|
||||
- title: 易于扩展
|
||||
details: 精心设计的消息处理流程使得你可以很方便地将原型扩充为具有大量实用功能的完整聊天机器人,并持续保证扩展性。
|
||||
- title: 高性能
|
||||
details: 采用异步 I/O,利用 WebSocket 进行通信,以获得极高的性能;同时,支持使用多账号同时接入,减少业务宕机的可能。
|
||||
footer: MIT Licensed | Copyright © 2020 NoneBot Team
|
||||
---
|
@@ -1,46 +0,0 @@
|
||||
# NoneBot Api Reference
|
||||
|
||||
|
||||
* **模块索引**
|
||||
|
||||
|
||||
* [nonebot](nonebot.html)
|
||||
|
||||
|
||||
* [nonebot.config](config.html)
|
||||
|
||||
|
||||
* [nonebot.matcher](matcher.html)
|
||||
|
||||
|
||||
* [nonebot.rule](rule.html)
|
||||
|
||||
|
||||
* [nonebot.permission](permission.html)
|
||||
|
||||
|
||||
* [nonebot.sched](sched.html)
|
||||
|
||||
|
||||
* [nonebot.log](log.html)
|
||||
|
||||
|
||||
* [nonebot.utils](utils.html)
|
||||
|
||||
|
||||
* [nonebot.typing](typing.html)
|
||||
|
||||
|
||||
* [nonebot.exception](exception.html)
|
||||
|
||||
|
||||
* [nonebot.drivers](drivers/)
|
||||
|
||||
|
||||
* [nonebot.drivers.fastapi](drivers/fastapi.html)
|
||||
|
||||
|
||||
* [nonebot.adapters](adapters/)
|
||||
|
||||
|
||||
* [nonebot.adapters.cqhttp](adapters/cqhttp.html)
|
@@ -1,323 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.adapters 模块
|
||||
|
||||
## 协议适配基类
|
||||
|
||||
各协议请继承以下基类,并使用 `driver.register_adapter` 注册适配器
|
||||
|
||||
|
||||
## _class_ `BaseBot`
|
||||
|
||||
基类:`abc.ABC`
|
||||
|
||||
Bot 基类。用于处理上报消息,并提供 API 调用接口。
|
||||
|
||||
|
||||
### _abstract_ `__init__(driver, connection_type, config, self_id, *, websocket=None)`
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `driver: Driver`: Driver 对象
|
||||
|
||||
|
||||
* `connection_type: str`: http 或者 websocket
|
||||
|
||||
|
||||
* `config: Config`: Config 对象
|
||||
|
||||
|
||||
* `self_id: str`: 机器人 ID
|
||||
|
||||
|
||||
* `websocket: Optional[WebSocket]`: Websocket 连接对象
|
||||
|
||||
|
||||
|
||||
### `driver`
|
||||
|
||||
Driver 对象
|
||||
|
||||
|
||||
### `connection_type`
|
||||
|
||||
连接类型
|
||||
|
||||
|
||||
### `config`
|
||||
|
||||
Config 配置对象
|
||||
|
||||
|
||||
### `self_id`
|
||||
|
||||
机器人 ID
|
||||
|
||||
|
||||
### `websocket`
|
||||
|
||||
Websocket 连接对象
|
||||
|
||||
|
||||
### _abstract property_ `type`
|
||||
|
||||
Adapter 类型
|
||||
|
||||
|
||||
### _abstract async_ `handle_message(message)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
处理上报消息的函数,转换为 `Event` 事件后调用 `nonebot.message.handle_event` 进一步处理事件。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `message: dict`: 收到的上报消息
|
||||
|
||||
|
||||
|
||||
### _abstract async_ `call_api(api, **data)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
调用机器人 API 接口,可以通过该函数或直接通过 bot 属性进行调用
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `api: str`: API 名称
|
||||
|
||||
|
||||
* `**data`: API 数据
|
||||
|
||||
|
||||
|
||||
* **示例**
|
||||
|
||||
|
||||
```python
|
||||
await bot.call_api("send_msg", data={"message": "hello world"})
|
||||
await bot.send_msg(message="hello world")
|
||||
```
|
||||
|
||||
|
||||
### _abstract async_ `send(event, message, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
调用机器人基础发送消息接口
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `event: Event`: 上报事件
|
||||
|
||||
|
||||
* `message: Union[str, Message, MessageSegment]`: 要发送的消息
|
||||
|
||||
|
||||
* `**kwargs`
|
||||
|
||||
|
||||
|
||||
## _class_ `BaseEvent`
|
||||
|
||||
基类:`abc.ABC`
|
||||
|
||||
Event 基类。提供上报信息的关键信息,其余信息可从原始上报消息获取。
|
||||
|
||||
|
||||
### `__init__(raw_event)`
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `raw_event: dict`: 原始上报消息
|
||||
|
||||
|
||||
|
||||
### _property_ `raw_event`
|
||||
|
||||
原始上报消息
|
||||
|
||||
|
||||
### _abstract property_ `id`
|
||||
|
||||
事件 ID
|
||||
|
||||
|
||||
### _abstract property_ `name`
|
||||
|
||||
事件名称
|
||||
|
||||
|
||||
### _abstract property_ `self_id`
|
||||
|
||||
机器人 ID
|
||||
|
||||
|
||||
### _abstract property_ `time`
|
||||
|
||||
事件发生时间
|
||||
|
||||
|
||||
### _abstract property_ `type`
|
||||
|
||||
事件主类型
|
||||
|
||||
|
||||
### _abstract property_ `detail_type`
|
||||
|
||||
事件详细类型
|
||||
|
||||
|
||||
### _abstract property_ `sub_type`
|
||||
|
||||
事件子类型
|
||||
|
||||
|
||||
### _abstract property_ `user_id`
|
||||
|
||||
触发事件的主体 ID
|
||||
|
||||
|
||||
### _abstract property_ `group_id`
|
||||
|
||||
触发事件的主体群 ID
|
||||
|
||||
|
||||
### _abstract property_ `to_me`
|
||||
|
||||
事件是否为发送给机器人的消息
|
||||
|
||||
|
||||
### _abstract property_ `message`
|
||||
|
||||
消息内容
|
||||
|
||||
|
||||
### _abstract property_ `reply`
|
||||
|
||||
回复的消息
|
||||
|
||||
|
||||
### _abstract property_ `raw_message`
|
||||
|
||||
原始消息
|
||||
|
||||
|
||||
### _abstract property_ `plain_text`
|
||||
|
||||
纯文本消息
|
||||
|
||||
|
||||
### _abstract property_ `sender`
|
||||
|
||||
消息发送者信息
|
||||
|
||||
|
||||
## _class_ `BaseMessageSegment`
|
||||
|
||||
基类:`abc.ABC`
|
||||
|
||||
消息段基类
|
||||
|
||||
|
||||
### `type`
|
||||
|
||||
|
||||
* 类型: `str`
|
||||
|
||||
|
||||
* 说明: 消息段类型
|
||||
|
||||
|
||||
### `data`
|
||||
|
||||
|
||||
* 类型: `Dict[str, Union[str, list]]`
|
||||
|
||||
|
||||
* 说明: 消息段数据
|
||||
|
||||
|
||||
## _class_ `BaseMessage`
|
||||
|
||||
基类:`list`, `abc.ABC`
|
||||
|
||||
消息数组
|
||||
|
||||
|
||||
### `__init__(message=None, *args, **kwargs)`
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `message: Union[str, dict, list, MessageSegment, Message]`: 消息内容
|
||||
|
||||
|
||||
|
||||
### `append(obj)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
添加一个消息段到消息数组末尾
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `obj: Union[str, MessageSegment]`: 要添加的消息段
|
||||
|
||||
|
||||
|
||||
### `extend(obj)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
拼接一个消息数组或多个消息段到消息数组末尾
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `obj: Union[Message, Iterable[MessageSegment]]`: 要添加的消息数组
|
||||
|
||||
|
||||
|
||||
### `reduce()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
缩减消息数组,即拼接相邻纯文本消息段
|
||||
|
||||
|
||||
|
||||
### `extract_plain_text()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
提取消息内纯文本消息
|
@@ -1,411 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.adapters.cqhttp 模块
|
||||
|
||||
## CQHTTP (OneBot) v11 协议适配
|
||||
|
||||
协议详情请看: [CQHTTP](http://cqhttp.cc/) | [OneBot](https://github.com/howmanybots/onebot)
|
||||
|
||||
|
||||
## `log(level, message)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
用于打印 CQHTTP 日志。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `level: str`: 日志等级
|
||||
|
||||
|
||||
* `message: str`: 日志信息
|
||||
|
||||
|
||||
|
||||
## `escape(s, *, escape_comma=True)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
对字符串进行 CQ 码转义。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `s: str`: 需要转义的字符串
|
||||
|
||||
|
||||
* `escape_comma: bool`: 是否转义逗号(`,`)。
|
||||
|
||||
|
||||
|
||||
## `unescape(s)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
对字符串进行 CQ 码去转义。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `s: str`: 需要转义的字符串
|
||||
|
||||
|
||||
|
||||
## `_b2s(b)`
|
||||
|
||||
转换布尔值为字符串。
|
||||
|
||||
|
||||
## _async_ `_check_reply(bot, event)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
检查消息中存在的回复,去除并赋值 `event.reply`, `event.to_me`
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `bot: Bot`: Bot 对象
|
||||
|
||||
|
||||
* `event: Event`: Event 对象
|
||||
|
||||
|
||||
|
||||
## `_check_at_me(bot, event)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
检查消息开头或结尾是否存在 @机器人,去除并赋值 `event.to_me`
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `bot: Bot`: Bot 对象
|
||||
|
||||
|
||||
* `event: Event`: Event 对象
|
||||
|
||||
|
||||
|
||||
## `_check_nickname(bot, event)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
检查消息开头是否存在,去除并赋值 `event.to_me`
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `bot: Bot`: Bot 对象
|
||||
|
||||
|
||||
* `event: Event`: Event 对象
|
||||
|
||||
|
||||
|
||||
## `_handle_api_result(result)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
处理 API 请求返回值。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `result: Optional[Dict[str, Any]]`: API 返回数据
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Any`: API 调用返回数据
|
||||
|
||||
|
||||
|
||||
* **异常**
|
||||
|
||||
|
||||
* `ActionFailed`: API 调用失败
|
||||
|
||||
|
||||
|
||||
## _class_ `Bot`
|
||||
|
||||
基类:[`nonebot.adapters.BaseBot`](#None)
|
||||
|
||||
CQHTTP 协议 Bot 适配。继承属性参考 [BaseBot](./#class-basebot) 。
|
||||
|
||||
|
||||
### _property_ `type`
|
||||
|
||||
|
||||
* 返回: `"cqhttp"`
|
||||
|
||||
|
||||
### _async_ `handle_message(message)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
调用 [_check_reply](#async-check-reply-bot-event), [_check_at_me](#check-at-me-bot-event), [_check_nickname](#check-nickname-bot-event) 处理事件并转换为 [Event](#class-event)
|
||||
|
||||
|
||||
|
||||
### _async_ `call_api(api, **data)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
调用 CQHTTP 协议 API
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `api: str`: API 名称
|
||||
|
||||
|
||||
* `**data: Any`: API 参数
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Any`: API 调用返回数据
|
||||
|
||||
|
||||
|
||||
* **异常**
|
||||
|
||||
|
||||
* `NetworkError`: 网络错误
|
||||
|
||||
|
||||
* `ActionFailed`: API 调用失败
|
||||
|
||||
|
||||
|
||||
### _async_ `send(event, message, at_sender=False, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
根据 `event` 向触发事件的主体发送消息。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `event: Event`: Event 对象
|
||||
|
||||
|
||||
* `message: Union[str, Message, MessageSegment]`: 要发送的消息
|
||||
|
||||
|
||||
* `at_sender: bool`: 是否 @ 事件主体
|
||||
|
||||
|
||||
* `**kwargs`: 覆盖默认参数
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Any`: API 调用返回数据
|
||||
|
||||
|
||||
|
||||
* **异常**
|
||||
|
||||
|
||||
* `ValueError`: 缺少 `user_id`, `group_id`
|
||||
|
||||
|
||||
* `NetworkError`: 网络错误
|
||||
|
||||
|
||||
* `ActionFailed`: API 调用失败
|
||||
|
||||
|
||||
|
||||
## _class_ `Event`
|
||||
|
||||
基类:[`nonebot.adapters.BaseEvent`](#None)
|
||||
|
||||
CQHTTP 协议 Event 适配。继承属性参考 [BaseEvent](./#class-baseevent) 。
|
||||
|
||||
|
||||
### _property_ `id`
|
||||
|
||||
|
||||
* 类型: `Optional[int]`
|
||||
|
||||
|
||||
* 说明: 事件/消息 ID
|
||||
|
||||
|
||||
### _property_ `name`
|
||||
|
||||
|
||||
* 类型: `str`
|
||||
|
||||
|
||||
* 说明: 事件名称,由类型与 `.` 组合而成
|
||||
|
||||
|
||||
### _property_ `self_id`
|
||||
|
||||
|
||||
* 类型: `str`
|
||||
|
||||
|
||||
* 说明: 机器人自身 ID
|
||||
|
||||
|
||||
### _property_ `time`
|
||||
|
||||
|
||||
* 类型: `int`
|
||||
|
||||
|
||||
* 说明: 事件发生时间
|
||||
|
||||
|
||||
### _property_ `type`
|
||||
|
||||
|
||||
* 类型: `str`
|
||||
|
||||
|
||||
* 说明: 事件类型
|
||||
|
||||
|
||||
### _property_ `detail_type`
|
||||
|
||||
|
||||
* 类型: `str`
|
||||
|
||||
|
||||
* 说明: 事件详细类型
|
||||
|
||||
|
||||
### _property_ `sub_type`
|
||||
|
||||
|
||||
* 类型: `Optional[str]`
|
||||
|
||||
|
||||
* 说明: 事件子类型
|
||||
|
||||
|
||||
### _property_ `user_id`
|
||||
|
||||
|
||||
* 类型: `Optional[int]`
|
||||
|
||||
|
||||
* 说明: 事件主体 ID
|
||||
|
||||
|
||||
### _property_ `group_id`
|
||||
|
||||
|
||||
* 类型: `Optional[int]`
|
||||
|
||||
|
||||
* 说明: 事件主体群 ID
|
||||
|
||||
|
||||
### _property_ `to_me`
|
||||
|
||||
|
||||
* 类型: `Optional[bool]`
|
||||
|
||||
|
||||
* 说明: 消息是否与机器人相关
|
||||
|
||||
|
||||
### _property_ `message`
|
||||
|
||||
|
||||
* 类型: `Optional[Message]`
|
||||
|
||||
|
||||
* 说明: 消息内容
|
||||
|
||||
|
||||
### _property_ `reply`
|
||||
|
||||
|
||||
* 类型: `Optional[dict]`
|
||||
|
||||
|
||||
* 说明: 回复消息详情
|
||||
|
||||
|
||||
### _property_ `raw_message`
|
||||
|
||||
|
||||
* 类型: `Optional[str]`
|
||||
|
||||
|
||||
* 说明: 原始消息
|
||||
|
||||
|
||||
### _property_ `plain_text`
|
||||
|
||||
|
||||
* 类型: `Optional[str]`
|
||||
|
||||
|
||||
* 说明: 纯文本消息内容
|
||||
|
||||
|
||||
### _property_ `sender`
|
||||
|
||||
|
||||
* 类型: `Optional[dict]`
|
||||
|
||||
|
||||
* 说明: 消息发送者信息
|
||||
|
||||
|
||||
## _class_ `MessageSegment`
|
||||
|
||||
基类:[`nonebot.adapters.BaseMessageSegment`](#None)
|
||||
|
||||
|
||||
## _class_ `Message`
|
||||
|
||||
基类:[`nonebot.adapters.BaseMessage`](#None)
|
@@ -1,265 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.config 模块
|
||||
|
||||
## 配置
|
||||
|
||||
NoneBot 使用 [pydantic](https://pydantic-docs.helpmanual.io/) 以及 [python-dotenv](https://saurabh-kumar.com/python-dotenv/) 来读取配置。
|
||||
|
||||
配置项需符合特殊格式或 json 序列化格式。详情见 [pydantic Field Type](https://pydantic-docs.helpmanual.io/usage/types/) 文档。
|
||||
|
||||
|
||||
## _class_ `Env`
|
||||
|
||||
基类:`pydantic.env_settings.BaseSettings`
|
||||
|
||||
运行环境配置。大小写不敏感。
|
||||
|
||||
将会从 `nonebot.init 参数` > `环境变量` > `.env 环境配置文件` 的优先级读取配置。
|
||||
|
||||
|
||||
### `environment`
|
||||
|
||||
|
||||
* 类型: `str`
|
||||
|
||||
|
||||
* 默认值: `"prod"`
|
||||
|
||||
|
||||
* 说明:
|
||||
当前环境名。 NoneBot 将从 `.env.{environment}` 文件中加载配置。
|
||||
|
||||
|
||||
## _class_ `Config`
|
||||
|
||||
基类:`nonebot.config.BaseConfig`
|
||||
|
||||
NoneBot 主要配置。大小写不敏感。
|
||||
|
||||
除了 NoneBot 的配置项外,还可以自行添加配置项到 `.env.{environment}` 文件中。
|
||||
这些配置将会在 json 反序列化后一起带入 `Config` 类中。
|
||||
|
||||
|
||||
### `driver`
|
||||
|
||||
|
||||
* 类型: `str`
|
||||
|
||||
|
||||
* 默认值: `"nonebot.drivers.fastapi"`
|
||||
|
||||
|
||||
* 说明:
|
||||
NoneBot 运行所使用的 `Driver` 。继承自 `nonebot.driver.BaseDriver` 。
|
||||
|
||||
|
||||
### `host`
|
||||
|
||||
|
||||
* 类型: `IPvAnyAddress`
|
||||
|
||||
|
||||
* 默认值: `127.0.0.1`
|
||||
|
||||
|
||||
* 说明:
|
||||
NoneBot 的 HTTP 和 WebSocket 服务端监听的 IP/主机名。
|
||||
|
||||
|
||||
### `port`
|
||||
|
||||
|
||||
* 类型: `int`
|
||||
|
||||
|
||||
* 默认值: `8080`
|
||||
|
||||
|
||||
* 说明:
|
||||
NoneBot 的 HTTP 和 WebSocket 服务端监听的端口。
|
||||
|
||||
|
||||
### `debug`
|
||||
|
||||
|
||||
* 类型: `bool`
|
||||
|
||||
|
||||
* 默认值: `False`
|
||||
|
||||
|
||||
* 说明:
|
||||
是否以调试模式运行 NoneBot。
|
||||
|
||||
|
||||
### `api_root`
|
||||
|
||||
|
||||
* 类型: `Dict[str, str]`
|
||||
|
||||
|
||||
* 默认值: `{}`
|
||||
|
||||
|
||||
* 说明:
|
||||
以机器人 ID 为键,上报地址为值的字典,环境变量或文件中应使用 json 序列化。
|
||||
|
||||
|
||||
* 示例:
|
||||
|
||||
```default
|
||||
API_ROOT={"123456": "http://127.0.0.1:5700"}
|
||||
```
|
||||
|
||||
|
||||
### `api_timeout`
|
||||
|
||||
|
||||
* 类型: `Optional[float]`
|
||||
|
||||
|
||||
* 默认值: `30.`
|
||||
|
||||
|
||||
* 说明:
|
||||
API 请求超时时间,单位: 秒。
|
||||
|
||||
|
||||
### `access_token`
|
||||
|
||||
|
||||
* 类型: `Optional[str]`
|
||||
|
||||
|
||||
* 默认值: `None`
|
||||
|
||||
|
||||
* 说明:
|
||||
API 请求以及上报所需密钥,在请求头中携带。
|
||||
|
||||
|
||||
* 示例:
|
||||
|
||||
```http
|
||||
POST /cqhttp/ HTTP/1.1
|
||||
Authorization: Bearer kSLuTF2GC2Q4q4ugm3
|
||||
```
|
||||
|
||||
|
||||
### `secret`
|
||||
|
||||
|
||||
* 类型: `Optional[str]`
|
||||
|
||||
|
||||
* 默认值: `None`
|
||||
|
||||
|
||||
* 说明:
|
||||
HTTP POST 形式上报所需签名,在请求头中携带。
|
||||
|
||||
|
||||
* 示例:
|
||||
|
||||
```http
|
||||
POST /cqhttp/ HTTP/1.1
|
||||
X-Signature: sha1=f9ddd4863ace61e64f462d41ca311e3d2c1176e2
|
||||
```
|
||||
|
||||
|
||||
### `superusers`
|
||||
|
||||
|
||||
* 类型: `Set[int]`
|
||||
|
||||
|
||||
* 默认值: `set()`
|
||||
|
||||
|
||||
* 说明:
|
||||
机器人超级用户。
|
||||
|
||||
|
||||
* 示例:
|
||||
|
||||
```default
|
||||
SUPER_USERS=[12345789]
|
||||
```
|
||||
|
||||
|
||||
### `nickname`
|
||||
|
||||
|
||||
* 类型: `Set[str]`
|
||||
|
||||
|
||||
* 默认值: `set()`
|
||||
|
||||
|
||||
* 说明:
|
||||
机器人昵称。
|
||||
|
||||
|
||||
### `command_start`
|
||||
|
||||
|
||||
* 类型: `Set[str]`
|
||||
|
||||
|
||||
* 默认值: `{"/"}`
|
||||
|
||||
|
||||
* 说明:
|
||||
命令的起始标记,用于判断一条消息是不是命令。
|
||||
|
||||
|
||||
### `command_sep`
|
||||
|
||||
|
||||
* 类型: `Set[str]`
|
||||
|
||||
|
||||
* 默认值: `{"."}`
|
||||
|
||||
|
||||
* 说明:
|
||||
命令的分隔标记,用于将文本形式的命令切分为元组(实际的命令名)。
|
||||
|
||||
|
||||
### `session_expire_timeout`
|
||||
|
||||
|
||||
* 类型: `timedelta`
|
||||
|
||||
|
||||
* 默认值: `timedelta(minutes=2)`
|
||||
|
||||
|
||||
* 说明:
|
||||
等待用户回复的超时时间。
|
||||
|
||||
|
||||
* 示例:
|
||||
|
||||
```default
|
||||
SESSION_EXPIRE_TIMEOUT=120 # 单位: 秒
|
||||
SESSION_EXPIRE_TIMEOUT=[DD ][HH:MM]SS[.ffffff]
|
||||
SESSION_EXPIRE_TIMEOUT=P[DD]DT[HH]H[MM]M[SS]S # ISO 8601
|
||||
```
|
||||
|
||||
|
||||
### `apscheduler_config`
|
||||
|
||||
|
||||
* 类型: `dict`
|
||||
|
||||
|
||||
* 默认值: `{"apscheduler.timezone": "Asia/Shanghai"}`
|
||||
|
||||
|
||||
* 说明:
|
||||
APScheduler 的配置对象,见 [Configuring the Scheduler](https://apscheduler.readthedocs.io/en/latest/userguide.html#configuring-the-scheduler)
|
@@ -1,37 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.drivers 模块
|
||||
|
||||
## 后端驱动适配基类
|
||||
|
||||
各驱动请继承以下基类
|
||||
|
||||
|
||||
## _class_ `BaseDriver`
|
||||
|
||||
基类:`abc.ABC`
|
||||
|
||||
Driver 基类。将后端框架封装,以满足适配器使用。
|
||||
|
||||
|
||||
### `_adapters`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Dict[str, Type[Bot]]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
已注册的适配器列表
|
||||
|
||||
|
||||
|
||||
### _abstract_ `__init__(env, config)`
|
||||
|
||||
Initialize self. See help(type(self)) for accurate signature.
|
@@ -1,16 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.drivers.fastapi 模块
|
||||
|
||||
|
||||
## _class_ `Driver`
|
||||
|
||||
基类:[`nonebot.drivers.BaseDriver`](#None)
|
||||
|
||||
|
||||
### `__init__(env, config)`
|
||||
|
||||
Initialize self. See help(type(self)) for accurate signature.
|
@@ -1,156 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.exception 模块
|
||||
|
||||
## 异常
|
||||
|
||||
下列文档中的异常是所有 NoneBot 运行时可能会抛出的。
|
||||
这些异常并非所有需要用户处理,在 NoneBot 内部运行时被捕获,并进行对应操作。
|
||||
|
||||
|
||||
## _exception_ `IgnoredException`
|
||||
|
||||
基类:`Exception`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
指示 NoneBot 应该忽略该事件。可由 PreProcessor 抛出。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `reason`: 忽略事件的原因
|
||||
|
||||
|
||||
|
||||
## _exception_ `PausedException`
|
||||
|
||||
基类:`Exception`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
指示 NoneBot 结束当前 `Handler` 并等待下一条消息后继续下一个 `Handler`。
|
||||
可用于用户输入新信息。
|
||||
|
||||
|
||||
|
||||
* **用法**
|
||||
|
||||
可以在 `Handler` 中通过 `Matcher.pause()` 抛出。
|
||||
|
||||
|
||||
|
||||
## _exception_ `RejectedException`
|
||||
|
||||
基类:`Exception`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
指示 NoneBot 结束当前 `Handler` 并等待下一条消息后重新运行当前 `Handler`。
|
||||
可用于用户重新输入。
|
||||
|
||||
|
||||
|
||||
* **用法**
|
||||
|
||||
可以在 `Handler` 中通过 `Matcher.reject()` 抛出。
|
||||
|
||||
|
||||
|
||||
## _exception_ `FinishedException`
|
||||
|
||||
基类:`Exception`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
指示 NoneBot 结束当前 `Handler` 且后续 `Handler` 不再被运行。
|
||||
可用于结束用户会话。
|
||||
|
||||
|
||||
|
||||
* **用法**
|
||||
|
||||
可以在 `Handler` 中通过 `Matcher.finish()` 抛出。
|
||||
|
||||
|
||||
|
||||
## _exception_ `ExpiredException`
|
||||
|
||||
基类:`Exception`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
指示 NoneBot 当前 `Matcher` 已失效。
|
||||
|
||||
|
||||
|
||||
* **用法**
|
||||
|
||||
当 `Matcher` 运行前检查时抛出。
|
||||
|
||||
|
||||
|
||||
## _exception_ `StopPropagation`
|
||||
|
||||
基类:`Exception`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
指示 NoneBot 终止事件向下层传播。
|
||||
|
||||
|
||||
|
||||
* **用法**
|
||||
|
||||
在 `Matcher.block == True` 时抛出。
|
||||
|
||||
|
||||
|
||||
## _exception_ `ApiNotAvailable`
|
||||
|
||||
基类:`Exception`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
在 API 连接不可用时抛出。
|
||||
|
||||
|
||||
|
||||
## _exception_ `NetworkError`
|
||||
|
||||
基类:`Exception`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
在网络出现问题时抛出,如: API 请求地址不正确, API 请求无返回或返回状态非正常等。
|
||||
|
||||
|
||||
|
||||
## _exception_ `ActionFailed`
|
||||
|
||||
基类:`Exception`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
API 请求成功返回数据,但 API 操作失败。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `retcode`: 错误代码
|
@@ -1,55 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.log 模块
|
||||
|
||||
## 日志
|
||||
|
||||
NoneBot 使用 [loguru](https://github.com/Delgan/loguru) 来记录日志信息。
|
||||
|
||||
自定义 logger 请参考 [loguru](https://github.com/Delgan/loguru) 文档。
|
||||
|
||||
|
||||
## `logger`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
NoneBot 日志记录器对象。
|
||||
|
||||
|
||||
|
||||
* **默认信息**
|
||||
|
||||
|
||||
* 格式: `[%(asctime)s %(name)s] %(levelname)s: %(message)s`
|
||||
|
||||
|
||||
* 等级: `DEBUG` / `INFO` ,根据 config 配置改变
|
||||
|
||||
|
||||
* 输出: 输出至 stdout
|
||||
|
||||
|
||||
|
||||
* **用法**
|
||||
|
||||
|
||||
```python
|
||||
from nonebot.log import logger
|
||||
```
|
||||
|
||||
|
||||
## _class_ `LoguruHandler`
|
||||
|
||||
基类:`logging.Handler`
|
||||
|
||||
|
||||
### `emit(record)`
|
||||
|
||||
Do whatever it takes to actually log the specified logging record.
|
||||
|
||||
This version is intended to be implemented by subclasses and so
|
||||
raises a NotImplementedError.
|
@@ -1,485 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.matcher 模块
|
||||
|
||||
## 事件响应器
|
||||
|
||||
该模块实现事件响应器的创建与运行,并提供一些快捷方法来帮助用户更好的与机器人进行 对话 。
|
||||
|
||||
|
||||
## `matchers`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Dict[int, List[Type[Matcher]]]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
用于存储当前所有的事件响应器
|
||||
|
||||
|
||||
|
||||
## _class_ `Matcher`
|
||||
|
||||
基类:`object`
|
||||
|
||||
事件响应器类
|
||||
|
||||
|
||||
### `module`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Optional[str]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器所在模块名称
|
||||
|
||||
|
||||
|
||||
### `type`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`str`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器类型
|
||||
|
||||
|
||||
|
||||
### `rule`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Rule`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器匹配规则
|
||||
|
||||
|
||||
|
||||
### `permission`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Permission`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器触发权限
|
||||
|
||||
|
||||
|
||||
### `priority`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`int`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器优先级
|
||||
|
||||
|
||||
|
||||
### `block`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`bool`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器是否阻止事件传播
|
||||
|
||||
|
||||
|
||||
### `temp`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`bool`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器是否为临时
|
||||
|
||||
|
||||
|
||||
### `expire_time`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Optional[datetime]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器过期时间点
|
||||
|
||||
|
||||
|
||||
### `_default_state`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`dict`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器默认状态
|
||||
|
||||
|
||||
|
||||
### `_default_parser`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Optional[ArgsParser]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器默认参数解析函数
|
||||
|
||||
|
||||
|
||||
### `__init__()`
|
||||
|
||||
实例化 Matcher 以便运行
|
||||
|
||||
|
||||
### `handlers`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`List[Handler]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
事件响应器拥有的事件处理函数列表
|
||||
|
||||
|
||||
|
||||
### _classmethod_ `new(type_='', rule=None, permission=None, handlers=None, temp=False, priority=1, block=False, *, module=None, default_state=None, expire_time=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
创建一个新的事件响应器,并存储至 [matchers](#matchers)
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `type_: str`: 事件响应器类型,与 `event.type` 一致时触发,空字符串表示任意
|
||||
|
||||
|
||||
* `rule: Optional[Rule]`: 匹配规则
|
||||
|
||||
|
||||
* `permission: Optional[Permission]`: 权限
|
||||
|
||||
|
||||
* `handlers: Optional[List[Handler]]`: 事件处理函数列表
|
||||
|
||||
|
||||
* `temp: bool`: 是否为临时事件响应器,即触发一次后删除
|
||||
|
||||
|
||||
* `priority: int`: 响应优先级
|
||||
|
||||
|
||||
* `block: bool`: 是否阻止事件向更低优先级的响应器传播
|
||||
|
||||
|
||||
* `module: Optional[str]`: 事件响应器所在模块名称
|
||||
|
||||
|
||||
* `default_state: Optional[dict]`: 默认状态 `state`
|
||||
|
||||
|
||||
* `expire_time: Optional[datetime]`: 事件响应器最终有效时间点,过时即被删除
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Type[Matcher]`: 新的事件响应器类
|
||||
|
||||
|
||||
|
||||
### _async classmethod_ `check_perm(bot, event)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
检查是否满足触发权限
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `bot: Bot`: Bot 对象
|
||||
|
||||
|
||||
* `event: Event`: 上报事件
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `bool`: 是否满足权限
|
||||
|
||||
|
||||
|
||||
### _async classmethod_ `check_rule(bot, event, state)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
检查是否满足匹配规则
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `bot: Bot`: Bot 对象
|
||||
|
||||
|
||||
* `event: Event`: 上报事件
|
||||
|
||||
|
||||
* `state: dict`: 当前状态
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `bool`: 是否满足匹配规则
|
||||
|
||||
|
||||
|
||||
### _classmethod_ `args_parser(func)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
装饰一个函数来更改当前事件响应器的默认参数解析函数
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `func: ArgsParser`: 参数解析函数
|
||||
|
||||
|
||||
|
||||
### _classmethod_ `handle()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
装饰一个函数来向事件响应器直接添加一个处理函数
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* 无
|
||||
|
||||
|
||||
|
||||
### _classmethod_ `receive()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
装饰一个函数来指示 NoneBot 在接收用户新的一条消息后继续运行该函数
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* 无
|
||||
|
||||
|
||||
|
||||
### _classmethod_ `got(key, prompt=None, args_parser=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
装饰一个函数来指示 NoneBot 当要获取的 `key` 不存在时接收用户新的一条消息并经过 `ArgsParser` 处理后再运行该函数,如果 `key` 已存在则直接继续运行
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `key: str`: 参数名
|
||||
|
||||
|
||||
* `prompt: Optional[Union[str, Message, MessageSegment]]`: 在参数不存在时向用户发送的消息
|
||||
|
||||
|
||||
* `args_parser: Optional[ArgsParser]`: 可选参数解析函数,空则使用默认解析函数
|
||||
|
||||
|
||||
|
||||
### _async classmethod_ `send(message)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
发送一条消息给当前交互用户
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `message: Union[str, Message, MessageSegment]`: 消息内容
|
||||
|
||||
|
||||
|
||||
### _async classmethod_ `finish(message=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
发送一条消息给当前交互用户并结束当前事件响应器
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `message: Union[str, Message, MessageSegment]`: 消息内容
|
||||
|
||||
|
||||
|
||||
### _async classmethod_ `pause(prompt=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
发送一条消息给当前交互用户并暂停事件响应器,在接收用户新的一条消息后继续下一个处理函数
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `prompt: Union[str, Message, MessageSegment]`: 消息内容
|
||||
|
||||
|
||||
|
||||
### _async classmethod_ `reject(prompt=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
发送一条消息给当前交互用户并暂停事件响应器,在接收用户新的一条消息后重新运行当前处理函数
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `prompt: Union[str, Message, MessageSegment]`: 消息内容
|
||||
|
||||
|
||||
|
||||
## _class_ `MatcherGroup`
|
||||
|
||||
基类:`object`
|
||||
|
||||
事件响应器组合,统一管理。用法同 `Matcher`
|
||||
|
||||
|
||||
### `__init__(type_='', rule=None, permission=None, handlers=None, temp=False, priority=1, block=False, *, module=None, default_state=None, expire_time=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
创建一个事件响应器组合,参数为默认值,与 `Matcher.new` 一致
|
||||
|
||||
|
||||
|
||||
### `matchers`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`List[Type[Matcher]]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
组内事件响应器列表
|
||||
|
||||
|
||||
|
||||
### `new(type_='', rule=None, permission=None, handlers=None, temp=False, priority=1, block=False, *, module=None, default_state=None, expire_time=None)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
在组中创建一个新的事件响应器,参数留空则使用组合默认值
|
||||
|
||||
|
||||
:::danger 警告
|
||||
如果使用 handlers 参数覆盖组合默认值则该事件响应器不会随组合一起添加新的事件处理函数
|
||||
:::
|
@@ -1,257 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot 模块
|
||||
|
||||
## 快捷导入
|
||||
|
||||
为方便使用,`nonebot` 模块从子模块导入了部分内容
|
||||
|
||||
|
||||
* `on_message` => `nonebot.plugin.on_message`
|
||||
|
||||
|
||||
* `on_notice` => `nonebot.plugin.on_notice`
|
||||
|
||||
|
||||
* `on_request` => `nonebot.plugin.on_request`
|
||||
|
||||
|
||||
* `on_metaevent` => `nonebot.plugin.on_metaevent`
|
||||
|
||||
|
||||
* `on_startswith` => `nonebot.plugin.on_startswith`
|
||||
|
||||
|
||||
* `on_endswith` => `nonebot.plugin.on_endswith`
|
||||
|
||||
|
||||
* `on_command` => `nonebot.plugin.on_command`
|
||||
|
||||
|
||||
* `on_regex` => `nonebot.plugin.on_regex`
|
||||
|
||||
|
||||
* `on_regex` => `nonebot.plugin.on_regex`
|
||||
|
||||
|
||||
* `on_regex` => `nonebot.plugin.on_regex`
|
||||
|
||||
|
||||
* `CommandGroup` => `nonebot.plugin.CommandGroup`
|
||||
|
||||
|
||||
* `load_plugin` => `nonebot.plugin.load_plugin`
|
||||
|
||||
|
||||
* `load_plugins` => `nonebot.plugin.load_plugins`
|
||||
|
||||
|
||||
* `load_builtin_plugins` => `nonebot.plugin.load_builtin_plugins`
|
||||
|
||||
|
||||
* `get_loaded_plugins` => `nonebot.plugin.get_loaded_plugins`
|
||||
|
||||
|
||||
## `get_driver()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
获取全局 Driver 对象。可用于在计划任务的回调中获取当前 Driver 对象。
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Driver`: 全局 Driver 对象
|
||||
|
||||
|
||||
|
||||
* **异常**
|
||||
|
||||
|
||||
* `ValueError`: 全局 Driver 对象尚未初始化 (nonebot.init 尚未调用)
|
||||
|
||||
|
||||
|
||||
* **用法**
|
||||
|
||||
|
||||
```python
|
||||
driver = nonebot.get_driver()
|
||||
```
|
||||
|
||||
|
||||
## `get_app()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
获取全局 Driver 对应 Server App 对象。
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Any`: Server App 对象
|
||||
|
||||
|
||||
|
||||
* **异常**
|
||||
|
||||
|
||||
* `ValueError`: 全局 Driver 对象尚未初始化 (nonebot.init 尚未调用)
|
||||
|
||||
|
||||
|
||||
* **用法**
|
||||
|
||||
|
||||
```python
|
||||
app = nonebot.get_app()
|
||||
```
|
||||
|
||||
|
||||
## `get_asgi()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
获取全局 Driver 对应 Asgi 对象。
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Any`: Asgi 对象
|
||||
|
||||
|
||||
|
||||
* **异常**
|
||||
|
||||
|
||||
* `ValueError`: 全局 Driver 对象尚未初始化 (nonebot.init 尚未调用)
|
||||
|
||||
|
||||
|
||||
* **用法**
|
||||
|
||||
|
||||
```python
|
||||
asgi = nonebot.get_asgi()
|
||||
```
|
||||
|
||||
|
||||
## `get_bots()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
获取所有通过 ws 连接 NoneBot 的 Bot 对象。
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Dict[str, Bot]`: 一个以字符串 ID 为键,Bot 对象为值的字典
|
||||
|
||||
|
||||
|
||||
* **异常**
|
||||
|
||||
|
||||
* `ValueError`: 全局 Driver 对象尚未初始化 (nonebot.init 尚未调用)
|
||||
|
||||
|
||||
|
||||
* **用法**
|
||||
|
||||
|
||||
```python
|
||||
bots = nonebot.get_bots()
|
||||
```
|
||||
|
||||
|
||||
## `init(*, _env_file=None, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
初始化 NoneBot 以及 全局 Driver 对象。
|
||||
|
||||
NoneBot 将会从 .env 文件中读取环境信息,并使用相应的 env 文件配置。
|
||||
|
||||
你也可以传入自定义的 _env_file 来指定 NoneBot 从该文件读取配置。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `_env_file: Optional[str]`: 配置文件名,默认从 .env.{env_name} 中读取配置
|
||||
|
||||
|
||||
* `**kwargs`: 任意变量,将会存储到 Config 对象里
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `None`
|
||||
|
||||
|
||||
|
||||
* **用法**
|
||||
|
||||
|
||||
```python
|
||||
nonebot.init(database=Database(...))
|
||||
```
|
||||
|
||||
|
||||
## `run(host=None, port=None, *args, **kwargs)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
启动 NoneBot,即运行全局 Driver 对象。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `host: Optional[str]`: 主机名/IP,若不传入则使用配置文件中指定的值
|
||||
|
||||
|
||||
* `port: Optional[int]`: 端口,若不传入则使用配置文件中指定的值
|
||||
|
||||
|
||||
* `*args`: 传入 Driver.run 的位置参数
|
||||
|
||||
|
||||
* `**kwargs`: 传入 Driver.run 的命名参数
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `None`
|
||||
|
||||
|
||||
|
||||
* **用法**
|
||||
|
||||
|
||||
```python
|
||||
nonebot.run(host="127.0.0.1", port=8080)
|
||||
```
|
@@ -1,121 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.permission 模块
|
||||
|
||||
## 权限
|
||||
|
||||
每个 `Matcher` 拥有一个 `Permission` ,其中是 **异步** `PermissionChecker` 的集合,只要有一个 `PermissionChecker` 检查结果为 `True` 时就会继续运行。
|
||||
|
||||
:::tip 提示
|
||||
`PermissionChecker` 既可以是 async function 也可以是 sync function
|
||||
:::
|
||||
|
||||
|
||||
## `MESSAGE`
|
||||
|
||||
|
||||
* **说明**: 匹配任意 `message` 类型事件,仅在需要同时捕获不同类型事件时使用。优先使用 message type 的 Matcher。
|
||||
|
||||
|
||||
## `NOTICE`
|
||||
|
||||
|
||||
* **说明**: 匹配任意 `notice` 类型事件,仅在需要同时捕获不同类型事件时使用。优先使用 notice type 的 Matcher。
|
||||
|
||||
|
||||
## `REQUEST`
|
||||
|
||||
|
||||
* **说明**: 匹配任意 `request` 类型事件,仅在需要同时捕获不同类型事件时使用。优先使用 request type 的 Matcher。
|
||||
|
||||
|
||||
## `METAEVENT`
|
||||
|
||||
|
||||
* **说明**: 匹配任意 `meta_event` 类型事件,仅在需要同时捕获不同类型事件时使用。优先使用 meta_event type 的 Matcher。
|
||||
|
||||
|
||||
## `USER(*user, perm=<nonebot.permission.Permission object>)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
在白名单内且满足 perm
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `*user: int`: 白名单
|
||||
|
||||
|
||||
* `perm: Permission`: 需要同时满足的权限
|
||||
|
||||
|
||||
|
||||
## `PRIVATE`
|
||||
|
||||
|
||||
* **说明**: 匹配任意私聊消息类型事件
|
||||
|
||||
|
||||
## `PRIVATE_FRIEND`
|
||||
|
||||
|
||||
* **说明**: 匹配任意好友私聊消息类型事件
|
||||
|
||||
|
||||
## `PRIVATE_GROUP`
|
||||
|
||||
|
||||
* **说明**: 匹配任意群临时私聊消息类型事件
|
||||
|
||||
|
||||
## `PRIVATE_OTHER`
|
||||
|
||||
|
||||
* **说明**: 匹配任意其他私聊消息类型事件
|
||||
|
||||
|
||||
## `GROUP`
|
||||
|
||||
|
||||
* **说明**: 匹配任意群聊消息类型事件
|
||||
|
||||
|
||||
## `GROUP_MEMBER`
|
||||
|
||||
|
||||
* **说明**: 匹配任意群员群聊消息类型事件
|
||||
|
||||
:::warning 警告
|
||||
该权限通过 event.sender 进行判断且不包含管理员以及群主!
|
||||
:::
|
||||
|
||||
|
||||
## `GROUP_ADMIN`
|
||||
|
||||
|
||||
* **说明**: 匹配任意群管理员群聊消息类型事件
|
||||
|
||||
|
||||
## `GROUP_OWNER`
|
||||
|
||||
|
||||
* **说明**: 匹配任意群主群聊消息类型事件
|
||||
|
||||
|
||||
## `SUPERUSER`
|
||||
|
||||
|
||||
* **说明**: 匹配任意超级用户消息类型事件
|
||||
|
||||
|
||||
## `EVERYBODY`
|
||||
|
||||
|
||||
* **说明**: 匹配任意消息类型事件
|
202
docs/api/rule.md
202
docs/api/rule.md
@@ -1,202 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.rule 模块
|
||||
|
||||
## 规则
|
||||
|
||||
每个事件响应器 `Matcher` 拥有一个匹配规则 `Rule` ,其中是 **异步** `RuleChecker` 的集合,只有当所有 `RuleChecker` 检查结果为 `True` 时继续运行。
|
||||
|
||||
:::tip 提示
|
||||
`RuleChecker` 既可以是 async function 也可以是 sync function,但在最终会被 `nonebot.utils.run_sync` 转换为 async function
|
||||
:::
|
||||
|
||||
|
||||
## _class_ `Rule`
|
||||
|
||||
基类:`object`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
`Matcher` 规则类,当事件传递时,在 `Matcher` 运行前进行检查。
|
||||
|
||||
|
||||
|
||||
* **示例**
|
||||
|
||||
|
||||
```python
|
||||
Rule(async_function) & sync_function
|
||||
# 等价于
|
||||
from nonebot.utils import run_sync
|
||||
Rule(async_function, run_sync(sync_function))
|
||||
```
|
||||
|
||||
|
||||
### `__init__(*checkers)`
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `*checkers: Callable[[Bot, Event, dict], Awaitable[bool]]`: **异步** RuleChecker
|
||||
|
||||
|
||||
|
||||
### `checkers`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
存储 `RuleChecker`
|
||||
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
|
||||
* `Set[Callable[[Bot, Event, dict], Awaitable[bool]]]`
|
||||
|
||||
|
||||
|
||||
### _async_ `__call__(bot, event, state)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
检查是否符合所有规则
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `bot: Bot`: Bot 对象
|
||||
|
||||
|
||||
* `event: Event`: Event 对象
|
||||
|
||||
|
||||
* `state: dict`: 当前 State
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `bool`
|
||||
|
||||
|
||||
|
||||
## `startswith(msg)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
匹配消息开头
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `msg: str`: 消息开头字符串
|
||||
|
||||
|
||||
|
||||
## `endswith(msg)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
匹配消息结尾
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `msg: str`: 消息结尾字符串
|
||||
|
||||
|
||||
|
||||
## `keyword(msg)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
匹配消息关键词
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `msg: str`: 关键词
|
||||
|
||||
|
||||
|
||||
## `command(command)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
命令形式匹配,根据配置里提供的 `command_start`, `command_sep` 判断消息是否为命令。
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `command: Tuples[str, ...]`: 命令内容
|
||||
|
||||
|
||||
|
||||
* **示例**
|
||||
|
||||
使用默认 `command_start`, `command_sep` 配置
|
||||
|
||||
命令 `("test",)` 可以匹配:`/test` 开头的消息
|
||||
命令 `("test", "sub")` 可以匹配”`/test.sub` 开头的消息
|
||||
|
||||
|
||||
:::tip 提示
|
||||
命令内容与后续消息间无需空格!
|
||||
:::
|
||||
|
||||
|
||||
## `regex(regex, flags=0)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
根据正则表达式进行匹配
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `regex: str`: 正则表达式
|
||||
|
||||
|
||||
* `flags: Union[int, re.RegexFlag]`: 正则标志
|
||||
|
||||
|
||||
|
||||
## `to_me()`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
通过 `event.to_me` 判断消息是否是发送给机器人
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* 无
|
@@ -1,41 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.sched 模块
|
||||
|
||||
## 计划任务
|
||||
|
||||
计划任务使用第三方库 [APScheduler](https://github.com/agronholm/apscheduler) ,使用文档请参考 [APScheduler使用文档](https://apscheduler.readthedocs.io/en/latest/) 。
|
||||
|
||||
|
||||
## `scheduler`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Optional[apscheduler.schedulers.asyncio.AsyncIOScheduler]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
当可选依赖 `APScheduler` 未安装时,`scheduler` 为 None
|
||||
|
||||
使用 `pip install nonebot[scheduler]` 安装可选依赖
|
||||
|
||||
|
||||
|
||||
* **常用示例**
|
||||
|
||||
|
||||
```python
|
||||
from nonebot import scheduler
|
||||
|
||||
@scheduler.scheduled_job("cron", hour="*/2", id="xxx", args=[1], kwargs={arg2: 2})
|
||||
async def run_every_2_hour(arg1, arg2):
|
||||
pass
|
||||
|
||||
scheduler.add_job(run_every_day_from_program_start, "interval", days=1, id="xxx")
|
||||
```
|
@@ -1,252 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.typing 模块
|
||||
|
||||
## 类型
|
||||
|
||||
下面的文档中,「类型」部分使用 Python 的 Type Hint 语法,见 [PEP 484](https://www.python.org/dev/peps/pep-0484/)、[PEP 526](https://www.python.org/dev/peps/pep-0526/) 和 [typing](https://docs.python.org/3/library/typing.html)。
|
||||
|
||||
除了 Python 内置的类型,下面还出现了如下 NoneBot 自定类型,实际上它们是 Python 内置类型的别名。
|
||||
|
||||
以下类型均可从 nonebot.typing 模块导入。
|
||||
|
||||
|
||||
## `Driver`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`BaseDriver`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
所有 Driver 的基类。
|
||||
|
||||
|
||||
|
||||
|
||||
## `WebSocket`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`BaseWebSocket`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
所有 WebSocket 的基类。
|
||||
|
||||
|
||||
|
||||
|
||||
## `Bot`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`BaseBot`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
所有 Bot 的基类。
|
||||
|
||||
|
||||
|
||||
|
||||
## `Event`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`BaseEvent`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
所有 Event 的基类。
|
||||
|
||||
|
||||
|
||||
|
||||
## `Message`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`BaseMessage`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
所有 Message 的基类。
|
||||
|
||||
|
||||
|
||||
|
||||
## `MessageSegment`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`BaseMessageSegment`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
所有 MessageSegment 的基类。
|
||||
|
||||
|
||||
|
||||
|
||||
## `PreProcessor`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Callable[[Bot, Event, dict], Union[Awaitable[None], Awaitable[NoReturn]]]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
消息预处理函数 PreProcessor 类型
|
||||
|
||||
|
||||
|
||||
|
||||
## `Matcher`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Matcher`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
Matcher 即响应事件的处理类。通过 Rule 判断是否响应事件,运行 Handler。
|
||||
|
||||
|
||||
|
||||
|
||||
## `MatcherGroup`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`MatcherGroup`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
MatcherGroup 为 Matcher 的集合。可以共享 Handler。
|
||||
|
||||
|
||||
|
||||
|
||||
## `Rule`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Rule`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
Rule 即判断是否响应事件的处理类。内部存储 RuleChecker ,返回全为 True 则响应事件。
|
||||
|
||||
|
||||
|
||||
|
||||
## `RuleChecker`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Callable[[Bot, Event, dict], Union[bool, Awaitable[bool]]]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
RuleChecker 即判断是否响应事件的处理函数。
|
||||
|
||||
|
||||
|
||||
|
||||
## `Permission`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Permission`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
Permission 即判断是否响应消息的处理类。内部存储 PermissionChecker ,返回只要有一个 True 则响应消息。
|
||||
|
||||
|
||||
|
||||
|
||||
## `PermissionChecker`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Callable[[Bot, Event], Union[bool, Awaitable[bool]]]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
RuleChecker 即判断是否响应消息的处理函数。
|
||||
|
||||
|
||||
|
||||
|
||||
## `Handler`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Callable[[Bot, Event, dict], Union[Awaitable[None], Awaitable[NoReturn]]]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
Handler 即事件的处理函数。
|
||||
|
||||
|
||||
|
||||
|
||||
## `ArgsParser`
|
||||
|
||||
|
||||
* **类型**
|
||||
|
||||
`Callable[[Bot, Event, dict], Union[Awaitable[None], Awaitable[NoReturn]]]`
|
||||
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
ArgsParser 即消息参数解析函数,在 Matcher.got 获取参数时被运行。
|
@@ -1,62 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
# NoneBot.utils 模块
|
||||
|
||||
|
||||
## `escape_tag(s)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
用于记录带颜色日志时转义 `<tag>` 类型特殊标签
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `s: str`: 需要转义的字符串
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `str`
|
||||
|
||||
|
||||
|
||||
## `run_sync(func)`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
一个用于包装 sync function 为 async function 的装饰器
|
||||
|
||||
|
||||
|
||||
* **参数**
|
||||
|
||||
|
||||
* `func: Callable[..., Any]`: 被装饰的同步函数
|
||||
|
||||
|
||||
|
||||
* **返回**
|
||||
|
||||
|
||||
* `Callable[..., Awaitable[Any]]`
|
||||
|
||||
|
||||
|
||||
## _class_ `DataclassEncoder`
|
||||
|
||||
基类:`json.encoder.JSONEncoder`
|
||||
|
||||
|
||||
* **说明**
|
||||
|
||||
在JSON序列化 `Message` (List[Dataclass]) 时使用的 `JSONEncoder`
|
@@ -1,34 +0,0 @@
|
||||
# 概览
|
||||
|
||||
:::tip 提示
|
||||
如果在阅读本文档时遇到难以理解的词汇,请随时查阅 [术语表](../glossary.md) 或使用 [Google 搜索](https://www.google.com/)。
|
||||
:::
|
||||
|
||||
:::tip 提示
|
||||
初次使用时可能会觉得这里的概览过于枯燥,可以先简单略读之后直接前往 [安装](./installation.md) 查看安装方法,并进行后续的基础使用教程。
|
||||
:::
|
||||
|
||||
NoneBot2 是一个可扩展的 Python 异步机器人框架,它会对机器人收到的消息进行解析和处理,并以插件化的形式,分发给消息所对应的命令处理器和自然语言处理器,来完成具体的功能。
|
||||
|
||||
除了起到解析消息的作用,NoneBot 还为插件提供了大量实用的预设操作和权限控制机制,尤其对于命令处理器,它更是提供了完善且易用的会话机制和内部调用机制,以分别适应命令的连续交互和插件内部功能复用等需求。
|
||||
|
||||
目前 NoneBot2 在 [FastAPI](https://fastapi.tiangolo.com/) 的基础上封装了与 [CQHTTP(OneBot) 协议](http://cqhttp.cc/)插件的网络交互。
|
||||
|
||||
得益于 Python 的 [asyncio](https://docs.python.org/3/library/asyncio.html) 机制,NoneBot 处理消息的吞吐量有了很大的保障,再配合 WebSocket 通信方式(也是最建议的通信方式),NoneBot 的性能可以达到 HTTP 通信方式的两倍以上,相较于传统同步 I/O 的 HTTP 通信,更是有质的飞跃。
|
||||
|
||||
需要注意的是,NoneBot 仅支持 Python 3.7+ 及 CQHTTP(OneBot) 插件 v11+。
|
||||
|
||||
## 它如何工作?
|
||||
|
||||
~~未填坑~~
|
||||
|
||||
## 特色
|
||||
|
||||
- 提供直观的测试前端
|
||||
- 提供使用简易的脚手架
|
||||
- 基于异步 I/O
|
||||
- 同时支持 HTTP 和反向 WebSocket 通信方式
|
||||
- 支持多个机器人账号负载均衡
|
||||
- 提供直观的交互式会话接口
|
||||
- 提供可自定义的权限控制机制
|
||||
- 多种方式渲染要发送的消息内容,使对话足够自然
|
@@ -1,68 +0,0 @@
|
||||
# 基本配置
|
||||
|
||||
到目前为止我们还在使用 NoneBot 的默认行为,在开始编写自己的插件之前,我们先尝试在配置文件上动动手脚,让 NoneBot 表现出不同的行为。
|
||||
|
||||
在上一章节中,我们创建了默认的项目结构,其中 `.env`, `.env.*` 均为项目的配置文件,下面将介绍几种 NoneBot 配置方式。
|
||||
|
||||
:::danger 警告
|
||||
请勿将敏感信息写入配置文件并提交至开源仓库!
|
||||
:::
|
||||
|
||||
## .env 文件
|
||||
|
||||
NoneBot 在启动时将会从系统环境变量或者 `.env` 文件中寻找变量 `ENVIRONMENT` (大小写不敏感),默认值为 `prod`。
|
||||
这将引导 NoneBot 从系统环境变量或者 `.env.{ENVIRONMENT}` 文件中进一步加载具体配置。
|
||||
|
||||
现在,我们在 `.env` 文件中写入当前环境信息
|
||||
|
||||
```bash
|
||||
# .env
|
||||
ENVIRONMENT=dev
|
||||
```
|
||||
|
||||
## .env.\* 文件
|
||||
|
||||
详细配置文件,使用 [pydantic](https://pydantic-docs.helpmanual.io/) 加载配置。在 NoneBot 初始化时可以指定忽略 `.env` 中的环境信息转而加载某个配置文件: `nonebot.init(_env_file=".env.dev")`。
|
||||
|
||||
:::warning 提示
|
||||
由于 `pydantic` 使用 JSON 加载配置项,请确保配置项值为 JSON 能够解析的数据。如果 JSON 解析失败将作为字符串处理。
|
||||
:::
|
||||
|
||||
示例及说明:
|
||||
|
||||
```bash
|
||||
HOST=0.0.0.0 # 配置 NoneBot 监听的 IP/主机名
|
||||
PORT=8080 # 配置 NoneBot 监听的端口
|
||||
DEBUG=true # 开启 debug 模式 **请勿在生产环境开启**
|
||||
SUPERUSERS=["123456789", "987654321"] # 配置 NoneBot 超级用户
|
||||
NICKNAME=["awesome", "bot"] # 配置机器人的昵称
|
||||
COMMAND_START=["/", ""] # 配置命令起始字符
|
||||
COMMAND_SEP=["."] # 配置命令分割字符
|
||||
|
||||
# Custom Configs
|
||||
CUSTOM_CONFIG1="config in env file"
|
||||
CUSTOM_CONFIG2= # 留空则从系统环境变量读取,如不存在则为空字符串
|
||||
```
|
||||
|
||||
详细的配置项参考 [Config Reference](../api/config.md) 。
|
||||
|
||||
## bot.py 文件
|
||||
|
||||
配置项也可以在 NoneBot 初始化时传入。此处可以传入任意合法 Python 变量。当然也可以在初始化完成后修改或新增。
|
||||
|
||||
示例:
|
||||
|
||||
```python
|
||||
# bot.py
|
||||
import nonebot
|
||||
|
||||
nonebot.init(custom_config3="config on init")
|
||||
|
||||
config = nonebot.get_driver().config
|
||||
config.custom_config3 = "changed after init"
|
||||
config.custom_config4 = "new config after init"
|
||||
```
|
||||
|
||||
## 优先级
|
||||
|
||||
`bot.py init` > `env file` > `system env`
|
@@ -1,55 +0,0 @@
|
||||
# 创建一个完整的项目
|
||||
|
||||
上一章中我们已经运行了一个最小的 NoneBot 实例,在这一章,我们将从零开始一个完整的项目。
|
||||
|
||||
## 目录结构
|
||||
|
||||
首先,我们可以使用 `nb-cli` 或者自行创建项目目录:
|
||||
|
||||
```bash
|
||||
pip install nonebot2[cli]
|
||||
# pip install nb-cli
|
||||
nb create
|
||||
```
|
||||
|
||||
这将创建默认的目录结构
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
:::vue
|
||||
AweSome-Bot
|
||||
├── `awesome_bot` _(**或是 src**)_
|
||||
│ └── `plugins`
|
||||
├── `.env` _(**可选的**)_
|
||||
├── `.env.dev` _(**可选的**)_
|
||||
├── `.env.prod` _(**可选的**)_
|
||||
├── .gitignore
|
||||
├── `bot.py`
|
||||
├── docker-compose.yml
|
||||
├── Dockerfile
|
||||
├── `pyproject.toml`
|
||||
└── README.md
|
||||
:::
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
- `awesome_bot/plugins` 或 `src/plugins`: 用于存放编写的 bot 插件
|
||||
- `.env`, `.env.dev`, `.env.prod`: 各环境配置文件
|
||||
- `bot.py`: bot 入口文件
|
||||
- `pyproject.toml`: 项目依赖管理文件,默认使用 [poetry](https://python-poetry.org/)
|
||||
|
||||
## 启动 Bot
|
||||
|
||||
如果你使用 `nb-cli`
|
||||
|
||||
```bash
|
||||
nb run [--file=bot.py] [--app=app]
|
||||
```
|
||||
|
||||
或者使用
|
||||
|
||||
```bash
|
||||
python bot.py
|
||||
```
|
||||
|
||||
:::tip 提示
|
||||
如果在 bot 入口文件内定义了 asgi server, `nb-cli` 将会为你启动**冷重载模式**
|
||||
:::
|
@@ -1,146 +0,0 @@
|
||||
# 开始使用
|
||||
|
||||
一切都安装成功后,你就已经做好了进行简单配置以运行一个最小的 NoneBot 实例的准备。
|
||||
|
||||
## 最小实例
|
||||
|
||||
使用你最熟悉的编辑器或 IDE,创建一个名为 `bot.py` 的文件,内容如下:
|
||||
|
||||
```python{3,4,7}
|
||||
import nonebot
|
||||
|
||||
nonebot.init()
|
||||
nonebot.load_builtin_plugins()
|
||||
|
||||
if __name__ == "__main__":
|
||||
nonebot.run()
|
||||
```
|
||||
|
||||
这几行高亮代码将依次:
|
||||
|
||||
1. 使用默认配置初始化 NoneBot 包
|
||||
2. 加载 NoneBot 内置的插件
|
||||
3. 在地址 `127.0.0.1:8080` 运行 NoneBot
|
||||
|
||||
在命令行使用如下命令即可运行这个 NoneBot 实例:
|
||||
|
||||
```bash
|
||||
python bot.py
|
||||
```
|
||||
|
||||
运行后会产生如下日志:
|
||||
|
||||
```default
|
||||
09-14 21:02:00 [INFO] nonebot | Succeeded to import "nonebot.plugins.base"
|
||||
09-14 21:02:00 [INFO] nonebot | Running NoneBot...
|
||||
09-14 21:02:00 [INFO] uvicorn | Started server process [1234]
|
||||
09-14 21:02:00 [INFO] uvicorn | Waiting for application startup.
|
||||
09-14 21:02:00 [INFO] nonebot | Scheduler Started
|
||||
09-14 21:02:00 [INFO] uvicorn | Application startup complete.
|
||||
09-14 21:02:00 [INFO] uvicorn | Uvicorn running on http://127.0.0.1:8080 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
## 配置 QQ 协议端
|
||||
|
||||
单纯运行 NoneBot 实例并不会产生任何效果,因为此刻 QQ 这边还不知道 NoneBot 的存在,也就无法把消息发送给它,因此现在需要使用一个无头 QQ 来把消息等事件上报给 NoneBot。
|
||||
|
||||
目前支持的协议有:
|
||||
|
||||
- [OneBot(CQHTTP)](https://github.com/howmanybots/onebot)
|
||||
|
||||
QQ 协议端举例:
|
||||
|
||||
- [Mirai](https://github.com/mamoe/mirai) + [cqhttp-mirai](https://github.com/yyuueexxiinngg/cqhttp-mirai)
|
||||
- [cqhttp-mirai-embedded](https://github.com/yyuueexxiinngg/cqhttp-mirai/tree/embedded)
|
||||
- [Mirai](https://github.com/mamoe/mirai) + [Mirai Native](https://github.com/iTXTech/mirai-native) + [CQHTTP](https://github.com/richardchien/coolq-http-api)
|
||||
- [go-cqhttp](https://github.com/Mrs4s/go-cqhttp) (基于 [MiraiGo](https://github.com/Mrs4s/MiraiGo))
|
||||
- [OICQ-http-api](https://github.com/takayama-lily/onebot) (基于 [OICQ](https://github.com/takayama-lily/oicq))
|
||||
|
||||
这里以 [go-cqhttp](https://github.com/Mrs4s/go-cqhttp) 为例
|
||||
|
||||
1. 下载 go-cqhttp 对应平台的 release 文件
|
||||
2. 双击 exe 文件或者使用 `./go-cqhttp` 启动
|
||||
3. 生成默认配置文件并修改默认配置
|
||||
|
||||
```json{2,3,30-31}
|
||||
{
|
||||
"uin": 你的QQ号,
|
||||
"password": "你的密码",
|
||||
"encrypt_password": false,
|
||||
"password_encrypted": "",
|
||||
"enable_db": true,
|
||||
"access_token": "",
|
||||
"relogin": {
|
||||
"enabled": true,
|
||||
"relogin_delay": 3,
|
||||
"max_relogin_times": 0
|
||||
},
|
||||
"ignore_invalid_cqcode": false,
|
||||
"force_fragmented": true,
|
||||
"heartbeat_interval": 0,
|
||||
"http_config": {
|
||||
"enabled": false,
|
||||
"host": "0.0.0.0",
|
||||
"port": 5700,
|
||||
"timeout": 0,
|
||||
"post_urls": {}
|
||||
},
|
||||
"ws_config": {
|
||||
"enabled": false,
|
||||
"host": "0.0.0.0",
|
||||
"port": 6700
|
||||
},
|
||||
"ws_reverse_servers": [
|
||||
{
|
||||
"enabled": true,
|
||||
"reverse_url": "ws://127.0.0.1:8080/cqhttp/ws",
|
||||
"reverse_api_url": "",
|
||||
"reverse_event_url": "",
|
||||
"reverse_reconnect_interval": 3000
|
||||
}
|
||||
],
|
||||
"post_message_format": "string",
|
||||
"debug": false,
|
||||
"log_level": ""
|
||||
}
|
||||
```
|
||||
|
||||
其中 `ws://127.0.0.1:8080/cqhttp/ws` 中的 `127.0.0.1` 和 `8080` 应分别对应 nonebot 配置的 HOST 和 PORT
|
||||
|
||||
## 历史性的第一次对话
|
||||
|
||||
一旦新的配置文件正确生效之后,NoneBot 所在的控制台(如果正在运行的话)应该会输出类似下面的内容(两条访问日志):
|
||||
|
||||
```default
|
||||
09-14 21:31:16 [INFO] uvicorn | ('127.0.0.1', 12345) - "WebSocket /cqhttp/ws" [accepted]
|
||||
09-14 21:31:16 [INFO] nonebot | WebSocket Connection from CQHTTP Bot 你的QQ号 Accepted!
|
||||
```
|
||||
|
||||
这表示 QQ 协议端已经成功地使用 CQHTTP 协议连接上了 NoneBot。
|
||||
|
||||
:::warning 注意
|
||||
如果到这一步你没有看到上面这样的成功日志,CQHTTP 的日志中在不断地重连或无反应,请注意检查配置中的 IP 和端口是否确实可以访问。比较常见的出错点包括:
|
||||
|
||||
- NoneBot 监听 `0.0.0.0`,然后在 CQHTTP 配置中填了 `ws://0.0.0.0:8080/cqhttp/ws`
|
||||
- 在 Docker 容器内运行 CQHTTP,并通过 `127.0.0.1` 访问宿主机上的 NoneBot
|
||||
- 想从公网访问,但没有修改云服务商的安全组策略或系统防火墙
|
||||
- NoneBot 所监听的端口存在冲突,已被其它程序占用
|
||||
- 弄混了 NoneBot 的 `host`、`port` 参数与 CQHTTP 配置中的 `host`、`port` 参数
|
||||
- 使用了 `ws_reverse_api_url` 和 `ws_reverse_event_url` 而非 universal client
|
||||
- `ws://` 错填为 `http://`
|
||||
- CQHTTP 或 NoneBot 启动时遭到外星武器干扰
|
||||
|
||||
请尝试重启 CQHTTP、重启 NoneBot、更换端口、修改防火墙、重启系统、仔细阅读前面的文档及提示、更新 CQHTTP 和 NoneBot 到最新版本等方式来解决。
|
||||
:::
|
||||
|
||||
现在,尝试向你的 QQ 机器人账号发送如下内容:
|
||||
|
||||
```default
|
||||
/say 你好,世界
|
||||
```
|
||||
|
||||
到这里如果一切 OK,你应该会收到机器人给你回复了 `你好,世界`。这一历史性的对话标志着你已经成功地运行了一个 NoneBot 的最小实例,开始了编写更强大的 QQ 机器人的创意之旅!
|
||||
|
||||
<ClientOnly>
|
||||
<Messenger :messages="[{ position: 'right', msg: '/say 你好,世界' }, { position: 'left', msg: '你好,世界' }]"/>
|
||||
</ClientOnly>
|
@@ -1,73 +0,0 @@
|
||||
# 安装
|
||||
|
||||
## NoneBot
|
||||
|
||||
:::warning 注意
|
||||
请确保你的 Python 版本 >= 3.7。
|
||||
:::
|
||||
|
||||
```bash
|
||||
pip install nonebot2
|
||||
```
|
||||
|
||||
如果你需要使用最新的(可能尚未发布的)特性,可以克隆 Git 仓库后手动安装:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/nonebot/nonebot2.git
|
||||
cd nonebot2
|
||||
poetry install --no-dev # 推荐
|
||||
pip install . # 不推荐
|
||||
```
|
||||
|
||||
## 额外依赖
|
||||
|
||||
### APScheduler
|
||||
|
||||
A task scheduling library for Python.
|
||||
|
||||
可用于计划任务,后台执行任务等
|
||||
|
||||
```bash
|
||||
pip install nonebot2[scheduler]
|
||||
poetry add nonebot2[scheduler]
|
||||
```
|
||||
|
||||
[View On GitHub](https://github.com/agronholm/apscheduler)
|
||||
|
||||
### NoneBot-Test
|
||||
|
||||
A test frontend for nonebot2.
|
||||
|
||||
通过前端展示 nonebot 已加载的插件以及运行状态,同时可以用于模拟发送事件测试机器人
|
||||
|
||||
```bash
|
||||
pip install nonebot2[test]
|
||||
poetry add nonebot2[test]
|
||||
```
|
||||
|
||||
[View On GitHub](https://github.com/nonebot/nonebot-test)
|
||||
|
||||
### CLI
|
||||
|
||||
CLI for nonebot2.
|
||||
|
||||
一个多功能脚手架
|
||||
|
||||
```bash
|
||||
pip install nonebot2[cli]
|
||||
poetry add nonebot2[cli]
|
||||
```
|
||||
|
||||
[View On GitHub](https://github.com/yanyongyu/nb-cli)
|
||||
|
||||
### 我全都要
|
||||
|
||||
```bash
|
||||
pip install nonebot2[full]
|
||||
poetry add nonebot2[full]
|
||||
```
|
||||
|
||||
```bash
|
||||
pip install nonebot2[cli,scheduler]
|
||||
poetry add nonebot2[cli,scheduler]
|
||||
```
|
@@ -1,290 +0,0 @@
|
||||
# 编写插件
|
||||
|
||||
本章将以一个天气查询插件为例,教学如何编写自己的命令。
|
||||
|
||||
## 加载插件
|
||||
|
||||
在 [创建一个完整的项目](creating-a-project) 一章节中,我们已经创建了插件目录 `awesome_bot/plugins`,现在我们在机器人入口文件中加载它。当然,你也可以单独加载一个插件。
|
||||
|
||||
:::tip 提示
|
||||
加载插件目录时,目录下以 `_` 下划线开头的插件将不会被加载!
|
||||
:::
|
||||
|
||||
在 `bot.py` 文件中添加以下行:
|
||||
|
||||
```python{5,7}
|
||||
import nonebot
|
||||
|
||||
nonebot.init()
|
||||
# 加载单独的一个插件,参数为合法的python包名
|
||||
nonebot.load_plugin("nonebot.plugins.base")
|
||||
# 加载插件目录,该目录下为各插件,以下划线开头的插件将不会被加载
|
||||
nonebot.load_plugins("awesome_bot/plugins")
|
||||
|
||||
app = nonebot.get_asgi()
|
||||
|
||||
if __name__ == "__main__":
|
||||
nonebot.run()
|
||||
```
|
||||
|
||||
尝试运行 `nb run` 或者 `python bot.py`,可以看到日志输出了类似如下内容:
|
||||
|
||||
```plain
|
||||
09-19 21:51:59 [INFO] nonebot | Succeeded to import "nonebot.plugins.base"
|
||||
09-19 21:51:59 [INFO] nonebot | Succeeded to import "plugin_in_folder"
|
||||
```
|
||||
|
||||
## 创建插件
|
||||
|
||||
现在我们已经有了一个空的插件目录,我们可以开始创建插件了!插件有两种形式
|
||||
|
||||
### 单文件形式
|
||||
|
||||
在插件目录下创建名为 `weather.py` 的 Python 文件,暂时留空,此时目录结构如下:
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
:::vue
|
||||
AweSome-Bot
|
||||
├── awesome_bot
|
||||
│ └── plugins
|
||||
│ └── `weather.py`
|
||||
├── .env
|
||||
├── .env.dev
|
||||
├── .env.prod
|
||||
├── .gitignore
|
||||
├── bot.py
|
||||
├── docker-compose.yml
|
||||
├── Dockerfile
|
||||
├── pyproject.toml
|
||||
└── README.md
|
||||
:::
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
这个时候它已经可以被称为一个插件了,尽管它还什么都没做。
|
||||
|
||||
### 包形式
|
||||
|
||||
在插件目录下创建文件夹 `weather`,并在该文件夹下创建文件 `__init__.py`,此时目录结构如下:
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
:::vue
|
||||
AweSome-Bot
|
||||
├── awesome_bot
|
||||
│ └── plugins
|
||||
│ └── `weather`
|
||||
│ └── `__init__.py`
|
||||
├── .env
|
||||
├── .env.dev
|
||||
├── .env.prod
|
||||
├── .gitignore
|
||||
├── bot.py
|
||||
├── docker-compose.yml
|
||||
├── Dockerfile
|
||||
├── pyproject.toml
|
||||
└── README.md
|
||||
:::
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
这个时候 `weather` 就是一个合法的 Python 包了,同时也是合法的 NoneBot 插件,插件内容可以在 `__init__.py` 中编写。
|
||||
|
||||
## 编写真正的内容
|
||||
|
||||
好了,现在插件已经可以正确加载,我们可以开始编写命令的实际代码了。在 `weather.py` 中添加如下代码:
|
||||
|
||||
```python
|
||||
from nonebot import on_command
|
||||
from nonebot.rule import to_me
|
||||
from nonebot.adapters.cqhttp import Bot, Event
|
||||
|
||||
weather = on_command("天气", rule=to_me(), priority=5)
|
||||
|
||||
|
||||
@weather.handle()
|
||||
async def handle_first_receive(bot: Bot, event: Event, state: dict):
|
||||
args = str(event.message).strip() # 首次发送命令时跟随的参数,例:/天气 上海,则args为上海
|
||||
if args:
|
||||
state["city"] = args # 如果用户发送了参数则直接赋值
|
||||
|
||||
|
||||
@weather.got("city", prompt="你想查询哪个城市的天气呢?")
|
||||
async def handle_city(bot: Bot, event: Event, state: dict):
|
||||
city = state["city"]
|
||||
if city not in ["上海", "北京"]:
|
||||
await weather.reject("你想查询的城市暂不支持,请重新输入!")
|
||||
city_weather = await get_weather(city)
|
||||
await weather.finish(city_weather)
|
||||
|
||||
|
||||
async def get_weather(city: str):
|
||||
return f"{city}的天气是..."
|
||||
```
|
||||
|
||||
为了简单起见,我们在这里的例子中没有接入真实的天气数据,但要接入也非常简单,你可以使用中国天气网、和风天气等网站提供的 API。
|
||||
|
||||
下面我们来说明这段代码是如何工作的。
|
||||
|
||||
:::tip 提示
|
||||
从这里开始,你需要对 Python 的 asyncio 编程有所了解,因为 NoneBot 是完全基于 asyncio 的,具体可以参考 [廖雪峰的 Python 教程](https://www.liaoxuefeng.com/wiki/1016959663602400/1017959540289152)
|
||||
:::
|
||||
|
||||
### 注册一个 [事件响应器](../api/matcher.md)
|
||||
|
||||
```python{4}
|
||||
from nonebot import on_command
|
||||
from nonebot.rule import to_me
|
||||
from nonebot.permission import Permission
|
||||
|
||||
weather = on_command("天气", rule=to_me(), permission=Permission(), priority=5)
|
||||
```
|
||||
|
||||
在上方代码中,我们注册了一个事件响应器 `Matcher`,它由几个部分组成:
|
||||
|
||||
1. `on_command` 注册一个消息类型的命令处理器
|
||||
2. `"天气"` 指定 command 参数 - 命令名
|
||||
3. `rule` 补充事件响应器的匹配规则
|
||||
4. `priority` 事件响应器优先级
|
||||
5. `block` 是否阻止事件传递
|
||||
|
||||
其他详细配置可以参考 API 文档,下面我们详细说明各个部分:
|
||||
|
||||
#### 事件响应器类型 type
|
||||
|
||||
事件响应器类型其实就是对应 `Event.type` ,NoneBot 提供了一个基础类型事件响应器 `on()` 以及一些内置的事件响应器。
|
||||
|
||||
- `on("事件类型")`: 基础事件响应器,第一个参数为事件类型,空字符串表示不限
|
||||
- `on_metaevent()` ~ `on("meta_event")`: 元事件响应器
|
||||
- `on_message()` ~ `on("message")`: 消息事件响应器
|
||||
- `on_request()` ~ `on("request")`: 请求事件响应器
|
||||
- `on_notice()` ~ `on("notice")`: 通知事件响应器
|
||||
- `on_startswith(str)` ~ `on("message", startswith(str))`: 消息开头匹配处理器
|
||||
- `on_endswith(str)` ~ `on("message", endswith(str))`: 消息结尾匹配处理器
|
||||
- `on_command(str|tuple)` ~ `on("message", command(str|tuple))`: 命令处理器
|
||||
- `on_regex(pattern_str)` ~ `on("message", regex(pattern_str))`: 正则匹配处理器
|
||||
|
||||
#### 匹配规则 rule
|
||||
|
||||
事件响应器的匹配规则即 `Rule`,由非负个 `RuleChecker` 组成,当所有 `RuleChecker` 返回 `True` 时匹配成功。这些 `RuleChecker` 的形式如下:
|
||||
|
||||
```python
|
||||
async def check(bot: Bot, event: Event, state: dict) -> bool:
|
||||
return True
|
||||
|
||||
def check(bot: Bot, event: Event, state: dict) -> bool:
|
||||
return True
|
||||
```
|
||||
|
||||
`Rule` 和 `RuleChecker` 之间可以使用 `与 &` 互相组合:
|
||||
|
||||
```python
|
||||
from nonebot.rule import Rule
|
||||
|
||||
Rule(async_checker1) & sync_checker & async_checker2
|
||||
```
|
||||
|
||||
:::danger 警告
|
||||
`Rule(*checkers)` 只接受 async function,或使用 `nonebot.utils.run_sync` 自行包裹 sync function。在使用 `与 &` 时,NoneBot 会自动包裹 sync function
|
||||
:::
|
||||
|
||||
#### 优先级 priority
|
||||
|
||||
事件响应器的优先级代表事件响应器的执行顺序,同一优先级的事件响应器会 **同时执行!**
|
||||
|
||||
:::tip 提示
|
||||
使用 `nonebot-test` 可以看到当前所有事件响应器的执行流程,有助理解事件响应流程!
|
||||
|
||||
```bash
|
||||
pip install nonebot2[test]
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
#### 阻断 block
|
||||
|
||||
当有任意事件响应器发出了阻止事件传递信号时,该事件将不再会传递给下一优先级,直接结束处理。
|
||||
|
||||
NoneBot 内置的事件响应器中,所有 `message` 类的事件响应器默认会阻断事件传递,其他则不会。
|
||||
|
||||
### 编写事件处理函数 [Handler](../api/typing.md#handler)
|
||||
|
||||
```python{1,2,8,9}
|
||||
@weather.handle()
|
||||
async def handle_first_receive(bot: Bot, event: Event, state: dict):
|
||||
args = str(event.message).strip() # 首次发送命令时跟随的参数,例:/天气 上海,则args为上海
|
||||
if args:
|
||||
state["city"] = args # 如果用户发送了参数则直接赋值
|
||||
|
||||
|
||||
@weather.got("city", prompt="你想查询哪个城市的天气呢?")
|
||||
async def handle_city(bot: Bot, event: Event, state: dict):
|
||||
city = state["city"]
|
||||
if city not in ["上海", "北京"]:
|
||||
await weather.reject("你想查询的城市暂不支持,请重新输入!")
|
||||
city_weather = await get_weather(city)
|
||||
await weather.finish(city_weather)
|
||||
```
|
||||
|
||||
在上面的代码中,我们给 `weather` 事件响应器添加了两个事件处理函数:`handle_first_receive`, `handle_city`
|
||||
|
||||
其中有几个要点,我们一一解释:
|
||||
|
||||
#### 添加一个事件处理函数
|
||||
|
||||
在事件响应器响应事件时,事件处理函数会依次顺序执行,也就是说,与添加顺序一致。
|
||||
|
||||
我们可以使用 `@matcher.handle()` 装饰器来简单地为该事件响应器添加一个处理函数。
|
||||
|
||||
同时,NoneBot 内置了几种添加事件处理函数方式以方便处理:
|
||||
|
||||
- `@matcher.receive()`: 指示 NoneBot 接收一条新的用户消息以继续执行后续处理函数。
|
||||
- `@matcher.got(key, [prompt="请输入key"], [args_parser=function])`: 指示 NoneBot 当 `state` 中不存在 `key` 时向用户发送 `prompt` 等待用户回复并赋值给 `state[key]`
|
||||
|
||||
这些装饰器可以套娃使用!例如:
|
||||
|
||||
```python
|
||||
@matcher.got("key1")
|
||||
@matcher.got("key2")
|
||||
async def handle(bot: Bot, event: Event, state: dict):
|
||||
pass
|
||||
```
|
||||
|
||||
#### 事件处理函数参数
|
||||
|
||||
事件处理函数类型为 `Callable[[Bot, Event, dict], Union[Awaitable[None], Awaitable[NoReturn]]]` 。
|
||||
|
||||
参数分别为:
|
||||
|
||||
1. [nonebot.typing.Bot](../api/typing.md#bot): 即事件上报连接对应的 Bot 对象,为 BaseBot 的子类。特别注意,此处的类型注释可以替换为指定的 Bot 类型,例如:`nonebot.adapters.cqhttp.Bot`,只有在上报事件的 Bot 类型与类型注释相符时才会执行该处理函数!可用于多平台进行不同的处理。
|
||||
2. [nonebot.typing.Event](../api/typing.md#event): 即上报事件对象,可以获取到上报的所有信息。
|
||||
3. `state`: 状态字典,可以存储任意的信息
|
||||
|
||||
#### 处理事件
|
||||
|
||||
在事件处理函数中,我们只需要对 `event` 做出相应的处理,存入状态字典 `state` 中,或者向用户发送消息、调用某个机器人 API 等等。
|
||||
|
||||
在 NoneBot 中,提供了几种特殊的处理函数:
|
||||
|
||||
##### `@matcher.args_parser`
|
||||
|
||||
这是一个装饰器,装饰一个函数来使它成为参数的默认解析函数,当使用 `matcher.got(xxx, [args_parser])` 获取到一条消息时,会运行 `matcher.got` 的 `args_parser` ,如果不存在则运行 `@matcher.args_parser`。
|
||||
|
||||
##### `matcher.pause`
|
||||
|
||||
这个函数用于结束当前事件处理函数,强制接收一条新的消息再运行**下一个消息处理函数**。
|
||||
|
||||
##### `matcher.reject`
|
||||
|
||||
这个函数用于结束当前事件处理函数,强制接收一条新的消息再**再次运行当前消息处理函数**。
|
||||
|
||||
##### `matcher.finish`
|
||||
|
||||
这个函数用于直接结束当前事件处理。
|
||||
|
||||
以上三个函数都拥有一个参数 `prompt`,用于向用户发送一条消息。
|
||||
|
||||
## 结语
|
||||
|
||||
至此,相信你已经能够写出一个基础的插件了,更多的用法将会在 进阶 部分进行介绍,这里给出几个小提示:
|
||||
|
||||
- 请千万注意事件处理器的优先级设定
|
||||
- 在匹配规则中请勿使用耗时极长的函数
|
||||
- 同一个用户可以跨群(私聊)继续他的事件处理(除非做出权限限制,将在后续介绍)
|
@@ -1,18 +1,12 @@
|
||||
NoneBot Api Reference
|
||||
=====================
|
||||
\-\-\-
|
||||
sidebar_position: 1
|
||||
id: index
|
||||
slug: /api
|
||||
\-\-\-
|
||||
|
||||
:模块索引:
|
||||
- `nonebot <nonebot.html>`_
|
||||
- `nonebot.config <config.html>`_
|
||||
- `nonebot.matcher <matcher.html>`_
|
||||
- `nonebot.rule <rule.html>`_
|
||||
- `nonebot.permission <permission.html>`_
|
||||
- `nonebot.sched <sched.html>`_
|
||||
- `nonebot.log <log.html>`_
|
||||
- `nonebot.utils <utils.html>`_
|
||||
- `nonebot.typing <typing.html>`_
|
||||
- `nonebot.exception <exception.html>`_
|
||||
- `nonebot.drivers <drivers/>`_
|
||||
- `nonebot.drivers.fastapi <drivers/fastapi.html>`_
|
||||
- `nonebot.adapters <adapters/>`_
|
||||
- `nonebot.adapters.cqhttp <adapters/cqhttp.html>`_
|
||||
NoneBot 模块
|
||||
===============
|
||||
|
||||
.. automodule:: nonebot
|
||||
:members:
|
||||
:show-inheritance:
|
||||
|
@@ -1,7 +1,7 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
\-\-\-
|
||||
id: index
|
||||
slug: /api/adapters/
|
||||
\-\-\-
|
||||
|
||||
NoneBot.adapters 模块
|
||||
=====================
|
||||
@@ -11,3 +11,33 @@ NoneBot.adapters 模块
|
||||
:private-members:
|
||||
:special-members: __init__
|
||||
:show-inheritance:
|
||||
|
||||
.. automodule:: nonebot.adapters._adapter
|
||||
:members:
|
||||
:private-members:
|
||||
:special-members: __init__
|
||||
:show-inheritance:
|
||||
|
||||
.. automodule:: nonebot.adapters._bot
|
||||
:members:
|
||||
:private-members:
|
||||
:special-members: __init__
|
||||
:show-inheritance:
|
||||
|
||||
.. automodule:: nonebot.adapters._message
|
||||
:members:
|
||||
:private-members:
|
||||
:special-members: __init__
|
||||
:show-inheritance:
|
||||
|
||||
.. automodule:: nonebot.adapters._event
|
||||
:members:
|
||||
:private-members:
|
||||
:special-members: __init__
|
||||
:show-inheritance:
|
||||
|
||||
.. automodule:: nonebot.adapters._template
|
||||
:members:
|
||||
:private-members:
|
||||
:special-members: __init__
|
||||
:show-inheritance:
|
||||
|
@@ -1,12 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
NoneBot.adapters.cqhttp 模块
|
||||
============================
|
||||
|
||||
.. automodule:: nonebot.adapters.cqhttp
|
||||
:members:
|
||||
:private-members:
|
||||
:show-inheritance:
|
@@ -12,6 +12,7 @@
|
||||
#
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(__file__))))
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
@@ -45,7 +46,7 @@ templates_path = ['_templates']
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = 'zh'
|
||||
language = 'zh_CN'
|
||||
|
||||
master_doc = "README"
|
||||
|
||||
@@ -72,6 +73,8 @@ html_static_path = ['_static']
|
||||
|
||||
# -- Options for autodoc extension ----------------------------------------------
|
||||
autodoc_default_options = {'member-order': 'bysource'}
|
||||
autodoc_inherit_docstrings = False
|
||||
autodoc_typehints = 'none'
|
||||
|
||||
# -- Options for todo extension ----------------------------------------------
|
||||
|
||||
|
@@ -1,7 +1,6 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
\-\-\-
|
||||
sidebar_position: 2
|
||||
\-\-\-
|
||||
|
||||
NoneBot.config 模块
|
||||
===================
|
||||
|
11
docs_build/dependencies.rst
Normal file
11
docs_build/dependencies.rst
Normal file
@@ -0,0 +1,11 @@
|
||||
\-\-\-
|
||||
sidebar_position: 8
|
||||
\-\-\-
|
||||
|
||||
NoneBot.dependencies 模块
|
||||
====================
|
||||
|
||||
.. automodule:: nonebot.dependencies
|
||||
:members:
|
||||
:private-members:
|
||||
:show-inheritance:
|
@@ -1,7 +1,7 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
\-\-\-
|
||||
id: index
|
||||
slug: /api/drivers/
|
||||
\-\-\-
|
||||
|
||||
NoneBot.drivers 模块
|
||||
=====================
|
||||
|
9
docs_build/drivers/aiohttp.rst
Normal file
9
docs_build/drivers/aiohttp.rst
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
|
||||
NoneBot.drivers.aiohttp 模块
|
||||
=============================
|
||||
|
||||
.. automodule:: nonebot.drivers.aiohttp
|
||||
:members:
|
||||
:private-members:
|
||||
:show-inheritance:
|
@@ -1,13 +1,9 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
|
||||
NoneBot.drivers.fastapi 模块
|
||||
=====================
|
||||
=============================
|
||||
|
||||
.. automodule:: nonebot.drivers.fastapi
|
||||
:members:
|
||||
:private-members:
|
||||
:special-members: __init__
|
||||
:show-inheritance:
|
||||
|
9
docs_build/drivers/httpx.rst
Normal file
9
docs_build/drivers/httpx.rst
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
|
||||
NoneBot.drivers.httpx 模块
|
||||
=============================
|
||||
|
||||
.. automodule:: nonebot.drivers.httpx
|
||||
:members:
|
||||
:private-members:
|
||||
:show-inheritance:
|
9
docs_build/drivers/quart.rst
Normal file
9
docs_build/drivers/quart.rst
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
|
||||
NoneBot.drivers.quart 模块
|
||||
==========================
|
||||
|
||||
.. automodule:: nonebot.drivers.quart
|
||||
:members:
|
||||
:private-members:
|
||||
:show-inheritance:
|
9
docs_build/drivers/websockets.rst
Normal file
9
docs_build/drivers/websockets.rst
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
|
||||
NoneBot.drivers.websockets 模块
|
||||
=============================
|
||||
|
||||
.. automodule:: nonebot.drivers.websockets
|
||||
:members:
|
||||
:private-members:
|
||||
:show-inheritance:
|
@@ -1,7 +1,6 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
\-\-\-
|
||||
sidebar_position: 12
|
||||
\-\-\-
|
||||
|
||||
NoneBot.exception 模块
|
||||
======================
|
||||
|
@@ -1,7 +1,6 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
\-\-\-
|
||||
sidebar_position: 9
|
||||
\-\-\-
|
||||
|
||||
NoneBot.log 模块
|
||||
=================
|
||||
|
@@ -1,7 +1,6 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
\-\-\-
|
||||
sidebar_position: 5
|
||||
\-\-\-
|
||||
|
||||
NoneBot.matcher 模块
|
||||
====================
|
||||
|
10
docs_build/message.rst
Normal file
10
docs_build/message.rst
Normal file
@@ -0,0 +1,10 @@
|
||||
\-\-\-
|
||||
sidebar_position: 4
|
||||
\-\-\-
|
||||
|
||||
NoneBot.message 模块
|
||||
======================
|
||||
|
||||
.. automodule:: nonebot.message
|
||||
:members:
|
||||
:show-inheritance:
|
@@ -1,11 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
NoneBot 模块
|
||||
===============
|
||||
|
||||
.. automodule:: nonebot
|
||||
:members:
|
||||
:show-inheritance:
|
@@ -1,7 +1,6 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
\-\-\-
|
||||
sidebar_position: 7
|
||||
\-\-\-
|
||||
|
||||
NoneBot.permission 模块
|
||||
=======================
|
||||
@@ -9,3 +8,4 @@ NoneBot.permission 模块
|
||||
.. automodule:: nonebot.permission
|
||||
:members:
|
||||
:show-inheritance:
|
||||
:special-members:
|
||||
|
31
docs_build/plugin.rst
Normal file
31
docs_build/plugin.rst
Normal file
@@ -0,0 +1,31 @@
|
||||
\-\-\-
|
||||
sidebar_position: 3
|
||||
\-\-\-
|
||||
|
||||
NoneBot.plugin 模块
|
||||
====================
|
||||
|
||||
.. automodule:: nonebot.plugin
|
||||
:members:
|
||||
:show-inheritance:
|
||||
:special-members: __init__
|
||||
|
||||
.. automodule:: nonebot.plugin.plugin
|
||||
:members:
|
||||
:show-inheritance:
|
||||
:special-members: __init__
|
||||
|
||||
.. automodule:: nonebot.plugin.on
|
||||
:members:
|
||||
:show-inheritance:
|
||||
:special-members: __init__
|
||||
|
||||
.. automodule:: nonebot.plugin.load
|
||||
:members:
|
||||
:show-inheritance:
|
||||
:special-members: __init__
|
||||
|
||||
.. automodule:: nonebot.plugin.export
|
||||
:members:
|
||||
:show-inheritance:
|
||||
:special-members: __init__
|
@@ -1,7 +1,6 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
\-\-\-
|
||||
sidebar_position: 6
|
||||
\-\-\-
|
||||
|
||||
NoneBot.rule 模块
|
||||
====================
|
||||
|
@@ -1,11 +0,0 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
|
||||
NoneBot.sched 模块
|
||||
===================
|
||||
|
||||
.. automodule:: nonebot.sched
|
||||
:members:
|
||||
:show-inheritance:
|
@@ -1,7 +1,6 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
\-\-\-
|
||||
sidebar_position: 11
|
||||
\-\-\-
|
||||
|
||||
NoneBot.typing 模块
|
||||
===================
|
||||
|
@@ -1,13 +1,10 @@
|
||||
---
|
||||
contentSidebar: true
|
||||
sidebarDepth: 0
|
||||
---
|
||||
\-\-\-
|
||||
sidebar_position: 10
|
||||
\-\-\-
|
||||
|
||||
NoneBot.utils 模块
|
||||
==================
|
||||
|
||||
|
||||
.. autofunction:: nonebot.utils.escape_tag
|
||||
.. autodecorator:: nonebot.utils.run_sync
|
||||
.. autoclass:: nonebot.utils.DataclassEncoder
|
||||
:show-inheritance:
|
||||
.. automodule:: nonebot.utils
|
||||
:members:
|
||||
:show-inheritance:
|
||||
|
@@ -1,5 +1,3 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
快捷导入
|
||||
========
|
||||
@@ -12,24 +10,47 @@
|
||||
- ``on_metaevent`` => ``nonebot.plugin.on_metaevent``
|
||||
- ``on_startswith`` => ``nonebot.plugin.on_startswith``
|
||||
- ``on_endswith`` => ``nonebot.plugin.on_endswith``
|
||||
- ``on_keyword`` => ``nonebot.plugin.on_keyword``
|
||||
- ``on_command`` => ``nonebot.plugin.on_command``
|
||||
- ``on_regex`` => ``nonebot.plugin.on_regex``
|
||||
- ``on_regex`` => ``nonebot.plugin.on_regex``
|
||||
- ``on_shell_command`` => ``nonebot.plugin.on_shell_command``
|
||||
- ``on_regex`` => ``nonebot.plugin.on_regex``
|
||||
- ``CommandGroup`` => ``nonebot.plugin.CommandGroup``
|
||||
- ``Matchergroup`` => ``nonebot.plugin.MatcherGroup``
|
||||
- ``load_plugin`` => ``nonebot.plugin.load_plugin``
|
||||
- ``load_plugins`` => ``nonebot.plugin.load_plugins``
|
||||
- ``load_all_plugins`` => ``nonebot.plugin.load_all_plugins``
|
||||
- ``load_from_json`` => ``nonebot.plugin.load_from_json``
|
||||
- ``load_from_toml`` => ``nonebot.plugin.load_from_toml``
|
||||
- ``load_builtin_plugins`` => ``nonebot.plugin.load_builtin_plugins``
|
||||
- ``get_plugin`` => ``nonebot.plugin.get_plugin``
|
||||
- ``get_loaded_plugins`` => ``nonebot.plugin.get_loaded_plugins``
|
||||
- ``export`` => ``nonebot.plugin.export``
|
||||
- ``require`` => ``nonebot.plugin.require``
|
||||
"""
|
||||
|
||||
import importlib
|
||||
from nonebot.typing import Bot, Dict, Type, Union, Driver, Optional, NoReturn
|
||||
from typing import Any, Dict, Type, Optional
|
||||
|
||||
import pkg_resources
|
||||
|
||||
from nonebot.adapters import Bot
|
||||
from nonebot.utils import escape_tag
|
||||
from nonebot.config import Env, Config
|
||||
from nonebot.log import logger, default_filter
|
||||
from nonebot.drivers import Driver, ReverseDriver, combine_driver
|
||||
|
||||
try:
|
||||
_dist: pkg_resources.Distribution = pkg_resources.get_distribution("nonebot2")
|
||||
__version__ = _dist.version
|
||||
VERSION = _dist.parsed_version
|
||||
except pkg_resources.DistributionNotFound: # pragma: no cover
|
||||
__version__ = None
|
||||
VERSION = None
|
||||
|
||||
_driver: Optional[Driver] = None
|
||||
|
||||
|
||||
def get_driver() -> Union[NoReturn, Driver]:
|
||||
def get_driver() -> Driver:
|
||||
"""
|
||||
:说明:
|
||||
|
||||
@@ -55,7 +76,7 @@ def get_driver() -> Union[NoReturn, Driver]:
|
||||
return _driver
|
||||
|
||||
|
||||
def get_app():
|
||||
def get_app() -> Any:
|
||||
"""
|
||||
:说明:
|
||||
|
||||
@@ -77,10 +98,13 @@ def get_app():
|
||||
|
||||
"""
|
||||
driver = get_driver()
|
||||
assert isinstance(
|
||||
driver, ReverseDriver
|
||||
), "app object is only available for reverse driver"
|
||||
return driver.server_app
|
||||
|
||||
|
||||
def get_asgi():
|
||||
def get_asgi() -> Any:
|
||||
"""
|
||||
:说明:
|
||||
|
||||
@@ -102,10 +126,51 @@ def get_asgi():
|
||||
|
||||
"""
|
||||
driver = get_driver()
|
||||
assert isinstance(
|
||||
driver, ReverseDriver
|
||||
), "asgi object is only available for reverse driver"
|
||||
return driver.asgi
|
||||
|
||||
|
||||
def get_bots() -> Union[NoReturn, Dict[str, Bot]]:
|
||||
def get_bot(self_id: Optional[str] = None) -> Bot:
|
||||
"""
|
||||
:说明:
|
||||
|
||||
当提供 self_id 时,此函数是 get_bots()[self_id] 的简写;当不提供时,返回一个 Bot。
|
||||
|
||||
:参数:
|
||||
|
||||
* ``self_id: Optional[str]``: 用来识别 Bot 的 ID
|
||||
|
||||
:返回:
|
||||
|
||||
* ``Bot``: Bot 对象
|
||||
|
||||
:异常:
|
||||
|
||||
* ``KeyError``: 对应 ID 的 Bot 不存在
|
||||
* ``ValueError``: 全局 Driver 对象尚未初始化 (nonebot.init 尚未调用)
|
||||
* ``ValueError``: 没有传入 ID 且没有 Bot 可用
|
||||
|
||||
:用法:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
assert nonebot.get_bot('12345') == nonebot.get_bots()['12345']
|
||||
|
||||
another_unspecified_bot = nonebot.get_bot()
|
||||
"""
|
||||
bots = get_bots()
|
||||
if self_id is not None:
|
||||
return bots[self_id]
|
||||
|
||||
for bot in bots.values():
|
||||
return bot
|
||||
|
||||
raise ValueError("There are no bots to get.")
|
||||
|
||||
|
||||
def get_bots() -> Dict[str, Bot]:
|
||||
"""
|
||||
:说明:
|
||||
|
||||
@@ -130,16 +195,35 @@ def get_bots() -> Union[NoReturn, Dict[str, Bot]]:
|
||||
return driver.bots
|
||||
|
||||
|
||||
from nonebot.sched import scheduler
|
||||
from nonebot.utils import escape_tag
|
||||
from nonebot.config import Env, Config
|
||||
from nonebot.log import logger, default_filter
|
||||
from nonebot.adapters.cqhttp import Bot as CQBot
|
||||
def _resolve_dot_notation(
|
||||
obj_str: str, default_attr: str, default_prefix: Optional[str] = None
|
||||
) -> Any:
|
||||
modulename, _, cls = obj_str.partition(":")
|
||||
if default_prefix is not None and modulename.startswith("~"):
|
||||
modulename = default_prefix + modulename[1:]
|
||||
module = importlib.import_module(modulename)
|
||||
if not cls:
|
||||
return getattr(module, default_attr)
|
||||
instance = module
|
||||
for attr_str in cls.split("."):
|
||||
instance = getattr(instance, attr_str)
|
||||
return instance
|
||||
|
||||
try:
|
||||
import nonebot_test
|
||||
except ImportError:
|
||||
nonebot_test = None
|
||||
|
||||
def _resolve_combine_expr(obj_str: str) -> Type[Driver]:
|
||||
drivers = obj_str.split("+")
|
||||
DriverClass = _resolve_dot_notation(
|
||||
drivers[0], "Driver", default_prefix="nonebot.drivers."
|
||||
)
|
||||
if len(drivers) == 1:
|
||||
logger.trace(f"Detected driver {DriverClass} with no mixins.")
|
||||
return DriverClass
|
||||
mixins = [
|
||||
_resolve_dot_notation(mixin, "Mixin", default_prefix="nonebot.drivers.")
|
||||
for mixin in drivers[1:]
|
||||
]
|
||||
logger.trace(f"Detected driver {DriverClass} with mixins {mixins}.")
|
||||
return combine_driver(DriverClass, *mixins)
|
||||
|
||||
|
||||
def init(*, _env_file: Optional[str] = None, **kwargs):
|
||||
@@ -170,37 +254,27 @@ def init(*, _env_file: Optional[str] = None, **kwargs):
|
||||
"""
|
||||
global _driver
|
||||
if not _driver:
|
||||
logger.info("NoneBot is initializing...")
|
||||
logger.success("NoneBot is initializing...")
|
||||
env = Env()
|
||||
logger.opt(
|
||||
colors=True).info(f"Current <y><b>Env: {env.environment}</b></y>")
|
||||
config = Config(**kwargs,
|
||||
_env_file=_env_file or f".env.{env.environment}")
|
||||
config = Config(
|
||||
**kwargs,
|
||||
_common_config=env.dict(),
|
||||
_env_file=_env_file or f".env.{env.environment}",
|
||||
)
|
||||
|
||||
default_filter.level = "DEBUG" if config.debug else "INFO"
|
||||
default_filter.level = config.log_level
|
||||
logger.opt(colors=True).info(
|
||||
f"Current <y><b>Env: {escape_tag(env.environment)}</b></y>"
|
||||
)
|
||||
logger.opt(colors=True).debug(
|
||||
f"Loaded <y><b>Config</b></y>: {escape_tag(str(config.dict()))}")
|
||||
f"Loaded <y><b>Config</b></y>: {escape_tag(str(config.dict()))}"
|
||||
)
|
||||
|
||||
DriverClass: Type[Driver] = getattr(
|
||||
importlib.import_module(config.driver), "Driver")
|
||||
DriverClass: Type[Driver] = _resolve_combine_expr(config.driver)
|
||||
_driver = DriverClass(env, config)
|
||||
|
||||
# register build-in adapters
|
||||
_driver.register_adapter("cqhttp", CQBot)
|
||||
|
||||
# load nonebot test frontend if debug
|
||||
if config.debug and nonebot_test:
|
||||
logger.debug("Loading nonebot test frontend...")
|
||||
nonebot_test.init()
|
||||
|
||||
if scheduler:
|
||||
_driver.on_startup(_start_scheduler)
|
||||
|
||||
|
||||
def run(host: Optional[str] = None,
|
||||
port: Optional[int] = None,
|
||||
*args,
|
||||
**kwargs):
|
||||
def run(*args: Any, **kwargs: Any) -> None:
|
||||
"""
|
||||
:说明:
|
||||
|
||||
@@ -208,8 +282,6 @@ def run(host: Optional[str] = None,
|
||||
|
||||
:参数:
|
||||
|
||||
* ``host: Optional[str]``: 主机名/IP,若不传入则使用配置文件中指定的值
|
||||
* ``port: Optional[int]``: 端口,若不传入则使用配置文件中指定的值
|
||||
* ``*args``: 传入 Driver.run 的位置参数
|
||||
* ``**kwargs``: 传入 Driver.run 的命名参数
|
||||
|
||||
@@ -224,17 +296,30 @@ def run(host: Optional[str] = None,
|
||||
nonebot.run(host="127.0.0.1", port=8080)
|
||||
|
||||
"""
|
||||
logger.info("Running NoneBot...")
|
||||
get_driver().run(host, port, *args, **kwargs)
|
||||
logger.success("Running NoneBot...")
|
||||
get_driver().run(*args, **kwargs)
|
||||
|
||||
|
||||
async def _start_scheduler():
|
||||
if scheduler and not scheduler.running:
|
||||
scheduler.configure(_driver.config.apscheduler_config)
|
||||
scheduler.start()
|
||||
logger.opt(colors=True).info("<y>Scheduler Started</y>")
|
||||
|
||||
|
||||
from nonebot.plugin import on_message, on_notice, on_request, on_metaevent
|
||||
from nonebot.plugin import on_startswith, on_endswith, on_command, on_regex, CommandGroup
|
||||
from nonebot.plugin import load_plugin, load_plugins, load_builtin_plugins, get_loaded_plugins
|
||||
import nonebot.params as params
|
||||
from nonebot.plugin import export as export
|
||||
from nonebot.plugin import require as require
|
||||
from nonebot.plugin import on_regex as on_regex
|
||||
from nonebot.plugin import on_notice as on_notice
|
||||
from nonebot.plugin import get_plugin as get_plugin
|
||||
from nonebot.plugin import on_command as on_command
|
||||
from nonebot.plugin import on_keyword as on_keyword
|
||||
from nonebot.plugin import on_message as on_message
|
||||
from nonebot.plugin import on_request as on_request
|
||||
from nonebot.plugin import load_plugin as load_plugin
|
||||
from nonebot.plugin import on_endswith as on_endswith
|
||||
from nonebot.plugin import CommandGroup as CommandGroup
|
||||
from nonebot.plugin import MatcherGroup as MatcherGroup
|
||||
from nonebot.plugin import load_plugins as load_plugins
|
||||
from nonebot.plugin import on_metaevent as on_metaevent
|
||||
from nonebot.plugin import on_startswith as on_startswith
|
||||
from nonebot.plugin import load_from_json as load_from_json
|
||||
from nonebot.plugin import load_from_toml as load_from_toml
|
||||
from nonebot.plugin import load_all_plugins as load_all_plugins
|
||||
from nonebot.plugin import on_shell_command as on_shell_command
|
||||
from nonebot.plugin import get_loaded_plugins as get_loaded_plugins
|
||||
from nonebot.plugin import load_builtin_plugins as load_builtin_plugins
|
||||
|
@@ -1,5 +1,3 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
协议适配基类
|
||||
============
|
||||
@@ -7,390 +5,24 @@
|
||||
各协议请继承以下基类,并使用 ``driver.register_adapter`` 注册适配器
|
||||
"""
|
||||
|
||||
import abc
|
||||
from functools import reduce, partial
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Iterable
|
||||
|
||||
from nonebot.config import Config
|
||||
from nonebot.typing import Driver, Message, WebSocket
|
||||
from nonebot.typing import Any, Dict, Union, Optional, Callable, Iterable, Awaitable
|
||||
try:
|
||||
import pkg_resources
|
||||
|
||||
pkg_resources.declare_namespace(__name__)
|
||||
del pkg_resources
|
||||
except ImportError:
|
||||
import pkgutil
|
||||
|
||||
class BaseBot(abc.ABC):
|
||||
"""
|
||||
Bot 基类。用于处理上报消息,并提供 API 调用接口。
|
||||
"""
|
||||
__path__: Iterable[str] = pkgutil.extend_path(__path__, __name__) # type: ignore
|
||||
del pkgutil
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def __init__(self,
|
||||
driver: Driver,
|
||||
connection_type: str,
|
||||
config: Config,
|
||||
self_id: str,
|
||||
*,
|
||||
websocket: Optional[WebSocket] = None):
|
||||
"""
|
||||
:参数:
|
||||
* ``driver: Driver``: Driver 对象
|
||||
* ``connection_type: str``: http 或者 websocket
|
||||
* ``config: Config``: Config 对象
|
||||
* ``self_id: str``: 机器人 ID
|
||||
* ``websocket: Optional[WebSocket]``: Websocket 连接对象
|
||||
"""
|
||||
self.driver = driver
|
||||
"""Driver 对象"""
|
||||
self.connection_type = connection_type
|
||||
"""连接类型"""
|
||||
self.config = config
|
||||
"""Config 配置对象"""
|
||||
self.self_id = self_id
|
||||
"""机器人 ID"""
|
||||
self.websocket = websocket
|
||||
"""Websocket 连接对象"""
|
||||
|
||||
def __getattr__(self, name: str) -> Callable[..., Awaitable[Any]]:
|
||||
return partial(self.call_api, name)
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def type(self) -> str:
|
||||
"""Adapter 类型"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
async def handle_message(self, message: dict):
|
||||
"""
|
||||
:说明:
|
||||
处理上报消息的函数,转换为 ``Event`` 事件后调用 ``nonebot.message.handle_event`` 进一步处理事件。
|
||||
:参数:
|
||||
* ``message: dict``: 收到的上报消息
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
async def call_api(self, api: str, **data):
|
||||
"""
|
||||
:说明:
|
||||
调用机器人 API 接口,可以通过该函数或直接通过 bot 属性进行调用
|
||||
:参数:
|
||||
* ``api: str``: API 名称
|
||||
* ``**data``: API 数据
|
||||
:示例:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
await bot.call_api("send_msg", data={"message": "hello world"})
|
||||
await bot.send_msg(message="hello world")
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
async def send(self, event: "BaseEvent",
|
||||
message: Union[str, "BaseMessage",
|
||||
"BaseMessageSegment"], **kwargs):
|
||||
"""
|
||||
:说明:
|
||||
调用机器人基础发送消息接口
|
||||
:参数:
|
||||
* ``event: Event``: 上报事件
|
||||
* ``message: Union[str, Message, MessageSegment]``: 要发送的消息
|
||||
* ``**kwargs``
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class BaseEvent(abc.ABC):
|
||||
"""
|
||||
Event 基类。提供上报信息的关键信息,其余信息可从原始上报消息获取。
|
||||
"""
|
||||
|
||||
def __init__(self, raw_event: dict):
|
||||
"""
|
||||
:参数:
|
||||
* ``raw_event: dict``: 原始上报消息
|
||||
"""
|
||||
self._raw_event = raw_event
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"<Event {self.self_id}: {self.name} {self.time}>"
|
||||
|
||||
@property
|
||||
def raw_event(self) -> dict:
|
||||
"""原始上报消息"""
|
||||
return self._raw_event
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def id(self) -> int:
|
||||
"""事件 ID"""
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def name(self) -> str:
|
||||
"""事件名称"""
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def self_id(self) -> str:
|
||||
"""机器人 ID"""
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def time(self) -> int:
|
||||
"""事件发生时间"""
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def type(self) -> str:
|
||||
"""事件主类型"""
|
||||
raise NotImplementedError
|
||||
|
||||
@type.setter
|
||||
@abc.abstractmethod
|
||||
def type(self, value) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def detail_type(self) -> str:
|
||||
"""事件详细类型"""
|
||||
raise NotImplementedError
|
||||
|
||||
@detail_type.setter
|
||||
@abc.abstractmethod
|
||||
def detail_type(self, value) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def sub_type(self) -> Optional[str]:
|
||||
"""事件子类型"""
|
||||
raise NotImplementedError
|
||||
|
||||
@sub_type.setter
|
||||
@abc.abstractmethod
|
||||
def sub_type(self, value) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def user_id(self) -> Optional[int]:
|
||||
"""触发事件的主体 ID"""
|
||||
raise NotImplementedError
|
||||
|
||||
@user_id.setter
|
||||
@abc.abstractmethod
|
||||
def user_id(self, value) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def group_id(self) -> Optional[int]:
|
||||
"""触发事件的主体群 ID"""
|
||||
raise NotImplementedError
|
||||
|
||||
@group_id.setter
|
||||
@abc.abstractmethod
|
||||
def group_id(self, value) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def to_me(self) -> Optional[bool]:
|
||||
"""事件是否为发送给机器人的消息"""
|
||||
raise NotImplementedError
|
||||
|
||||
@to_me.setter
|
||||
@abc.abstractmethod
|
||||
def to_me(self, value) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def message(self) -> Optional[Message]:
|
||||
"""消息内容"""
|
||||
raise NotImplementedError
|
||||
|
||||
@message.setter
|
||||
@abc.abstractmethod
|
||||
def message(self, value) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def reply(self) -> Optional[dict]:
|
||||
"""回复的消息"""
|
||||
raise NotImplementedError
|
||||
|
||||
@reply.setter
|
||||
@abc.abstractmethod
|
||||
def reply(self, value) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def raw_message(self) -> Optional[str]:
|
||||
"""原始消息"""
|
||||
raise NotImplementedError
|
||||
|
||||
@raw_message.setter
|
||||
@abc.abstractmethod
|
||||
def raw_message(self, value) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def plain_text(self) -> Optional[str]:
|
||||
"""纯文本消息"""
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def sender(self) -> Optional[dict]:
|
||||
"""消息发送者信息"""
|
||||
raise NotImplementedError
|
||||
|
||||
@sender.setter
|
||||
@abc.abstractmethod
|
||||
def sender(self, value) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
@dataclass
|
||||
class BaseMessageSegment(abc.ABC):
|
||||
"""消息段基类"""
|
||||
type: str
|
||||
"""
|
||||
- 类型: ``str``
|
||||
- 说明: 消息段类型
|
||||
"""
|
||||
data: Dict[str, Any] = field(default_factory=lambda: {})
|
||||
"""
|
||||
- 类型: ``Dict[str, Union[str, list]]``
|
||||
- 说明: 消息段数据
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def __str__(self):
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
def __add__(self, other):
|
||||
raise NotImplementedError
|
||||
|
||||
def __getitem__(self, key):
|
||||
return getattr(self, key)
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
return setattr(self, key, value)
|
||||
|
||||
@classmethod
|
||||
@abc.abstractmethod
|
||||
def text(cls, text: str) -> "BaseMessageSegment":
|
||||
return cls("text", {"text": text})
|
||||
|
||||
|
||||
class BaseMessage(list, abc.ABC):
|
||||
"""消息数组"""
|
||||
|
||||
def __init__(self,
|
||||
message: Union[str, dict, list, BaseMessageSegment,
|
||||
"BaseMessage"] = None,
|
||||
*args,
|
||||
**kwargs):
|
||||
"""
|
||||
:参数:
|
||||
* ``message: Union[str, dict, list, MessageSegment, Message]``: 消息内容
|
||||
"""
|
||||
super().__init__(*args, **kwargs)
|
||||
if isinstance(message, (str, dict, list)):
|
||||
self.extend(self._construct(message))
|
||||
elif isinstance(message, BaseMessage):
|
||||
self.extend(message)
|
||||
elif isinstance(message, BaseMessageSegment):
|
||||
self.append(message)
|
||||
|
||||
def __str__(self):
|
||||
return ''.join((str(seg) for seg in self))
|
||||
|
||||
@staticmethod
|
||||
@abc.abstractmethod
|
||||
def _construct(msg: Union[str, dict, list]) -> Iterable[BaseMessageSegment]:
|
||||
raise NotImplementedError
|
||||
|
||||
def __add__(
|
||||
self, other: Union[str, BaseMessageSegment,
|
||||
"BaseMessage"]) -> "BaseMessage":
|
||||
result = self.__class__(self)
|
||||
if isinstance(other, str):
|
||||
result.extend(self._construct(other))
|
||||
elif isinstance(other, BaseMessageSegment):
|
||||
result.append(other)
|
||||
elif isinstance(other, BaseMessage):
|
||||
result.extend(other)
|
||||
return result
|
||||
|
||||
def __radd__(self, other: Union[str, BaseMessageSegment, "BaseMessage"]):
|
||||
result = self.__class__(other)
|
||||
return result.__add__(self)
|
||||
|
||||
def append(self, obj: Union[str, BaseMessageSegment]) -> "BaseMessage":
|
||||
"""
|
||||
:说明:
|
||||
添加一个消息段到消息数组末尾
|
||||
:参数:
|
||||
* ``obj: Union[str, MessageSegment]``: 要添加的消息段
|
||||
"""
|
||||
if isinstance(obj, BaseMessageSegment):
|
||||
if obj.type == "text" and self and self[-1].type == "text":
|
||||
self[-1].data["text"] += obj.data["text"]
|
||||
else:
|
||||
super().append(obj)
|
||||
elif isinstance(obj, str):
|
||||
self.extend(self._construct(obj))
|
||||
else:
|
||||
raise ValueError(f"Unexpected type: {type(obj)} {obj}")
|
||||
return self
|
||||
|
||||
def extend(
|
||||
self, obj: Union["BaseMessage",
|
||||
Iterable[BaseMessageSegment]]) -> "BaseMessage":
|
||||
"""
|
||||
:说明:
|
||||
拼接一个消息数组或多个消息段到消息数组末尾
|
||||
:参数:
|
||||
* ``obj: Union[Message, Iterable[MessageSegment]]``: 要添加的消息数组
|
||||
"""
|
||||
for segment in obj:
|
||||
self.append(segment)
|
||||
return self
|
||||
|
||||
def reduce(self) -> None:
|
||||
"""
|
||||
:说明:
|
||||
缩减消息数组,即拼接相邻纯文本消息段
|
||||
"""
|
||||
index = 0
|
||||
while index < len(self):
|
||||
if index > 0 and self[
|
||||
index - 1].type == "text" and self[index].type == "text":
|
||||
self[index - 1].data["text"] += self[index].data["text"]
|
||||
del self[index]
|
||||
else:
|
||||
index += 1
|
||||
|
||||
def extract_plain_text(self) -> str:
|
||||
"""
|
||||
:说明:
|
||||
提取消息内纯文本消息
|
||||
"""
|
||||
|
||||
def _concat(x: str, y: BaseMessageSegment) -> str:
|
||||
return f"{x} {y.data['text']}" if y.type == "text" else x
|
||||
|
||||
plain_text = reduce(_concat, self, "")
|
||||
return plain_text[1:] if plain_text else plain_text
|
||||
from ._bot import Bot as Bot
|
||||
from ._event import Event as Event
|
||||
from ._adapter import Adapter as Adapter
|
||||
from ._message import Message as Message
|
||||
from ._message import MessageSegment as MessageSegment
|
||||
from ._template import MessageTemplate as MessageTemplate
|
||||
|
75
nonebot/adapters/_adapter.py
Normal file
75
nonebot/adapters/_adapter.py
Normal file
@@ -0,0 +1,75 @@
|
||||
import abc
|
||||
from contextlib import asynccontextmanager
|
||||
from typing import Any, Dict, AsyncGenerator
|
||||
|
||||
from ._bot import Bot
|
||||
from nonebot.config import Config
|
||||
from nonebot.drivers import (
|
||||
Driver,
|
||||
Request,
|
||||
Response,
|
||||
WebSocket,
|
||||
ForwardDriver,
|
||||
ReverseDriver,
|
||||
HTTPServerSetup,
|
||||
WebSocketServerSetup,
|
||||
)
|
||||
|
||||
|
||||
class Adapter(abc.ABC):
|
||||
def __init__(self, driver: Driver, **kwargs: Any):
|
||||
self.driver: Driver = driver
|
||||
self.bots: Dict[str, Bot] = {}
|
||||
|
||||
@classmethod
|
||||
@abc.abstractmethod
|
||||
def get_name(cls) -> str:
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
def config(self) -> Config:
|
||||
return self.driver.config
|
||||
|
||||
def bot_connect(self, bot: Bot) -> None:
|
||||
self.driver._bot_connect(bot)
|
||||
self.bots[bot.self_id] = bot
|
||||
|
||||
def bot_disconnect(self, bot: Bot) -> None:
|
||||
self.driver._bot_disconnect(bot)
|
||||
self.bots.pop(bot.self_id, None)
|
||||
|
||||
def setup_http_server(self, setup: HTTPServerSetup):
|
||||
if not isinstance(self.driver, ReverseDriver):
|
||||
raise TypeError("Current driver does not support http server")
|
||||
self.driver.setup_http_server(setup)
|
||||
|
||||
def setup_websocket_server(self, setup: WebSocketServerSetup):
|
||||
if not isinstance(self.driver, ReverseDriver):
|
||||
raise TypeError("Current driver does not support websocket server")
|
||||
self.driver.setup_websocket_server(setup)
|
||||
|
||||
async def request(self, setup: Request) -> Response:
|
||||
if not isinstance(self.driver, ForwardDriver):
|
||||
raise TypeError("Current driver does not support http client")
|
||||
return await self.driver.request(setup)
|
||||
|
||||
@asynccontextmanager
|
||||
async def websocket(self, setup: Request) -> AsyncGenerator[WebSocket, None]:
|
||||
if not isinstance(self.driver, ForwardDriver):
|
||||
raise TypeError("Current driver does not support websocket client")
|
||||
async with self.driver.websocket(setup) as ws:
|
||||
yield ws
|
||||
|
||||
@abc.abstractmethod
|
||||
async def _call_api(self, bot: Bot, api: str, **data) -> Any:
|
||||
"""
|
||||
:说明:
|
||||
|
||||
``adapter`` 实际调用 api 的逻辑实现函数,实现该方法以调用 api。
|
||||
|
||||
:参数:
|
||||
|
||||
* ``api: str``: API 名称
|
||||
* ``**data``: API 数据
|
||||
"""
|
||||
raise NotImplementedError
|
178
nonebot/adapters/_bot.py
Normal file
178
nonebot/adapters/_bot.py
Normal file
@@ -0,0 +1,178 @@
|
||||
import abc
|
||||
import asyncio
|
||||
from functools import partial
|
||||
from typing_extensions import Protocol
|
||||
from typing import TYPE_CHECKING, Any, Set, Union, Optional
|
||||
|
||||
from nonebot.log import logger
|
||||
from nonebot.config import Config
|
||||
from nonebot.exception import MockApiException
|
||||
from nonebot.typing import T_CalledAPIHook, T_CallingAPIHook
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ._event import Event
|
||||
from ._adapter import Adapter
|
||||
from ._message import Message, MessageSegment
|
||||
|
||||
|
||||
class _ApiCall(Protocol):
|
||||
async def __call__(self, **kwargs: Any) -> Any:
|
||||
...
|
||||
|
||||
|
||||
class Bot(abc.ABC):
|
||||
"""
|
||||
Bot 基类。用于处理上报消息,并提供 API 调用接口。
|
||||
"""
|
||||
|
||||
_calling_api_hook: Set[T_CallingAPIHook] = set()
|
||||
"""
|
||||
:类型: ``Set[T_CallingAPIHook]``
|
||||
:说明: call_api 时执行的函数
|
||||
"""
|
||||
_called_api_hook: Set[T_CalledAPIHook] = set()
|
||||
"""
|
||||
:类型: ``Set[T_CalledAPIHook]``
|
||||
:说明: call_api 后执行的函数
|
||||
"""
|
||||
|
||||
def __init__(self, adapter: "Adapter", self_id: str):
|
||||
"""
|
||||
:参数:
|
||||
|
||||
* ``self_id: str``: 机器人 ID
|
||||
* ``request: HTTPConnection``: request 连接对象
|
||||
"""
|
||||
self.adapter: "Adapter" = adapter
|
||||
self.self_id: str = self_id
|
||||
"""机器人 ID"""
|
||||
|
||||
def __getattr__(self, name: str) -> _ApiCall:
|
||||
return partial(self.call_api, name)
|
||||
|
||||
@property
|
||||
def type(self) -> str:
|
||||
return self.adapter.get_name()
|
||||
|
||||
@property
|
||||
def config(self) -> Config:
|
||||
return self.adapter.config
|
||||
|
||||
async def call_api(self, api: str, **data: Any) -> Any:
|
||||
"""
|
||||
:说明:
|
||||
|
||||
调用机器人 API 接口,可以通过该函数或直接通过 bot 属性进行调用
|
||||
|
||||
:参数:
|
||||
|
||||
* ``api: str``: API 名称
|
||||
* ``**data``: API 数据
|
||||
|
||||
:示例:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
await bot.call_api("send_msg", message="hello world")
|
||||
await bot.send_msg(message="hello world")
|
||||
"""
|
||||
|
||||
result: Any = None
|
||||
skip_calling_api: bool = False
|
||||
exception: Optional[Exception] = None
|
||||
|
||||
coros = list(map(lambda x: x(self, api, data), self._calling_api_hook))
|
||||
if coros:
|
||||
try:
|
||||
logger.debug("Running CallingAPI hooks...")
|
||||
await asyncio.gather(*coros)
|
||||
except MockApiException as e:
|
||||
skip_calling_api = True
|
||||
result = e.result
|
||||
logger.debug(
|
||||
f"Calling API {api} is cancelled. Return {result} instead."
|
||||
)
|
||||
except Exception as e:
|
||||
logger.opt(colors=True, exception=e).error(
|
||||
"<r><bg #f8bbd0>Error when running CallingAPI hook. "
|
||||
"Running cancelled!</bg #f8bbd0></r>"
|
||||
)
|
||||
|
||||
if not skip_calling_api:
|
||||
try:
|
||||
result = await self.adapter._call_api(self, api, **data)
|
||||
except Exception as e:
|
||||
exception = e
|
||||
|
||||
coros = list(
|
||||
map(lambda x: x(self, exception, api, data, result), self._called_api_hook)
|
||||
)
|
||||
if coros:
|
||||
try:
|
||||
logger.debug("Running CalledAPI hooks...")
|
||||
await asyncio.gather(*coros)
|
||||
except MockApiException as e:
|
||||
result = e.result
|
||||
logger.debug(
|
||||
f"Calling API {api} result is mocked. Return {result} instead."
|
||||
)
|
||||
except Exception as e:
|
||||
logger.opt(colors=True, exception=e).error(
|
||||
"<r><bg #f8bbd0>Error when running CalledAPI hook. "
|
||||
"Running cancelled!</bg #f8bbd0></r>"
|
||||
)
|
||||
|
||||
if exception:
|
||||
raise exception
|
||||
return result
|
||||
|
||||
@abc.abstractmethod
|
||||
async def send(
|
||||
self, event: "Event", message: Union[str, "Message", "MessageSegment"], **kwargs
|
||||
) -> Any:
|
||||
"""
|
||||
:说明:
|
||||
|
||||
调用机器人基础发送消息接口
|
||||
|
||||
:参数:
|
||||
|
||||
* ``event: Event``: 上报事件
|
||||
* ``message: Union[str, Message, MessageSegment]``: 要发送的消息
|
||||
* ``**kwargs``
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@classmethod
|
||||
def on_calling_api(cls, func: T_CallingAPIHook) -> T_CallingAPIHook:
|
||||
"""
|
||||
:说明:
|
||||
|
||||
调用 api 预处理。
|
||||
|
||||
:参数:
|
||||
|
||||
* ``bot: Bot``: 当前 bot 对象
|
||||
* ``api: str``: 调用的 api 名称
|
||||
* ``data: Dict[str, Any]``: api 调用的参数字典
|
||||
"""
|
||||
cls._calling_api_hook.add(func)
|
||||
return func
|
||||
|
||||
@classmethod
|
||||
def on_called_api(cls, func: T_CalledAPIHook) -> T_CalledAPIHook:
|
||||
"""
|
||||
:说明:
|
||||
|
||||
调用 api 后处理。
|
||||
|
||||
:参数:
|
||||
|
||||
* ``bot: Bot``: 当前 bot 对象
|
||||
* ``exception: Optional[Exception]``: 调用 api 时发生的错误
|
||||
* ``api: str``: 调用的 api 名称
|
||||
* ``data: Dict[str, Any]``: api 调用的参数字典
|
||||
* ``result: Any``: api 调用的返回
|
||||
"""
|
||||
cls._called_api_hook.add(func)
|
||||
return func
|
137
nonebot/adapters/_event.py
Normal file
137
nonebot/adapters/_event.py
Normal file
@@ -0,0 +1,137 @@
|
||||
import abc
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from ._message import Message
|
||||
from nonebot.utils import DataclassEncoder
|
||||
|
||||
|
||||
class Event(abc.ABC, BaseModel):
|
||||
"""Event 基类。提供获取关键信息的方法,其余信息可直接获取。"""
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
json_encoders = {Message: DataclassEncoder}
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_type(self) -> str:
|
||||
"""
|
||||
:说明:
|
||||
|
||||
获取事件类型的方法,类型通常为 NoneBot 内置的四种类型。
|
||||
|
||||
:返回:
|
||||
|
||||
* ``Literal["message", "notice", "request", "meta_event"]``
|
||||
* 其他自定义 ``str``
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_event_name(self) -> str:
|
||||
"""
|
||||
:说明:
|
||||
|
||||
获取事件名称的方法。
|
||||
|
||||
:返回:
|
||||
|
||||
* ``str``
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_event_description(self) -> str:
|
||||
"""
|
||||
:说明:
|
||||
|
||||
获取事件描述的方法,通常为事件具体内容。
|
||||
|
||||
:返回:
|
||||
|
||||
* ``str``
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"[{self.get_event_name()}]: {self.get_event_description()}"
|
||||
|
||||
def get_log_string(self) -> str:
|
||||
"""
|
||||
:说明:
|
||||
|
||||
获取事件日志信息的方法,通常你不需要修改这个方法,只有当希望 NoneBot 隐藏该事件日志时,可以抛出 ``NoLogException`` 异常。
|
||||
|
||||
:返回:
|
||||
|
||||
* ``str``
|
||||
|
||||
:异常:
|
||||
|
||||
- ``NoLogException``
|
||||
"""
|
||||
return f"[{self.get_event_name()}]: {self.get_event_description()}"
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_user_id(self) -> str:
|
||||
"""
|
||||
:说明:
|
||||
|
||||
获取事件主体 id 的方法,通常是用户 id 。
|
||||
|
||||
:返回:
|
||||
|
||||
* ``str``
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_session_id(self) -> str:
|
||||
"""
|
||||
:说明:
|
||||
|
||||
获取会话 id 的方法,用于判断当前事件属于哪一个会话,通常是用户 id、群组 id 组合。
|
||||
|
||||
:返回:
|
||||
|
||||
* ``str``
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_message(self) -> "Message":
|
||||
"""
|
||||
:说明:
|
||||
|
||||
获取事件消息内容的方法。
|
||||
|
||||
:返回:
|
||||
|
||||
* ``Message``
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_plaintext(self) -> str:
|
||||
"""
|
||||
:说明:
|
||||
|
||||
获取消息纯文本的方法,通常不需要修改,默认通过 ``get_message().extract_plain_text`` 获取。
|
||||
|
||||
:返回:
|
||||
|
||||
* ``str``
|
||||
"""
|
||||
return self.get_message().extract_plain_text()
|
||||
|
||||
@abc.abstractmethod
|
||||
def is_tome(self) -> bool:
|
||||
"""
|
||||
:说明:
|
||||
|
||||
获取事件是否与机器人有关的方法。
|
||||
|
||||
:返回:
|
||||
|
||||
* ``bool``
|
||||
"""
|
||||
raise NotImplementedError
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user