mirror of
https://github.com/eternnoir/pyTelegramBotAPI.git
synced 2023-08-10 21:12:57 +03:00
Compare commits
771 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
e10517e088 | ||
|
1946393c36 | ||
|
0f52ca688f | ||
|
b18bcd494a | ||
|
8f41df0ee4 | ||
|
cb7f6a8c99 | ||
|
3960115ec7 | ||
|
916569cdc5 | ||
|
75d3fa2eba | ||
|
67e3774e8e | ||
|
f799157314 | ||
|
af3a98057f | ||
|
447fc1d461 | ||
|
fb98df3dfe | ||
|
0b34da3900 | ||
|
5ea1abaadd | ||
|
5a81353420 | ||
|
eaf90cce7f | ||
|
b219218c8d | ||
|
2dac17aa75 | ||
|
48377ac905 | ||
|
14294d1aa3 | ||
|
ea3c159044 | ||
|
58d53e1a54 | ||
|
abec3dc60e | ||
|
ecb5d9b4f6 | ||
|
26575dc5e7 | ||
|
be69feb252 | ||
|
1d62adc262 | ||
|
77e1928628 | ||
|
d6f4987197 | ||
|
966b451869 | ||
|
d1417e5616 | ||
|
a7cafd1f24 | ||
|
92907ced30 | ||
|
1b2ed0e2f7 | ||
|
370f0370c7 | ||
|
e4bddd91cb | ||
|
d466da3542 | ||
|
e64c06b7bc | ||
|
7d168ebbd8 | ||
|
c5689f383b | ||
|
8796168efb | ||
|
100659fecd | ||
|
7bf87a306a | ||
|
351d021e01 | ||
|
4ffe0f8833 | ||
|
3f07dc4ce8 | ||
|
2e589ab6e1 | ||
|
8b63f6a6ef | ||
|
dc98aca173 | ||
|
39360e0640 | ||
|
b1c172c421 | ||
|
6b5c263ee8 | ||
|
46100edd97 | ||
|
018b89cdc0 | ||
|
f3486b3730 | ||
|
b0e64d828c | ||
|
14434b398e | ||
|
1d62bf2ac8 | ||
|
fe2e9a7a30 | ||
|
c9ef0d71f0 | ||
|
b0740a920a | ||
|
6a9c25cf80 | ||
|
e56c60ac00 | ||
|
7c7a063fb6 | ||
|
bd69492ed4 | ||
|
37cdb52ed2 | ||
|
d8569394b0 | ||
|
da57174635 | ||
|
776ce0a7eb | ||
|
886806135e | ||
|
1e450ebd15 | ||
|
41521f5618 | ||
|
603a7cf9f2 | ||
|
535a14ca0c | ||
|
67a52b2e98 | ||
|
c47c26d2b0 | ||
|
9d2f7c02a4 | ||
|
991679bedc | ||
|
3b4e6fed04 | ||
|
5c6b867582 | ||
|
715aabaf49 | ||
|
9fa5b91e58 | ||
|
de5a32e45c | ||
|
db087427fc | ||
|
385fc6a6da | ||
|
ac0b386625 | ||
|
ae44b0022d | ||
|
73135d6012 | ||
|
19dcce0d5b | ||
|
f527fc91f6 | ||
|
c0185dad44 | ||
|
8a858cac4e | ||
|
f30457bd75 | ||
|
54caf30f69 | ||
|
09e4a2a437 | ||
|
9b81a29a6a | ||
|
65dcd67140 | ||
|
c84b771e5a | ||
|
2bd81a5f5c | ||
|
5d9a76b0dd | ||
|
6459f13f25 | ||
|
c9b6d3f868 | ||
|
80c1a4798d | ||
|
7a67d5f9f9 | ||
|
d12ea91e12 | ||
|
4f2c89c4a8 | ||
|
fb7d60f09d | ||
|
8dc4e77287 | ||
|
a999161384 | ||
|
b4196f5891 | ||
|
e55fe962ca | ||
|
3d2c5c9590 | ||
|
40567570e8 | ||
|
4179e502c3 | ||
|
a9b878107c | ||
|
2094120ec7 | ||
|
d1348606e3 | ||
|
d0d03d0c09 | ||
|
fdd82a5e4b | ||
|
9e68f76f5d | ||
|
4000c9fb48 | ||
|
ae42d0b1fe | ||
|
a3891ff363 | ||
|
4d7f5310fb | ||
|
3e0d69f7f4 | ||
|
2e5fb10430 | ||
|
c39c050abf | ||
|
ed6d6cc03f | ||
|
10a80e1cfa | ||
|
d99f48f975 | ||
|
dae2790c61 | ||
|
f5eac56afa | ||
|
268c3a9210 | ||
|
ad7e4bbaf7 | ||
|
b9bedef73f | ||
|
9fb5f89f18 | ||
|
409ff49603 | ||
|
5e0da40fcd | ||
|
b743aa5813 | ||
|
1797f076dc | ||
|
68c1fe8cb5 | ||
|
1eda7cafd4 | ||
|
291566908b | ||
|
bef29d9318 | ||
|
a5af586a46 | ||
|
93dcbbeb02 | ||
|
bd94d8d91c | ||
|
6b399ab8cd | ||
|
8744402efc | ||
|
d5bbaa900e | ||
|
02ae255701 | ||
|
c27f60b94b | ||
|
a781929a2d | ||
|
e6f8acadf4 | ||
|
c298d95d0f | ||
|
8aee5372ee | ||
|
df105ab1d8 | ||
|
b93ec5d0e0 | ||
|
f201df3275 | ||
|
206e4e024b | ||
|
bd1290592b | ||
|
9b9eb775f7 | ||
|
3cfa24f9c0 | ||
|
b540a6c4d4 | ||
|
a0ba5ae9af | ||
|
651db29cb2 | ||
|
490168f3f6 | ||
|
bf38071e8f | ||
|
e8aaa524fe | ||
|
e2e754fdff | ||
|
d64f305fd4 | ||
|
611bf4235c | ||
|
fe0dc6930c | ||
|
6d4d3f8005 | ||
|
0f7464e8c4 | ||
|
6f86382e33 | ||
|
43cc203654 | ||
|
3b62ad4765 | ||
|
3be5015f9e | ||
|
267a33c329 | ||
|
667e82d073 | ||
|
dd50273c95 | ||
|
8e9d566d5c | ||
|
79bc869143 | ||
|
68edb4990c | ||
|
19544ecc58 | ||
|
eed56be596 | ||
|
9f8256607a | ||
|
f297ad23c7 | ||
|
a20a3ae321 | ||
|
107f92314b | ||
|
9f5d9861a4 | ||
|
4537b237c8 | ||
|
4d11e97c25 | ||
|
f0a1cefdda | ||
|
24cd014410 | ||
|
ba64180b5f | ||
|
3812fd05e3 | ||
|
69afd7232e | ||
|
81600cf27e | ||
|
bb8023ecc6 | ||
|
a50a6e2e54 | ||
|
0329e5adb8 | ||
|
2f25b56659 | ||
|
2aaab08517 | ||
|
a6a22c351a | ||
|
d211db90cf | ||
|
f2c211616c | ||
|
c5e733a4c1 | ||
|
925f7012f1 | ||
|
625ae09573 | ||
|
5b279b7ad9 | ||
|
247cddf23d | ||
|
171172d12e | ||
|
c3c12b93dd | ||
|
add240adfd | ||
|
45fe2ea319 | ||
|
6373af78f3 | ||
|
4ed460b137 | ||
|
ae20cb9f31 | ||
|
669c18fdc0 | ||
|
34acae9a59 | ||
|
109ae69f27 | ||
|
43abedbff7 | ||
|
42d162f732 | ||
|
cd4dc899a1 | ||
|
5066626692 | ||
|
e255d9cbab | ||
|
8e1c8a2742 | ||
|
e358abc1bd | ||
|
42da2d1794 | ||
|
feaef2b2b8 | ||
|
6cf60a3dcb | ||
|
91ff06eeba | ||
|
1c2111d689 | ||
|
bf039df122 | ||
|
44309797d1 | ||
|
8489383eb4 | ||
|
848a2cc7ec | ||
|
cc87dbce50 | ||
|
15f6bbeacb | ||
|
29befa4d0c | ||
|
cce03dab78 | ||
|
7702d63fd7 | ||
|
d636cdf88b | ||
|
06a28380d7 | ||
|
d7e9d3accc | ||
|
736c03fe84 | ||
|
7502d26b1a | ||
|
b4d59fdf0a | ||
|
8d723bdcb3 | ||
|
a169404a7c | ||
|
7a20017dfb | ||
|
8d82b3d56b | ||
|
0759c8e081 | ||
|
8992db1d24 | ||
|
deb2099396 | ||
|
8a74198276 | ||
|
15bd5f991a | ||
|
25571b581c | ||
|
bf617ab8da | ||
|
74732f2eda | ||
|
0a79f7e4f3 | ||
|
8b735aa114 | ||
|
ae1845f285 | ||
|
0846852ea1 | ||
|
4825624d48 | ||
|
876d679765 | ||
|
7958d0dca7 | ||
|
4e2ea90db3 | ||
|
566aef1679 | ||
|
2dad99ad95 | ||
|
f288470b43 | ||
|
475394d241 | ||
|
76f06cacfe | ||
|
77738b2537 | ||
|
070479f7af | ||
|
f1f18c6df2 | ||
|
81c8ee5820 | ||
|
76a689d939 | ||
|
92ecfdec48 | ||
|
20376168c1 | ||
|
507d53efbd | ||
|
1d8dc78c87 | ||
|
ebec3bf5c1 | ||
|
d11b9802da | ||
|
572f103db7 | ||
|
231371f1f8 | ||
|
623d8b27ec | ||
|
31c3a2b2a3 | ||
|
c45af810f9 | ||
|
81f090cce6 | ||
|
5d16b8bd4a | ||
|
0fecf46201 | ||
|
982e642c73 | ||
|
97bca49c00 | ||
|
e0ee087162 | ||
|
620b1364a6 | ||
|
c561cf3076 | ||
|
b3953d6249 | ||
|
2d7170feee | ||
|
0ca8007633 | ||
|
c541533762 | ||
|
4798c26188 | ||
|
30aaf8d0f1 | ||
|
82ad37fed8 | ||
|
2d1f39085d | ||
|
b523cec22f | ||
|
27e0197855 | ||
|
ea69b8093d | ||
|
04ff428bba | ||
|
eb576d83fb | ||
|
d3080b6d4e | ||
|
7c9b01b10a | ||
|
b3993bb019 | ||
|
36b889feab | ||
|
d943f40643 | ||
|
dafafd2ad2 | ||
|
e002484a9b | ||
|
52e09637c2 | ||
|
e7a96ec2ed | ||
|
598de25b6d | ||
|
b841fc10ed | ||
|
c14760d81c | ||
|
da639dd1f6 | ||
|
96e137f5e6 | ||
|
8d9dfcfac8 | ||
|
a1c77db236 | ||
|
4f97b26e81 | ||
|
0028feb4c5 | ||
|
a06b4a1e9c | ||
|
da5084f53c | ||
|
2f8d878f06 | ||
|
783beb165b | ||
|
4fd01e3ac8 | ||
|
b4c28de104 | ||
|
de344bd5e0 | ||
|
e3a4fdff9a | ||
|
71d3ec8b42 | ||
|
1b1d6c8239 | ||
|
9216f15c16 | ||
|
0f7ab0d05f | ||
|
e0ffe0b4f5 | ||
|
f4c5dd0d22 | ||
|
e4179ea65f | ||
|
d7770bf670 | ||
|
095bf03227 | ||
|
85bd174fdc | ||
|
b86c38367a | ||
|
b8214d32d5 | ||
|
f4e66f6807 | ||
|
b1a4136603 | ||
|
3d97b08289 | ||
|
3d2576ca24 | ||
|
b2d2ab5c33 | ||
|
c9a732e3dd | ||
|
01be1fb583 | ||
|
7b95874627 | ||
|
426f9f3787 | ||
|
47ae696528 | ||
|
a9b8baea2c | ||
|
d3cab9cdba | ||
|
d6ef67073e | ||
|
345fa3433c | ||
|
c95ba8c9c2 | ||
|
20bdb54e94 | ||
|
124dfbf392 | ||
|
9f9821bbe8 | ||
|
c8d1dac61e | ||
|
ffb34da610 | ||
|
2647a02fc6 | ||
|
dd4073fd74 | ||
|
737c3a439d | ||
|
40698408c9 | ||
|
ffa1c37204 | ||
|
d42c8e2961 | ||
|
5471b88da6 | ||
|
26db76f207 | ||
|
e860f114c6 | ||
|
c5a69944be | ||
|
2fe5ba403e | ||
|
d2a7f975de | ||
|
41b1519786 | ||
|
93e1813139 | ||
|
dab5d7f632 | ||
|
1667b51034 | ||
|
7d94e01009 | ||
|
c0ed659f30 | ||
|
047777fada | ||
|
839aced912 | ||
|
d03f3b2c52 | ||
|
65b353ffae | ||
|
914c5fdf0c | ||
|
8aa3d052cc | ||
|
5beb51f907 | ||
|
c145b7ef8f | ||
|
6303ecc7c6 | ||
|
fc01ec50fc | ||
|
51b2ec701d | ||
|
3d7f334d79 | ||
|
a61508ca0c | ||
|
9d9e76e724 | ||
|
b0e06253ff | ||
|
7c12162576 | ||
|
f0feb45e87 | ||
|
c2cfe24426 | ||
|
f6ec3493ad | ||
|
e553f3aa1d | ||
|
49d3b463ed | ||
|
147278733b | ||
|
54ad1582aa | ||
|
e379708af6 | ||
|
9f7b113e2f | ||
|
482498e1e5 | ||
|
22beead3b5 | ||
|
2b01765627 | ||
|
5dbe1b3523 | ||
|
3ffd06fcca | ||
|
ea1efad1ea | ||
|
1efe465e9d | ||
|
0c6f84c79a | ||
|
bf415e4bd7 | ||
|
2fcfdc2584 | ||
|
659501efef | ||
|
92654ee970 | ||
|
a1bcd3c42e | ||
|
b276bfacaf | ||
|
726b203724 | ||
|
16703161aa | ||
|
a3a55e7393 | ||
|
1c11898ea1 | ||
|
8c6f81546c | ||
|
194bf6e95d | ||
|
124606fdcb | ||
|
90a90d4a34 | ||
|
d67ee2a5c5 | ||
|
970b9d6be4 | ||
|
0b5b7ad39a | ||
|
a7c420aa14 | ||
|
0cf2a0fe77 | ||
|
2f32236680 | ||
|
f8f147f9f4 | ||
|
140befc132 | ||
|
36fbb13663 | ||
|
e353572c03 | ||
|
ebca668979 | ||
|
7b8c98d731 | ||
|
3cf5305845 | ||
|
eb4cd7aba0 | ||
|
01f9e3b710 | ||
|
e1094c6f02 | ||
|
174bbf9c84 | ||
|
1df19e3b2d | ||
|
e0e6eee374 | ||
|
78251cdf43 | ||
|
81cbddb8cd | ||
|
0aa9f0fb42 | ||
|
f3b1f97362 | ||
|
df1977911e | ||
|
d861fd0042 | ||
|
1fb14e28d4 | ||
|
b691a467c0 | ||
|
badf982147 | ||
|
6d52090ef9 | ||
|
cf3a85d699 | ||
|
ef86453126 | ||
|
d9ab5b0d28 | ||
|
c920809fa9 | ||
|
5939e754bb | ||
|
3019b71f7f | ||
|
0bdf925fbe | ||
|
d14064a84d | ||
|
49c93b6027 | ||
|
36749cbdd9 | ||
|
6d12b1f2a7 | ||
|
419bc5878f | ||
|
b9b4885568 | ||
|
ce0a974c91 | ||
|
c36f3a228e | ||
|
ca525b5bea | ||
|
6ff015689a | ||
|
6459aded82 | ||
|
fec47cecaf | ||
|
3892b0fb80 | ||
|
fbb9a73fc0 | ||
|
db5c53b8e5 | ||
|
6e8abc709e | ||
|
752f35614c | ||
|
a2893945b2 | ||
|
1686ce4f44 | ||
|
24b1129c8a | ||
|
7f9dac4147 | ||
|
f96775e9eb | ||
|
1342cab259 | ||
|
dd8125cbd0 | ||
|
8769802744 | ||
|
a7fb8a2bec | ||
|
d7f34ae370 | ||
|
7d931abe37 | ||
|
f52124827f | ||
|
0d0f9ef330 | ||
|
24cdcb1bcc | ||
|
7994a80a00 | ||
|
b2662274f9 | ||
|
a21ab203a1 | ||
|
e689e968db | ||
|
808810e6d6 | ||
|
5a60846c7f | ||
|
d2c1615392 | ||
|
7cdb48c3e0 | ||
|
28ae0867f8 | ||
|
e84cc0e0af | ||
|
42ce47914d | ||
|
4401780ba9 | ||
|
82f056e88a | ||
|
6b19d631d1 | ||
|
ee7adb00df | ||
|
82a8aa65f0 | ||
|
72aaf44dc7 | ||
|
1d0efce76e | ||
|
74d0604c05 | ||
|
1943f659bc | ||
|
d6ec104829 | ||
|
7edaa51995 | ||
|
6bb47e9a44 | ||
|
8da749ee05 | ||
|
0c59d1187e | ||
|
e9d1d98f03 | ||
|
c63b0d6a3d | ||
|
388306b7fe | ||
|
5e3fd17436 | ||
|
ccc09ffaf3 | ||
|
e086303535 | ||
|
d6e93f85f1 | ||
|
d954f8f5b3 | ||
|
33375ac135 | ||
|
28662876a2 | ||
|
0f44fd3c40 | ||
|
8fefd7b5b3 | ||
|
7567750276 | ||
|
f526a9d8a4 | ||
|
feffe726dd | ||
|
3ff7e28467 | ||
|
5d74e18d1a | ||
|
91b665ea94 | ||
|
6e4c63b09c | ||
|
42efb8488c | ||
|
03a567ea93 | ||
|
3f28bb6e9d | ||
|
e051dda113 | ||
|
856debe7d2 | ||
|
42955d1886 | ||
|
a2f3cd03e1 | ||
|
7e68721475 | ||
|
7965ba4f69 | ||
|
aba4d3e246 | ||
|
caae6bb93f | ||
|
096d7a4eea | ||
|
ab4140ba9f | ||
|
77c3587012 | ||
|
efb1b44e59 | ||
|
2c8793b794 | ||
|
146fd57b10 | ||
|
8a12ae3565 | ||
|
2d8c2312e3 | ||
|
f9cd0d7e08 | ||
|
59cd1a00e7 | ||
|
836130a718 | ||
|
a7db2d8d9c | ||
|
c022d49996 | ||
|
825827cb1e | ||
|
cd92b70d6b | ||
|
617c990994 | ||
|
9b959373db | ||
|
76c0197ab7 | ||
|
7d9658b062 | ||
|
db0c946780 | ||
|
c6202da36f | ||
|
532011138c | ||
|
191164cba0 | ||
|
5688aaa03b | ||
|
88a76c0a15 | ||
|
e1dc6d7beb | ||
|
730d11012d | ||
|
b43b636ba0 | ||
|
a7ca6c057e | ||
|
bd002c6429 | ||
|
453df01f26 | ||
|
24ae38cca6 | ||
|
3b386965ea | ||
|
5077289d0d | ||
|
a54b21cb50 | ||
|
fa80cb0002 | ||
|
ad5b92b650 | ||
|
9b1b324ab4 | ||
|
e444bc2a0b | ||
|
dd25432359 | ||
|
cfbbfe84ad | ||
|
b25d2846e9 | ||
|
ab64e17464 | ||
|
3a5db47c1b | ||
|
4812dcb02b | ||
|
b146df346d | ||
|
5f2713bcfb | ||
|
a1bf961fd2 | ||
|
a8451a5e30 | ||
|
9417c49d8e | ||
|
1a40f1da7a | ||
|
5e28f27764 | ||
|
43d0e10ba4 | ||
|
9652fdbecb | ||
|
110575ca40 | ||
|
22b4e636e2 | ||
|
1688a466f4 | ||
|
625da4cdd9 | ||
|
a9e0f5b7b0 | ||
|
7b1b1a7caa | ||
|
a6477541c0 | ||
|
b652a9f6dc | ||
|
73b2813512 | ||
|
ace28983b6 | ||
|
e82675320c | ||
|
1e88671799 | ||
|
1cdf9640d7 | ||
|
91badb53e5 | ||
|
477d02468d | ||
|
9f3a270fae | ||
|
244b058648 | ||
|
886c9b9bc0 | ||
|
41025ba97b | ||
|
4875bb6188 | ||
|
5f91c3d4e6 | ||
|
7b62915a5b | ||
|
05c3cb2c1d | ||
|
60a96d1400 | ||
|
dcd0df93da | ||
|
f15101fc6f | ||
|
5f03253398 | ||
|
8fab55e937 | ||
|
60a23665cb | ||
|
b292b275cb | ||
|
403028bf35 | ||
|
3dda5cff06 | ||
|
dd589e2490 | ||
|
c8fb83c97c | ||
|
854f6a9506 | ||
|
be0557c2b5 | ||
|
436422e4da | ||
|
fc72576aaa | ||
|
f69a2ba044 | ||
|
c45e06c694 | ||
|
78bdf1ca4e | ||
|
3c7d3c0196 | ||
|
441a5793cc | ||
|
388477686b | ||
|
4f654d9e12 | ||
|
ac12d0fc02 | ||
|
b8ebe4fd58 | ||
|
c84896391e | ||
|
995e28e9d8 | ||
|
1bfc082d46 | ||
|
1a35bbb127 | ||
|
e585c77830 | ||
|
5ca92ff637 | ||
|
f4c76553ed | ||
|
75baf6dd96 | ||
|
301b9288a4 | ||
|
70b9fc86d2 | ||
|
dde9cd323c | ||
|
01a6827542 | ||
|
b960a9e574 | ||
|
102fe3a8fb | ||
|
292df419ba | ||
|
7993e1d1c9 | ||
|
7309f92c36 | ||
|
7875ff293d | ||
|
4adac4d852 | ||
|
38bff65caf | ||
|
9ecadf1bc1 | ||
|
5d7ae385ec | ||
|
74e9780b30 | ||
|
9b20f41ece | ||
|
967309120e | ||
|
94be2abdbd | ||
|
6c31b53cd9 | ||
|
9bfc0b2c6f | ||
|
fc374ec57a | ||
|
7a8e60ddc2 | ||
|
7f43f26886 | ||
|
4521982837 | ||
|
30c43b557c | ||
|
10b5886dcc | ||
|
93b97fc3fe | ||
|
1f6e60fd74 | ||
|
5337d4838d | ||
|
ae5d183db0 | ||
|
0d85a34551 | ||
|
002c608d45 | ||
|
ec766a3e43 | ||
|
0ef8d04ed2 | ||
|
3a86916e72 | ||
|
b41435f407 | ||
|
f689d90815 | ||
|
966f2e7ef7 | ||
|
9075430210 | ||
|
68095ad69a | ||
|
8c3d1e608c | ||
|
6822f18cbb | ||
|
6e4f2e19d6 | ||
|
8bbd062d13 | ||
|
5f7ccc8c9b | ||
|
5b1483f646 | ||
|
3cd86d0e93 | ||
|
a893fbc358 | ||
|
6fd2a38fe9 | ||
|
b89ecb3e5a | ||
|
2e5590b566 | ||
|
733bb2ebbb | ||
|
64a22457e2 | ||
|
0c8e94d2c6 | ||
|
b9436821e0 | ||
|
a8af9120de | ||
|
0655a1f6b6 | ||
|
97dbedaa54 | ||
|
4028b44d07 | ||
|
661218c7e3 | ||
|
cd4a9add68 | ||
|
7d2915c7f9 | ||
|
ce56a035b5 | ||
|
9fa79aabc0 | ||
|
62fad9ca3a | ||
|
388f055643 | ||
|
71be20636a | ||
|
3b38d1b46e | ||
|
1e0c2ea633 | ||
|
4e7652be7a | ||
|
723075d2da | ||
|
7ba021871a | ||
|
d7cb819502 | ||
|
5ee2aa77c6 | ||
|
80cf5d8d5b | ||
|
69277400b7 | ||
|
8d380b4913 | ||
|
23d20e0753 | ||
|
6fc7beba57 | ||
|
8d49d22074 | ||
|
6aa97d055f | ||
|
e55938e23a | ||
|
4166fb229e | ||
|
2e9947277a | ||
|
c350ea0ced | ||
|
588b5c4d89 | ||
|
91d0877c61 | ||
|
8045ad56ea | ||
|
124b07ee44 | ||
|
195974ddc1 | ||
|
2b081b42bb | ||
|
321d241483 | ||
|
ad4ff5835e | ||
|
a3cda2e0ff | ||
|
cf2eb1fec7 | ||
|
7eb759d1fd | ||
|
a07bf86c30 | ||
|
64c4aca3b7 | ||
|
40465643b9 | ||
|
56fbf491bc | ||
|
685c071056 | ||
|
fdbc0e6a61 | ||
|
7fe8d27686 |
14
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
14
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
## Description
|
||||
Include changes, new features and etc:
|
||||
|
||||
## Describe your tests
|
||||
How did you test your change?
|
||||
|
||||
Python version:
|
||||
|
||||
OS:
|
||||
|
||||
## Checklist:
|
||||
- [ ] I added/edited example on new feature/change (if exists)
|
||||
- [ ] My changes won't break backward compatibility
|
||||
- [ ] I made changes both for sync and async
|
2
.github/workflows/setup_python.yml
vendored
2
.github/workflows/setup_python.yml
vendored
|
@ -20,7 +20,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [ '3.6','3.7','3.8','3.9', 'pypy-3.6', 'pypy-3.7' ] #'pypy-3.8', 'pypy-3.9' NOT SUPPORTED NOW
|
||||
python-version: [ '3.7', '3.8', '3.9', '3.10', '3.11', 'pypy-3.7', 'pypy-3.8', 'pypy-3.9']
|
||||
name: ${{ matrix.python-version }} and tests
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
|
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -64,3 +64,7 @@ testMain.py
|
|||
#VS Code
|
||||
.vscode/
|
||||
.DS_Store
|
||||
*.code-workspace
|
||||
|
||||
# documentation
|
||||
_build/
|
||||
|
|
22
.readthedocs.yaml
Normal file
22
.readthedocs.yaml
Normal file
|
@ -0,0 +1,22 @@
|
|||
# .readthedocs.yaml
|
||||
# Read the Docs configuration file
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
|
||||
# Required
|
||||
version: 2
|
||||
|
||||
# Set the version of Python and other tools you might need
|
||||
build:
|
||||
os: ubuntu-22.04
|
||||
tools:
|
||||
python: "3.9"
|
||||
|
||||
# Build documentation in the docs/ directory with Sphinx
|
||||
sphinx:
|
||||
configuration: docs/conf.py
|
||||
|
||||
# We recommend specifying your dependencies to enable reproducible builds:
|
||||
# https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
|
||||
python:
|
||||
install:
|
||||
- requirements: docs/requirements.txt
|
19
.readthedocs.yml
Normal file
19
.readthedocs.yml
Normal file
|
@ -0,0 +1,19 @@
|
|||
# .readthedocs.yml
|
||||
# Read the Docs configuration file
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
|
||||
# Required
|
||||
version: 2
|
||||
|
||||
# Build documentation in the docs/ directory with Sphinx
|
||||
sphinx:
|
||||
configuration: docs/source/conf.py
|
||||
|
||||
# Optionally build your docs in additional formats such as PDF and ePub
|
||||
formats: all
|
||||
|
||||
# Optionally set the version of Python and requirements required to build your docs
|
||||
python:
|
||||
version: 3.7
|
||||
install:
|
||||
- requirements: doc_req.txt
|
|
@ -4,6 +4,7 @@ python:
|
|||
- "3.8"
|
||||
- "3.9"
|
||||
- "3.10"
|
||||
- "3.11"
|
||||
- "pypy3"
|
||||
install: "pip install -r requirements.txt"
|
||||
script:
|
||||
|
|
121
README.md
121
README.md
|
@ -1,16 +1,20 @@
|
|||
|
||||
[![PyPi Package Version](https://img.shields.io/pypi/v/pyTelegramBotAPI.svg)](https://pypi.python.org/pypi/pyTelegramBotAPI)
|
||||
[![Supported Python versions](https://img.shields.io/pypi/pyversions/pyTelegramBotAPI.svg)](https://pypi.python.org/pypi/pyTelegramBotAPI)
|
||||
[![Build Status](https://travis-ci.org/eternnoir/pyTelegramBotAPI.svg?branch=master)](https://travis-ci.org/eternnoir/pyTelegramBotAPI)
|
||||
[![Documentation Status](https://readthedocs.org/projects/pytba/badge/?version=latest)](https://pytba.readthedocs.io/en/latest/?badge=latest)
|
||||
[![PyPi downloads](https://img.shields.io/pypi/dm/pyTelegramBotAPI.svg)](https://pypi.org/project/pyTelegramBotAPI/)
|
||||
[![PyPi status](https://img.shields.io/pypi/status/pytelegrambotapi.svg?style=flat-square)](https://pypi.python.org/pypi/pytelegrambotapi)
|
||||
|
||||
# <p align="center">pyTelegramBotAPI
|
||||
|
||||
<p align="center">A simple, but extensible Python implementation for the <a href="https://core.telegram.org/bots/api">Telegram Bot API</a>.</p>
|
||||
<p align="center">Supports both sync and async ways.</p>
|
||||
<p align="center">Both synchronous and asynchronous.</p>
|
||||
|
||||
## <p align="center">Supporting Bot API version: <a href="https://core.telegram.org/bots/api#december-30-2021">5.6</a>!
|
||||
## <p align="center">Supported Bot API version: <a href="https://core.telegram.org/bots/api#april-21-2023">6.7</a>!
|
||||
|
||||
<h2><a href='https://pytba.readthedocs.io/en/latest/index.html'>Official documentation</a></h2>
|
||||
<h2><a href='https://pytba.readthedocs.io/ru/latest/index.html'>Official ru documentation</a></h2>
|
||||
|
||||
## Contents
|
||||
|
||||
* [Getting started](#getting-started)
|
||||
|
@ -52,7 +56,7 @@
|
|||
* [Logging](#logging)
|
||||
* [Proxy](#proxy)
|
||||
* [Testing](#testing)
|
||||
* [API conformance](#api-conformance)
|
||||
* [API conformance limitations](#api-conformance-limitations)
|
||||
* [AsyncTeleBot](#asynctelebot)
|
||||
* [F.A.Q.](#faq)
|
||||
* [How can I distinguish a User and a GroupChat in message.chat?](#how-can-i-distinguish-a-user-and-a-groupchat-in-messagechat)
|
||||
|
@ -60,14 +64,15 @@
|
|||
* [The Telegram Chat Group](#the-telegram-chat-group)
|
||||
* [Telegram Channel](#telegram-channel)
|
||||
* [More examples](#more-examples)
|
||||
* [Bots using this API](#bots-using-this-api)
|
||||
* [Code Template](#code-template)
|
||||
* [Bots using this library](#bots-using-this-library)
|
||||
|
||||
## Getting started
|
||||
|
||||
This API is tested with Python 3.6-3.10 and Pypy 3.
|
||||
This API is tested with Python 3.7-3.11 and Pypy 3.
|
||||
There are two ways to install the library:
|
||||
|
||||
* Installation using pip (a Python package manager)*:
|
||||
* Installation using pip (a Python package manager):
|
||||
|
||||
```
|
||||
$ pip install pyTelegramBotAPI
|
||||
|
@ -79,10 +84,17 @@ $ git clone https://github.com/eternnoir/pyTelegramBotAPI.git
|
|||
$ cd pyTelegramBotAPI
|
||||
$ python setup.py install
|
||||
```
|
||||
or:
|
||||
```
|
||||
$ pip install git+https://github.com/eternnoir/pyTelegramBotAPI.git
|
||||
```
|
||||
|
||||
It is generally recommended to use the first option.
|
||||
|
||||
**While the API is production-ready, it is still under development and it has regular updates, do not forget to update it regularly by calling `pip install pytelegrambotapi --upgrade`*
|
||||
*While the API is production-ready, it is still under development and it has regular updates, do not forget to update it regularly by calling*
|
||||
```
|
||||
pip install pytelegrambotapi --upgrade
|
||||
```
|
||||
|
||||
## Writing your first bot
|
||||
|
||||
|
@ -153,7 +165,7 @@ To start the bot, simply open up a terminal and enter `python echo_bot.py` to ru
|
|||
All types are defined in types.py. They are all completely in line with the [Telegram API's definition of the types](https://core.telegram.org/bots/api#available-types), except for the Message's `from` field, which is renamed to `from_user` (because `from` is a Python reserved token). Thus, attributes such as `message_id` can be accessed directly with `message.message_id`. Note that `message.chat` can be either an instance of `User` or `GroupChat` (see [How can I distinguish a User and a GroupChat in message.chat?](#how-can-i-distinguish-a-user-and-a-groupchat-in-messagechat)).
|
||||
|
||||
The Message object also has a `content_type`attribute, which defines the type of the Message. `content_type` can be one of the following strings:
|
||||
`text`, `audio`, `document`, `photo`, `sticker`, `video`, `video_note`, `voice`, `location`, `contact`, `new_chat_members`, `left_chat_member`, `new_chat_title`, `new_chat_photo`, `delete_chat_photo`, `group_chat_created`, `supergroup_chat_created`, `channel_chat_created`, `migrate_to_chat_id`, `migrate_from_chat_id`, `pinned_message`.
|
||||
`text`, `audio`, `document`, `photo`, `sticker`, `video`, `video_note`, `voice`, `location`, `contact`, `new_chat_members`, `left_chat_member`, `new_chat_title`, `new_chat_photo`, `delete_chat_photo`, `group_chat_created`, `supergroup_chat_created`, `channel_chat_created`, `migrate_to_chat_id`, `migrate_from_chat_id`, `pinned_message`, `web_app_data`.
|
||||
|
||||
You can use some types in one function. Example:
|
||||
|
||||
|
@ -253,7 +265,7 @@ def test_callback(call): # <- passes a CallbackQuery type object to your functio
|
|||
|
||||
#### Shipping Query Handler
|
||||
Handle shipping queries
|
||||
`@bot.shipping_query_handeler() # <- passes a ShippingQuery type object to your function`
|
||||
`@bot.shipping_query_handler() # <- passes a ShippingQuery type object to your function`
|
||||
|
||||
#### Pre Checkout Query Handler
|
||||
Handle pre checkoupt queries
|
||||
|
@ -344,7 +356,27 @@ def start(message):
|
|||
assert message.another_text == message.text + ':changed'
|
||||
```
|
||||
There are other examples using middleware handler in the [examples/middleware](examples/middleware) directory.
|
||||
|
||||
|
||||
#### Class-based middlewares
|
||||
There are class-based middlewares.
|
||||
Basic class-based middleware looks like this:
|
||||
```python
|
||||
class Middleware(BaseMiddleware):
|
||||
def __init__(self):
|
||||
self.update_types = ['message']
|
||||
def pre_process(self, message, data):
|
||||
data['foo'] = 'Hello' # just for example
|
||||
# we edited the data. now, this data is passed to handler.
|
||||
# return SkipHandler() -> this will skip handler
|
||||
# return CancelUpdate() -> this will cancel update
|
||||
def post_process(self, message, data, exception=None):
|
||||
print(data['foo'])
|
||||
if exception: # check for exception
|
||||
print(exception)
|
||||
```
|
||||
Class-based middleware should have to functions: post and pre process.
|
||||
So, as you can see, class-based middlewares work before and after handler execution.
|
||||
For more, check out in [examples](https://github.com/eternnoir/pyTelegramBotAPI/tree/master/examples/middleware/class_based)
|
||||
|
||||
#### Custom filters
|
||||
Also, you can use built-in custom filters. Or, you can create your own filter.
|
||||
|
@ -366,7 +398,7 @@ Here is example of creating filter-class:
|
|||
```python
|
||||
class IsAdmin(telebot.custom_filters.SimpleCustomFilter):
|
||||
# Class will check whether the user is admin or creator in group or not
|
||||
key='is_admin'
|
||||
key='is_chat_admin'
|
||||
@staticmethod
|
||||
def check(message: telebot.types.Message):
|
||||
return bot.get_chat_member(message.chat.id,message.from_user.id).status in ['administrator','creator']
|
||||
|
@ -375,7 +407,7 @@ class IsAdmin(telebot.custom_filters.SimpleCustomFilter):
|
|||
bot.add_custom_filter(IsAdmin())
|
||||
|
||||
# Now, you can use it in handler.
|
||||
@bot.message_handler(is_admin=True)
|
||||
@bot.message_handler(is_chat_admin=True)
|
||||
def admin_of_group(message):
|
||||
bot.send_message(message.chat.id, 'You are admin of this group!')
|
||||
|
||||
|
@ -642,6 +674,8 @@ telebot.logger.setLevel(logging.DEBUG) # Outputs debug messages to console.
|
|||
```
|
||||
|
||||
### Proxy
|
||||
For sync:
|
||||
|
||||
You can use proxy for request. `apihelper.proxy` object will use by call `requests` proxies argument.
|
||||
|
||||
```python
|
||||
|
@ -656,6 +690,14 @@ If you want to use socket5 proxy you need install dependency `pip install reques
|
|||
apihelper.proxy = {'https':'socks5://userproxy:password@proxy_address:port'}
|
||||
```
|
||||
|
||||
For async:
|
||||
```python
|
||||
from telebot import asyncio_helper
|
||||
|
||||
asyncio_helper.proxy = 'http://127.0.0.1:3128' #url
|
||||
```
|
||||
|
||||
|
||||
### Testing
|
||||
You can disable or change the interaction with real Telegram server by using
|
||||
```python
|
||||
|
@ -684,25 +726,10 @@ Result will be:
|
|||
|
||||
|
||||
|
||||
## API conformance
|
||||
|
||||
* ✔ [Bot API 5.6](https://core.telegram.org/bots/api#december-30-2021)
|
||||
* ✔ [Bot API 5.5](https://core.telegram.org/bots/api#december-7-2021)
|
||||
* ✔ [Bot API 5.4](https://core.telegram.org/bots/api#november-5-2021)
|
||||
* ➕ [Bot API 5.3](https://core.telegram.org/bots/api#june-25-2021) - ChatMember* classes are full copies of ChatMember
|
||||
* ✔ [Bot API 5.2](https://core.telegram.org/bots/api#april-26-2021)
|
||||
* ✔ [Bot API 5.1](https://core.telegram.org/bots/api#march-9-2021)
|
||||
* ✔ [Bot API 5.0](https://core.telegram.org/bots/api-changelog#november-4-2020)
|
||||
* ✔ [Bot API 4.9](https://core.telegram.org/bots/api-changelog#june-4-2020)
|
||||
* ✔ [Bot API 4.8](https://core.telegram.org/bots/api-changelog#april-24-2020)
|
||||
* ✔ [Bot API 4.7](https://core.telegram.org/bots/api-changelog#march-30-2020)
|
||||
* ✔ [Bot API 4.6](https://core.telegram.org/bots/api-changelog#january-23-2020)
|
||||
## API conformance limitations
|
||||
* ➕ [Bot API 4.5](https://core.telegram.org/bots/api-changelog#december-31-2019) - No nested MessageEntities and Markdown2 support
|
||||
* ✔ [Bot API 4.4](https://core.telegram.org/bots/api-changelog#july-29-2019)
|
||||
* ✔ [Bot API 4.3](https://core.telegram.org/bots/api-changelog#may-31-2019)
|
||||
* ✔ [Bot API 4.2](https://core.telegram.org/bots/api-changelog#april-14-2019)
|
||||
* ➕ [Bot API 4.1](https://core.telegram.org/bots/api-changelog#august-27-2018) - No Passport support
|
||||
* ➕ [Bot API 4.0](https://core.telegram.org/bots/api-changelog#july-26-2018) - No Passport support
|
||||
* ➕ [Bot API 4.1](https://core.telegram.org/bots/api-changelog#august-27-2018) - No Passport support
|
||||
* ➕ [Bot API 4.0](https://core.telegram.org/bots/api-changelog#july-26-2018) - No Passport support
|
||||
|
||||
|
||||
## AsyncTeleBot
|
||||
|
@ -746,10 +773,10 @@ As you can see here, keywords are await and async.
|
|||
Asynchronous tasks depend on processor performance. Many asynchronous tasks can run parallelly, while thread tasks will block each other.
|
||||
|
||||
### Differences in AsyncTeleBot
|
||||
AsyncTeleBot has different middlewares. See example on [middlewares](https://github.com/coder2020official/pyTelegramBotAPI/tree/master/examples/asynchronous_telebot/middleware)
|
||||
AsyncTeleBot is asynchronous. It uses aiohttp instead of requests module.
|
||||
|
||||
### Examples
|
||||
See more examples in our [examples](https://github.com/coder2020official/pyTelegramBotAPI/tree/master/examples/asynchronous_telebot) folder
|
||||
See more examples in our [examples](https://github.com/eternnoir/pyTelegramBotAPI/tree/master/examples/asynchronous_telebot) folder
|
||||
|
||||
|
||||
## F.A.Q.
|
||||
|
@ -758,7 +785,6 @@ See more examples in our [examples](https://github.com/coder2020official/pyTeleg
|
|||
Telegram Bot API support new type Chat for message.chat.
|
||||
|
||||
- Check the ```type``` attribute in ```Chat``` object:
|
||||
-
|
||||
```python
|
||||
if message.chat.type == "private":
|
||||
# private chat message
|
||||
|
@ -794,7 +820,15 @@ Join the [News channel](https://t.me/pyTelegramBotAPI). Here we will post releas
|
|||
* [Deep Linking](https://github.com/eternnoir/pyTelegramBotAPI/blob/master/examples/deep_linking.py)
|
||||
* [next_step_handler Example](https://github.com/eternnoir/pyTelegramBotAPI/blob/master/examples/step_example.py)
|
||||
|
||||
## Bots using this API
|
||||
## Code Template
|
||||
Template is a ready folder that contains architecture of basic project.
|
||||
Here are some examples of template:
|
||||
|
||||
* [AsyncTeleBot template](https://github.com/coder2020official/asynctelebot_template)
|
||||
* [TeleBot template](https://github.com/coder2020official/telebot_template)
|
||||
|
||||
|
||||
## Bots using this library
|
||||
* [SiteAlert bot](https://telegram.me/SiteAlert_bot) ([source](https://github.com/ilteoood/SiteAlert-Python)) by *ilteoood* - Monitors websites and sends a notification on changes
|
||||
* [TelegramLoggingBot](https://github.com/aRandomStranger/TelegramLoggingBot) by *aRandomStranger*
|
||||
* [Telegram LMGTFY_bot](https://github.com/GabrielRF/telegram-lmgtfy_bot) by *GabrielRF* - Let me Google that for you.
|
||||
|
@ -843,5 +877,20 @@ Join the [News channel](https://t.me/pyTelegramBotAPI). Here we will post releas
|
|||
* [GrandQuiz Bot](https://github.com/Carlosma7/TFM-GrandQuiz) by [Carlosma7](https://github.com/Carlosma7). This bot is a trivia game that allows you to play with people from different ages. This project addresses the use of a system through chatbots to carry out a social and intergenerational game as an alternative to traditional game development.
|
||||
* [Diccionario de la RAE](https://t.me/dleraebot) ([source](https://github.com/studentenherz/dleraebot)) This bot lets you find difinitions of words in Spanish using [RAE's dictionary](https://dle.rae.es/). It features direct message and inline search.
|
||||
* [remoteTelegramShell](https://github.com/EnriqueMoran/remoteTelegramShell) by [EnriqueMoran](https://github.com/EnriqueMoran). Control your LinuxOS computer through Telegram.
|
||||
|
||||
* [Commerce Telegram Bot](https://github.com/ayitinya/commerce-telegram-bot/). Make purchases of items in a store with an Admin panel for data control and notifications.
|
||||
* [Pyfram-telegram-bot](https://github.com/skelly37/pyfram-telegram-bot) Query wolframalpha.com and make use of its API through Telegram.
|
||||
* [TranslateThisVideoBot](https://gitlab.com/WuerfelDev/translatethisvideo) This Bot can understand spoken text in videos and translate it to English
|
||||
* [Zyprexa](https://t.me/mathemathicsBot) ([source](https://github.com/atif5/zyprexa)) Zyprexa can solve, help you solve any mathematical problem you encounter and convert your regular mathematical expressions into beautiful imagery using LaTeX.
|
||||
* [Bincode-telegram-bot](https://github.com/tusharhero/bincode-telegram-bot) by [tusharhero](https://github.com/tusharhero) - Makes [bincodes](https://github.com/tusharhero/bincode) from text provides and also converts them back to text.
|
||||
* [hydrolib_bot](https://github.com/Mayson90/hydrolib_bot) Toolset for Hydrophilia tabletop game (game cards, rules, structure...).
|
||||
* [Gugumoe-bot](http://t.me/gugumoe_bot) ([source](https://github.com/GooGuJiang/Gugumoe-bot)) by [咕谷酱](https://gmoe.cc) GuXiaoJiang is a multi-functional robot, such as OSU game information query, IP test, animation screenshot search and other functions.
|
||||
* [Feedback-bot](https://github.com/coder2020official/feedbackbot) A feedback bot for user-admin communication. Made on AsyncTeleBot, using [template](https://github.com/coder2020official/asynctelebot_template).
|
||||
* [TeleServ](https://github.com/ablakely/TeleServ) by [ablakely](https://github.com/ablakely) This is a Telegram to IRC bridge which links as an IRC server and makes Telegram users appear as native IRC users.
|
||||
* [Simple Store Bot](https://github.com/AntonGlyzin/myshopbot) by [Anton Glyzin](https://github.com/AntonGlyzin) This is a simple telegram-store with an admin panel. Designed according to a template.
|
||||
* [Media Rating Bot](https://t.me/mediaratingbot) ([source](https://github.com/CommanderCRM/MediaRatingBot))by [CommanderCRM](https://github.com/CommanderCRM). This bot aggregates media (movies, TV series, etc.) ratings from IMDb, Rotten Tomatoes, Metacritic, TheMovieDB, FilmAffinity and also provides number of votes of said media on IMDb.
|
||||
* [Spot Seek Bot](https://t.me/SpotSeekBot) ([source](https://github.com/arashnm80/spot-seek-bot)) by [Arashnm80](https://github.com/arashnm80). This is a free & open source telegram bot for downloading tracks, albums or playlists from spotify.
|
||||
* [CalendarIT Bot](https://t.me/calendarit_bot) ([source](https://github.com/codebyzen/CalendarIT_Telegram_Bot))by [CodeByZen](https://github.com/codebyzen). A simple, but extensible Python Telegram bot, can post acquainted with what is happening today, tomorrow or what happened 20 years ago to channel.
|
||||
* [DownloadMusicBOT](https://github.com/fcoagz/DownloadMusicBOT) by *Francisco Griman* - It is a simple bot that downloads audio from YouTube videos on Telegram.
|
||||
* [AwesomeChatGPTBot](https://github.com/Kourva/AwesomeChatGPTBot) - Simple ChatGTP-3.5 bot. It is FREE and can remember chat history for a while With pre-defined roles!
|
||||
|
||||
**Want to have your bot listed here? Just make a pull request. Only bots with public source code are accepted.**
|
||||
|
|
5
doc_req.txt
Normal file
5
doc_req.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
-r requirements.txt
|
||||
|
||||
furo
|
||||
sphinx_copybutton
|
||||
git+https://github.com/eternnoir/pyTelegramBotAPI.git
|
20
docs/Makefile
Normal file
20
docs/Makefile
Normal file
|
@ -0,0 +1,20 @@
|
|||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line, and also
|
||||
# from the environment for the first two.
|
||||
SPHINXOPTS ?=
|
||||
SPHINXBUILD ?= sphinx-build
|
||||
SOURCEDIR = source
|
||||
BUILDDIR = build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
BIN
docs/source/_static/logo.png
Normal file
BIN
docs/source/_static/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 57 KiB |
BIN
docs/source/_static/logo2.png
Normal file
BIN
docs/source/_static/logo2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
48
docs/source/async_version/index.rst
Normal file
48
docs/source/async_version/index.rst
Normal file
|
@ -0,0 +1,48 @@
|
|||
====================
|
||||
AsyncTeleBot
|
||||
====================
|
||||
|
||||
|
||||
.. meta::
|
||||
:description: Asynchronous pyTelegramBotAPI
|
||||
:keywords: ptba, pytba, pyTelegramBotAPI, asynctelebot, documentation
|
||||
|
||||
|
||||
AsyncTeleBot methods
|
||||
--------------------
|
||||
|
||||
.. automodule:: telebot.async_telebot
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
|
||||
|
||||
Asyncio filters
|
||||
---------------
|
||||
|
||||
.. automodule:: telebot.asyncio_filters
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
Asyncio handler backends
|
||||
------------------------
|
||||
|
||||
|
||||
|
||||
.. automodule:: telebot.asyncio_handler_backends
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
|
||||
Extensions
|
||||
------------------------
|
||||
|
||||
|
||||
|
||||
.. automodule:: telebot.ext.aio.webhooks
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
17
docs/source/calldata.rst
Normal file
17
docs/source/calldata.rst
Normal file
|
@ -0,0 +1,17 @@
|
|||
|
||||
=====================
|
||||
Callback data factory
|
||||
=====================
|
||||
|
||||
.. meta::
|
||||
:description: Callback data factory in pyTelegramBotAPI
|
||||
:keywords: ptba, pytba, pyTelegramBotAPI, callbackdatafactory, guide, callbackdata, factory
|
||||
|
||||
|
||||
callback\_data file
|
||||
-----------------------------
|
||||
|
||||
.. automodule:: telebot.callback_data
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
72
docs/source/conf.py
Normal file
72
docs/source/conf.py
Normal file
|
@ -0,0 +1,72 @@
|
|||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file only contains a selection of the most common options. For a full
|
||||
# list see the documentation:
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = 'pyTelegramBotAPI Documentation'
|
||||
copyright = '2022-2023, coder2020official'
|
||||
author = 'coder2020official'
|
||||
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = '4.12.0'
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autosectionlabel',
|
||||
'sphinx.ext.autodoc',
|
||||
"sphinx.ext.autosummary",
|
||||
"sphinx.ext.napoleon",
|
||||
"sphinx_copybutton",
|
||||
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = []
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = 'furo'
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
#html_logo = 'logo.png'
|
||||
html_theme_options = {
|
||||
"light_css_variables": {
|
||||
"color-brand-primary": "#7C4DFF",
|
||||
"color-brand-content": "#7C4DFF",
|
||||
},
|
||||
"light_logo": "logo.png",
|
||||
"dark_logo": "logo2.png",
|
||||
}
|
||||
|
||||
locale_dirs = ["locales/"]
|
12
docs/source/formatting.rst
Normal file
12
docs/source/formatting.rst
Normal file
|
@ -0,0 +1,12 @@
|
|||
==================
|
||||
Formatting options
|
||||
==================
|
||||
|
||||
.. meta::
|
||||
:description: Formatting options in pyTelegramBotAPI
|
||||
:keywords: html, markdown, parse_mode, formatting, ptba, pytba, pyTelegramBotAPI
|
||||
|
||||
.. automodule:: telebot.formatting
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
69
docs/source/index.rst
Normal file
69
docs/source/index.rst
Normal file
|
@ -0,0 +1,69 @@
|
|||
.. pyTelegramBotAPI documentation master file, created by
|
||||
sphinx-quickstart on Fri Feb 18 20:58:37 2022.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
|
||||
Welcome to pyTelegramBotAPI's documentation!
|
||||
============================================
|
||||
|
||||
.. meta::
|
||||
:description: Official documentation of pyTelegramBotAPI
|
||||
:keywords: ptba, pytba, pyTelegramBotAPI, documentation, guide
|
||||
|
||||
|
||||
=======
|
||||
TeleBot
|
||||
=======
|
||||
TeleBot is synchronous and asynchronous implementation of `Telegram Bot API <https://core.telegram.org/bots/api>`_.
|
||||
|
||||
Chats
|
||||
-----
|
||||
English chat: `Private chat <https://telegram.me/joinchat/Bn4ixj84FIZVkwhk2jag6A>`__
|
||||
|
||||
Russian chat: `@pytelegrambotapi_talks_ru <https://t.me/pytelegrambotapi_talks_ru>`__
|
||||
|
||||
News: `@pyTelegramBotAPI <https://t.me/pytelegrambotapi>`__
|
||||
|
||||
Pypi: `Pypi <https://pypi.org/project/pyTelegramBotAPI/>`__
|
||||
|
||||
Source: `Github repository <https://github.com/eternnoir/pyTelegramBotAPI>`__
|
||||
|
||||
Some features:
|
||||
--------------
|
||||
Easy to learn and use.
|
||||
|
||||
Easy to understand.
|
||||
|
||||
Both sync and async.
|
||||
|
||||
Examples on features.
|
||||
|
||||
States
|
||||
|
||||
And more...
|
||||
|
||||
Content
|
||||
--------
|
||||
.. toctree::
|
||||
|
||||
install
|
||||
quick_start
|
||||
types
|
||||
sync_version/index
|
||||
async_version/index
|
||||
calldata
|
||||
util
|
||||
formatting
|
||||
|
||||
|
||||
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
|
||||
|
45
docs/source/install.rst
Normal file
45
docs/source/install.rst
Normal file
|
@ -0,0 +1,45 @@
|
|||
==================
|
||||
Installation Guide
|
||||
==================
|
||||
|
||||
.. meta::
|
||||
:description: Installation of pyTelegramBotAPI
|
||||
:keywords: ptba, pytba, pyTelegramBotAPI, installation, guide
|
||||
|
||||
|
||||
Using PIP
|
||||
----------
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install pyTelegramBotAPI
|
||||
|
||||
Using pipenv
|
||||
------------
|
||||
.. code-block:: bash
|
||||
|
||||
$ pipenv install pyTelegramBotAPI
|
||||
|
||||
By cloning repository
|
||||
---------------------
|
||||
.. code-block:: bash
|
||||
|
||||
$ git clone https://github.com/eternnoir/pyTelegramBotAPI.git
|
||||
$ cd pyTelegramBotAPI
|
||||
$ python setup.py install
|
||||
|
||||
Directly using pip
|
||||
------------------
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install git+https://github.com/eternnoir/pyTelegramBotAPI.git
|
||||
|
||||
|
||||
It is generally recommended to use the first option.
|
||||
|
||||
While the API is production-ready, it is still under development and it has regular updates, do not forget to update it regularly by calling:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install pytelegrambotapi --upgrade
|
||||
|
||||
|
5280
docs/source/locales/en/LC_MESSAGES/async_version.po
Normal file
5280
docs/source/locales/en/LC_MESSAGES/async_version.po
Normal file
File diff suppressed because it is too large
Load Diff
127
docs/source/locales/en/LC_MESSAGES/calldata.po
Normal file
127
docs/source/locales/en/LC_MESSAGES/calldata.po
Normal file
|
@ -0,0 +1,127 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) 2022, coder2020official
|
||||
# This file is distributed under the same license as the pyTelegramBotAPI
|
||||
# Documentation package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: pyTelegramBotAPI Documentation \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-11-29 14:44+0400\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.9.1\n"
|
||||
|
||||
#: ../../calldata.rst:4
|
||||
msgid "Callback data factory"
|
||||
msgstr ""
|
||||
|
||||
#: ../../calldata.rst:6
|
||||
msgid "Callback data factory in pyTelegramBotAPI"
|
||||
msgstr ""
|
||||
|
||||
#: ../../calldata.rst:6
|
||||
msgid ""
|
||||
"ptba, pytba, pyTelegramBotAPI, callbackdatafactory, guide, callbackdata, "
|
||||
"factory"
|
||||
msgstr ""
|
||||
|
||||
#: ../../calldata.rst:12
|
||||
msgid "callback\\_data file"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.callback_data:1
|
||||
msgid "Callback data factory's file."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.callback_data.CallbackData:1
|
||||
#: telebot.callback_data.CallbackDataFilter:1
|
||||
msgid "Bases: :py:class:`object`"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.callback_data.CallbackData:1
|
||||
msgid "Callback data factory This class will help you to work with CallbackQuery"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.callback_data.CallbackData.filter:1
|
||||
msgid "Generate filter"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.callback_data.CallbackData.filter
|
||||
#: telebot.callback_data.CallbackData.new
|
||||
#: telebot.callback_data.CallbackData.parse
|
||||
#: telebot.callback_data.CallbackDataFilter.check
|
||||
msgid "Parameters"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.callback_data.CallbackData.filter:3
|
||||
msgid "specified named parameters will be checked with CallbackQuery.data"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.callback_data.CallbackData.filter
|
||||
#: telebot.callback_data.CallbackData.new
|
||||
#: telebot.callback_data.CallbackData.parse
|
||||
#: telebot.callback_data.CallbackDataFilter.check
|
||||
msgid "Returns"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.callback_data.CallbackData.filter:4
|
||||
msgid "CallbackDataFilter class"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.callback_data.CallbackData.new:1
|
||||
msgid "Generate callback data"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.callback_data.CallbackData.new:3
|
||||
msgid "positional parameters of CallbackData instance parts"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.callback_data.CallbackData.new:4
|
||||
msgid "named parameters"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.callback_data.CallbackData.new:5
|
||||
msgid "str"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.callback_data.CallbackData.parse:1
|
||||
msgid "Parse data from the callback data"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.callback_data.CallbackData.parse:3
|
||||
msgid ""
|
||||
"string, use to telebot.types.CallbackQuery to parse it from string to a "
|
||||
"dict"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.callback_data.CallbackData.parse:4
|
||||
msgid "dict parsed from callback data"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.callback_data.CallbackDataFilter:1
|
||||
msgid "Filter for CallbackData."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.callback_data.CallbackDataFilter.check:1
|
||||
msgid "Checks if query.data appropriates to specified config"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.callback_data.CallbackDataFilter.check:3
|
||||
msgid "telebot.types.CallbackQuery"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.callback_data.CallbackDataFilter.check:6
|
||||
msgid "True if query.data appropriates to specified config"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.callback_data.CallbackDataFilter.check
|
||||
msgid "Return type"
|
||||
msgstr ""
|
||||
|
251
docs/source/locales/en/LC_MESSAGES/formatting.po
Normal file
251
docs/source/locales/en/LC_MESSAGES/formatting.po
Normal file
|
@ -0,0 +1,251 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) 2022, coder2020official
|
||||
# This file is distributed under the same license as the pyTelegramBotAPI
|
||||
# Documentation package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: pyTelegramBotAPI Documentation \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-11-29 14:44+0400\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.9.1\n"
|
||||
|
||||
#: ../../formatting.rst:3
|
||||
msgid "Formatting options"
|
||||
msgstr ""
|
||||
|
||||
#: ../../formatting.rst:5
|
||||
msgid "Formatting options in pyTelegramBotAPI"
|
||||
msgstr ""
|
||||
|
||||
#: ../../formatting.rst:5
|
||||
msgid "html, markdown, parse_mode, formatting, ptba, pytba, pyTelegramBotAPI"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting:1
|
||||
msgid "Markdown & HTML formatting functions."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.escape_html:1
|
||||
msgid "Escapes HTML characters in a string of HTML."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.escape_html telebot.formatting.escape_markdown
|
||||
#: telebot.formatting.format_text telebot.formatting.hbold
|
||||
#: telebot.formatting.hcode telebot.formatting.hide_link
|
||||
#: telebot.formatting.hitalic telebot.formatting.hlink telebot.formatting.hpre
|
||||
#: telebot.formatting.hspoiler telebot.formatting.hstrikethrough
|
||||
#: telebot.formatting.hunderline telebot.formatting.mbold
|
||||
#: telebot.formatting.mcode telebot.formatting.mitalic telebot.formatting.mlink
|
||||
#: telebot.formatting.mspoiler telebot.formatting.mstrikethrough
|
||||
#: telebot.formatting.munderline
|
||||
msgid "Parameters"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.escape_html:3
|
||||
msgid "The string of HTML to escape."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.escape_html telebot.formatting.escape_markdown
|
||||
#: telebot.formatting.format_text telebot.formatting.hbold
|
||||
#: telebot.formatting.hcode telebot.formatting.hide_link
|
||||
#: telebot.formatting.hitalic telebot.formatting.hlink telebot.formatting.hpre
|
||||
#: telebot.formatting.hspoiler telebot.formatting.hstrikethrough
|
||||
#: telebot.formatting.hunderline telebot.formatting.mbold
|
||||
#: telebot.formatting.mcode telebot.formatting.mitalic telebot.formatting.mlink
|
||||
#: telebot.formatting.mspoiler telebot.formatting.mstrikethrough
|
||||
#: telebot.formatting.munderline
|
||||
msgid "Returns"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.escape_html:6 telebot.formatting.escape_markdown:8
|
||||
msgid "The escaped string."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.escape_html telebot.formatting.escape_markdown
|
||||
#: telebot.formatting.format_text telebot.formatting.hbold
|
||||
#: telebot.formatting.hcode telebot.formatting.hide_link
|
||||
#: telebot.formatting.hitalic telebot.formatting.hlink telebot.formatting.hpre
|
||||
#: telebot.formatting.hspoiler telebot.formatting.hstrikethrough
|
||||
#: telebot.formatting.hunderline telebot.formatting.mbold
|
||||
#: telebot.formatting.mcode telebot.formatting.mitalic telebot.formatting.mlink
|
||||
#: telebot.formatting.mspoiler telebot.formatting.mstrikethrough
|
||||
#: telebot.formatting.munderline
|
||||
msgid "Return type"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.escape_html:7 telebot.formatting.escape_markdown:9
|
||||
#: telebot.formatting.format_text:17 telebot.formatting.hbold:10
|
||||
#: telebot.formatting.hcode:10 telebot.formatting.hide_link:7
|
||||
#: telebot.formatting.hitalic:10 telebot.formatting.hlink:13
|
||||
#: telebot.formatting.hpre:10 telebot.formatting.hspoiler:10
|
||||
#: telebot.formatting.hstrikethrough:10 telebot.formatting.hunderline:10
|
||||
#: telebot.formatting.mbold:10 telebot.formatting.mcode:10
|
||||
#: telebot.formatting.mitalic:10 telebot.formatting.mlink:13
|
||||
#: telebot.formatting.mspoiler:10 telebot.formatting.mstrikethrough:10
|
||||
#: telebot.formatting.munderline:10
|
||||
msgid ":obj:`str`"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.escape_markdown:1
|
||||
msgid "Escapes Markdown characters in a string of Markdown."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.escape_markdown:3
|
||||
msgid "Credits to: simonsmh"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.escape_markdown:5
|
||||
msgid "The string of Markdown to escape."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.format_text:1
|
||||
msgid "Formats a list of strings into a single string."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.format_text:10
|
||||
msgid "Strings to format."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.format_text:13
|
||||
msgid "The separator to use between each string."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.format_text:16 telebot.formatting.hbold:9
|
||||
#: telebot.formatting.hcode:9 telebot.formatting.hitalic:9
|
||||
#: telebot.formatting.hlink:12 telebot.formatting.hpre:9
|
||||
#: telebot.formatting.hspoiler:9 telebot.formatting.hstrikethrough:9
|
||||
#: telebot.formatting.hunderline:9 telebot.formatting.mbold:9
|
||||
#: telebot.formatting.mcode:9 telebot.formatting.mitalic:9
|
||||
#: telebot.formatting.mlink:12 telebot.formatting.mspoiler:9
|
||||
#: telebot.formatting.mstrikethrough:9 telebot.formatting.munderline:9
|
||||
msgid "The formatted string."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.hbold:1
|
||||
msgid "Returns an HTML-formatted bold string."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.hbold:3 telebot.formatting.mbold:3
|
||||
msgid "The string to bold."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.hbold:6 telebot.formatting.hcode:6
|
||||
#: telebot.formatting.hitalic:6 telebot.formatting.hlink:9
|
||||
#: telebot.formatting.hpre:6 telebot.formatting.hspoiler:6
|
||||
#: telebot.formatting.hstrikethrough:6 telebot.formatting.hunderline:6
|
||||
#: telebot.formatting.mbold:6 telebot.formatting.mcode:6
|
||||
#: telebot.formatting.mitalic:6 telebot.formatting.mlink:9
|
||||
#: telebot.formatting.mspoiler:6 telebot.formatting.mstrikethrough:6
|
||||
#: telebot.formatting.munderline:6
|
||||
msgid "True if you need to escape special characters. Defaults to True."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.hcode:1
|
||||
msgid "Returns an HTML-formatted code string."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.hcode:3 telebot.formatting.mcode:3
|
||||
msgid "The string to code."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.hide_link:1
|
||||
msgid "Hide url of an image."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.hide_link:3
|
||||
msgid "The url of the image."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.hide_link:6
|
||||
msgid "The hidden url."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.hitalic:1
|
||||
msgid "Returns an HTML-formatted italic string."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.hitalic:3 telebot.formatting.mitalic:3
|
||||
msgid "The string to italicize."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.hlink:1
|
||||
msgid "Returns an HTML-formatted link string."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.hlink:3 telebot.formatting.mlink:3
|
||||
msgid "The string to link."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.hlink:6 telebot.formatting.mlink:6
|
||||
msgid "The URL to link to."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.hpre:1
|
||||
msgid "Returns an HTML-formatted preformatted string."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.hpre:3
|
||||
msgid "The string to preformatted."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.hspoiler:1
|
||||
msgid "Returns an HTML-formatted spoiler string."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.hspoiler:3 telebot.formatting.mspoiler:3
|
||||
msgid "The string to spoiler."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.hstrikethrough:1
|
||||
msgid "Returns an HTML-formatted strikethrough string."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.hstrikethrough:3 telebot.formatting.mstrikethrough:3
|
||||
msgid "The string to strikethrough."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.hunderline:1
|
||||
msgid "Returns an HTML-formatted underline string."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.hunderline:3 telebot.formatting.munderline:3
|
||||
msgid "The string to underline."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.mbold:1
|
||||
msgid "Returns a Markdown-formatted bold string."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.mcode:1
|
||||
msgid "Returns a Markdown-formatted code string."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.mitalic:1
|
||||
msgid "Returns a Markdown-formatted italic string."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.mlink:1
|
||||
msgid "Returns a Markdown-formatted link string."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.mspoiler:1
|
||||
msgid "Returns a Markdown-formatted spoiler string."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.mstrikethrough:1
|
||||
msgid "Returns a Markdown-formatted strikethrough string."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.munderline:1
|
||||
msgid "Returns a Markdown-formatted underline string."
|
||||
msgstr ""
|
||||
|
120
docs/source/locales/en/LC_MESSAGES/index.po
Normal file
120
docs/source/locales/en/LC_MESSAGES/index.po
Normal file
|
@ -0,0 +1,120 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) 2022, coder2020official
|
||||
# This file is distributed under the same license as the pyTelegramBotAPI
|
||||
# Documentation package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: pyTelegramBotAPI Documentation \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-11-29 14:44+0400\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.9.1\n"
|
||||
|
||||
#: ../../index.rst:8
|
||||
msgid "Welcome to pyTelegramBotAPI's documentation!"
|
||||
msgstr ""
|
||||
|
||||
#: ../../index.rst:10
|
||||
msgid "Official documentation of pyTelegramBotAPI"
|
||||
msgstr ""
|
||||
|
||||
#: ../../index.rst:10
|
||||
msgid "ptba, pytba, pyTelegramBotAPI, documentation, guide"
|
||||
msgstr ""
|
||||
|
||||
#: ../../index.rst:17
|
||||
msgid "TeleBot"
|
||||
msgstr ""
|
||||
|
||||
#: ../../index.rst:18
|
||||
msgid ""
|
||||
"TeleBot is synchronous and asynchronous implementation of `Telegram Bot "
|
||||
"API <https://core.telegram.org/bots/api>`_."
|
||||
msgstr ""
|
||||
|
||||
#: ../../index.rst:21
|
||||
msgid "Chats"
|
||||
msgstr ""
|
||||
|
||||
#: ../../index.rst:22
|
||||
msgid ""
|
||||
"English chat: `Private chat "
|
||||
"<https://telegram.me/joinchat/Bn4ixj84FIZVkwhk2jag6A>`__"
|
||||
msgstr ""
|
||||
|
||||
#: ../../index.rst:24
|
||||
msgid ""
|
||||
"Russian chat: `@pytelegrambotapi_talks_ru "
|
||||
"<https://t.me/pytelegrambotapi_talks_ru>`__"
|
||||
msgstr ""
|
||||
|
||||
#: ../../index.rst:26
|
||||
msgid "News: `@pyTelegramBotAPI <https://t.me/pytelegrambotapi>`__"
|
||||
msgstr ""
|
||||
|
||||
#: ../../index.rst:28
|
||||
msgid "Pypi: `Pypi <https://pypi.org/project/pyTelegramBotAPI/>`__"
|
||||
msgstr ""
|
||||
|
||||
#: ../../index.rst:30
|
||||
msgid ""
|
||||
"Source: `Github repository "
|
||||
"<https://github.com/eternnoir/pyTelegramBotAPI>`__"
|
||||
msgstr ""
|
||||
|
||||
#: ../../index.rst:33
|
||||
msgid "Some features:"
|
||||
msgstr ""
|
||||
|
||||
#: ../../index.rst:34
|
||||
msgid "Easy to learn and use."
|
||||
msgstr ""
|
||||
|
||||
#: ../../index.rst:36
|
||||
msgid "Easy to understand."
|
||||
msgstr ""
|
||||
|
||||
#: ../../index.rst:38
|
||||
msgid "Both sync and async."
|
||||
msgstr ""
|
||||
|
||||
#: ../../index.rst:40
|
||||
msgid "Examples on features."
|
||||
msgstr ""
|
||||
|
||||
#: ../../index.rst:42
|
||||
msgid "States"
|
||||
msgstr ""
|
||||
|
||||
#: ../../index.rst:44
|
||||
msgid "And more..."
|
||||
msgstr ""
|
||||
|
||||
#: ../../index.rst:47
|
||||
msgid "Content"
|
||||
msgstr ""
|
||||
|
||||
#: ../../index.rst:63
|
||||
msgid "Indices and tables"
|
||||
msgstr ""
|
||||
|
||||
#: ../../index.rst:65
|
||||
msgid ":ref:`genindex`"
|
||||
msgstr ""
|
||||
|
||||
#: ../../index.rst:66
|
||||
msgid ":ref:`modindex`"
|
||||
msgstr ""
|
||||
|
||||
#: ../../index.rst:67
|
||||
msgid ":ref:`search`"
|
||||
msgstr ""
|
||||
|
58
docs/source/locales/en/LC_MESSAGES/install.po
Normal file
58
docs/source/locales/en/LC_MESSAGES/install.po
Normal file
|
@ -0,0 +1,58 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) 2022, coder2020official
|
||||
# This file is distributed under the same license as the pyTelegramBotAPI
|
||||
# Documentation package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: pyTelegramBotAPI Documentation \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-11-29 14:44+0400\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.9.1\n"
|
||||
|
||||
#: ../../install.rst:3
|
||||
msgid "Installation Guide"
|
||||
msgstr ""
|
||||
|
||||
#: ../../install.rst:5
|
||||
msgid "Installation of pyTelegramBotAPI"
|
||||
msgstr ""
|
||||
|
||||
#: ../../install.rst:5
|
||||
msgid "ptba, pytba, pyTelegramBotAPI, installation, guide"
|
||||
msgstr ""
|
||||
|
||||
#: ../../install.rst:11
|
||||
msgid "Using PIP"
|
||||
msgstr ""
|
||||
|
||||
#: ../../install.rst:17
|
||||
msgid "Using pipenv"
|
||||
msgstr ""
|
||||
|
||||
#: ../../install.rst:23
|
||||
msgid "By cloning repository"
|
||||
msgstr ""
|
||||
|
||||
#: ../../install.rst:31
|
||||
msgid "Directly using pip"
|
||||
msgstr ""
|
||||
|
||||
#: ../../install.rst:37
|
||||
msgid "It is generally recommended to use the first option."
|
||||
msgstr ""
|
||||
|
||||
#: ../../install.rst:39
|
||||
msgid ""
|
||||
"While the API is production-ready, it is still under development and it "
|
||||
"has regular updates, do not forget to update it regularly by calling:"
|
||||
msgstr ""
|
||||
|
40
docs/source/locales/en/LC_MESSAGES/quick_start.po
Normal file
40
docs/source/locales/en/LC_MESSAGES/quick_start.po
Normal file
|
@ -0,0 +1,40 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) 2022, coder2020official
|
||||
# This file is distributed under the same license as the pyTelegramBotAPI
|
||||
# Documentation package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: pyTelegramBotAPI Documentation \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-11-29 14:44+0400\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.9.1\n"
|
||||
|
||||
#: ../../quick_start.rst:4
|
||||
msgid "Quick start"
|
||||
msgstr ""
|
||||
|
||||
#: ../../quick_start.rst:6
|
||||
msgid "Quickstart guide"
|
||||
msgstr ""
|
||||
|
||||
#: ../../quick_start.rst:6
|
||||
msgid "ptba, pytba, pyTelegramBotAPI, quickstart, guide"
|
||||
msgstr ""
|
||||
|
||||
#: ../../quick_start.rst:11
|
||||
msgid "Synchronous TeleBot"
|
||||
msgstr ""
|
||||
|
||||
#: ../../quick_start.rst:16
|
||||
msgid "Asynchronous TeleBot"
|
||||
msgstr ""
|
||||
|
5406
docs/source/locales/en/LC_MESSAGES/sync_version.po
Normal file
5406
docs/source/locales/en/LC_MESSAGES/sync_version.po
Normal file
File diff suppressed because it is too large
Load Diff
6111
docs/source/locales/en/LC_MESSAGES/types.po
Normal file
6111
docs/source/locales/en/LC_MESSAGES/types.po
Normal file
File diff suppressed because it is too large
Load Diff
355
docs/source/locales/en/LC_MESSAGES/util.po
Normal file
355
docs/source/locales/en/LC_MESSAGES/util.po
Normal file
|
@ -0,0 +1,355 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) 2022, coder2020official
|
||||
# This file is distributed under the same license as the pyTelegramBotAPI
|
||||
# Documentation package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: pyTelegramBotAPI Documentation \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-07-08 23:07+0500\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.9.1\n"
|
||||
|
||||
#: ../../source/util.rst:3
|
||||
msgid "Utils"
|
||||
msgstr ""
|
||||
|
||||
#: ../../source/util.rst:5
|
||||
msgid "Utils in pyTelegramBotAPI"
|
||||
msgstr ""
|
||||
|
||||
#: ../../source/util.rst:5
|
||||
msgid "ptba, pytba, pyTelegramBotAPI, utils, guide"
|
||||
msgstr ""
|
||||
|
||||
#: ../../source/util.rst:11
|
||||
msgid "util file"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.antiflood:1
|
||||
msgid ""
|
||||
"Use this function inside loops in order to avoid getting TooManyRequests "
|
||||
"error. Example:"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.service_utils.is_bytes telebot.service_utils.is_dict
|
||||
#: telebot.service_utils.is_pil_image telebot.util.antiflood
|
||||
#: telebot.util.escape telebot.util.extract_arguments
|
||||
#: telebot.util.extract_command telebot.util.is_command
|
||||
#: telebot.util.parse_web_app_data telebot.util.quick_markup
|
||||
#: telebot.util.smart_split telebot.util.split_string telebot.util.user_link
|
||||
#: telebot.util.validate_web_app_data telebot.util.webhook_google_functions
|
||||
msgid "Parameters"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.antiflood:10
|
||||
msgid "The function to call"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.antiflood:13
|
||||
msgid "Number of retries to send"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.antiflood:16
|
||||
msgid "The arguments to pass to the function"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.antiflood:19
|
||||
msgid "The keyword arguments to pass to the function"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.service_utils.generate_random_token
|
||||
#: telebot.service_utils.is_bytes telebot.service_utils.is_dict
|
||||
#: telebot.service_utils.is_pil_image telebot.util.antiflood
|
||||
#: telebot.util.escape telebot.util.extract_arguments
|
||||
#: telebot.util.extract_command telebot.util.is_command
|
||||
#: telebot.util.parse_web_app_data telebot.util.quick_markup
|
||||
#: telebot.util.smart_split telebot.util.split_string telebot.util.user_link
|
||||
#: telebot.util.validate_web_app_data telebot.util.webhook_google_functions
|
||||
msgid "Returns"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.antiflood:22
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.service_utils.chunks:1
|
||||
msgid "Yield successive n-sized chunks from lst."
|
||||
msgstr ""
|
||||
|
||||
#: ../../docstring of telebot.util.content_type_media:1
|
||||
msgid "Contains all media content types."
|
||||
msgstr ""
|
||||
|
||||
#: ../../docstring of telebot.util.content_type_service:1
|
||||
msgid "Contains all service content types such as `User joined the group`."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.escape:1
|
||||
msgid ""
|
||||
"Replaces the following chars in `text` ('&' with '&', '<' with '<'"
|
||||
" and '>' with '>')."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.escape:3
|
||||
msgid "the text to escape"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.escape:4
|
||||
msgid "the escaped text"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.extract_arguments:1
|
||||
msgid "Returns the argument after the command."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.extract_arguments:3 telebot.util.extract_command:4
|
||||
msgid "Examples:"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.extract_arguments:10
|
||||
msgid "String to extract the arguments from a command"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.extract_arguments:13
|
||||
msgid "the arguments if `text` is a command (according to is_command), else None."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.service_utils.generate_random_token
|
||||
#: telebot.service_utils.is_bytes telebot.service_utils.is_dict
|
||||
#: telebot.service_utils.is_pil_image telebot.util.extract_arguments
|
||||
#: telebot.util.extract_command telebot.util.is_command
|
||||
#: telebot.util.quick_markup telebot.util.smart_split telebot.util.split_string
|
||||
#: telebot.util.user_link
|
||||
msgid "Return type"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.extract_arguments:14 telebot.util.extract_command:16
|
||||
msgid ":obj:`str` or :obj:`None`"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.extract_command:1
|
||||
msgid ""
|
||||
"Extracts the command from `text` (minus the '/') if `text` is a command "
|
||||
"(see is_command). If `text` is not a command, this function returns None."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.extract_command:12
|
||||
msgid "String to extract the command from"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.extract_command:15
|
||||
msgid "the command if `text` is a command (according to is_command), else None."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.service_utils.generate_random_token:1
|
||||
msgid ""
|
||||
"Generates a random token consisting of letters and digits, 16 characters "
|
||||
"long."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.service_utils.generate_random_token:3
|
||||
msgid "a random token"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.service_utils.generate_random_token:4 telebot.util.user_link:22
|
||||
msgid ":obj:`str`"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.service_utils.is_bytes:1
|
||||
msgid "Returns True if the given object is a bytes object."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.service_utils.is_bytes:3 telebot.service_utils.is_dict:3
|
||||
#: telebot.service_utils.is_pil_image:3
|
||||
msgid "object to be checked"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.service_utils.is_bytes:6
|
||||
msgid "True if the given object is a bytes object."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.service_utils.is_bytes:7 telebot.service_utils.is_dict:7
|
||||
#: telebot.service_utils.is_pil_image:7 telebot.util.is_command:7
|
||||
msgid ":obj:`bool`"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.is_command:1
|
||||
msgid ""
|
||||
"Checks if `text` is a command. Telegram chat commands start with the '/' "
|
||||
"character."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.is_command:3
|
||||
msgid "Text to check."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.is_command:6
|
||||
msgid "True if `text` is a command, else False."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.service_utils.is_dict:1
|
||||
msgid "Returns True if the given object is a dictionary."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.service_utils.is_dict:6
|
||||
msgid "True if the given object is a dictionary."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.service_utils.is_pil_image:1
|
||||
msgid "Returns True if the given object is a PIL.Image.Image object."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.service_utils.is_pil_image:6
|
||||
msgid "True if the given object is a PIL.Image.Image object."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.service_utils.is_string:1
|
||||
msgid "Returns True if the given object is a string."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.parse_web_app_data:1
|
||||
msgid "Parses web app data."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.parse_web_app_data:3 telebot.util.validate_web_app_data:3
|
||||
msgid "The bot token"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.parse_web_app_data:6 telebot.util.validate_web_app_data:6
|
||||
msgid "The raw init data"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.parse_web_app_data:9 telebot.util.validate_web_app_data:9
|
||||
msgid "The parsed init data"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.quick_markup:1
|
||||
msgid ""
|
||||
"Returns a reply markup from a dict in this format: {'text': kwargs} This "
|
||||
"is useful to avoid always typing 'btn1 = InlineKeyboardButton(...)' 'btn2"
|
||||
" = InlineKeyboardButton(...)'"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.quick_markup:4 telebot.util.user_link:5
|
||||
msgid "Example:"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.quick_markup:6
|
||||
msgid "Using quick_markup:"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.quick_markup:31
|
||||
msgid ""
|
||||
"a dict containing all buttons to create in this format: {text: kwargs} "
|
||||
"{str:}"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.quick_markup:34
|
||||
msgid "number of :class:`telebot.types.InlineKeyboardButton` objects on each row"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.quick_markup:37
|
||||
msgid "InlineKeyboardMarkup"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.quick_markup:38
|
||||
msgid ":obj:`types.InlineKeyboardMarkup`"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.smart_split:1
|
||||
msgid ""
|
||||
"Splits one string into multiple strings, with a maximum amount of "
|
||||
"`chars_per_string` characters per string. This is very useful for "
|
||||
"splitting one giant message into multiples. If `chars_per_string` > 4096:"
|
||||
" `chars_per_string` = 4096. Splits by '\\n', '. ' or ' ' in exactly this "
|
||||
"priority."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.smart_split:6 telebot.util.split_string:4
|
||||
msgid "The text to split"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.smart_split:9
|
||||
msgid "The number of maximum characters per part the text is split to."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.smart_split:12 telebot.util.split_string:10
|
||||
msgid "The splitted text as a list of strings."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.smart_split:13 telebot.util.split_string:11
|
||||
msgid ":obj:`list` of :obj:`str`"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.split_string:1
|
||||
msgid ""
|
||||
"Splits one string into multiple strings, with a maximum amount of "
|
||||
"`chars_per_string` characters per string. This is very useful for "
|
||||
"splitting one giant message into multiples."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.split_string:7
|
||||
msgid "The number of characters per line the text is split into."
|
||||
msgstr ""
|
||||
|
||||
#: ../../docstring of telebot.util.update_types:1
|
||||
msgid "All update types, should be used for allowed_updates parameter in polling."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.user_link:1
|
||||
msgid ""
|
||||
"Returns an HTML user link. This is useful for reports. Attention: Don't "
|
||||
"forget to set parse_mode to 'HTML'!"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.user_link:11
|
||||
msgid ""
|
||||
"You can use formatting.* for all other formatting options(bold, italic, "
|
||||
"links, and etc.) This method is kept for backward compatibility, and it "
|
||||
"is recommended to use formatting.* for more options."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.user_link:15
|
||||
msgid "the user (not the user_id)"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.user_link:18
|
||||
msgid "include the user_id"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.user_link:21
|
||||
msgid "HTML user link"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.validate_web_app_data:1
|
||||
msgid "Validates web app data."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.webhook_google_functions:1
|
||||
msgid "A webhook endpoint for Google Cloud Functions FaaS."
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.webhook_google_functions:3
|
||||
msgid "The bot instance"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.webhook_google_functions:6
|
||||
msgid "The request object"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.webhook_google_functions:9
|
||||
msgid "The response object"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "int row width"
|
||||
#~ msgstr ""
|
||||
|
6307
docs/source/locales/ru/LC_MESSAGES/async_version.po
Normal file
6307
docs/source/locales/ru/LC_MESSAGES/async_version.po
Normal file
File diff suppressed because it is too large
Load Diff
130
docs/source/locales/ru/LC_MESSAGES/calldata.po
Normal file
130
docs/source/locales/ru/LC_MESSAGES/calldata.po
Normal file
|
@ -0,0 +1,130 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) 2022, coder2020official
|
||||
# This file is distributed under the same license as the pyTelegramBotAPI
|
||||
# Documentation package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: pyTelegramBotAPI Documentation \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-11-29 14:44+0400\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.9.1\n"
|
||||
|
||||
#: ../../calldata.rst:4
|
||||
msgid "Callback data factory"
|
||||
msgstr "Фабрика callback data"
|
||||
|
||||
#: ../../calldata.rst:6
|
||||
msgid "Callback data factory in pyTelegramBotAPI"
|
||||
msgstr "Фабрика callback data в pyTelegramBotAPI"
|
||||
|
||||
#: ../../calldata.rst:6
|
||||
msgid ""
|
||||
"ptba, pytba, pyTelegramBotAPI, callbackdatafactory, guide, callbackdata, "
|
||||
"factory"
|
||||
msgstr ""
|
||||
"ptba, pytba, pyTelegramBotAPI, callbackdatafactory, гайд, callbackdata, "
|
||||
"фабрика"
|
||||
|
||||
#: ../../calldata.rst:12
|
||||
msgid "callback\\_data file"
|
||||
msgstr "Файл callback\\_data"
|
||||
|
||||
#: of telebot.callback_data:1
|
||||
msgid "Callback data factory's file."
|
||||
msgstr "Файл фабрики callback data."
|
||||
|
||||
#: of telebot.callback_data.CallbackData:1
|
||||
#: telebot.callback_data.CallbackDataFilter:1
|
||||
msgid "Bases: :py:class:`object`"
|
||||
msgstr "Базовые классы: :py:class:`object`"
|
||||
|
||||
#: of telebot.callback_data.CallbackData:1
|
||||
msgid "Callback data factory This class will help you to work with CallbackQuery"
|
||||
msgstr "Фабрика Callback data. Этот класс поможет вам в работе с CallbackQuery"
|
||||
|
||||
#: of telebot.callback_data.CallbackData.filter:1
|
||||
msgid "Generate filter"
|
||||
msgstr "Сгенерировать фильтр"
|
||||
|
||||
#: of telebot.callback_data.CallbackData.filter
|
||||
#: telebot.callback_data.CallbackData.new
|
||||
#: telebot.callback_data.CallbackData.parse
|
||||
#: telebot.callback_data.CallbackDataFilter.check
|
||||
msgid "Parameters"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.callback_data.CallbackData.filter:3
|
||||
msgid "specified named parameters will be checked with CallbackQuery.data"
|
||||
msgstr "заданные именованные параметры будут проверены в CallbackQuery.data"
|
||||
|
||||
#: of telebot.callback_data.CallbackData.filter
|
||||
#: telebot.callback_data.CallbackData.new
|
||||
#: telebot.callback_data.CallbackData.parse
|
||||
#: telebot.callback_data.CallbackDataFilter.check
|
||||
msgid "Returns"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.callback_data.CallbackData.filter:4
|
||||
msgid "CallbackDataFilter class"
|
||||
msgstr "Класс CallbackDataFilter"
|
||||
|
||||
#: of telebot.callback_data.CallbackData.new:1
|
||||
msgid "Generate callback data"
|
||||
msgstr "Сгенерировать callback data"
|
||||
|
||||
#: of telebot.callback_data.CallbackData.new:3
|
||||
msgid "positional parameters of CallbackData instance parts"
|
||||
msgstr "позиционные параметры экземпляра CallbackData"
|
||||
|
||||
#: of telebot.callback_data.CallbackData.new:4
|
||||
msgid "named parameters"
|
||||
msgstr "именованные параметры"
|
||||
|
||||
#: of telebot.callback_data.CallbackData.new:5
|
||||
msgid "str"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.callback_data.CallbackData.parse:1
|
||||
msgid "Parse data from the callback data"
|
||||
msgstr "Получить данные из callback data"
|
||||
|
||||
#: of telebot.callback_data.CallbackData.parse:3
|
||||
msgid ""
|
||||
"string, use to telebot.types.CallbackQuery to parse it from string to a "
|
||||
"dict"
|
||||
msgstr ""
|
||||
"string, примените к telebot.types.CallbackQuery, чтобы преобразовать "
|
||||
"callback_data из строки (str) в словарь (dict)"
|
||||
|
||||
#: of telebot.callback_data.CallbackData.parse:4
|
||||
msgid "dict parsed from callback data"
|
||||
msgstr "словарь (dict), полученный из callback data"
|
||||
|
||||
#: of telebot.callback_data.CallbackDataFilter:1
|
||||
msgid "Filter for CallbackData."
|
||||
msgstr "Фильтр для CallbackData."
|
||||
|
||||
#: of telebot.callback_data.CallbackDataFilter.check:1
|
||||
msgid "Checks if query.data appropriates to specified config"
|
||||
msgstr "Проверяет, соответствует ли query.data заданной конфигурации"
|
||||
|
||||
#: of telebot.callback_data.CallbackDataFilter.check:3
|
||||
msgid "telebot.types.CallbackQuery"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.callback_data.CallbackDataFilter.check:6
|
||||
msgid "True if query.data appropriates to specified config"
|
||||
msgstr "True, если query.data соответствует заданной конфигурации"
|
||||
|
||||
#: of telebot.callback_data.CallbackDataFilter.check
|
||||
msgid "Return type"
|
||||
msgstr ""
|
251
docs/source/locales/ru/LC_MESSAGES/formatting.po
Normal file
251
docs/source/locales/ru/LC_MESSAGES/formatting.po
Normal file
|
@ -0,0 +1,251 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) 2022, coder2020official
|
||||
# This file is distributed under the same license as the pyTelegramBotAPI
|
||||
# Documentation package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: pyTelegramBotAPI Documentation \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-11-29 14:44+0400\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.9.1\n"
|
||||
|
||||
#: ../../formatting.rst:3
|
||||
msgid "Formatting options"
|
||||
msgstr "Параметры форматирования"
|
||||
|
||||
#: ../../formatting.rst:5
|
||||
msgid "Formatting options in pyTelegramBotAPI"
|
||||
msgstr "Параметры форматирования в pyTelegramBotAPI"
|
||||
|
||||
#: ../../formatting.rst:5
|
||||
msgid "html, markdown, parse_mode, formatting, ptba, pytba, pyTelegramBotAPI"
|
||||
msgstr "html, markdown, parse_mode, форматирование, ptba, pytba, pyTelegramBotAPI"
|
||||
|
||||
#: of telebot.formatting:1
|
||||
msgid "Markdown & HTML formatting functions."
|
||||
msgstr "Функции форматирования Markdown & HTML."
|
||||
|
||||
#: of telebot.formatting.escape_html:1
|
||||
msgid "Escapes HTML characters in a string of HTML."
|
||||
msgstr "Пропускает HTML символы в HTML строке."
|
||||
|
||||
#: of telebot.formatting.escape_html telebot.formatting.escape_markdown
|
||||
#: telebot.formatting.format_text telebot.formatting.hbold
|
||||
#: telebot.formatting.hcode telebot.formatting.hide_link
|
||||
#: telebot.formatting.hitalic telebot.formatting.hlink telebot.formatting.hpre
|
||||
#: telebot.formatting.hspoiler telebot.formatting.hstrikethrough
|
||||
#: telebot.formatting.hunderline telebot.formatting.mbold
|
||||
#: telebot.formatting.mcode telebot.formatting.mitalic telebot.formatting.mlink
|
||||
#: telebot.formatting.mspoiler telebot.formatting.mstrikethrough
|
||||
#: telebot.formatting.munderline
|
||||
msgid "Parameters"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.escape_html:3
|
||||
msgid "The string of HTML to escape."
|
||||
msgstr "HTML строка, которую нужно пропустить."
|
||||
|
||||
#: of telebot.formatting.escape_html telebot.formatting.escape_markdown
|
||||
#: telebot.formatting.format_text telebot.formatting.hbold
|
||||
#: telebot.formatting.hcode telebot.formatting.hide_link
|
||||
#: telebot.formatting.hitalic telebot.formatting.hlink telebot.formatting.hpre
|
||||
#: telebot.formatting.hspoiler telebot.formatting.hstrikethrough
|
||||
#: telebot.formatting.hunderline telebot.formatting.mbold
|
||||
#: telebot.formatting.mcode telebot.formatting.mitalic telebot.formatting.mlink
|
||||
#: telebot.formatting.mspoiler telebot.formatting.mstrikethrough
|
||||
#: telebot.formatting.munderline
|
||||
msgid "Returns"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.escape_html:6 telebot.formatting.escape_markdown:8
|
||||
msgid "The escaped string."
|
||||
msgstr "Пропускаемая строка."
|
||||
|
||||
#: of telebot.formatting.escape_html telebot.formatting.escape_markdown
|
||||
#: telebot.formatting.format_text telebot.formatting.hbold
|
||||
#: telebot.formatting.hcode telebot.formatting.hide_link
|
||||
#: telebot.formatting.hitalic telebot.formatting.hlink telebot.formatting.hpre
|
||||
#: telebot.formatting.hspoiler telebot.formatting.hstrikethrough
|
||||
#: telebot.formatting.hunderline telebot.formatting.mbold
|
||||
#: telebot.formatting.mcode telebot.formatting.mitalic telebot.formatting.mlink
|
||||
#: telebot.formatting.mspoiler telebot.formatting.mstrikethrough
|
||||
#: telebot.formatting.munderline
|
||||
msgid "Return type"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.escape_html:7 telebot.formatting.escape_markdown:9
|
||||
#: telebot.formatting.format_text:17 telebot.formatting.hbold:10
|
||||
#: telebot.formatting.hcode:10 telebot.formatting.hide_link:7
|
||||
#: telebot.formatting.hitalic:10 telebot.formatting.hlink:13
|
||||
#: telebot.formatting.hpre:10 telebot.formatting.hspoiler:10
|
||||
#: telebot.formatting.hstrikethrough:10 telebot.formatting.hunderline:10
|
||||
#: telebot.formatting.mbold:10 telebot.formatting.mcode:10
|
||||
#: telebot.formatting.mitalic:10 telebot.formatting.mlink:13
|
||||
#: telebot.formatting.mspoiler:10 telebot.formatting.mstrikethrough:10
|
||||
#: telebot.formatting.munderline:10
|
||||
msgid ":obj:`str`"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.escape_markdown:1
|
||||
msgid "Escapes Markdown characters in a string of Markdown."
|
||||
msgstr "Пропускает Markdown символы в Markdown строке."
|
||||
|
||||
#: of telebot.formatting.escape_markdown:3
|
||||
msgid "Credits to: simonsmh"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.formatting.escape_markdown:5
|
||||
msgid "The string of Markdown to escape."
|
||||
msgstr "Markdown строка, которую нужно пропустить."
|
||||
|
||||
#: of telebot.formatting.format_text:1
|
||||
msgid "Formats a list of strings into a single string."
|
||||
msgstr "Преобразовывает набор строк в одну."
|
||||
|
||||
#: of telebot.formatting.format_text:10
|
||||
msgid "Strings to format."
|
||||
msgstr "Строки для преобразования."
|
||||
|
||||
#: of telebot.formatting.format_text:13
|
||||
msgid "The separator to use between each string."
|
||||
msgstr "Символ для разделения строк."
|
||||
|
||||
#: of telebot.formatting.format_text:16 telebot.formatting.hbold:9
|
||||
#: telebot.formatting.hcode:9 telebot.formatting.hitalic:9
|
||||
#: telebot.formatting.hlink:12 telebot.formatting.hpre:9
|
||||
#: telebot.formatting.hspoiler:9 telebot.formatting.hstrikethrough:9
|
||||
#: telebot.formatting.hunderline:9 telebot.formatting.mbold:9
|
||||
#: telebot.formatting.mcode:9 telebot.formatting.mitalic:9
|
||||
#: telebot.formatting.mlink:12 telebot.formatting.mspoiler:9
|
||||
#: telebot.formatting.mstrikethrough:9 telebot.formatting.munderline:9
|
||||
msgid "The formatted string."
|
||||
msgstr "Преобразованная строка."
|
||||
|
||||
#: of telebot.formatting.hbold:1
|
||||
msgid "Returns an HTML-formatted bold string."
|
||||
msgstr "Возвращает выделенную жирным шрифтом HTML строку."
|
||||
|
||||
#: of telebot.formatting.hbold:3 telebot.formatting.mbold:3
|
||||
msgid "The string to bold."
|
||||
msgstr "Строка для выделения жирным шрифтом."
|
||||
|
||||
#: of telebot.formatting.hbold:6 telebot.formatting.hcode:6
|
||||
#: telebot.formatting.hitalic:6 telebot.formatting.hlink:9
|
||||
#: telebot.formatting.hpre:6 telebot.formatting.hspoiler:6
|
||||
#: telebot.formatting.hstrikethrough:6 telebot.formatting.hunderline:6
|
||||
#: telebot.formatting.mbold:6 telebot.formatting.mcode:6
|
||||
#: telebot.formatting.mitalic:6 telebot.formatting.mlink:9
|
||||
#: telebot.formatting.mspoiler:6 telebot.formatting.mstrikethrough:6
|
||||
#: telebot.formatting.munderline:6
|
||||
msgid "True if you need to escape special characters. Defaults to True."
|
||||
msgstr "True если вам нужно пропустить спец. символы. По умолчанию True."
|
||||
|
||||
#: of telebot.formatting.hcode:1
|
||||
msgid "Returns an HTML-formatted code string."
|
||||
msgstr "Возвращает выделенную как код HTML строку."
|
||||
|
||||
#: of telebot.formatting.hcode:3 telebot.formatting.mcode:3
|
||||
msgid "The string to code."
|
||||
msgstr "Строка для выделения как код."
|
||||
|
||||
#: of telebot.formatting.hide_link:1
|
||||
msgid "Hide url of an image."
|
||||
msgstr "Делает невидимым URL изображения."
|
||||
|
||||
#: of telebot.formatting.hide_link:3
|
||||
msgid "The url of the image."
|
||||
msgstr "URL изображения."
|
||||
|
||||
#: of telebot.formatting.hide_link:6
|
||||
msgid "The hidden url."
|
||||
msgstr "Невидимый URL."
|
||||
|
||||
#: of telebot.formatting.hitalic:1
|
||||
msgid "Returns an HTML-formatted italic string."
|
||||
msgstr "Возвращает выделенную курсивом HTML строку."
|
||||
|
||||
#: of telebot.formatting.hitalic:3 telebot.formatting.mitalic:3
|
||||
msgid "The string to italicize."
|
||||
msgstr "Строка для выделения курсивом."
|
||||
|
||||
#: of telebot.formatting.hlink:1
|
||||
msgid "Returns an HTML-formatted link string."
|
||||
msgstr "Возвращает HTML строку с гиперссылкой."
|
||||
|
||||
#: of telebot.formatting.hlink:3 telebot.formatting.mlink:3
|
||||
msgid "The string to link."
|
||||
msgstr "Строка для добавления гиперссылки."
|
||||
|
||||
#: of telebot.formatting.hlink:6 telebot.formatting.mlink:6
|
||||
msgid "The URL to link to."
|
||||
msgstr "URL для создания гиперссылки."
|
||||
|
||||
#: of telebot.formatting.hpre:1
|
||||
msgid "Returns an HTML-formatted preformatted string."
|
||||
msgstr "Возвращает предварительно отформатированную HTML строку."
|
||||
|
||||
#: of telebot.formatting.hpre:3
|
||||
msgid "The string to preformatted."
|
||||
msgstr "Строка для предварительного форматирования."
|
||||
|
||||
#: of telebot.formatting.hspoiler:1
|
||||
msgid "Returns an HTML-formatted spoiler string."
|
||||
msgstr "Возвращает выделенную как спойлер HTML строку."
|
||||
|
||||
#: of telebot.formatting.hspoiler:3 telebot.formatting.mspoiler:3
|
||||
msgid "The string to spoiler."
|
||||
msgstr "Строка для выделения как спойлер."
|
||||
|
||||
#: of telebot.formatting.hstrikethrough:1
|
||||
msgid "Returns an HTML-formatted strikethrough string."
|
||||
msgstr "Возвращает зачеркнутую HTML строку."
|
||||
|
||||
#: of telebot.formatting.hstrikethrough:3 telebot.formatting.mstrikethrough:3
|
||||
msgid "The string to strikethrough."
|
||||
msgstr "Строка для зачеркивания."
|
||||
|
||||
#: of telebot.formatting.hunderline:1
|
||||
msgid "Returns an HTML-formatted underline string."
|
||||
msgstr "Возвращает подчеркнутую HTML строку."
|
||||
|
||||
#: of telebot.formatting.hunderline:3 telebot.formatting.munderline:3
|
||||
msgid "The string to underline."
|
||||
msgstr "Строка для подчёркивания."
|
||||
|
||||
#: of telebot.formatting.mbold:1
|
||||
msgid "Returns a Markdown-formatted bold string."
|
||||
msgstr "Возвращает выделенную жирным шрифтом Markdown строку."
|
||||
|
||||
#: of telebot.formatting.mcode:1
|
||||
msgid "Returns a Markdown-formatted code string."
|
||||
msgstr "Возвращает выделенную как код Markdown строку."
|
||||
|
||||
#: of telebot.formatting.mitalic:1
|
||||
msgid "Returns a Markdown-formatted italic string."
|
||||
msgstr "Возвращает выделенную курсивом Markdown строку."
|
||||
|
||||
#: of telebot.formatting.mlink:1
|
||||
msgid "Returns a Markdown-formatted link string."
|
||||
msgstr "Возвращает Markdown строку с гиперссылкой."
|
||||
|
||||
#: of telebot.formatting.mspoiler:1
|
||||
msgid "Returns a Markdown-formatted spoiler string."
|
||||
msgstr "Возвращает выделенную как спойлер Markdown строку."
|
||||
|
||||
#: of telebot.formatting.mstrikethrough:1
|
||||
msgid "Returns a Markdown-formatted strikethrough string."
|
||||
msgstr "Возвращает зачеркнутую Markdown строку."
|
||||
|
||||
#: of telebot.formatting.munderline:1
|
||||
msgid "Returns a Markdown-formatted underline string."
|
||||
msgstr "Возвращает подчеркнутую Markdown строку."
|
||||
|
128
docs/source/locales/ru/LC_MESSAGES/index.po
Normal file
128
docs/source/locales/ru/LC_MESSAGES/index.po
Normal file
|
@ -0,0 +1,128 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) 2022, coder2020official
|
||||
# This file is distributed under the same license as the pyTelegramBotAPI
|
||||
# Documentation package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: pyTelegramBotAPI Documentation \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-11-29 14:44+0400\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.9.1\n"
|
||||
|
||||
#: ../../index.rst:8
|
||||
msgid "Welcome to pyTelegramBotAPI's documentation!"
|
||||
msgstr "Добро пожаловать в документацию pyTelegramBotAPI!"
|
||||
|
||||
#: ../../index.rst:10
|
||||
msgid "Official documentation of pyTelegramBotAPI"
|
||||
msgstr "Официальная документация pyTelegramBotAPI"
|
||||
|
||||
#: ../../index.rst:10
|
||||
msgid "ptba, pytba, pyTelegramBotAPI, documentation, guide"
|
||||
msgstr "ptba, pytba, pyTelegramBotAPI, документация, гайд"
|
||||
|
||||
#: ../../index.rst:17
|
||||
msgid "TeleBot"
|
||||
msgstr ""
|
||||
|
||||
#: ../../index.rst:18
|
||||
msgid ""
|
||||
"TeleBot is synchronous and asynchronous implementation of `Telegram Bot "
|
||||
"API <https://core.telegram.org/bots/api>`_."
|
||||
msgstr ""
|
||||
"TeleBot это синхронная и асинхронная реализация `Telegram Bot "
|
||||
"API <https://core.telegram.org/bots/api>`_."
|
||||
|
||||
#: ../../index.rst:21
|
||||
msgid "Chats"
|
||||
msgstr "Чаты"
|
||||
|
||||
#: ../../index.rst:22
|
||||
msgid ""
|
||||
"English chat: `Private chat "
|
||||
"<https://telegram.me/joinchat/Bn4ixj84FIZVkwhk2jag6A>`__"
|
||||
msgstr ""
|
||||
"Англоязычный чат: `Private chat "
|
||||
"<https://telegram.me/joinchat/Bn4ixj84FIZVkwhk2jag6A>`__"
|
||||
|
||||
#: ../../index.rst:24
|
||||
msgid ""
|
||||
"Russian chat: `@pytelegrambotapi_talks_ru "
|
||||
"<https://t.me/pytelegrambotapi_talks_ru>`__"
|
||||
msgstr ""
|
||||
"Русскоязычный чат: `@pytelegrambotapi_talks_ru "
|
||||
"<https://t.me/pytelegrambotapi_talks_ru>`__"
|
||||
|
||||
#: ../../index.rst:26
|
||||
msgid "News: `@pyTelegramBotAPI <https://t.me/pytelegrambotapi>`__"
|
||||
msgstr "Новости: `@pyTelegramBotAPI <https://t.me/pytelegrambotapi>`__"
|
||||
|
||||
#: ../../index.rst:28
|
||||
msgid "Pypi: `Pypi <https://pypi.org/project/pyTelegramBotAPI/>`__"
|
||||
msgstr ""
|
||||
|
||||
#: ../../index.rst:30
|
||||
msgid ""
|
||||
"Source: `Github repository "
|
||||
"<https://github.com/eternnoir/pyTelegramBotAPI>`__"
|
||||
msgstr ""
|
||||
"Исходники: `Github repository "
|
||||
"<https://github.com/eternnoir/pyTelegramBotAPI>`__"
|
||||
|
||||
#: ../../index.rst:33
|
||||
msgid "Some features:"
|
||||
msgstr "Некоторые особенности:"
|
||||
|
||||
#: ../../index.rst:34
|
||||
msgid "Easy to learn and use."
|
||||
msgstr "Простой в изучении и использовании."
|
||||
|
||||
#: ../../index.rst:36
|
||||
msgid "Easy to understand."
|
||||
msgstr "Простой в понимании."
|
||||
|
||||
#: ../../index.rst:38
|
||||
msgid "Both sync and async."
|
||||
msgstr "И синхронный, и асинхронный."
|
||||
|
||||
#: ../../index.rst:40
|
||||
msgid "Examples on features."
|
||||
msgstr "Примеры возможностей."
|
||||
|
||||
#: ../../index.rst:42
|
||||
msgid "States"
|
||||
msgstr "Состояния (стейты, FSM)"
|
||||
|
||||
#: ../../index.rst:44
|
||||
msgid "And more..."
|
||||
msgstr "И другое..."
|
||||
|
||||
#: ../../index.rst:47
|
||||
msgid "Content"
|
||||
msgstr "Содержимое"
|
||||
|
||||
#: ../../index.rst:63
|
||||
msgid "Indices and tables"
|
||||
msgstr "Ссылки"
|
||||
|
||||
#: ../../index.rst:65
|
||||
msgid ":ref:`genindex`"
|
||||
msgstr ""
|
||||
|
||||
#: ../../index.rst:66
|
||||
msgid ":ref:`modindex`"
|
||||
msgstr ""
|
||||
|
||||
#: ../../index.rst:67
|
||||
msgid ":ref:`search`"
|
||||
msgstr ""
|
||||
|
59
docs/source/locales/ru/LC_MESSAGES/install.po
Normal file
59
docs/source/locales/ru/LC_MESSAGES/install.po
Normal file
|
@ -0,0 +1,59 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) 2022, coder2020official
|
||||
# This file is distributed under the same license as the pyTelegramBotAPI
|
||||
# Documentation package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: pyTelegramBotAPI Documentation \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-11-29 14:44+0400\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.9.1\n"
|
||||
|
||||
#: ../../install.rst:3
|
||||
msgid "Installation Guide"
|
||||
msgstr "Гайд по установке"
|
||||
|
||||
#: ../../install.rst:5
|
||||
msgid "Installation of pyTelegramBotAPI"
|
||||
msgstr "Установка pyTelegramBotAPI"
|
||||
|
||||
#: ../../install.rst:5
|
||||
msgid "ptba, pytba, pyTelegramBotAPI, installation, guide"
|
||||
msgstr "ptba, pytba, pyTelegramBotAPI, установка, гайд"
|
||||
|
||||
#: ../../install.rst:11
|
||||
msgid "Using PIP"
|
||||
msgstr "Используя PIP"
|
||||
|
||||
#: ../../install.rst:17
|
||||
msgid "Using pipenv"
|
||||
msgstr "Используя pipenv"
|
||||
|
||||
#: ../../install.rst:23
|
||||
msgid "By cloning repository"
|
||||
msgstr "Клонируя репозиторий"
|
||||
|
||||
#: ../../install.rst:31
|
||||
msgid "Directly using pip"
|
||||
msgstr "Напрямую используя pip"
|
||||
|
||||
#: ../../install.rst:37
|
||||
msgid "It is generally recommended to use the first option."
|
||||
msgstr "Рекомендуется использовать первый вариант."
|
||||
|
||||
#: ../../install.rst:39
|
||||
msgid ""
|
||||
"While the API is production-ready, it is still under development and it "
|
||||
"has regular updates, do not forget to update it regularly by calling:"
|
||||
msgstr "Новые версии библиотеки имеют больше фич, улучшений и баг фиксов. Не забывайте"
|
||||
" обновляться вызывая:"
|
||||
|
40
docs/source/locales/ru/LC_MESSAGES/quick_start.po
Normal file
40
docs/source/locales/ru/LC_MESSAGES/quick_start.po
Normal file
|
@ -0,0 +1,40 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) 2022, coder2020official
|
||||
# This file is distributed under the same license as the pyTelegramBotAPI
|
||||
# Documentation package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: pyTelegramBotAPI Documentation \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-11-29 14:44+0400\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.9.1\n"
|
||||
|
||||
#: ../../quick_start.rst:4
|
||||
msgid "Quick start"
|
||||
msgstr "Быстрый старт"
|
||||
|
||||
#: ../../quick_start.rst:6
|
||||
msgid "Quickstart guide"
|
||||
msgstr "Быстрый старт - гайд"
|
||||
|
||||
#: ../../quick_start.rst:6
|
||||
msgid "ptba, pytba, pyTelegramBotAPI, quickstart, guide"
|
||||
msgstr "ptba, pytba, pyTelegramBotAPI, быстрый старт, гайд"
|
||||
|
||||
#: ../../quick_start.rst:11
|
||||
msgid "Synchronous TeleBot"
|
||||
msgstr "Синхронный телебот"
|
||||
|
||||
#: ../../quick_start.rst:16
|
||||
msgid "Asynchronous TeleBot"
|
||||
msgstr "Асинхронный телебот"
|
||||
|
6504
docs/source/locales/ru/LC_MESSAGES/sync_version.po
Normal file
6504
docs/source/locales/ru/LC_MESSAGES/sync_version.po
Normal file
File diff suppressed because it is too large
Load Diff
6111
docs/source/locales/ru/LC_MESSAGES/types.po
Normal file
6111
docs/source/locales/ru/LC_MESSAGES/types.po
Normal file
File diff suppressed because it is too large
Load Diff
393
docs/source/locales/ru/LC_MESSAGES/util.po
Normal file
393
docs/source/locales/ru/LC_MESSAGES/util.po
Normal file
|
@ -0,0 +1,393 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) 2022, coder2020official
|
||||
# This file is distributed under the same license as the pyTelegramBotAPI
|
||||
# Documentation package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: pyTelegramBotAPI Documentation \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-07-08 23:07+0500\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.9.1\n"
|
||||
|
||||
#: ../../source/util.rst:3
|
||||
msgid "Utils"
|
||||
msgstr "Утилиты"
|
||||
|
||||
#: ../../source/util.rst:5
|
||||
msgid "Utils in pyTelegramBotAPI"
|
||||
msgstr "Утилиты в pyTelegramBotAPI"
|
||||
|
||||
#: ../../source/util.rst:5
|
||||
msgid "ptba, pytba, pyTelegramBotAPI, utils, guide"
|
||||
msgstr "ptba, pytba, pyTelegramBotAPI, утилиты, гайд"
|
||||
|
||||
#: ../../source/util.rst:11
|
||||
msgid "util file"
|
||||
msgstr "Файл util"
|
||||
|
||||
#: of telebot.util.antiflood:1
|
||||
msgid ""
|
||||
"Use this function inside loops in order to avoid getting TooManyRequests "
|
||||
"error. Example:"
|
||||
msgstr ""
|
||||
"Используйте эту функцию в циклах, чтобы избежать ошибки TooManyRequests. "
|
||||
"Пример:"
|
||||
|
||||
#: of telebot.service_utils.is_bytes telebot.service_utils.is_dict
|
||||
#: telebot.service_utils.is_pil_image telebot.util.antiflood
|
||||
#: telebot.util.escape telebot.util.extract_arguments
|
||||
#: telebot.util.extract_command telebot.util.is_command
|
||||
#: telebot.util.parse_web_app_data telebot.util.quick_markup
|
||||
#: telebot.util.smart_split telebot.util.split_string telebot.util.user_link
|
||||
#: telebot.util.validate_web_app_data telebot.util.webhook_google_functions
|
||||
msgid "Parameters"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.antiflood:10
|
||||
msgid "The function to call"
|
||||
msgstr "Вызываемая функция"
|
||||
|
||||
#: of telebot.util.antiflood:13
|
||||
msgid "Number of retries to send"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.antiflood:16
|
||||
msgid "The arguments to pass to the function"
|
||||
msgstr "Аргументы, для передачи в функцию"
|
||||
|
||||
#: of telebot.util.antiflood:19
|
||||
msgid "The keyword arguments to pass to the function"
|
||||
msgstr "Именованные аргументы для передачи в функцию"
|
||||
|
||||
#: of telebot.service_utils.generate_random_token
|
||||
#: telebot.service_utils.is_bytes telebot.service_utils.is_dict
|
||||
#: telebot.service_utils.is_pil_image telebot.util.antiflood
|
||||
#: telebot.util.escape telebot.util.extract_arguments
|
||||
#: telebot.util.extract_command telebot.util.is_command
|
||||
#: telebot.util.parse_web_app_data telebot.util.quick_markup
|
||||
#: telebot.util.smart_split telebot.util.split_string telebot.util.user_link
|
||||
#: telebot.util.validate_web_app_data telebot.util.webhook_google_functions
|
||||
msgid "Returns"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.antiflood:22
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.service_utils.chunks:1
|
||||
msgid "Yield successive n-sized chunks from lst."
|
||||
msgstr "Генерирует последовательные части списка, состоящие из n элементов."
|
||||
|
||||
#: ../../docstring of telebot.util.content_type_media:1
|
||||
msgid "Contains all media content types."
|
||||
msgstr "Содержит все виды медиа."
|
||||
|
||||
#: ../../docstring of telebot.util.content_type_service:1
|
||||
msgid "Contains all service content types such as `User joined the group`."
|
||||
msgstr "Содержит все виды сервисных сообщений, такие как `User joined the group`."
|
||||
|
||||
#: of telebot.util.escape:1
|
||||
msgid ""
|
||||
"Replaces the following chars in `text` ('&' with '&', '<' with '<'"
|
||||
" and '>' with '>')."
|
||||
msgstr ""
|
||||
"Заменяет следующие символы в `text` ('&' на '&', '<' на '<' и '>' "
|
||||
"на '>')."
|
||||
|
||||
#: of telebot.util.escape:3
|
||||
msgid "the text to escape"
|
||||
msgstr "Текст для замены символов"
|
||||
|
||||
#: of telebot.util.escape:4
|
||||
msgid "the escaped text"
|
||||
msgstr "Отформатированный текст"
|
||||
|
||||
#: of telebot.util.extract_arguments:1
|
||||
msgid "Returns the argument after the command."
|
||||
msgstr "Возвращает аргументы команды."
|
||||
|
||||
#: of telebot.util.extract_arguments:3 telebot.util.extract_command:4
|
||||
msgid "Examples:"
|
||||
msgstr "Примеры:"
|
||||
|
||||
#: of telebot.util.extract_arguments:10
|
||||
msgid "String to extract the arguments from a command"
|
||||
msgstr "Строка для извлечения аргументов команды"
|
||||
|
||||
#: of telebot.util.extract_arguments:13
|
||||
msgid "the arguments if `text` is a command (according to is_command), else None."
|
||||
msgstr ""
|
||||
"Аргументы, если `text` является командой (согласно is_command), в "
|
||||
"остальных случаях None."
|
||||
|
||||
#: of telebot.service_utils.generate_random_token
|
||||
#: telebot.service_utils.is_bytes telebot.service_utils.is_dict
|
||||
#: telebot.service_utils.is_pil_image telebot.util.extract_arguments
|
||||
#: telebot.util.extract_command telebot.util.is_command
|
||||
#: telebot.util.quick_markup telebot.util.smart_split telebot.util.split_string
|
||||
#: telebot.util.user_link
|
||||
msgid "Return type"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.extract_arguments:14 telebot.util.extract_command:16
|
||||
msgid ":obj:`str` or :obj:`None`"
|
||||
msgstr ":obj:`str` или :obj:`None`"
|
||||
|
||||
#: of telebot.util.extract_command:1
|
||||
msgid ""
|
||||
"Extracts the command from `text` (minus the '/') if `text` is a command "
|
||||
"(see is_command). If `text` is not a command, this function returns None."
|
||||
msgstr ""
|
||||
"Извлекает команду из `text` (исключает '/') если `text` является командой"
|
||||
" (см. is_command). Если `text` не является командой, эта функция "
|
||||
"возвращает None."
|
||||
|
||||
#: of telebot.util.extract_command:12
|
||||
msgid "String to extract the command from"
|
||||
msgstr "Строка, из которой нужно извлечь команду"
|
||||
|
||||
#: of telebot.util.extract_command:15
|
||||
msgid "the command if `text` is a command (according to is_command), else None."
|
||||
msgstr ""
|
||||
"Команда, если `text` является командой (согласно is_command), в остальных"
|
||||
" случаях None."
|
||||
|
||||
#: of telebot.service_utils.generate_random_token:1
|
||||
msgid ""
|
||||
"Generates a random token consisting of letters and digits, 16 characters "
|
||||
"long."
|
||||
msgstr ""
|
||||
"Генерирует рандомный токен, состоящий из латинских букв и цифр длиной 16 "
|
||||
"символов."
|
||||
|
||||
#: of telebot.service_utils.generate_random_token:3
|
||||
msgid "a random token"
|
||||
msgstr "Сгенерированный токен"
|
||||
|
||||
#: of telebot.service_utils.generate_random_token:4 telebot.util.user_link:22
|
||||
msgid ":obj:`str`"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.service_utils.is_bytes:1
|
||||
msgid "Returns True if the given object is a bytes object."
|
||||
msgstr "Возвращает True если полученный объект является bytes."
|
||||
|
||||
#: of telebot.service_utils.is_bytes:3 telebot.service_utils.is_dict:3
|
||||
#: telebot.service_utils.is_pil_image:3
|
||||
msgid "object to be checked"
|
||||
msgstr "Объект для проверки"
|
||||
|
||||
#: of telebot.service_utils.is_bytes:6
|
||||
msgid "True if the given object is a bytes object."
|
||||
msgstr "True, если полученный объект является bytes."
|
||||
|
||||
#: of telebot.service_utils.is_bytes:7 telebot.service_utils.is_dict:7
|
||||
#: telebot.service_utils.is_pil_image:7 telebot.util.is_command:7
|
||||
msgid ":obj:`bool`"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.is_command:1
|
||||
msgid ""
|
||||
"Checks if `text` is a command. Telegram chat commands start with the '/' "
|
||||
"character."
|
||||
msgstr ""
|
||||
"Проверяет, является ли `text` командой. Команды в Telegram начинаются с "
|
||||
"символа '/'."
|
||||
|
||||
#: of telebot.util.is_command:3
|
||||
msgid "Text to check."
|
||||
msgstr "Текст для проверки."
|
||||
|
||||
#: of telebot.util.is_command:6
|
||||
msgid "True if `text` is a command, else False."
|
||||
msgstr "True, если `text` является командой, иначе False."
|
||||
|
||||
#: of telebot.service_utils.is_dict:1
|
||||
msgid "Returns True if the given object is a dictionary."
|
||||
msgstr "Возвращает True, если полученный объект является словарём (dict)."
|
||||
|
||||
#: of telebot.service_utils.is_dict:6
|
||||
msgid "True if the given object is a dictionary."
|
||||
msgstr "True, если полученный объект является словарём (dict)."
|
||||
|
||||
#: of telebot.service_utils.is_pil_image:1
|
||||
msgid "Returns True if the given object is a PIL.Image.Image object."
|
||||
msgstr "Возвращает True, если полученный объект является PIL.Image.Image."
|
||||
|
||||
#: of telebot.service_utils.is_pil_image:6
|
||||
msgid "True if the given object is a PIL.Image.Image object."
|
||||
msgstr "True, если полученный объект является PIL.Image.Image."
|
||||
|
||||
#: of telebot.service_utils.is_string:1
|
||||
msgid "Returns True if the given object is a string."
|
||||
msgstr "Возвращает True, если полученный объект является строкой (str)."
|
||||
|
||||
#: of telebot.util.parse_web_app_data:1
|
||||
msgid "Parses web app data."
|
||||
msgstr "Обрабатывает данные, полученные от web app."
|
||||
|
||||
#: of telebot.util.parse_web_app_data:3 telebot.util.validate_web_app_data:3
|
||||
msgid "The bot token"
|
||||
msgstr "Токен бота"
|
||||
|
||||
#: of telebot.util.parse_web_app_data:6 telebot.util.validate_web_app_data:6
|
||||
msgid "The raw init data"
|
||||
msgstr "Необработанные данные"
|
||||
|
||||
#: of telebot.util.parse_web_app_data:9 telebot.util.validate_web_app_data:9
|
||||
msgid "The parsed init data"
|
||||
msgstr "Обработанные данные"
|
||||
|
||||
#: of telebot.util.quick_markup:1
|
||||
msgid ""
|
||||
"Returns a reply markup from a dict in this format: {'text': kwargs} This "
|
||||
"is useful to avoid always typing 'btn1 = InlineKeyboardButton(...)' 'btn2"
|
||||
" = InlineKeyboardButton(...)'"
|
||||
msgstr ""
|
||||
"Возвращает reply markup из словаря следующего формата: {'text': kwargs}. "
|
||||
"Удобно использовать вместо постоянного использования 'btn1 = "
|
||||
"InlineKeyboardButton(...)' 'btn2 = InlineKeyboardButton(...)'"
|
||||
|
||||
#: of telebot.util.quick_markup:4 telebot.util.user_link:5
|
||||
msgid "Example:"
|
||||
msgstr "Пример:"
|
||||
|
||||
#: of telebot.util.quick_markup:6
|
||||
msgid "Using quick_markup:"
|
||||
msgstr "Используя quick_markup:"
|
||||
|
||||
#: of telebot.util.quick_markup:31
|
||||
msgid ""
|
||||
"a dict containing all buttons to create in this format: {text: kwargs} "
|
||||
"{str:}"
|
||||
msgstr ""
|
||||
"Словарь, содержащий все кнопки для создания reply markup в следующем "
|
||||
"формате: {text: kwargs} {str:}"
|
||||
|
||||
#: of telebot.util.quick_markup:34
|
||||
msgid "number of :class:`telebot.types.InlineKeyboardButton` objects on each row"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.quick_markup:37
|
||||
msgid "InlineKeyboardMarkup"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.quick_markup:38
|
||||
msgid ":obj:`types.InlineKeyboardMarkup`"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.smart_split:1
|
||||
msgid ""
|
||||
"Splits one string into multiple strings, with a maximum amount of "
|
||||
"`chars_per_string` characters per string. This is very useful for "
|
||||
"splitting one giant message into multiples. If `chars_per_string` > 4096:"
|
||||
" `chars_per_string` = 4096. Splits by '\\n', '. ' or ' ' in exactly this "
|
||||
"priority."
|
||||
msgstr ""
|
||||
"Разбивает строку на несколько, каждая из которых будет не длиннее "
|
||||
"`characters_per_string`. Удобно использовать для разбиения одного "
|
||||
"гигантского сообщения на несколько. Если `chars_per_string` > 4096: "
|
||||
"`chars_per_string` = 4096. Разбивает строку по '\\n', '. ' или ' ' именно"
|
||||
" в таком порядке."
|
||||
|
||||
#: of telebot.util.smart_split:6 telebot.util.split_string:4
|
||||
msgid "The text to split"
|
||||
msgstr "Текст для разбиения"
|
||||
|
||||
#: of telebot.util.smart_split:9
|
||||
msgid "The number of maximum characters per part the text is split to."
|
||||
msgstr ""
|
||||
"Максимальное количество символов в части текста, на которые он будет "
|
||||
"разбит."
|
||||
|
||||
#: of telebot.util.smart_split:12 telebot.util.split_string:10
|
||||
msgid "The splitted text as a list of strings."
|
||||
msgstr "Список частей разбитого текста."
|
||||
|
||||
#: of telebot.util.smart_split:13 telebot.util.split_string:11
|
||||
msgid ":obj:`list` of :obj:`str`"
|
||||
msgstr ""
|
||||
|
||||
#: of telebot.util.split_string:1
|
||||
msgid ""
|
||||
"Splits one string into multiple strings, with a maximum amount of "
|
||||
"`chars_per_string` characters per string. This is very useful for "
|
||||
"splitting one giant message into multiples."
|
||||
msgstr ""
|
||||
"Разбивает одну строку на несколько, каждая из которых будет не длиннее "
|
||||
"`characters_per_string`. Удобно использовать для разбиения одного "
|
||||
"гигантского сообщения на несколько."
|
||||
|
||||
#: of telebot.util.split_string:7
|
||||
msgid "The number of characters per line the text is split into."
|
||||
msgstr "Количество символов в одной строке, на которые будет разбит текст."
|
||||
|
||||
#: ../../docstring of telebot.util.update_types:1
|
||||
msgid "All update types, should be used for allowed_updates parameter in polling."
|
||||
msgstr ""
|
||||
"Все виды апдейтов, рекомендуется использовать в качестве параметра "
|
||||
"allowed_updates функции polling."
|
||||
|
||||
#: of telebot.util.user_link:1
|
||||
msgid ""
|
||||
"Returns an HTML user link. This is useful for reports. Attention: Don't "
|
||||
"forget to set parse_mode to 'HTML'!"
|
||||
msgstr ""
|
||||
"Возвращает HTML ссылку на пользователя. Удобно использовать для отчетов. "
|
||||
"Важно: Не забудьте установить значение 'HTML' в parse_mode!"
|
||||
|
||||
#: of telebot.util.user_link:11
|
||||
msgid ""
|
||||
"You can use formatting.* for all other formatting options(bold, italic, "
|
||||
"links, and etc.) This method is kept for backward compatibility, and it "
|
||||
"is recommended to use formatting.* for more options."
|
||||
msgstr ""
|
||||
"Вы можете использовать formatting.* во всех остальных вариантах "
|
||||
"форматирования(bold, italic, links, и прочее). Этот метод сохранён для "
|
||||
"обратной совместимости, рекомендуется использовать formatting.* для "
|
||||
"большего количества вариантов."
|
||||
|
||||
#: of telebot.util.user_link:15
|
||||
msgid "the user (not the user_id)"
|
||||
msgstr "Пользователь (не id пользователя)"
|
||||
|
||||
#: of telebot.util.user_link:18
|
||||
msgid "include the user_id"
|
||||
msgstr "Добавить id пользователя"
|
||||
|
||||
#: of telebot.util.user_link:21
|
||||
msgid "HTML user link"
|
||||
msgstr "Ссылка на пользователя в формате HTML"
|
||||
|
||||
#: of telebot.util.validate_web_app_data:1
|
||||
msgid "Validates web app data."
|
||||
msgstr "Проверяет данные, полученные от web app."
|
||||
|
||||
#: of telebot.util.webhook_google_functions:1
|
||||
msgid "A webhook endpoint for Google Cloud Functions FaaS."
|
||||
msgstr "Endpoint вебхука для Google Cloud Functions FaaS."
|
||||
|
||||
#: of telebot.util.webhook_google_functions:3
|
||||
msgid "The bot instance"
|
||||
msgstr "Инстанс бота"
|
||||
|
||||
#: of telebot.util.webhook_google_functions:6
|
||||
msgid "The request object"
|
||||
msgstr "HTTP-запрос"
|
||||
|
||||
#: of telebot.util.webhook_google_functions:9
|
||||
msgid "The response object"
|
||||
msgstr "Объект, полученный в качестве ответа"
|
||||
|
||||
#~ msgid "int row width"
|
||||
#~ msgstr "Количество кнопок в одной строке, int"
|
||||
|
20
docs/source/quick_start.rst
Normal file
20
docs/source/quick_start.rst
Normal file
|
@ -0,0 +1,20 @@
|
|||
|
||||
===========
|
||||
Quick start
|
||||
===========
|
||||
|
||||
.. meta::
|
||||
:description: Quickstart guide
|
||||
:keywords: ptba, pytba, pyTelegramBotAPI, quickstart, guide
|
||||
|
||||
Synchronous TeleBot
|
||||
-------------------
|
||||
.. literalinclude:: ../../examples/echo_bot.py
|
||||
:language: python
|
||||
|
||||
Asynchronous TeleBot
|
||||
--------------------
|
||||
.. literalinclude:: ../../examples/asynchronous_telebot/echo_bot.py
|
||||
:language: python
|
||||
|
||||
|
41
docs/source/sync_version/index.rst
Normal file
41
docs/source/sync_version/index.rst
Normal file
|
@ -0,0 +1,41 @@
|
|||
===============
|
||||
TeleBot version
|
||||
===============
|
||||
|
||||
.. meta::
|
||||
:description: Synchronous pyTelegramBotAPI documentation
|
||||
:keywords: ptba, pytba, pyTelegramBotAPI, methods, guide, files, sync
|
||||
|
||||
TeleBot methods
|
||||
---------------
|
||||
.. automodule:: telebot
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
custom_filters file
|
||||
------------------------------
|
||||
|
||||
.. automodule:: telebot.custom_filters
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
handler_backends file
|
||||
--------------------------------
|
||||
|
||||
.. automodule:: telebot.handler_backends
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
|
||||
Extensions
|
||||
------------------------
|
||||
|
||||
|
||||
|
||||
.. automodule:: telebot.ext.sync.webhooks
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
10
docs/source/types.rst
Normal file
10
docs/source/types.rst
Normal file
|
@ -0,0 +1,10 @@
|
|||
============
|
||||
Types of API
|
||||
============
|
||||
|
||||
|
||||
|
||||
.. automodule:: telebot.types
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
16
docs/source/util.rst
Normal file
16
docs/source/util.rst
Normal file
|
@ -0,0 +1,16 @@
|
|||
============
|
||||
Utils
|
||||
============
|
||||
|
||||
.. meta::
|
||||
:description: Utils in pyTelegramBotAPI
|
||||
:keywords: ptba, pytba, pyTelegramBotAPI, utils, guide
|
||||
|
||||
|
||||
util file
|
||||
-------------------
|
||||
|
||||
.. automodule:: telebot.util
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
|
@ -9,7 +9,7 @@ import telebot
|
|||
from telebot import types
|
||||
|
||||
# Initialize bot with your token
|
||||
bot = telebot.TeleBot(TOKEN)
|
||||
bot = telebot.TeleBot('TOKEN')
|
||||
|
||||
# The `users` variable is needed to contain chat ids that are either in the search or in the active dialog, like {chat_id, chat_id}
|
||||
users = {}
|
||||
|
@ -47,7 +47,7 @@ def find(message: types.Message):
|
|||
if message.chat.id not in users:
|
||||
bot.send_message(message.chat.id, 'Finding...')
|
||||
|
||||
if freeid == None:
|
||||
if freeid is None:
|
||||
freeid = message.chat.id
|
||||
else:
|
||||
# Question:
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
from telebot import types
|
||||
from telebot.async_telebot import AsyncTeleBot
|
||||
from telebot.asyncio_filters import AdvancedCustomFilter
|
||||
from telebot.callback_data import CallbackData, CallbackDataFilter
|
||||
|
||||
calendar_factory = CallbackData("year", "month", prefix="calendar")
|
||||
calendar_zoom = CallbackData("year", prefix="calendar_zoom")
|
||||
|
||||
|
||||
class CalendarCallbackFilter(AdvancedCustomFilter):
|
||||
key = 'calendar_config'
|
||||
|
||||
async def check(self, call: types.CallbackQuery, config: CallbackDataFilter):
|
||||
return config.check(query=call)
|
||||
|
||||
|
||||
class CalendarZoomCallbackFilter(AdvancedCustomFilter):
|
||||
key = 'calendar_zoom_config'
|
||||
|
||||
async def check(self, call: types.CallbackQuery, config: CallbackDataFilter):
|
||||
return config.check(query=call)
|
||||
|
||||
|
||||
def bind_filters(bot: AsyncTeleBot):
|
||||
bot.add_custom_filter(CalendarCallbackFilter())
|
||||
bot.add_custom_filter(CalendarZoomCallbackFilter())
|
|
@ -0,0 +1,92 @@
|
|||
import calendar
|
||||
from datetime import date, timedelta
|
||||
|
||||
from filters import calendar_factory, calendar_zoom
|
||||
from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton
|
||||
|
||||
EMTPY_FIELD = '1'
|
||||
WEEK_DAYS = [calendar.day_abbr[i] for i in range(7)]
|
||||
MONTHS = [(i, calendar.month_name[i]) for i in range(1, 13)]
|
||||
|
||||
|
||||
def generate_calendar_days(year: int, month: int):
|
||||
keyboard = InlineKeyboardMarkup(row_width=7)
|
||||
today = date.today()
|
||||
|
||||
keyboard.add(
|
||||
InlineKeyboardButton(
|
||||
text=date(year=year, month=month, day=1).strftime('%b %Y'),
|
||||
callback_data=EMTPY_FIELD
|
||||
)
|
||||
)
|
||||
keyboard.add(*[
|
||||
InlineKeyboardButton(
|
||||
text=day,
|
||||
callback_data=EMTPY_FIELD
|
||||
)
|
||||
for day in WEEK_DAYS
|
||||
])
|
||||
|
||||
for week in calendar.Calendar().monthdayscalendar(year=year, month=month):
|
||||
week_buttons = []
|
||||
for day in week:
|
||||
day_name = ' '
|
||||
if day == today.day and today.year == year and today.month == month:
|
||||
day_name = '🔘'
|
||||
elif day != 0:
|
||||
day_name = str(day)
|
||||
week_buttons.append(
|
||||
InlineKeyboardButton(
|
||||
text=day_name,
|
||||
callback_data=EMTPY_FIELD
|
||||
)
|
||||
)
|
||||
keyboard.add(*week_buttons)
|
||||
|
||||
previous_date = date(year=year, month=month, day=1) - timedelta(days=1)
|
||||
next_date = date(year=year, month=month, day=1) + timedelta(days=31)
|
||||
|
||||
keyboard.add(
|
||||
InlineKeyboardButton(
|
||||
text='Previous month',
|
||||
callback_data=calendar_factory.new(year=previous_date.year, month=previous_date.month)
|
||||
),
|
||||
InlineKeyboardButton(
|
||||
text='Zoom out',
|
||||
callback_data=calendar_zoom.new(year=year)
|
||||
),
|
||||
InlineKeyboardButton(
|
||||
text='Next month',
|
||||
callback_data=calendar_factory.new(year=next_date.year, month=next_date.month)
|
||||
),
|
||||
)
|
||||
|
||||
return keyboard
|
||||
|
||||
|
||||
def generate_calendar_months(year: int):
|
||||
keyboard = InlineKeyboardMarkup(row_width=3)
|
||||
keyboard.add(
|
||||
InlineKeyboardButton(
|
||||
text=date(year=year, month=1, day=1).strftime('Year %Y'),
|
||||
callback_data=EMTPY_FIELD
|
||||
)
|
||||
)
|
||||
keyboard.add(*[
|
||||
InlineKeyboardButton(
|
||||
text=month,
|
||||
callback_data=calendar_factory.new(year=year, month=month_number)
|
||||
)
|
||||
for month_number, month in MONTHS
|
||||
])
|
||||
keyboard.add(
|
||||
InlineKeyboardButton(
|
||||
text='Previous year',
|
||||
callback_data=calendar_zoom.new(year=year - 1)
|
||||
),
|
||||
InlineKeyboardButton(
|
||||
text='Next year',
|
||||
callback_data=calendar_zoom.new(year=year + 1)
|
||||
)
|
||||
)
|
||||
return keyboard
|
|
@ -0,0 +1,57 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
This Example will show you an advanced usage of CallbackData.
|
||||
In this example calendar was implemented
|
||||
"""
|
||||
import asyncio
|
||||
from datetime import date
|
||||
|
||||
from filters import calendar_factory, calendar_zoom, bind_filters
|
||||
from keyboards import generate_calendar_days, generate_calendar_months, EMTPY_FIELD
|
||||
from telebot import types
|
||||
from telebot.async_telebot import AsyncTeleBot
|
||||
|
||||
API_TOKEN = ''
|
||||
bot = AsyncTeleBot(API_TOKEN)
|
||||
|
||||
|
||||
@bot.message_handler(commands='start')
|
||||
async def start_command_handler(message: types.Message):
|
||||
await bot.send_message(message.chat.id,
|
||||
f"Hello {message.from_user.first_name}. This bot is an example of calendar keyboard."
|
||||
"\nPress /calendar to see it.")
|
||||
|
||||
|
||||
@bot.message_handler(commands='calendar')
|
||||
async def calendar_command_handler(message: types.Message):
|
||||
now = date.today()
|
||||
await bot.send_message(message.chat.id, 'Calendar',
|
||||
reply_markup=generate_calendar_days(year=now.year, month=now.month))
|
||||
|
||||
|
||||
@bot.callback_query_handler(func=None, calendar_config=calendar_factory.filter())
|
||||
async def calendar_action_handler(call: types.CallbackQuery):
|
||||
callback_data: dict = calendar_factory.parse(callback_data=call.data)
|
||||
year, month = int(callback_data['year']), int(callback_data['month'])
|
||||
|
||||
await bot.edit_message_reply_markup(call.message.chat.id, call.message.id,
|
||||
reply_markup=generate_calendar_days(year=year, month=month))
|
||||
|
||||
|
||||
@bot.callback_query_handler(func=None, calendar_zoom_config=calendar_zoom.filter())
|
||||
async def calendar_zoom_out_handler(call: types.CallbackQuery):
|
||||
callback_data: dict = calendar_zoom.parse(callback_data=call.data)
|
||||
year = int(callback_data.get('year'))
|
||||
|
||||
await bot.edit_message_reply_markup(call.message.chat.id, call.message.id,
|
||||
reply_markup=generate_calendar_months(year=year))
|
||||
|
||||
|
||||
@bot.callback_query_handler(func=lambda call: call.data == EMTPY_FIELD)
|
||||
async def callback_empty_field_handler(call: types.CallbackQuery):
|
||||
await bot.answer_callback_query(call.id)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
bind_filters(bot)
|
||||
asyncio.run(bot.infinity_polling())
|
|
@ -23,12 +23,12 @@ async def my_chat_m(message: types.ChatMemberUpdated):
|
|||
#content_Type_service is:
|
||||
#'new_chat_members', 'left_chat_member', 'new_chat_title', 'new_chat_photo', 'delete_chat_photo', 'group_chat_created',
|
||||
#'supergroup_chat_created', 'channel_chat_created', 'migrate_to_chat_id', 'migrate_from_chat_id', 'pinned_message',
|
||||
#'proximity_alert_triggered', 'voice_chat_scheduled', 'voice_chat_started', 'voice_chat_ended',
|
||||
#'voice_chat_participants_invited', 'message_auto_delete_timer_changed'
|
||||
#'proximity_alert_triggered', 'video_chat_scheduled', 'video_chat_started', 'video_chat_ended',
|
||||
#'video_chat_participants_invited', 'message_auto_delete_timer_changed'
|
||||
# this handler deletes service messages
|
||||
|
||||
@bot.message_handler(content_types=util.content_type_service)
|
||||
async def delall(message: types.Message):
|
||||
await bot.delete_message(message.chat.id,message.message_id)
|
||||
import asyncio
|
||||
asyncio.run(bot.polling())
|
||||
asyncio.run(bot.polling(allowed_updates=util.update_types))
|
||||
|
|
27
examples/asynchronous_telebot/continue_handling.py
Normal file
27
examples/asynchronous_telebot/continue_handling.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
from telebot.async_telebot import AsyncTeleBot
|
||||
from telebot.asyncio_handler_backends import ContinueHandling
|
||||
|
||||
|
||||
bot = AsyncTeleBot('TOKEN')
|
||||
|
||||
@bot.message_handler(commands=['start'])
|
||||
async def start(message):
|
||||
await bot.send_message(message.chat.id, 'Hello World!')
|
||||
return ContinueHandling()
|
||||
|
||||
@bot.message_handler(commands=['start'])
|
||||
async def start2(message):
|
||||
"""
|
||||
This handler comes after the first one, but it will never be called.
|
||||
But you can call it by returning ContinueHandling() in the first handler.
|
||||
|
||||
If you return ContinueHandling() in the first handler, the next
|
||||
registered handler with appropriate filters will be called.
|
||||
"""
|
||||
await bot.send_message(message.chat.id, 'Hello World2!')
|
||||
|
||||
import asyncio
|
||||
asyncio.run(bot.polling()) # just a reminder that infinity polling
|
||||
# wraps polling into try/except block just as sync version,
|
||||
# but you can use any of them because neither of them stops if you
|
||||
# pass non_stop=True
|
|
@ -0,0 +1,127 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
This Example will show you usage of TextFilter
|
||||
In this example you will see how to use TextFilter
|
||||
with (message_handler, callback_query_handler, poll_handler)
|
||||
"""
|
||||
import asyncio
|
||||
|
||||
from telebot import types
|
||||
from telebot.async_telebot import AsyncTeleBot
|
||||
from telebot.asyncio_filters import TextMatchFilter, TextFilter, IsReplyFilter
|
||||
|
||||
bot = AsyncTeleBot("")
|
||||
|
||||
|
||||
@bot.message_handler(text=TextFilter(equals='hello'))
|
||||
async def hello_handler(message: types.Message):
|
||||
await bot.send_message(message.chat.id, message.text)
|
||||
|
||||
|
||||
@bot.message_handler(text=TextFilter(equals='hello', ignore_case=True))
|
||||
async def hello_handler_ignore_case(message: types.Message):
|
||||
await bot.send_message(message.chat.id, message.text + ' ignore case')
|
||||
|
||||
|
||||
@bot.message_handler(text=TextFilter(contains=['good', 'bad']))
|
||||
async def contains_handler(message: types.Message):
|
||||
await bot.send_message(message.chat.id, message.text)
|
||||
|
||||
|
||||
@bot.message_handler(text=TextFilter(contains=['good', 'bad'], ignore_case=True))
|
||||
async def contains_handler_ignore_case(message: types.Message):
|
||||
await bot.send_message(message.chat.id, message.text + ' ignore case')
|
||||
|
||||
|
||||
@bot.message_handler(text=TextFilter(starts_with='st')) # stArk, steve, stONE
|
||||
async def starts_with_handler(message: types.Message):
|
||||
await bot.send_message(message.chat.id, message.text)
|
||||
|
||||
|
||||
@bot.message_handler(text=TextFilter(starts_with='st', ignore_case=True)) # STark, sTeve, stONE
|
||||
async def starts_with_handler_ignore_case(message: types.Message):
|
||||
await bot.send_message(message.chat.id, message.text + ' ignore case')
|
||||
|
||||
|
||||
@bot.message_handler(text=TextFilter(ends_with='ay')) # wednesday, SUNday, WeekDay
|
||||
async def ends_with_handler(message: types.Message):
|
||||
await bot.send_message(message.chat.id, message.text)
|
||||
|
||||
|
||||
@bot.message_handler(text=TextFilter(ends_with='ay', ignore_case=True)) # wednesdAY, sundAy, WeekdaY
|
||||
async def ends_with_handler_ignore_case(message: types.Message):
|
||||
await bot.send_message(message.chat.id, message.text + ' ignore case')
|
||||
|
||||
|
||||
@bot.message_handler(text=TextFilter(equals='/callback'))
|
||||
async def send_callback(message: types.Message):
|
||||
keyboard = types.InlineKeyboardMarkup(
|
||||
keyboard=[
|
||||
[types.InlineKeyboardButton(text='callback data', callback_data='example')],
|
||||
[types.InlineKeyboardButton(text='ignore case callback data', callback_data='ExAmPLe')]
|
||||
]
|
||||
)
|
||||
await bot.send_message(message.chat.id, message.text, reply_markup=keyboard)
|
||||
|
||||
|
||||
@bot.callback_query_handler(func=None, text=TextFilter(equals='example'))
|
||||
async def callback_query_handler(call: types.CallbackQuery):
|
||||
await bot.answer_callback_query(call.id, call.data, show_alert=True)
|
||||
|
||||
|
||||
@bot.callback_query_handler(func=None, text=TextFilter(equals='example', ignore_case=True))
|
||||
async def callback_query_handler_ignore_case(call: types.CallbackQuery):
|
||||
await bot.answer_callback_query(call.id, call.data + " ignore case", show_alert=True)
|
||||
|
||||
|
||||
@bot.message_handler(text=TextFilter(equals='/poll'))
|
||||
async def send_poll(message: types.Message):
|
||||
await bot.send_poll(message.chat.id, question='When do you prefer to work?', options=['Morning', 'Night'])
|
||||
await bot.send_poll(message.chat.id, question='WHEN DO you pRefeR to worK?', options=['Morning', 'Night'])
|
||||
|
||||
|
||||
@bot.poll_handler(func=None, text=TextFilter(equals='When do you prefer to work?'))
|
||||
async def poll_question_handler(poll: types.Poll):
|
||||
print(poll.question)
|
||||
|
||||
|
||||
@bot.poll_handler(func=None, text=TextFilter(equals='When do you prefer to work?', ignore_case=True))
|
||||
async def poll_question_handler_ignore_case(poll: types.Poll):
|
||||
print(poll.question + ' ignore case')
|
||||
|
||||
|
||||
# either hi or contains one of (привет, salom)
|
||||
@bot.message_handler(text=TextFilter(equals="hi", contains=('привет', 'salom'), ignore_case=True))
|
||||
async def multiple_patterns_handler(message: types.Message):
|
||||
await bot.send_message(message.chat.id, message.text)
|
||||
|
||||
|
||||
# starts with one of (mi, mea) for ex. minor, milk, meal, meat
|
||||
@bot.message_handler(text=TextFilter(starts_with=['mi', 'mea'], ignore_case=True))
|
||||
async def multiple_starts_with_handler(message: types.Message):
|
||||
await bot.send_message(message.chat.id, message.text)
|
||||
|
||||
|
||||
# ends with one of (es, on) for ex. Jones, Davies, Johnson, Wilson
|
||||
@bot.message_handler(text=TextFilter(ends_with=['es', 'on'], ignore_case=True))
|
||||
async def multiple_ends_with_handler(message: types.Message):
|
||||
await bot.send_message(message.chat.id, message.text)
|
||||
|
||||
|
||||
# !ban /ban .ban !бан /бан .бан
|
||||
@bot.message_handler(is_reply=True,
|
||||
text=TextFilter(starts_with=('!', '/', '.'), ends_with=['ban', 'бан'], ignore_case=True))
|
||||
async def ban_command_handler(message: types.Message):
|
||||
if len(message.text) == 4 and message.chat.type != 'private':
|
||||
try:
|
||||
await bot.ban_chat_member(message.chat.id, message.reply_to_message.from_user.id)
|
||||
await bot.reply_to(message.reply_to_message, 'Banned.')
|
||||
except Exception as err:
|
||||
print(err.args)
|
||||
return
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
bot.add_custom_filter(TextMatchFilter())
|
||||
bot.add_custom_filter(IsReplyFilter())
|
||||
asyncio.run(bot.polling())
|
|
@ -1,15 +1,27 @@
|
|||
import telebot
|
||||
from telebot import asyncio_filters
|
||||
from telebot.async_telebot import AsyncTeleBot
|
||||
bot = AsyncTeleBot('TOKEN')
|
||||
|
||||
# list of storages, you can use any storage
|
||||
from telebot.asyncio_storage import StateMemoryStorage
|
||||
|
||||
# new feature for states.
|
||||
from telebot.asyncio_handler_backends import State, StatesGroup
|
||||
|
||||
# default state storage is statememorystorage
|
||||
bot = AsyncTeleBot('TOKEN', state_storage=StateMemoryStorage())
|
||||
|
||||
|
||||
# Just create different statesgroup
|
||||
class MyStates(StatesGroup):
|
||||
name = State() # statesgroup should contain states
|
||||
surname = State()
|
||||
age = State()
|
||||
|
||||
|
||||
|
||||
class MyStates:
|
||||
name = 1
|
||||
surname = 2
|
||||
age = 3
|
||||
|
||||
# set_state -> sets a new state
|
||||
# delete_state -> delets state if exists
|
||||
# get_state -> returns state if exists
|
||||
|
||||
|
||||
@bot.message_handler(commands=['start'])
|
||||
|
@ -17,7 +29,7 @@ async def start_ex(message):
|
|||
"""
|
||||
Start command. Here we are starting state
|
||||
"""
|
||||
await bot.set_state(message.from_user.id, MyStates.name)
|
||||
await bot.set_state(message.from_user.id, MyStates.name, message.chat.id)
|
||||
await bot.send_message(message.chat.id, 'Hi, write me a name')
|
||||
|
||||
|
||||
|
@ -28,39 +40,45 @@ async def any_state(message):
|
|||
Cancel state
|
||||
"""
|
||||
await bot.send_message(message.chat.id, "Your state was cancelled.")
|
||||
await bot.delete_state(message.from_user.id)
|
||||
await bot.delete_state(message.from_user.id, message.chat.id)
|
||||
|
||||
@bot.message_handler(state=MyStates.name)
|
||||
async def name_get(message):
|
||||
"""
|
||||
State 1. Will process when user's state is 1.
|
||||
State 1. Will process when user's state is MyStates.name.
|
||||
"""
|
||||
await bot.send_message(message.chat.id, f'Now write me a surname')
|
||||
await bot.set_state(message.from_user.id, MyStates.surname)
|
||||
async with bot.retrieve_data(message.from_user.id) as data:
|
||||
await bot.set_state(message.from_user.id, MyStates.surname, message.chat.id)
|
||||
async with bot.retrieve_data(message.from_user.id, message.chat.id) as data:
|
||||
data['name'] = message.text
|
||||
|
||||
|
||||
@bot.message_handler(state=MyStates.surname)
|
||||
async def ask_age(message):
|
||||
"""
|
||||
State 2. Will process when user's state is 2.
|
||||
State 2. Will process when user's state is MyStates.surname.
|
||||
"""
|
||||
await bot.send_message(message.chat.id, "What is your age?")
|
||||
await bot.set_state(message.from_user.id, MyStates.age)
|
||||
async with bot.retrieve_data(message.from_user.id) as data:
|
||||
await bot.set_state(message.from_user.id, MyStates.age, message.chat.id)
|
||||
async with bot.retrieve_data(message.from_user.id, message.chat.id) as data:
|
||||
data['surname'] = message.text
|
||||
|
||||
# result
|
||||
@bot.message_handler(state=MyStates.age, is_digit=True)
|
||||
async def ready_for_answer(message):
|
||||
async with bot.retrieve_data(message.from_user.id) as data:
|
||||
"""
|
||||
State 3. Will process when user's state is MyStates.age.
|
||||
"""
|
||||
async with bot.retrieve_data(message.from_user.id, message.chat.id) as data:
|
||||
await bot.send_message(message.chat.id, "Ready, take a look:\n<b>Name: {name}\nSurname: {surname}\nAge: {age}</b>".format(name=data['name'], surname=data['surname'], age=message.text), parse_mode="html")
|
||||
await bot.delete_state(message.from_user.id)
|
||||
await bot.delete_state(message.from_user.id, message.chat.id)
|
||||
|
||||
#incorrect number
|
||||
@bot.message_handler(state=MyStates.age, is_digit=False)
|
||||
async def age_incorrect(message):
|
||||
"""
|
||||
Will process for wrong input when state is MyState.age
|
||||
"""
|
||||
await bot.send_message(message.chat.id, 'Looks like you are submitting a string in the field age. Please enter a number')
|
||||
|
||||
# register filters
|
||||
|
@ -68,8 +86,6 @@ async def age_incorrect(message):
|
|||
bot.add_custom_filter(asyncio_filters.StateFilter(bot))
|
||||
bot.add_custom_filter(asyncio_filters.IsDigitFilter())
|
||||
|
||||
# set saving states into file.
|
||||
bot.enable_saving_states() # you can delete this if you do not need to save states
|
||||
|
||||
import asyncio
|
||||
asyncio.run(bot.polling())
|
28
examples/asynchronous_telebot/detect_changes.py
Normal file
28
examples/asynchronous_telebot/detect_changes.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# This is a simple echo bot using the decorator mechanism.
|
||||
# It echoes any incoming text messages.
|
||||
|
||||
from telebot.async_telebot import AsyncTeleBot
|
||||
bot = AsyncTeleBot('TOKEN')
|
||||
|
||||
|
||||
|
||||
# Handle '/start' and '/help'
|
||||
@bot.message_handler(commands=['help', 'start'])
|
||||
async def send_welcome(message):
|
||||
await bot.reply_to(message, """\
|
||||
Hi there, I am EchoBot.
|
||||
I am here to echo your kind words back to you. Just say anything nice and I'll say the exact same thing to you!\
|
||||
""")
|
||||
|
||||
|
||||
# Handle all other messages with content_type 'text' (content_types defaults to ['text'])
|
||||
@bot.message_handler(func=lambda message: True)
|
||||
async def echo_message(message):
|
||||
await bot.reply_to(message, message.text)
|
||||
|
||||
|
||||
import asyncio
|
||||
# only for versions 4.7.0+
|
||||
asyncio.run(bot.polling(restart_on_change=True))
|
54
examples/asynchronous_telebot/formatting_example.py
Normal file
54
examples/asynchronous_telebot/formatting_example.py
Normal file
|
@ -0,0 +1,54 @@
|
|||
from telebot.async_telebot import AsyncTeleBot
|
||||
from telebot import formatting
|
||||
|
||||
bot = AsyncTeleBot('token')
|
||||
|
||||
|
||||
@bot.message_handler(commands=['start'])
|
||||
async def start_message(message):
|
||||
await bot.send_message(
|
||||
message.chat.id,
|
||||
# function which connects all strings
|
||||
formatting.format_text(
|
||||
formatting.mbold(message.from_user.first_name),
|
||||
formatting.mitalic(message.from_user.first_name),
|
||||
formatting.munderline(message.from_user.first_name),
|
||||
formatting.mstrikethrough(message.from_user.first_name),
|
||||
formatting.mcode(message.from_user.first_name),
|
||||
separator=" " # separator separates all strings
|
||||
),
|
||||
parse_mode='MarkdownV2'
|
||||
)
|
||||
|
||||
# just a bold text using markdownv2
|
||||
await bot.send_message(
|
||||
message.chat.id,
|
||||
formatting.mbold(message.from_user.first_name),
|
||||
parse_mode='MarkdownV2'
|
||||
)
|
||||
|
||||
# html
|
||||
await bot.send_message(
|
||||
message.chat.id,
|
||||
formatting.format_text(
|
||||
formatting.hbold(message.from_user.first_name),
|
||||
formatting.hitalic(message.from_user.first_name),
|
||||
formatting.hunderline(message.from_user.first_name),
|
||||
formatting.hstrikethrough(message.from_user.first_name),
|
||||
formatting.hcode(message.from_user.first_name),
|
||||
# hide_link is only for html
|
||||
formatting.hide_link('https://telegra.ph/file/c158e3a6e2a26a160b253.jpg'),
|
||||
separator=" "
|
||||
),
|
||||
parse_mode='HTML'
|
||||
)
|
||||
|
||||
# just a bold text in html
|
||||
await bot.send_message(
|
||||
message.chat.id,
|
||||
formatting.hbold(message.from_user.first_name),
|
||||
parse_mode='HTML'
|
||||
)
|
||||
|
||||
import asyncio
|
||||
asyncio.run(bot.polling())
|
|
@ -1,9 +1,7 @@
|
|||
# Just a little example of middleware handlers
|
||||
|
||||
import telebot
|
||||
from telebot.asyncio_handler_backends import BaseMiddleware
|
||||
from telebot.asyncio_handler_backends import BaseMiddleware, CancelUpdate
|
||||
from telebot.async_telebot import AsyncTeleBot
|
||||
from telebot.async_telebot import CancelUpdate
|
||||
bot = AsyncTeleBot('TOKEN')
|
||||
|
||||
|
||||
|
@ -37,4 +35,4 @@ async def start(message):
|
|||
await bot.send_message(message.chat.id, 'Hello!')
|
||||
|
||||
import asyncio
|
||||
asyncio.run(bot.polling())
|
||||
asyncio.run(bot.polling())
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
import contextvars
|
||||
import gettext
|
||||
import os
|
||||
|
||||
from telebot.asyncio_handler_backends import BaseMiddleware
|
||||
|
||||
try:
|
||||
from babel.support import LazyProxy
|
||||
|
||||
babel_imported = True
|
||||
except ImportError:
|
||||
babel_imported = False
|
||||
|
||||
|
||||
class I18N(BaseMiddleware):
|
||||
"""
|
||||
This middleware provides high-level tool for internationalization
|
||||
It is based on gettext util.
|
||||
"""
|
||||
|
||||
context_lang = contextvars.ContextVar('language', default=None)
|
||||
|
||||
def __init__(self, translations_path, domain_name: str):
|
||||
super().__init__()
|
||||
self.update_types = self.process_update_types()
|
||||
|
||||
self.path = translations_path
|
||||
self.domain = domain_name
|
||||
self.translations = self.find_translations()
|
||||
|
||||
@property
|
||||
def available_translations(self):
|
||||
return list(self.translations)
|
||||
|
||||
def gettext(self, text: str, lang: str = None):
|
||||
"""
|
||||
Singular translations
|
||||
"""
|
||||
|
||||
if lang is None:
|
||||
lang = self.context_lang.get()
|
||||
|
||||
if lang not in self.translations:
|
||||
return text
|
||||
|
||||
translator = self.translations[lang]
|
||||
return translator.gettext(text)
|
||||
|
||||
def ngettext(self, singular: str, plural: str, lang: str = None, n=1):
|
||||
"""
|
||||
Plural translations
|
||||
"""
|
||||
if lang is None:
|
||||
lang = self.context_lang.get()
|
||||
|
||||
if lang not in self.translations:
|
||||
if n == 1:
|
||||
return singular
|
||||
return plural
|
||||
|
||||
translator = self.translations[lang]
|
||||
return translator.ngettext(singular, plural, n)
|
||||
|
||||
def lazy_gettext(self, text: str, lang: str = None):
|
||||
if not babel_imported:
|
||||
raise RuntimeError('babel module is not imported. Check that you installed it.')
|
||||
return LazyProxy(self.gettext, text, lang, enable_cache=False)
|
||||
|
||||
def lazy_ngettext(self, singular: str, plural: str, lang: str = None, n=1):
|
||||
if not babel_imported:
|
||||
raise RuntimeError('babel module is not imported. Check that you installed it.')
|
||||
return LazyProxy(self.ngettext, singular, plural, lang, n, enable_cache=False)
|
||||
|
||||
async def get_user_language(self, obj):
|
||||
"""
|
||||
You need to override this method and return user language
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def process_update_types(self) -> list:
|
||||
"""
|
||||
You need to override this method and return any update types which you want to be processed
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
async def pre_process(self, message, data):
|
||||
"""
|
||||
context language variable will be set each time when update from 'process_update_types' comes
|
||||
value is the result of 'get_user_language' method
|
||||
"""
|
||||
self.context_lang.set(await self.get_user_language(obj=message))
|
||||
|
||||
async def post_process(self, message, data, exception):
|
||||
pass
|
||||
|
||||
def find_translations(self):
|
||||
"""
|
||||
Looks for translations with passed 'domain' in passed 'path'
|
||||
"""
|
||||
if not os.path.exists(self.path):
|
||||
raise RuntimeError(f"Translations directory by path: {self.path!r} was not found")
|
||||
|
||||
result = {}
|
||||
|
||||
for name in os.listdir(self.path):
|
||||
translations_path = os.path.join(self.path, name, 'LC_MESSAGES')
|
||||
|
||||
if not os.path.isdir(translations_path):
|
||||
continue
|
||||
|
||||
po_file = os.path.join(translations_path, self.domain + '.po')
|
||||
mo_file = po_file[:-2] + 'mo'
|
||||
|
||||
if os.path.isfile(po_file) and not os.path.isfile(mo_file):
|
||||
raise FileNotFoundError(f"Translations for: {name!r} were not compiled!")
|
||||
|
||||
with open(mo_file, 'rb') as file:
|
||||
result[name] = gettext.GNUTranslations(file)
|
||||
|
||||
return result
|
|
@ -0,0 +1,34 @@
|
|||
from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton, ReplyKeyboardMarkup, KeyboardButton
|
||||
|
||||
|
||||
def languages_keyboard():
|
||||
return InlineKeyboardMarkup(
|
||||
keyboard=[
|
||||
[
|
||||
InlineKeyboardButton(text="English", callback_data='en'),
|
||||
InlineKeyboardButton(text="Русский", callback_data='ru'),
|
||||
InlineKeyboardButton(text="O'zbekcha", callback_data='uz_Latn')
|
||||
]
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def clicker_keyboard(_):
|
||||
return InlineKeyboardMarkup(
|
||||
keyboard=[
|
||||
[
|
||||
InlineKeyboardButton(text=_("click"), callback_data='click'),
|
||||
]
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def menu_keyboard(_):
|
||||
keyboard = ReplyKeyboardMarkup(resize_keyboard=True)
|
||||
keyboard.add(
|
||||
KeyboardButton(text=_("My user id")),
|
||||
KeyboardButton(text=_("My user name")),
|
||||
KeyboardButton(text=_("My first name"))
|
||||
)
|
||||
|
||||
return keyboard
|
|
@ -0,0 +1,81 @@
|
|||
# English translations for PROJECT.
|
||||
# Copyright (C) 2022 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2022-02-19 18:37+0500\n"
|
||||
"PO-Revision-Date: 2022-02-18 16:22+0500\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language: en\n"
|
||||
"Language-Team: en <LL@li.org>\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.9.1\n"
|
||||
|
||||
#: keyboards.py:20
|
||||
msgid "click"
|
||||
msgstr ""
|
||||
|
||||
#: keyboards.py:29
|
||||
msgid "My user id"
|
||||
msgstr ""
|
||||
|
||||
#: keyboards.py:30
|
||||
msgid "My user name"
|
||||
msgstr ""
|
||||
|
||||
#: keyboards.py:31
|
||||
msgid "My first name"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:97
|
||||
msgid ""
|
||||
"Hello, {user_fist_name}!\n"
|
||||
"This is the example of multilanguage bot.\n"
|
||||
"Available commands:\n"
|
||||
"\n"
|
||||
"/lang - change your language\n"
|
||||
"/plural - pluralization example\n"
|
||||
"/menu - text menu example"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:121
|
||||
msgid "Language has been changed"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:130 main.py:150
|
||||
#, fuzzy
|
||||
msgid "You have {number} click"
|
||||
msgid_plural "You have {number} clicks"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: main.py:135 main.py:155
|
||||
msgid ""
|
||||
"This is clicker.\n"
|
||||
"\n"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:163
|
||||
msgid "This is ReplyKeyboardMarkup menu example in multilanguage bot."
|
||||
msgstr ""
|
||||
|
||||
#: main.py:203
|
||||
msgid "Seems you confused language"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Hello, {user_fist_name}!\n"
|
||||
#~ "This is the example of multilanguage bot.\n"
|
||||
#~ "Available commands:\n"
|
||||
#~ "\n"
|
||||
#~ "/lang - change your language\n"
|
||||
#~ "/plural - pluralization example"
|
||||
#~ msgstr ""
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
# Russian translations for PROJECT.
|
||||
# Copyright (C) 2022 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2022-02-19 18:37+0500\n"
|
||||
"PO-Revision-Date: 2022-02-18 16:22+0500\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language: ru\n"
|
||||
"Language-Team: ru <LL@li.org>\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
||||
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.9.1\n"
|
||||
|
||||
#: keyboards.py:20
|
||||
msgid "click"
|
||||
msgstr "Клик"
|
||||
|
||||
#: keyboards.py:29
|
||||
msgid "My user id"
|
||||
msgstr "Мой user id"
|
||||
|
||||
#: keyboards.py:30
|
||||
msgid "My user name"
|
||||
msgstr "Мой user name"
|
||||
|
||||
#: keyboards.py:31
|
||||
msgid "My first name"
|
||||
msgstr "Мой first name"
|
||||
|
||||
#: main.py:97
|
||||
msgid ""
|
||||
"Hello, {user_fist_name}!\n"
|
||||
"This is the example of multilanguage bot.\n"
|
||||
"Available commands:\n"
|
||||
"\n"
|
||||
"/lang - change your language\n"
|
||||
"/plural - pluralization example\n"
|
||||
"/menu - text menu example"
|
||||
msgstr ""
|
||||
"Привет, {user_fist_name}!\n"
|
||||
"Это пример мультиязычного бота.\n"
|
||||
"Доступные команды:\n"
|
||||
"\n"
|
||||
"/lang - изменить язык\n"
|
||||
"/plural - пример плюрализации\n"
|
||||
"/menu - Пример текстового меню"
|
||||
|
||||
#: main.py:121
|
||||
msgid "Language has been changed"
|
||||
msgstr "Язык был сменён"
|
||||
|
||||
#: main.py:130 main.py:150
|
||||
msgid "You have {number} click"
|
||||
msgid_plural "You have {number} clicks"
|
||||
msgstr[0] "У вас {number} клик"
|
||||
msgstr[1] "У вас {number} клика"
|
||||
msgstr[2] "У вас {number} кликов"
|
||||
|
||||
#: main.py:135 main.py:155
|
||||
msgid ""
|
||||
"This is clicker.\n"
|
||||
"\n"
|
||||
msgstr ""
|
||||
"Это кликер.\n"
|
||||
"\n"
|
||||
|
||||
#: main.py:163
|
||||
msgid "This is ReplyKeyboardMarkup menu example in multilanguage bot."
|
||||
msgstr "Это пример ReplyKeyboardMarkup меню в мультиязычном боте."
|
||||
|
||||
#: main.py:203
|
||||
msgid "Seems you confused language"
|
||||
msgstr "Кажется, вы перепутали язык"
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
# Uzbek (Latin) translations for PROJECT.
|
||||
# Copyright (C) 2022 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2022-02-19 18:37+0500\n"
|
||||
"PO-Revision-Date: 2022-02-18 16:22+0500\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language: uz_Latn\n"
|
||||
"Language-Team: uz_Latn <LL@li.org>\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.9.1\n"
|
||||
|
||||
#: keyboards.py:20
|
||||
msgid "click"
|
||||
msgstr "clik"
|
||||
|
||||
#: keyboards.py:29
|
||||
msgid "My user id"
|
||||
msgstr "Mani user id"
|
||||
|
||||
#: keyboards.py:30
|
||||
msgid "My user name"
|
||||
msgstr "Mani user name"
|
||||
|
||||
#: keyboards.py:31
|
||||
msgid "My first name"
|
||||
msgstr "Mani first name"
|
||||
|
||||
#: main.py:97
|
||||
msgid ""
|
||||
"Hello, {user_fist_name}!\n"
|
||||
"This is the example of multilanguage bot.\n"
|
||||
"Available commands:\n"
|
||||
"\n"
|
||||
"/lang - change your language\n"
|
||||
"/plural - pluralization example\n"
|
||||
"/menu - text menu example"
|
||||
msgstr ""
|
||||
"Salom, {user_fist_name}!\n"
|
||||
"Bu multilanguage bot misoli.\n"
|
||||
"Mavjud buyruqlar:\n"
|
||||
"\n"
|
||||
"/lang - tilni ozgartirish\n"
|
||||
"/plural - pluralizatsiya misoli\n"
|
||||
"/menu - text menu misoli"
|
||||
|
||||
#: main.py:121
|
||||
msgid "Language has been changed"
|
||||
msgstr "Til ozgartirildi"
|
||||
|
||||
#: main.py:130 main.py:150
|
||||
msgid "You have {number} click"
|
||||
msgid_plural "You have {number} clicks"
|
||||
msgstr[0] "Sizda {number}ta clik"
|
||||
msgstr[1] "Sizda {number}ta clik"
|
||||
|
||||
#: main.py:135 main.py:155
|
||||
msgid ""
|
||||
"This is clicker.\n"
|
||||
"\n"
|
||||
msgstr ""
|
||||
"Bu clicker.\n"
|
||||
"\n"
|
||||
|
||||
#: main.py:163
|
||||
msgid "This is ReplyKeyboardMarkup menu example in multilanguage bot."
|
||||
msgstr "Bu multilanguage bot da replykeyboardmarkup menyu misoli."
|
||||
|
||||
#: main.py:203
|
||||
msgid "Seems you confused language"
|
||||
msgstr "Tilni adashtirdiz"
|
||||
|
|
@ -0,0 +1,214 @@
|
|||
"""
|
||||
In this example you will learn how to adapt your bot to different languages
|
||||
Using built-in middleware I18N.
|
||||
|
||||
You need to install babel package 'https://pypi.org/project/Babel/'
|
||||
Babel provides a command-line interface for working with message catalogs
|
||||
After installing babel package you have a script called 'pybabel'
|
||||
Too see all the commands open terminal and type 'pybabel --help'
|
||||
Full description for pybabel commands can be found here: 'https://babel.pocoo.org/en/latest/cmdline.html'
|
||||
|
||||
Create a directory 'locales' where our translations will be stored
|
||||
|
||||
First we need to extract texts:
|
||||
pybabel extract -o locales/{domain_name}.pot --input-dirs .
|
||||
{domain_name}.pot - is the file where all translations are saved
|
||||
The name of this file should be the same as domain which you pass to I18N class
|
||||
In this example domain_name will be 'messages'
|
||||
|
||||
For gettext (singular texts) we use '_' alias and it works perfect
|
||||
You may also you some alias for ngettext (plural texts) but you can face with a problem that
|
||||
your plural texts are not being extracted
|
||||
That is because by default 'pybabel extract' recognizes the following keywords:
|
||||
_, gettext, ngettext, ugettext, ungettext, dgettext, dngettext, N_
|
||||
To add your own keyword you can use '-k' flag
|
||||
In this example for 'ngettext' i will assign double underscore alias '__'
|
||||
|
||||
Full command with pluralization support will look so:
|
||||
pybabel extract -o locales/{domain_name}.pot -k __:1,2 --input-dirs .
|
||||
|
||||
Then create directories with translations (get list of all locales: 'pybabel --list-locales'):
|
||||
pybabel init -i locales/{domain_name}.pot -d locales -l en
|
||||
pybabel init -i locales/{domain_name}.pot -d locales -l ru
|
||||
pybabel init -i locales/{domain_name}.pot -d locales -l uz_Latn
|
||||
|
||||
Now you can translate the texts located in locales/{language}/LC_MESSAGES/{domain_name}.po
|
||||
After you translated all the texts you need to compile .po files:
|
||||
pybabel compile -d locales
|
||||
|
||||
When you delete/update your texts you also need to update them in .po files:
|
||||
pybabel extract -o locales/{domain_name}.pot -k __:1,2 --input-dirs .
|
||||
pybabel update -i locales/{domain_name}.pot -d locales
|
||||
- translate
|
||||
pybabel compile -d locales
|
||||
|
||||
If you have any exceptions check:
|
||||
- you have installed babel
|
||||
- translations are ready, so you just compiled it
|
||||
- in the commands above you replaced {domain_name} to messages
|
||||
- you are writing commands from correct path in terminal
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from typing import Union
|
||||
|
||||
import keyboards
|
||||
from telebot import types
|
||||
from telebot.async_telebot import AsyncTeleBot
|
||||
from telebot.asyncio_filters import TextMatchFilter, TextFilter
|
||||
from i18n_base_middleware import I18N
|
||||
from telebot.asyncio_storage.memory_storage import StateMemoryStorage
|
||||
|
||||
|
||||
class I18NMiddleware(I18N):
|
||||
|
||||
def process_update_types(self) -> list:
|
||||
"""
|
||||
Here you need to return a list of update types which you want to be processed
|
||||
"""
|
||||
return ['message', 'callback_query']
|
||||
|
||||
async def get_user_language(self, obj: Union[types.Message, types.CallbackQuery]):
|
||||
"""
|
||||
This method is called when new update comes (only updates which you return in 'process_update_types' method)
|
||||
Returned language will be used in 'pre_process' method of parent class
|
||||
Returned language will be set to context language variable.
|
||||
If you need to get translation with user's actual language you don't have to pass it manually
|
||||
It will be automatically passed from context language value.
|
||||
However if you need some other language you can always pass it.
|
||||
"""
|
||||
|
||||
user_id = obj.from_user.id
|
||||
|
||||
if user_id not in users_lang:
|
||||
users_lang[user_id] = 'en'
|
||||
|
||||
return users_lang[user_id]
|
||||
|
||||
|
||||
storage = StateMemoryStorage()
|
||||
bot = AsyncTeleBot("", state_storage=storage)
|
||||
|
||||
i18n = I18NMiddleware(translations_path='locales', domain_name='messages')
|
||||
_ = i18n.gettext # for singular translations
|
||||
__ = i18n.ngettext # for plural translations
|
||||
|
||||
# These are example storages, do not use it in a production development
|
||||
users_lang = {}
|
||||
users_clicks = {}
|
||||
|
||||
|
||||
@bot.message_handler(commands='start')
|
||||
async def start_handler(message: types.Message):
|
||||
text = _("Hello, {user_fist_name}!\n"
|
||||
"This is the example of multilanguage bot.\n"
|
||||
"Available commands:\n\n"
|
||||
"/lang - change your language\n"
|
||||
"/plural - pluralization example\n"
|
||||
"/menu - text menu example")
|
||||
|
||||
# remember don't use f string for interpolation, use .format method instead
|
||||
text = text.format(user_fist_name=message.from_user.first_name)
|
||||
await bot.send_message(message.from_user.id, text)
|
||||
|
||||
|
||||
@bot.message_handler(commands='lang')
|
||||
async def change_language_handler(message: types.Message):
|
||||
await bot.send_message(message.chat.id, "Choose language\nВыберите язык\nTilni tanlang",
|
||||
reply_markup=keyboards.languages_keyboard())
|
||||
|
||||
|
||||
@bot.callback_query_handler(func=None, text=TextFilter(contains=['en', 'ru', 'uz_Latn']))
|
||||
async def language_handler(call: types.CallbackQuery):
|
||||
lang = call.data
|
||||
users_lang[call.from_user.id] = lang
|
||||
|
||||
# When you changed user language, you have to pass it manually beacause it is not changed in context
|
||||
await bot.edit_message_text(_("Language has been changed", lang=lang), call.from_user.id, call.message.id)
|
||||
|
||||
|
||||
@bot.message_handler(commands='plural')
|
||||
async def pluralization_handler(message: types.Message):
|
||||
if not users_clicks.get(message.from_user.id):
|
||||
users_clicks[message.from_user.id] = 0
|
||||
clicks = users_clicks[message.from_user.id]
|
||||
|
||||
text = __(
|
||||
singular="You have {number} click",
|
||||
plural="You have {number} clicks",
|
||||
n=clicks
|
||||
)
|
||||
text = _("This is clicker.\n\n") + text.format(number=clicks)
|
||||
|
||||
await bot.send_message(message.chat.id, text, reply_markup=keyboards.clicker_keyboard(_))
|
||||
|
||||
|
||||
@bot.callback_query_handler(func=None, text=TextFilter(equals='click'))
|
||||
async def click_handler(call: types.CallbackQuery):
|
||||
if not users_clicks.get(call.from_user.id):
|
||||
users_clicks[call.from_user.id] = 1
|
||||
else:
|
||||
users_clicks[call.from_user.id] += 1
|
||||
|
||||
clicks = users_clicks[call.from_user.id]
|
||||
|
||||
text = __(
|
||||
singular="You have {number} click",
|
||||
plural="You have {number} clicks",
|
||||
n=clicks
|
||||
)
|
||||
text = _("This is clicker.\n\n") + text.format(number=clicks)
|
||||
|
||||
await bot.edit_message_text(text, call.from_user.id, call.message.message_id,
|
||||
reply_markup=keyboards.clicker_keyboard(_))
|
||||
|
||||
|
||||
@bot.message_handler(commands='menu')
|
||||
async def menu_handler(message: types.Message):
|
||||
text = _("This is ReplyKeyboardMarkup menu example in multilanguage bot.")
|
||||
await bot.send_message(message.chat.id, text, reply_markup=keyboards.menu_keyboard(_))
|
||||
|
||||
|
||||
# For lazy tranlations
|
||||
# lazy gettext is used when you don't know user's locale
|
||||
# It can be used for example to handle text buttons in multilanguage bot
|
||||
# The actual translation will be delayed until update comes and context language is set
|
||||
l_ = i18n.lazy_gettext
|
||||
|
||||
|
||||
# Handlers below will handle text according to user's language
|
||||
@bot.message_handler(text=l_("My user id"))
|
||||
async def return_user_id(message: types.Message):
|
||||
await bot.send_message(message.chat.id, str(message.from_user.id))
|
||||
|
||||
|
||||
@bot.message_handler(text=l_("My user name"))
|
||||
async def return_user_id(message: types.Message):
|
||||
username = message.from_user.username
|
||||
if not username:
|
||||
username = '-'
|
||||
await bot.send_message(message.chat.id, username)
|
||||
|
||||
|
||||
# You can make it case insensitive
|
||||
@bot.message_handler(text=TextFilter(equals=l_("My first name"), ignore_case=True))
|
||||
async def return_user_id(message: types.Message):
|
||||
await bot.send_message(message.chat.id, message.from_user.first_name)
|
||||
|
||||
|
||||
all_menu_texts = []
|
||||
for language in i18n.available_translations:
|
||||
for menu_text in ("My user id", "My user name", "My first name"):
|
||||
all_menu_texts.append(_(menu_text, language))
|
||||
|
||||
|
||||
# When user confused language. (handles all menu buttons texts)
|
||||
@bot.message_handler(text=TextFilter(contains=all_menu_texts, ignore_case=True))
|
||||
async def missed_message(message: types.Message):
|
||||
await bot.send_message(message.chat.id, _("Seems you confused language"), reply_markup=keyboards.menu_keyboard(_))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
bot.setup_middleware(i18n)
|
||||
bot.add_custom_filter(TextMatchFilter())
|
||||
asyncio.run(bot.infinity_polling())
|
17
examples/asynchronous_telebot/multibot/README.MD
Normal file
17
examples/asynchronous_telebot/multibot/README.MD
Normal file
|
@ -0,0 +1,17 @@
|
|||
You probably have seen bots which allow you to send them token of your bot and then handle updates providing some functionality for your bot.
|
||||
<br>
|
||||
This type of bots are called <b>multibots</b>. They are created using webhooks.
|
||||
<br>
|
||||
|
||||
This is the example of simple multibot.<br>
|
||||
In order to reproduce this example you need to have <b>domain and ssl connection</b>.
|
||||
<br>
|
||||
If you have, go to config.py and specify your data.
|
||||
<br>
|
||||
There is also file called <b>nginx_conf.conf</b>, we will use nginx as proxy-server and this file is example nginx.conf file.
|
||||
<br>
|
||||
Make sure that server_name and port are the same in both config and nginx_conf
|
||||
<br>
|
||||
(nginx_conf.conf IS NOT complete, you would probably use tools like certbot to add ssl connection to it)
|
||||
<br>
|
||||
Also, in this example I used dictionary as tokens storage, but in production you should use database so that you can re-set webhooks in case bot restarts.
|
6
examples/asynchronous_telebot/multibot/config.py
Normal file
6
examples/asynchronous_telebot/multibot/config.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
MAIN_BOT_TOKEN = "your_main_bot_token"
|
||||
|
||||
WEBHOOK_HOST = "your_domain.com"
|
||||
WEBHOOK_PATH = "telegram_webhook"
|
||||
WEBAPP_HOST = "0.0.0.0"
|
||||
WEBAPP_PORT = 3500
|
15
examples/asynchronous_telebot/multibot/handlers.py
Normal file
15
examples/asynchronous_telebot/multibot/handlers.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
from telebot.async_telebot import AsyncTeleBot
|
||||
from telebot import types
|
||||
|
||||
|
||||
async def hello_handler(message: types.Message, bot: AsyncTeleBot):
|
||||
await bot.send_message(message.chat.id, "Hi :)")
|
||||
|
||||
|
||||
async def echo_handler(message: types.Message, bot: AsyncTeleBot):
|
||||
await bot.send_message(message.chat.id, message.text)
|
||||
|
||||
|
||||
def register_handlers(bot: AsyncTeleBot):
|
||||
bot.register_message_handler(hello_handler, func=lambda message: message.text == 'Hello', pass_bot=True)
|
||||
bot.register_message_handler(echo_handler, pass_bot=True)
|
56
examples/asynchronous_telebot/multibot/main.py
Normal file
56
examples/asynchronous_telebot/multibot/main.py
Normal file
|
@ -0,0 +1,56 @@
|
|||
import asyncio
|
||||
|
||||
from aiohttp import web
|
||||
from telebot import types, util
|
||||
from telebot.async_telebot import AsyncTeleBot
|
||||
from handlers import register_handlers
|
||||
|
||||
import config
|
||||
|
||||
main_bot = AsyncTeleBot(config.MAIN_BOT_TOKEN)
|
||||
app = web.Application()
|
||||
tokens = {config.MAIN_BOT_TOKEN: True}
|
||||
|
||||
|
||||
async def webhook(request):
|
||||
token = request.match_info.get('token')
|
||||
if not tokens.get(token):
|
||||
return web.Response(status=404)
|
||||
|
||||
if request.headers.get('content-type') != 'application/json':
|
||||
return web.Response(status=403)
|
||||
|
||||
json_string = await request.json()
|
||||
update = types.Update.de_json(json_string)
|
||||
if token == main_bot.token:
|
||||
await main_bot.process_new_updates([update])
|
||||
return web.Response()
|
||||
|
||||
from_update_bot = AsyncTeleBot(token)
|
||||
register_handlers(from_update_bot)
|
||||
await from_update_bot.process_new_updates([update])
|
||||
return web.Response()
|
||||
|
||||
|
||||
app.router.add_post("/" + config.WEBHOOK_PATH + "/{token}", webhook)
|
||||
|
||||
|
||||
@main_bot.message_handler(commands=['add_bot'])
|
||||
async def add_bot(message: types.Message):
|
||||
token = util.extract_arguments(message.text)
|
||||
tokens[token] = True
|
||||
|
||||
new_bot = AsyncTeleBot(token)
|
||||
await new_bot.delete_webhook()
|
||||
await new_bot.set_webhook(f"{config.WEBHOOK_HOST}/{config.WEBHOOK_PATH}/{token}")
|
||||
|
||||
await new_bot.send_message(message.chat.id, "Webhook was set.")
|
||||
|
||||
|
||||
async def main():
|
||||
await main_bot.delete_webhook()
|
||||
await main_bot.set_webhook(f"{config.WEBHOOK_HOST}/{config.WEBHOOK_PATH}/{config.MAIN_BOT_TOKEN}")
|
||||
web.run_app(app, host=config.WEBAPP_HOST, port=config.WEBAPP_PORT)
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
8
examples/asynchronous_telebot/multibot/nginx_conf.conf
Normal file
8
examples/asynchronous_telebot/multibot/nginx_conf.conf
Normal file
|
@ -0,0 +1,8 @@
|
|||
server {
|
||||
server_name your_domain.com;
|
||||
|
||||
location /telegram_webhook/ {
|
||||
proxy_pass http://localhost:3500;
|
||||
}
|
||||
|
||||
}
|
35
examples/asynchronous_telebot/set_command_example.py
Normal file
35
examples/asynchronous_telebot/set_command_example.py
Normal file
|
@ -0,0 +1,35 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# This is a set_my_commands example.
|
||||
# Press on [/] button in telegram client.
|
||||
# Important, to update the command menu, be sure to exit the chat with the bot and log in again
|
||||
# Important, command for chat_id and for group have a higher priority than for all
|
||||
|
||||
import asyncio
|
||||
import telebot
|
||||
from telebot.async_telebot import AsyncTeleBot
|
||||
|
||||
|
||||
API_TOKEN = '<api_token>'
|
||||
bot = AsyncTeleBot(API_TOKEN)
|
||||
|
||||
|
||||
async def main():
|
||||
# use in for delete with the necessary scope and language_code if necessary
|
||||
await bot.delete_my_commands(scope=None, language_code=None)
|
||||
|
||||
await bot.set_my_commands(
|
||||
commands=[
|
||||
telebot.types.BotCommand("command1", "command1 description"),
|
||||
telebot.types.BotCommand("command2", "command2 description")
|
||||
],
|
||||
# scope=telebot.types.BotCommandScopeChat(12345678) # use for personal command menu for users
|
||||
# scope=telebot.types.BotCommandScopeAllPrivateChats() # use for all private chats
|
||||
)
|
||||
|
||||
cmd = await bot.get_my_commands(scope=None, language_code=None)
|
||||
print([c.to_json() for c in cmd])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
52
examples/asynchronous_telebot/timer_bot_async.py
Normal file
52
examples/asynchronous_telebot/timer_bot_async.py
Normal file
|
@ -0,0 +1,52 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
# This is a simple bot with schedule timer
|
||||
# https://github.com/ibrb/python-aioschedule
|
||||
# https://schedule.readthedocs.io
|
||||
|
||||
import asyncio
|
||||
import aioschedule
|
||||
from telebot.async_telebot import AsyncTeleBot
|
||||
|
||||
API_TOKEN = '<api_token>'
|
||||
bot = AsyncTeleBot(API_TOKEN)
|
||||
|
||||
|
||||
async def beep(chat_id) -> None:
|
||||
"""Send the beep message."""
|
||||
await bot.send_message(chat_id, text='Beep!')
|
||||
aioschedule.clear(chat_id) # return schedule.CancelJob not working in aioschedule use tag for delete
|
||||
|
||||
|
||||
@bot.message_handler(commands=['help', 'start'])
|
||||
async def send_welcome(message):
|
||||
await bot.reply_to(message, "Hi! Use /set <seconds> to set a timer")
|
||||
|
||||
|
||||
@bot.message_handler(commands=['set'])
|
||||
async def set_timer(message):
|
||||
args = message.text.split()
|
||||
if len(args) > 1 and args[1].isdigit():
|
||||
sec = int(args[1])
|
||||
aioschedule.every(sec).seconds.do(beep, message.chat.id).tag(message.chat.id)
|
||||
else:
|
||||
await bot.reply_to(message, 'Usage: /set <seconds>')
|
||||
|
||||
|
||||
@bot.message_handler(commands=['unset'])
|
||||
def unset_timer(message):
|
||||
aioschedule.clean(message.chat.id)
|
||||
|
||||
|
||||
async def scheduler():
|
||||
while True:
|
||||
await aioschedule.run_pending()
|
||||
await asyncio.sleep(1)
|
||||
|
||||
|
||||
async def main():
|
||||
await asyncio.gather(bot.infinity_polling(), scheduler())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
|
@ -0,0 +1,93 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This is an async echo bot using decorators and webhook with aiohttp
|
||||
# It echoes any incoming text messages and does not use the polling method.
|
||||
|
||||
import logging
|
||||
import ssl
|
||||
import asyncio
|
||||
from aiohttp import web
|
||||
import telebot
|
||||
from telebot.async_telebot import AsyncTeleBot
|
||||
|
||||
API_TOKEN = '<api_token>'
|
||||
WEBHOOK_HOST = '<ip/host where the bot is running>'
|
||||
WEBHOOK_PORT = 8443 # 443, 80, 88 or 8443 (port need to be 'open')
|
||||
WEBHOOK_LISTEN = '0.0.0.0' # In some VPS you may need to put here the IP addr
|
||||
WEBHOOK_SSL_CERT = './webhook_cert.pem' # Path to the ssl certificate
|
||||
WEBHOOK_SSL_PRIV = './webhook_pkey.pem' # Path to the ssl private key
|
||||
WEBHOOK_URL_BASE = "https://{}:{}".format(WEBHOOK_HOST, WEBHOOK_PORT)
|
||||
WEBHOOK_URL_PATH = "/{}/".format(API_TOKEN)
|
||||
|
||||
# Quick'n'dirty SSL certificate generation:
|
||||
#
|
||||
# openssl genrsa -out webhook_pkey.pem 2048
|
||||
# openssl req -new -x509 -days 3650 -key webhook_pkey.pem -out webhook_cert.pem
|
||||
#
|
||||
# When asked for "Common Name (e.g. server FQDN or YOUR name)" you should reply
|
||||
# with the same value in you put in WEBHOOK_HOST
|
||||
|
||||
logger = telebot.logger
|
||||
telebot.logger.setLevel(logging.INFO)
|
||||
bot = AsyncTeleBot(API_TOKEN)
|
||||
|
||||
|
||||
# Process webhook calls
|
||||
async def handle(request):
|
||||
if request.match_info.get('token') == bot.token:
|
||||
request_body_dict = await request.json()
|
||||
update = telebot.types.Update.de_json(request_body_dict)
|
||||
asyncio.ensure_future(bot.process_new_updates([update]))
|
||||
return web.Response()
|
||||
else:
|
||||
return web.Response(status=403)
|
||||
|
||||
|
||||
# Handle '/start' and '/help'
|
||||
@bot.message_handler(commands=['help', 'start'])
|
||||
async def send_welcome(message):
|
||||
await bot.reply_to(message,
|
||||
("Hi there, I am EchoBot.\n"
|
||||
"I am here to echo your kind words back to you."))
|
||||
|
||||
|
||||
# Handle all other messages
|
||||
@bot.message_handler(func=lambda message: True, content_types=['text'])
|
||||
async def echo_message(message):
|
||||
await bot.reply_to(message, message.text)
|
||||
|
||||
|
||||
# Remove webhook and closing session before exiting
|
||||
async def shutdown(app):
|
||||
logger.info('Shutting down: removing webhook')
|
||||
await bot.remove_webhook()
|
||||
logger.info('Shutting down: closing session')
|
||||
await bot.close_session()
|
||||
|
||||
|
||||
async def setup():
|
||||
# Remove webhook, it fails sometimes the set if there is a previous webhook
|
||||
logger.info('Starting up: removing old webhook')
|
||||
await bot.remove_webhook()
|
||||
# Set webhook
|
||||
logger.info('Starting up: setting webhook')
|
||||
await bot.set_webhook(url=WEBHOOK_URL_BASE + WEBHOOK_URL_PATH,
|
||||
certificate=open(WEBHOOK_SSL_CERT, 'r'))
|
||||
app = web.Application()
|
||||
app.router.add_post('/{token}/', handle)
|
||||
app.on_cleanup.append(shutdown)
|
||||
return app
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Build ssl context
|
||||
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
|
||||
context.load_cert_chain(WEBHOOK_SSL_CERT, WEBHOOK_SSL_PRIV)
|
||||
# Start aiohttp server
|
||||
web.run_app(
|
||||
setup(),
|
||||
host=WEBHOOK_LISTEN,
|
||||
port=WEBHOOK_PORT,
|
||||
ssl_context=context,
|
||||
)
|
45
examples/asynchronous_telebot/webhooks/run_webhooks.py
Normal file
45
examples/asynchronous_telebot/webhooks/run_webhooks.py
Normal file
|
@ -0,0 +1,45 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# This is a simple echo bot using the decorator mechanism.
|
||||
# It echoes any incoming text messages.
|
||||
# Example on built-in function to receive and process webhooks.
|
||||
|
||||
from telebot.async_telebot import AsyncTeleBot
|
||||
import asyncio
|
||||
bot = AsyncTeleBot('TOKEN')
|
||||
|
||||
|
||||
WEBHOOK_SSL_CERT = './webhook_cert.pem' # Path to the ssl certificate
|
||||
WEBHOOK_SSL_PRIV = './webhook_pkey.pem' # Path to the ssl private key
|
||||
DOMAIN = '1.2.3.4' # either domain, or ip address of vps
|
||||
|
||||
# Quick'n'dirty SSL certificate generation:
|
||||
#
|
||||
# openssl genrsa -out webhook_pkey.pem 2048
|
||||
# openssl req -new -x509 -days 3650 -key webhook_pkey.pem -out webhook_cert.pem
|
||||
#
|
||||
# When asked for "Common Name (e.g. server FQDN or YOUR name)" you should reply
|
||||
# with the same value in you put in WEBHOOK_HOST
|
||||
|
||||
|
||||
# Handle '/start' and '/help'
|
||||
@bot.message_handler(commands=['help', 'start'])
|
||||
async def send_welcome(message):
|
||||
await bot.reply_to(message, """\
|
||||
Hi there, I am EchoBot.
|
||||
I am here to echo your kind words back to you. Just say anything nice and I'll say the exact same thing to you!\
|
||||
""")
|
||||
|
||||
|
||||
# Handle all other messages with content_type 'text' (content_types defaults to ['text'])
|
||||
@bot.message_handler(func=lambda message: True)
|
||||
async def echo_message(message):
|
||||
await bot.reply_to(message, message.text)
|
||||
|
||||
|
||||
# it uses fastapi + uvicorn
|
||||
asyncio.run(bot.run_webhooks(
|
||||
listen=DOMAIN,
|
||||
certificate=WEBHOOK_SSL_CERT,
|
||||
certificate_key=WEBHOOK_SSL_PRIV
|
||||
))
|
|
@ -0,0 +1,89 @@
|
|||
#!/usr/bin/env python
|
||||
"""
|
||||
Asynchronous Telegram Echo Bot example.
|
||||
|
||||
This is a simple bot that echoes each message that is received onto the chat.
|
||||
It uses the Starlette ASGI framework to receive updates via webhook requests.
|
||||
"""
|
||||
|
||||
import uvicorn
|
||||
from starlette.applications import Starlette
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import PlainTextResponse, Response
|
||||
from starlette.routing import Route
|
||||
from telebot.async_telebot import AsyncTeleBot
|
||||
from telebot.types import Message, Update
|
||||
|
||||
API_TOKEN = "TOKEN"
|
||||
|
||||
WEBHOOK_HOST = "<ip/domain>"
|
||||
WEBHOOK_PORT = 8443 # 443, 80, 88 or 8443 (port need to be 'open')
|
||||
WEBHOOK_LISTEN = "0.0.0.0"
|
||||
WEBHOOK_SSL_CERT = "./webhook_cert.pem" # Path to the ssl certificate
|
||||
WEBHOOK_SSL_PRIV = "./webhook_pkey.pem" # Path to the ssl private key
|
||||
WEBHOOK_URL = f"https://{WEBHOOK_HOST}:{WEBHOOK_PORT}/telegram"
|
||||
WEBHOOK_SECRET_TOKEN = "SECRET_TOKEN"
|
||||
|
||||
logger = telebot.logger
|
||||
telebot.logger.setLevel(logging.INFO)
|
||||
|
||||
bot = AsyncTeleBot(token=API_TOKEN)
|
||||
|
||||
# BOT HANDLERS
|
||||
@bot.message_handler(commands=["help", "start"])
|
||||
async def send_welcome(message: Message):
|
||||
"""
|
||||
Handle '/start' and '/help'
|
||||
"""
|
||||
await bot.reply_to(
|
||||
message,
|
||||
("Hi there, I am EchoBot.\n" "I am here to echo your kind words back to you."),
|
||||
)
|
||||
|
||||
|
||||
@bot.message_handler(func=lambda _: True, content_types=["text"])
|
||||
async def echo_message(message: Message):
|
||||
"""
|
||||
Handle all other messages
|
||||
"""
|
||||
await bot.reply_to(message, message.text)
|
||||
|
||||
|
||||
# WEBSERVER HANDLERS
|
||||
async def telegram(request: Request) -> Response:
|
||||
"""Handle incoming Telegram updates."""
|
||||
token_header_name = "X-Telegram-Bot-Api-Secret-Token"
|
||||
if request.headers.get(token_header_name) != WEBHOOK_SECRET_TOKEN:
|
||||
return PlainTextResponse("Forbidden", status_code=403)
|
||||
await bot.process_new_updates([Update.de_json(await request.json())])
|
||||
return Response()
|
||||
|
||||
|
||||
async def startup() -> None:
|
||||
"""Register webhook for telegram updates."""
|
||||
webhook_info = await bot.get_webhook_info(30)
|
||||
if WEBHOOK_URL != webhook_info.url:
|
||||
logger.debug(
|
||||
f"updating webhook url, old: {webhook_info.url}, new: {WEBHOOK_URL}"
|
||||
)
|
||||
if not await bot.set_webhook(
|
||||
url=WEBHOOK_URL, secret_token=WEBHOOK_SECRET_TOKEN
|
||||
):
|
||||
raise RuntimeError("unable to set webhook")
|
||||
|
||||
|
||||
app = Starlette(
|
||||
routes=[
|
||||
Route("/telegram", telegram, methods=["POST"]),
|
||||
],
|
||||
on_startup=[startup],
|
||||
)
|
||||
|
||||
|
||||
uvicorn.run(
|
||||
app,
|
||||
host=WEBHOOK_HOST,
|
||||
port=WEBHOOK_LISTEN,
|
||||
ssl_certfile=WEBHOOK_SSL_CERT,
|
||||
ssl_keyfile=WEBHOOK_SSL_PRIV,
|
||||
)
|
|
@ -0,0 +1,25 @@
|
|||
import telebot
|
||||
from telebot import types, AdvancedCustomFilter
|
||||
from telebot.callback_data import CallbackData, CallbackDataFilter
|
||||
|
||||
calendar_factory = CallbackData("year", "month", prefix="calendar")
|
||||
calendar_zoom = CallbackData("year", prefix="calendar_zoom")
|
||||
|
||||
|
||||
class CalendarCallbackFilter(AdvancedCustomFilter):
|
||||
key = 'calendar_config'
|
||||
|
||||
def check(self, call: types.CallbackQuery, config: CallbackDataFilter):
|
||||
return config.check(query=call)
|
||||
|
||||
|
||||
class CalendarZoomCallbackFilter(AdvancedCustomFilter):
|
||||
key = 'calendar_zoom_config'
|
||||
|
||||
def check(self, call: types.CallbackQuery, config: CallbackDataFilter):
|
||||
return config.check(query=call)
|
||||
|
||||
|
||||
def bind_filters(bot: telebot.TeleBot):
|
||||
bot.add_custom_filter(CalendarCallbackFilter())
|
||||
bot.add_custom_filter(CalendarZoomCallbackFilter())
|
|
@ -0,0 +1,92 @@
|
|||
import calendar
|
||||
from datetime import date, timedelta
|
||||
|
||||
from examples.callback_data_examples.advanced_calendar_example.filters import calendar_factory, calendar_zoom
|
||||
from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton
|
||||
|
||||
EMTPY_FIELD = '1'
|
||||
WEEK_DAYS = [calendar.day_abbr[i] for i in range(7)]
|
||||
MONTHS = [(i, calendar.month_name[i]) for i in range(1, 13)]
|
||||
|
||||
|
||||
def generate_calendar_days(year: int, month: int):
|
||||
keyboard = InlineKeyboardMarkup(row_width=7)
|
||||
today = date.today()
|
||||
|
||||
keyboard.add(
|
||||
InlineKeyboardButton(
|
||||
text=date(year=year, month=month, day=1).strftime('%b %Y'),
|
||||
callback_data=EMTPY_FIELD
|
||||
)
|
||||
)
|
||||
keyboard.add(*[
|
||||
InlineKeyboardButton(
|
||||
text=day,
|
||||
callback_data=EMTPY_FIELD
|
||||
)
|
||||
for day in WEEK_DAYS
|
||||
])
|
||||
|
||||
for week in calendar.Calendar().monthdayscalendar(year=year, month=month):
|
||||
week_buttons = []
|
||||
for day in week:
|
||||
day_name = ' '
|
||||
if day == today.day and today.year == year and today.month == month:
|
||||
day_name = '🔘'
|
||||
elif day != 0:
|
||||
day_name = str(day)
|
||||
week_buttons.append(
|
||||
InlineKeyboardButton(
|
||||
text=day_name,
|
||||
callback_data=EMTPY_FIELD
|
||||
)
|
||||
)
|
||||
keyboard.add(*week_buttons)
|
||||
|
||||
previous_date = date(year=year, month=month, day=1) - timedelta(days=1)
|
||||
next_date = date(year=year, month=month, day=1) + timedelta(days=31)
|
||||
|
||||
keyboard.add(
|
||||
InlineKeyboardButton(
|
||||
text='Previous month',
|
||||
callback_data=calendar_factory.new(year=previous_date.year, month=previous_date.month)
|
||||
),
|
||||
InlineKeyboardButton(
|
||||
text='Zoom out',
|
||||
callback_data=calendar_zoom.new(year=year)
|
||||
),
|
||||
InlineKeyboardButton(
|
||||
text='Next month',
|
||||
callback_data=calendar_factory.new(year=next_date.year, month=next_date.month)
|
||||
),
|
||||
)
|
||||
|
||||
return keyboard
|
||||
|
||||
|
||||
def generate_calendar_months(year: int):
|
||||
keyboard = InlineKeyboardMarkup(row_width=3)
|
||||
keyboard.add(
|
||||
InlineKeyboardButton(
|
||||
text=date(year=year, month=1, day=1).strftime('Year %Y'),
|
||||
callback_data=EMTPY_FIELD
|
||||
)
|
||||
)
|
||||
keyboard.add(*[
|
||||
InlineKeyboardButton(
|
||||
text=month,
|
||||
callback_data=calendar_factory.new(year=year, month=month_number)
|
||||
)
|
||||
for month_number, month in MONTHS
|
||||
])
|
||||
keyboard.add(
|
||||
InlineKeyboardButton(
|
||||
text='Previous year',
|
||||
callback_data=calendar_zoom.new(year=year - 1)
|
||||
),
|
||||
InlineKeyboardButton(
|
||||
text='Next year',
|
||||
callback_data=calendar_zoom.new(year=year + 1)
|
||||
)
|
||||
)
|
||||
return keyboard
|
|
@ -0,0 +1,56 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
This Example will show you an advanced usage of CallbackData.
|
||||
In this example calendar was implemented
|
||||
"""
|
||||
|
||||
from datetime import date
|
||||
|
||||
from examples.callback_data_examples.advanced_calendar_example.keyboards import generate_calendar_days, \
|
||||
generate_calendar_months, EMTPY_FIELD
|
||||
from filters import calendar_factory, calendar_zoom, bind_filters
|
||||
from telebot import types, TeleBot
|
||||
|
||||
API_TOKEN = ''
|
||||
bot = TeleBot(API_TOKEN)
|
||||
|
||||
|
||||
@bot.message_handler(commands='start')
|
||||
def start_command_handler(message: types.Message):
|
||||
bot.send_message(message.chat.id,
|
||||
f"Hello {message.from_user.first_name}. This bot is an example of calendar keyboard."
|
||||
"\nPress /calendar to see it.")
|
||||
|
||||
|
||||
@bot.message_handler(commands='calendar')
|
||||
def calendar_command_handler(message: types.Message):
|
||||
now = date.today()
|
||||
bot.send_message(message.chat.id, 'Calendar', reply_markup=generate_calendar_days(year=now.year, month=now.month))
|
||||
|
||||
|
||||
@bot.callback_query_handler(func=None, calendar_config=calendar_factory.filter())
|
||||
def calendar_action_handler(call: types.CallbackQuery):
|
||||
callback_data: dict = calendar_factory.parse(callback_data=call.data)
|
||||
year, month = int(callback_data['year']), int(callback_data['month'])
|
||||
|
||||
bot.edit_message_reply_markup(call.message.chat.id, call.message.id,
|
||||
reply_markup=generate_calendar_days(year=year, month=month))
|
||||
|
||||
|
||||
@bot.callback_query_handler(func=None, calendar_zoom_config=calendar_zoom.filter())
|
||||
def calendar_zoom_out_handler(call: types.CallbackQuery):
|
||||
callback_data: dict = calendar_zoom.parse(callback_data=call.data)
|
||||
year = int(callback_data.get('year'))
|
||||
|
||||
bot.edit_message_reply_markup(call.message.chat.id, call.message.id,
|
||||
reply_markup=generate_calendar_months(year=year))
|
||||
|
||||
|
||||
@bot.callback_query_handler(func=lambda call: call.data == EMTPY_FIELD)
|
||||
def callback_empty_field_handler(call: types.CallbackQuery):
|
||||
bot.answer_callback_query(call.id)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
bind_filters(bot)
|
||||
bot.infinity_polling()
|
|
@ -23,8 +23,8 @@ def my_chat_m(message: types.ChatMemberUpdated):
|
|||
#content_Type_service is:
|
||||
#'new_chat_members', 'left_chat_member', 'new_chat_title', 'new_chat_photo', 'delete_chat_photo', 'group_chat_created',
|
||||
#'supergroup_chat_created', 'channel_chat_created', 'migrate_to_chat_id', 'migrate_from_chat_id', 'pinned_message',
|
||||
#'proximity_alert_triggered', 'voice_chat_scheduled', 'voice_chat_started', 'voice_chat_ended',
|
||||
#'voice_chat_participants_invited', 'message_auto_delete_timer_changed'
|
||||
#'proximity_alert_triggered', 'video_chat_scheduled', 'video_chat_started', 'video_chat_ended',
|
||||
#'video_chat_participants_invited', 'message_auto_delete_timer_changed'
|
||||
# this handler deletes service messages
|
||||
|
||||
@bot.message_handler(content_types=util.content_type_service)
|
||||
|
|
23
examples/continue_handling.py
Normal file
23
examples/continue_handling.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
from telebot import TeleBot
|
||||
from telebot.handler_backends import ContinueHandling
|
||||
|
||||
|
||||
bot = TeleBot('TOKEN')
|
||||
|
||||
@bot.message_handler(commands=['start'])
|
||||
def start(message):
|
||||
bot.send_message(message.chat.id, 'Hello World!')
|
||||
return ContinueHandling()
|
||||
|
||||
@bot.message_handler(commands=['start'])
|
||||
def start2(message):
|
||||
"""
|
||||
This handler comes after the first one, but it will never be called.
|
||||
But you can call it by returning ContinueHandling() in the first handler.
|
||||
|
||||
If you return ContinueHandling() in the first handler, the next
|
||||
registered handler with appropriate filters will be called.
|
||||
"""
|
||||
bot.send_message(message.chat.id, 'Hello World2!')
|
||||
|
||||
bot.infinity_polling()
|
33
examples/create_invite_link.py
Normal file
33
examples/create_invite_link.py
Normal file
|
@ -0,0 +1,33 @@
|
|||
import telebot
|
||||
from time import sleep, time
|
||||
from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton #Only for creating Inline Buttons, not necessary for creating Invite Links
|
||||
|
||||
Token = "api_token" #Your Bot Access Token
|
||||
Group_ID = -1234567890 #Group ID for which invite link is to be created
|
||||
|
||||
bot = telebot.TeleBot(Token, parse_mode="HTML")
|
||||
|
||||
#/start command message
|
||||
@bot.message_handler(commands=['start'])
|
||||
def startmsg(msg):
|
||||
bot.reply_to(msg, "Hey there, I'm a bot made by pyTelegramBotAPI!")
|
||||
|
||||
#Get notified of incoming members in group
|
||||
@bot.message_handler(content_types=['new_chat_members'])
|
||||
def newmember(msg):
|
||||
#Create an invite link class that contains info about the created invite link using create_chat_invite_link() with parameters
|
||||
invite = bot.create_chat_invite_link(Group_ID, member_limit=1, expire_date=int(time())+45) #Here, the link will auto-expire in 45 seconds
|
||||
InviteLink = invite.invite_link #Get the actual invite link from 'invite' class
|
||||
|
||||
mrkplink = InlineKeyboardMarkup() #Created Inline Keyboard Markup
|
||||
mrkplink.add(InlineKeyboardButton("Join our group 🚀", url=InviteLink)) #Added Invite Link to Inline Keyboard
|
||||
|
||||
bot.send_message(msg.chat.id, f"Hey there {msg.from_user.first_name}, Click the link below to join our Official Group.", reply_markup=mrkplink)
|
||||
|
||||
#This will send a message with the newly-created invite link as markup button.
|
||||
#The member limit will be 1 and expiring time will be 45 sec.
|
||||
|
||||
|
||||
|
||||
|
||||
bot.infinity_polling()
|
125
examples/custom_filters/advanced_text_filter.py
Normal file
125
examples/custom_filters/advanced_text_filter.py
Normal file
|
@ -0,0 +1,125 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
This Example will show you usage of TextFilter
|
||||
In this example you will see how to use TextFilter
|
||||
with (message_handler, callback_query_handler, poll_handler)
|
||||
"""
|
||||
|
||||
from telebot import TeleBot, types
|
||||
from telebot.custom_filters import TextFilter, TextMatchFilter, IsReplyFilter
|
||||
|
||||
bot = TeleBot("")
|
||||
|
||||
|
||||
@bot.message_handler(text=TextFilter(equals='hello'))
|
||||
def hello_handler(message: types.Message):
|
||||
bot.send_message(message.chat.id, message.text)
|
||||
|
||||
|
||||
@bot.message_handler(text=TextFilter(equals='hello', ignore_case=True))
|
||||
def hello_handler_ignore_case(message: types.Message):
|
||||
bot.send_message(message.chat.id, message.text + ' ignore case')
|
||||
|
||||
|
||||
@bot.message_handler(text=TextFilter(contains=['good', 'bad']))
|
||||
def contains_handler(message: types.Message):
|
||||
bot.send_message(message.chat.id, message.text)
|
||||
|
||||
|
||||
@bot.message_handler(text=TextFilter(contains=['good', 'bad'], ignore_case=True))
|
||||
def contains_handler_ignore_case(message: types.Message):
|
||||
bot.send_message(message.chat.id, message.text + ' ignore case')
|
||||
|
||||
|
||||
@bot.message_handler(text=TextFilter(starts_with='st')) # stArk, steve, stONE
|
||||
def starts_with_handler(message: types.Message):
|
||||
bot.send_message(message.chat.id, message.text)
|
||||
|
||||
|
||||
@bot.message_handler(text=TextFilter(starts_with='st', ignore_case=True)) # STark, sTeve, stONE
|
||||
def starts_with_handler_ignore_case(message: types.Message):
|
||||
bot.send_message(message.chat.id, message.text + ' ignore case')
|
||||
|
||||
|
||||
@bot.message_handler(text=TextFilter(ends_with='ay')) # wednesday, SUNday, WeekDay
|
||||
def ends_with_handler(message: types.Message):
|
||||
bot.send_message(message.chat.id, message.text)
|
||||
|
||||
|
||||
@bot.message_handler(text=TextFilter(ends_with='ay', ignore_case=True)) # wednesdAY, sundAy, WeekdaY
|
||||
def ends_with_handler_ignore_case(message: types.Message):
|
||||
bot.send_message(message.chat.id, message.text + ' ignore case')
|
||||
|
||||
|
||||
@bot.message_handler(text=TextFilter(equals='/callback'))
|
||||
def send_callback(message: types.Message):
|
||||
keyboard = types.InlineKeyboardMarkup(
|
||||
keyboard=[
|
||||
[types.InlineKeyboardButton(text='callback data', callback_data='example')],
|
||||
[types.InlineKeyboardButton(text='ignore case callback data', callback_data='ExAmPLe')]
|
||||
]
|
||||
)
|
||||
bot.send_message(message.chat.id, message.text, reply_markup=keyboard)
|
||||
|
||||
|
||||
@bot.callback_query_handler(func=None, text=TextFilter(equals='example'))
|
||||
def callback_query_handler(call: types.CallbackQuery):
|
||||
bot.answer_callback_query(call.id, call.data, show_alert=True)
|
||||
|
||||
|
||||
@bot.callback_query_handler(func=None, text=TextFilter(equals='example', ignore_case=True))
|
||||
def callback_query_handler_ignore_case(call: types.CallbackQuery):
|
||||
bot.answer_callback_query(call.id, call.data + " ignore case", show_alert=True)
|
||||
|
||||
|
||||
@bot.message_handler(text=TextFilter(equals='/poll'))
|
||||
def send_poll(message: types.Message):
|
||||
bot.send_poll(message.chat.id, question='When do you prefer to work?', options=['Morning', 'Night'])
|
||||
bot.send_poll(message.chat.id, question='WHEN DO you pRefeR to worK?', options=['Morning', 'Night'])
|
||||
|
||||
|
||||
@bot.poll_handler(func=None, text=TextFilter(equals='When do you prefer to work?'))
|
||||
def poll_question_handler(poll: types.Poll):
|
||||
print(poll.question)
|
||||
|
||||
|
||||
@bot.poll_handler(func=None, text=TextFilter(equals='When do you prefer to work?', ignore_case=True))
|
||||
def poll_question_handler_ignore_case(poll: types.Poll):
|
||||
print(poll.question + ' ignore case')
|
||||
|
||||
|
||||
# either hi or contains one of (привет, salom)
|
||||
@bot.message_handler(text=TextFilter(equals="hi", contains=('привет', 'salom'), ignore_case=True))
|
||||
def multiple_patterns_handler(message: types.Message):
|
||||
bot.send_message(message.chat.id, message.text)
|
||||
|
||||
|
||||
# starts with one of (mi, mea) for ex. minor, milk, meal, meat
|
||||
@bot.message_handler(text=TextFilter(starts_with=['mi', 'mea'], ignore_case=True))
|
||||
def multiple_starts_with_handler(message: types.Message):
|
||||
bot.send_message(message.chat.id, message.text)
|
||||
|
||||
|
||||
# ends with one of (es, on) for ex. Jones, Davies, Johnson, Wilson
|
||||
@bot.message_handler(text=TextFilter(ends_with=['es', 'on'], ignore_case=True))
|
||||
def multiple_ends_with_handler(message: types.Message):
|
||||
bot.send_message(message.chat.id, message.text)
|
||||
|
||||
|
||||
# !ban /ban .ban !бан /бан .бан
|
||||
@bot.message_handler(is_reply=True,
|
||||
text=TextFilter(starts_with=('!', '/', '.'), ends_with=['ban', 'бан'], ignore_case=True))
|
||||
def ban_command_handler(message: types.Message):
|
||||
if len(message.text) == 4 and message.chat.type != 'private':
|
||||
try:
|
||||
bot.ban_chat_member(message.chat.id, message.reply_to_message.from_user.id)
|
||||
bot.reply_to(message.reply_to_message, 'Banned.')
|
||||
except Exception as err:
|
||||
print(err.args)
|
||||
return
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
bot.add_custom_filter(TextMatchFilter())
|
||||
bot.add_custom_filter(IsReplyFilter())
|
||||
bot.infinity_polling()
|
|
@ -1,14 +1,39 @@
|
|||
import telebot
|
||||
import telebot # telebot
|
||||
|
||||
from telebot import custom_filters
|
||||
from telebot.handler_backends import State, StatesGroup #States
|
||||
|
||||
bot = telebot.TeleBot("")
|
||||
# States storage
|
||||
from telebot.storage import StateMemoryStorage
|
||||
|
||||
|
||||
class MyStates:
|
||||
name = 1
|
||||
surname = 2
|
||||
age = 3
|
||||
# Starting from version 4.4.0+, we support storages.
|
||||
# StateRedisStorage -> Redis-based storage.
|
||||
# StatePickleStorage -> Pickle-based storage.
|
||||
# For redis, you will need to install redis.
|
||||
# Pass host, db, password, or anything else,
|
||||
# if you need to change config for redis.
|
||||
# Pickle requires path. Default path is in folder .state-saves.
|
||||
# If you were using older version of pytba for pickle,
|
||||
# you need to migrate from old pickle to new by using
|
||||
# StatePickleStorage().convert_old_to_new()
|
||||
|
||||
|
||||
|
||||
# Now, you can pass storage to bot.
|
||||
state_storage = StateMemoryStorage() # you can init here another storage
|
||||
|
||||
bot = telebot.TeleBot("TOKEN",
|
||||
state_storage=state_storage)
|
||||
|
||||
|
||||
# States group.
|
||||
class MyStates(StatesGroup):
|
||||
# Just name variables differently
|
||||
name = State() # creating instances of State class is enough from now
|
||||
surname = State()
|
||||
age = State()
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -17,50 +42,60 @@ def start_ex(message):
|
|||
"""
|
||||
Start command. Here we are starting state
|
||||
"""
|
||||
bot.set_state(message.from_user.id, MyStates.name)
|
||||
bot.set_state(message.from_user.id, MyStates.name, message.chat.id)
|
||||
bot.send_message(message.chat.id, 'Hi, write me a name')
|
||||
|
||||
|
||||
|
||||
@bot.message_handler(state="*", commands='cancel')
|
||||
# Any state
|
||||
@bot.message_handler(state="*", commands=['cancel'])
|
||||
def any_state(message):
|
||||
"""
|
||||
Cancel state
|
||||
"""
|
||||
bot.send_message(message.chat.id, "Your state was cancelled.")
|
||||
bot.delete_state(message.from_user.id)
|
||||
bot.delete_state(message.from_user.id, message.chat.id)
|
||||
|
||||
@bot.message_handler(state=MyStates.name)
|
||||
def name_get(message):
|
||||
"""
|
||||
State 1. Will process when user's state is 1.
|
||||
State 1. Will process when user's state is MyStates.name.
|
||||
"""
|
||||
bot.send_message(message.chat.id, f'Now write me a surname')
|
||||
bot.set_state(message.from_user.id, MyStates.surname)
|
||||
with bot.retrieve_data(message.from_user.id) as data:
|
||||
bot.send_message(message.chat.id, 'Now write me a surname')
|
||||
bot.set_state(message.from_user.id, MyStates.surname, message.chat.id)
|
||||
with bot.retrieve_data(message.from_user.id, message.chat.id) as data:
|
||||
data['name'] = message.text
|
||||
|
||||
|
||||
@bot.message_handler(state=MyStates.surname)
|
||||
def ask_age(message):
|
||||
"""
|
||||
State 2. Will process when user's state is 2.
|
||||
State 2. Will process when user's state is MyStates.surname.
|
||||
"""
|
||||
bot.send_message(message.chat.id, "What is your age?")
|
||||
bot.set_state(message.from_user.id, MyStates.age)
|
||||
with bot.retrieve_data(message.from_user.id) as data:
|
||||
bot.set_state(message.from_user.id, MyStates.age, message.chat.id)
|
||||
with bot.retrieve_data(message.from_user.id, message.chat.id) as data:
|
||||
data['surname'] = message.text
|
||||
|
||||
# result
|
||||
@bot.message_handler(state=MyStates.age, is_digit=True)
|
||||
def ready_for_answer(message):
|
||||
with bot.retrieve_data(message.from_user.id) as data:
|
||||
bot.send_message(message.chat.id, "Ready, take a look:\n<b>Name: {name}\nSurname: {surname}\nAge: {age}</b>".format(name=data['name'], surname=data['surname'], age=message.text), parse_mode="html")
|
||||
bot.delete_state(message.from_user.id)
|
||||
"""
|
||||
State 3. Will process when user's state is MyStates.age.
|
||||
"""
|
||||
with bot.retrieve_data(message.from_user.id, message.chat.id) as data:
|
||||
msg = ("Ready, take a look:\n<b>"
|
||||
f"Name: {data['name']}\n"
|
||||
f"Surname: {data['surname']}\n"
|
||||
f"Age: {message.text}</b>")
|
||||
bot.send_message(message.chat.id, msg, parse_mode="html")
|
||||
bot.delete_state(message.from_user.id, message.chat.id)
|
||||
|
||||
#incorrect number
|
||||
@bot.message_handler(state=MyStates.age, is_digit=False)
|
||||
def age_incorrect(message):
|
||||
"""
|
||||
Wrong response for MyStates.age
|
||||
"""
|
||||
bot.send_message(message.chat.id, 'Looks like you are submitting a string in the field age. Please enter a number')
|
||||
|
||||
# register filters
|
||||
|
@ -68,7 +103,4 @@ def age_incorrect(message):
|
|||
bot.add_custom_filter(custom_filters.StateFilter(bot))
|
||||
bot.add_custom_filter(custom_filters.IsDigitFilter())
|
||||
|
||||
# set saving states into file.
|
||||
bot.enable_saving_states() # you can delete this if you do not need to save states
|
||||
|
||||
bot.infinity_polling(skip_pending=True)
|
||||
bot.infinity_polling(skip_pending=True)
|
||||
|
|
28
examples/detect_changes.py
Normal file
28
examples/detect_changes.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# This is a simple echo bot using the decorator mechanism.
|
||||
# It echoes any incoming text messages.
|
||||
|
||||
import telebot
|
||||
|
||||
API_TOKEN = '<api_token>'
|
||||
|
||||
bot = telebot.TeleBot(API_TOKEN)
|
||||
|
||||
|
||||
# Handle '/start' and '/help'
|
||||
@bot.message_handler(commands=['help', 'start'])
|
||||
def send_welcome(message):
|
||||
bot.reply_to(message, """\
|
||||
Hi there, I am EchoBot.
|
||||
I am here to echo your kind words back to you. Just say anything nice and I'll say the exact same thing to you!\
|
||||
""")
|
||||
|
||||
|
||||
# Handle all other messages with content_type 'text' (content_types defaults to ['text'])
|
||||
@bot.message_handler(func=lambda message: True)
|
||||
def echo_message(message):
|
||||
bot.reply_to(message, message.text)
|
||||
|
||||
# only for versions 4.7.0+
|
||||
bot.infinity_polling(restart_on_change=True)
|
53
examples/formatting_example.py
Normal file
53
examples/formatting_example.py
Normal file
|
@ -0,0 +1,53 @@
|
|||
from telebot import TeleBot
|
||||
from telebot import formatting
|
||||
|
||||
bot = TeleBot('TOKEN')
|
||||
|
||||
|
||||
@bot.message_handler(commands=['start'])
|
||||
def start_message(message):
|
||||
bot.send_message(
|
||||
message.chat.id,
|
||||
# function which connects all strings
|
||||
formatting.format_text(
|
||||
formatting.mbold(message.from_user.first_name),
|
||||
formatting.mitalic(message.from_user.first_name),
|
||||
formatting.munderline(message.from_user.first_name),
|
||||
formatting.mstrikethrough(message.from_user.first_name),
|
||||
formatting.mcode(message.from_user.first_name),
|
||||
separator=" " # separator separates all strings
|
||||
),
|
||||
parse_mode='MarkdownV2'
|
||||
)
|
||||
|
||||
# just a bold text using markdownv2
|
||||
bot.send_message(
|
||||
message.chat.id,
|
||||
formatting.mbold(message.from_user.first_name),
|
||||
parse_mode='MarkdownV2'
|
||||
)
|
||||
|
||||
# html
|
||||
bot.send_message(
|
||||
message.chat.id,
|
||||
formatting.format_text(
|
||||
formatting.hbold(message.from_user.first_name),
|
||||
formatting.hitalic(message.from_user.first_name),
|
||||
formatting.hunderline(message.from_user.first_name),
|
||||
formatting.hstrikethrough(message.from_user.first_name),
|
||||
formatting.hcode(message.from_user.first_name),
|
||||
# hide_link is only for html
|
||||
formatting.hide_link('https://telegra.ph/file/c158e3a6e2a26a160b253.jpg'),
|
||||
separator=" "
|
||||
),
|
||||
parse_mode='HTML'
|
||||
)
|
||||
|
||||
# just a bold text in html
|
||||
bot.send_message(
|
||||
message.chat.id,
|
||||
formatting.hbold(message.from_user.first_name),
|
||||
parse_mode='HTML'
|
||||
)
|
||||
|
||||
bot.infinity_polling()
|
|
@ -42,7 +42,7 @@ def query_video(inline_query):
|
|||
try:
|
||||
r = types.InlineQueryResultVideo('1',
|
||||
'https://github.com/eternnoir/pyTelegramBotAPI/blob/master/tests/test_data/test_video.mp4?raw=true',
|
||||
'video/mp4', 'Video',
|
||||
'video/mp4',
|
||||
'https://raw.githubusercontent.com/eternnoir/pyTelegramBotAPI/master/examples/detailed_example/rooster.jpg',
|
||||
'Title'
|
||||
)
|
||||
|
|
35
examples/middleware/README.md
Normal file
35
examples/middleware/README.md
Normal file
|
@ -0,0 +1,35 @@
|
|||
# Middlewares
|
||||
|
||||
## Type of middlewares in pyTelegramBotAPI
|
||||
Currently, synchronous version of pyTelegramBotAPI has two types of middlewares:
|
||||
|
||||
- Class-based middlewares
|
||||
- Function-based middlewares
|
||||
|
||||
## Purpose of middlewares
|
||||
Middlewares are designed to get update before handler's execution.
|
||||
|
||||
## Class-based middlewares
|
||||
This type of middleware has more functionality compared to function-based one.
|
||||
|
||||
Class based middleware should be instance of `telebot.handler_backends.BaseMiddleware.`
|
||||
|
||||
Each middleware should have 2 main functions:
|
||||
|
||||
`pre_process` -> is a method of class which receives update, and data.
|
||||
|
||||
Data - is a dictionary, which could be passed right to handler, and `post_process` function.
|
||||
|
||||
`post_process` -> is a function of class which receives update, data, and exception, that happened in handler. If handler was executed correctly - then exception will equal to None.
|
||||
|
||||
## Function-based middlewares
|
||||
To use function-based middleware, you should set `apihelper.ENABLE_MIDDLEWARE = True`.
|
||||
This type of middleware is created by using a decorator for middleware.
|
||||
With this type middleware, you can retrieve update immediately after update came. You should set update_types as well.
|
||||
|
||||
## Why class-based middlewares are better?
|
||||
- You can pass data between post, pre_process functions, and handler.
|
||||
- If there is an exception in handler, you will get exception parameter with exception class in post_process.
|
||||
- Has post_process -> method which works after the handler's execution.
|
||||
|
||||
## Take a look at examples for more.
|
39
examples/middleware/class_based/antiflood_middleware.py
Normal file
39
examples/middleware/class_based/antiflood_middleware.py
Normal file
|
@ -0,0 +1,39 @@
|
|||
# Just a little example of middleware handlers
|
||||
|
||||
from telebot.handler_backends import BaseMiddleware
|
||||
from telebot import TeleBot
|
||||
from telebot.handler_backends import CancelUpdate
|
||||
bot = TeleBot('TOKEN',
|
||||
use_class_middlewares=True) # if you don't set it to true, middlewares won't work
|
||||
|
||||
|
||||
class SimpleMiddleware(BaseMiddleware):
|
||||
def __init__(self, limit) -> None:
|
||||
self.last_time = {}
|
||||
self.limit = limit
|
||||
self.update_types = ['message']
|
||||
# Always specify update types, otherwise middlewares won't work
|
||||
|
||||
|
||||
def pre_process(self, message, data):
|
||||
if not message.from_user.id in self.last_time:
|
||||
# User is not in a dict, so lets add and cancel this function
|
||||
self.last_time[message.from_user.id] = message.date
|
||||
return
|
||||
if message.date - self.last_time[message.from_user.id] < self.limit:
|
||||
# User is flooding
|
||||
bot.send_message(message.chat.id, 'You are making request too often')
|
||||
return CancelUpdate()
|
||||
self.last_time[message.from_user.id] = message.date
|
||||
|
||||
|
||||
def post_process(self, message, data, exception):
|
||||
pass
|
||||
|
||||
bot.setup_middleware(SimpleMiddleware(2))
|
||||
|
||||
@bot.message_handler(commands=['start'])
|
||||
def start(message): # you don't have to put data in handler.
|
||||
bot.send_message(message.chat.id, 'Hello!')
|
||||
|
||||
bot.infinity_polling()
|
32
examples/middleware/class_based/basic_example.py
Normal file
32
examples/middleware/class_based/basic_example.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
from telebot import TeleBot
|
||||
from telebot.handler_backends import BaseMiddleware
|
||||
|
||||
bot = TeleBot('TOKEN', use_class_middlewares=True) # set use_class_middlewares to True!
|
||||
# otherwise, class-based middlewares won't execute.
|
||||
|
||||
# You can use this classes for cancelling update or skipping handler:
|
||||
# from telebot.handler_backends import CancelUpdate, SkipHandler
|
||||
|
||||
class Middleware(BaseMiddleware):
|
||||
def __init__(self):
|
||||
self.update_types = ['message']
|
||||
def pre_process(self, message, data):
|
||||
data['foo'] = 'Hello' # just for example
|
||||
# we edited the data. now, this data is passed to handler.
|
||||
# return SkipHandler() -> this will skip handler
|
||||
# return CancelUpdate() -> this will cancel update
|
||||
def post_process(self, message, data, exception=None):
|
||||
print(data['foo'])
|
||||
if exception: # check for exception
|
||||
print(exception)
|
||||
|
||||
@bot.message_handler(commands=['start'])
|
||||
def start(message, data: dict): # you don't have to put data parameter in handler if you don't need it.
|
||||
bot.send_message(message.chat.id, data['foo'])
|
||||
data['foo'] = 'Processed' # we changed value of data.. this data is now passed to post_process.
|
||||
|
||||
|
||||
# Setup middleware
|
||||
bot.setup_middleware(Middleware())
|
||||
|
||||
bot.infinity_polling()
|
|
@ -0,0 +1,121 @@
|
|||
import gettext
|
||||
import os
|
||||
import threading
|
||||
|
||||
from telebot.handler_backends import BaseMiddleware
|
||||
|
||||
try:
|
||||
from babel.support import LazyProxy
|
||||
|
||||
babel_imported = True
|
||||
except ImportError:
|
||||
babel_imported = False
|
||||
|
||||
|
||||
class I18N(BaseMiddleware):
|
||||
"""
|
||||
This middleware provides high-level tool for internationalization
|
||||
It is based on gettext util.
|
||||
"""
|
||||
|
||||
context_lang = threading.local()
|
||||
|
||||
def __init__(self, translations_path, domain_name: str):
|
||||
super().__init__()
|
||||
self.update_types = self.process_update_types()
|
||||
|
||||
self.path = translations_path
|
||||
self.domain = domain_name
|
||||
self.translations = self.find_translations()
|
||||
|
||||
@property
|
||||
def available_translations(self):
|
||||
return list(self.translations)
|
||||
|
||||
def gettext(self, text: str, lang: str = None):
|
||||
"""
|
||||
Singular translations
|
||||
"""
|
||||
|
||||
if lang is None:
|
||||
lang = self.context_lang.language
|
||||
|
||||
if lang not in self.translations:
|
||||
return text
|
||||
|
||||
translator = self.translations[lang]
|
||||
return translator.gettext(text)
|
||||
|
||||
def ngettext(self, singular: str, plural: str, lang: str = None, n=1):
|
||||
"""
|
||||
Plural translations
|
||||
"""
|
||||
if lang is None:
|
||||
lang = self.context_lang.language
|
||||
|
||||
if lang not in self.translations:
|
||||
if n == 1:
|
||||
return singular
|
||||
return plural
|
||||
|
||||
translator = self.translations[lang]
|
||||
return translator.ngettext(singular, plural, n)
|
||||
|
||||
def lazy_gettext(self, text: str, lang: str = None):
|
||||
if not babel_imported:
|
||||
raise RuntimeError('babel module is not imported. Check that you installed it.')
|
||||
return LazyProxy(self.gettext, text, lang, enable_cache=False)
|
||||
|
||||
def lazy_ngettext(self, singular: str, plural: str, lang: str = None, n=1):
|
||||
if not babel_imported:
|
||||
raise RuntimeError('babel module is not imported. Check that you installed it.')
|
||||
return LazyProxy(self.ngettext, singular, plural, lang, n, enable_cache=False)
|
||||
|
||||
def get_user_language(self, obj):
|
||||
"""
|
||||
You need to override this method and return user language
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def process_update_types(self) -> list:
|
||||
"""
|
||||
You need to override this method and return any update types which you want to be processed
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def pre_process(self, message, data):
|
||||
"""
|
||||
context language variable will be set each time when update from 'process_update_types' comes
|
||||
value is the result of 'get_user_language' method
|
||||
"""
|
||||
|
||||
self.context_lang.language = self.get_user_language(obj=message)
|
||||
|
||||
def post_process(self, message, data, exception):
|
||||
pass
|
||||
|
||||
def find_translations(self):
|
||||
"""
|
||||
Looks for translations with passed 'domain' in passed 'path'
|
||||
"""
|
||||
if not os.path.exists(self.path):
|
||||
raise RuntimeError(f"Translations directory by path: {self.path!r} was not found")
|
||||
|
||||
result = {}
|
||||
|
||||
for name in os.listdir(self.path):
|
||||
translations_path = os.path.join(self.path, name, 'LC_MESSAGES')
|
||||
|
||||
if not os.path.isdir(translations_path):
|
||||
continue
|
||||
|
||||
po_file = os.path.join(translations_path, self.domain + '.po')
|
||||
mo_file = po_file[:-2] + 'mo'
|
||||
|
||||
if os.path.isfile(po_file) and not os.path.isfile(mo_file):
|
||||
raise FileNotFoundError(f"Translations for: {name!r} were not compiled!")
|
||||
|
||||
with open(mo_file, 'rb') as file:
|
||||
result[name] = gettext.GNUTranslations(file)
|
||||
|
||||
return result
|
34
examples/middleware/class_based/i18n_middleware/keyboards.py
Normal file
34
examples/middleware/class_based/i18n_middleware/keyboards.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton, ReplyKeyboardMarkup, KeyboardButton
|
||||
|
||||
|
||||
def languages_keyboard():
|
||||
return InlineKeyboardMarkup(
|
||||
keyboard=[
|
||||
[
|
||||
InlineKeyboardButton(text="English", callback_data='en'),
|
||||
InlineKeyboardButton(text="Русский", callback_data='ru'),
|
||||
InlineKeyboardButton(text="O'zbekcha", callback_data='uz_Latn')
|
||||
]
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def clicker_keyboard(_):
|
||||
return InlineKeyboardMarkup(
|
||||
keyboard=[
|
||||
[
|
||||
InlineKeyboardButton(text=_("click"), callback_data='click'),
|
||||
]
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def menu_keyboard(_):
|
||||
keyboard = ReplyKeyboardMarkup(resize_keyboard=True)
|
||||
keyboard.add(
|
||||
KeyboardButton(text=_("My user id")),
|
||||
KeyboardButton(text=_("My user name")),
|
||||
KeyboardButton(text=_("My first name"))
|
||||
)
|
||||
|
||||
return keyboard
|
|
@ -0,0 +1,81 @@
|
|||
# English translations for PROJECT.
|
||||
# Copyright (C) 2022 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2022-02-19 18:37+0500\n"
|
||||
"PO-Revision-Date: 2022-02-18 16:22+0500\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language: en\n"
|
||||
"Language-Team: en <LL@li.org>\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.9.1\n"
|
||||
|
||||
#: keyboards.py:20
|
||||
msgid "click"
|
||||
msgstr ""
|
||||
|
||||
#: keyboards.py:29
|
||||
msgid "My user id"
|
||||
msgstr ""
|
||||
|
||||
#: keyboards.py:30
|
||||
msgid "My user name"
|
||||
msgstr ""
|
||||
|
||||
#: keyboards.py:31
|
||||
msgid "My first name"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:97
|
||||
msgid ""
|
||||
"Hello, {user_fist_name}!\n"
|
||||
"This is the example of multilanguage bot.\n"
|
||||
"Available commands:\n"
|
||||
"\n"
|
||||
"/lang - change your language\n"
|
||||
"/plural - pluralization example\n"
|
||||
"/menu - text menu example"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:121
|
||||
msgid "Language has been changed"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:130 main.py:150
|
||||
#, fuzzy
|
||||
msgid "You have {number} click"
|
||||
msgid_plural "You have {number} clicks"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: main.py:135 main.py:155
|
||||
msgid ""
|
||||
"This is clicker.\n"
|
||||
"\n"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:163
|
||||
msgid "This is ReplyKeyboardMarkup menu example in multilanguage bot."
|
||||
msgstr ""
|
||||
|
||||
#: main.py:203
|
||||
msgid "Seems you confused language"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Hello, {user_fist_name}!\n"
|
||||
#~ "This is the example of multilanguage bot.\n"
|
||||
#~ "Available commands:\n"
|
||||
#~ "\n"
|
||||
#~ "/lang - change your language\n"
|
||||
#~ "/plural - pluralization example"
|
||||
#~ msgstr ""
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
# Russian translations for PROJECT.
|
||||
# Copyright (C) 2022 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2022-02-19 18:37+0500\n"
|
||||
"PO-Revision-Date: 2022-02-18 16:22+0500\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language: ru\n"
|
||||
"Language-Team: ru <LL@li.org>\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
||||
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.9.1\n"
|
||||
|
||||
#: keyboards.py:20
|
||||
msgid "click"
|
||||
msgstr "Клик"
|
||||
|
||||
#: keyboards.py:29
|
||||
msgid "My user id"
|
||||
msgstr "Мой user id"
|
||||
|
||||
#: keyboards.py:30
|
||||
msgid "My user name"
|
||||
msgstr "Мой user name"
|
||||
|
||||
#: keyboards.py:31
|
||||
msgid "My first name"
|
||||
msgstr "Мой first name"
|
||||
|
||||
#: main.py:97
|
||||
msgid ""
|
||||
"Hello, {user_fist_name}!\n"
|
||||
"This is the example of multilanguage bot.\n"
|
||||
"Available commands:\n"
|
||||
"\n"
|
||||
"/lang - change your language\n"
|
||||
"/plural - pluralization example\n"
|
||||
"/menu - text menu example"
|
||||
msgstr ""
|
||||
"Привет, {user_fist_name}!\n"
|
||||
"Это пример мультиязычного бота.\n"
|
||||
"Доступные команды:\n"
|
||||
"\n"
|
||||
"/lang - изменить язык\n"
|
||||
"/plural - пример плюрализации\n"
|
||||
"/menu - Пример текстового меню"
|
||||
|
||||
#: main.py:121
|
||||
msgid "Language has been changed"
|
||||
msgstr "Язык был сменён"
|
||||
|
||||
#: main.py:130 main.py:150
|
||||
msgid "You have {number} click"
|
||||
msgid_plural "You have {number} clicks"
|
||||
msgstr[0] "У вас {number} клик"
|
||||
msgstr[1] "У вас {number} клика"
|
||||
msgstr[2] "У вас {number} кликов"
|
||||
|
||||
#: main.py:135 main.py:155
|
||||
msgid ""
|
||||
"This is clicker.\n"
|
||||
"\n"
|
||||
msgstr ""
|
||||
"Это кликер.\n"
|
||||
"\n"
|
||||
|
||||
#: main.py:163
|
||||
msgid "This is ReplyKeyboardMarkup menu example in multilanguage bot."
|
||||
msgstr "Это пример ReplyKeyboardMarkup меню в мультиязычном боте."
|
||||
|
||||
#: main.py:203
|
||||
msgid "Seems you confused language"
|
||||
msgstr "Кажется, вы перепутали язык"
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
# Uzbek (Latin) translations for PROJECT.
|
||||
# Copyright (C) 2022 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2022-02-19 18:37+0500\n"
|
||||
"PO-Revision-Date: 2022-02-18 16:22+0500\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language: uz_Latn\n"
|
||||
"Language-Team: uz_Latn <LL@li.org>\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.9.1\n"
|
||||
|
||||
#: keyboards.py:20
|
||||
msgid "click"
|
||||
msgstr "clik"
|
||||
|
||||
#: keyboards.py:29
|
||||
msgid "My user id"
|
||||
msgstr "Mani user id"
|
||||
|
||||
#: keyboards.py:30
|
||||
msgid "My user name"
|
||||
msgstr "Mani user name"
|
||||
|
||||
#: keyboards.py:31
|
||||
msgid "My first name"
|
||||
msgstr "Mani first name"
|
||||
|
||||
#: main.py:97
|
||||
msgid ""
|
||||
"Hello, {user_fist_name}!\n"
|
||||
"This is the example of multilanguage bot.\n"
|
||||
"Available commands:\n"
|
||||
"\n"
|
||||
"/lang - change your language\n"
|
||||
"/plural - pluralization example\n"
|
||||
"/menu - text menu example"
|
||||
msgstr ""
|
||||
"Salom, {user_fist_name}!\n"
|
||||
"Bu multilanguage bot misoli.\n"
|
||||
"Mavjud buyruqlar:\n"
|
||||
"\n"
|
||||
"/lang - tilni ozgartirish\n"
|
||||
"/plural - pluralizatsiya misoli\n"
|
||||
"/menu - text menu misoli"
|
||||
|
||||
#: main.py:121
|
||||
msgid "Language has been changed"
|
||||
msgstr "Til ozgartirildi"
|
||||
|
||||
#: main.py:130 main.py:150
|
||||
msgid "You have {number} click"
|
||||
msgid_plural "You have {number} clicks"
|
||||
msgstr[0] "Sizda {number}ta clik"
|
||||
msgstr[1] "Sizda {number}ta clik"
|
||||
|
||||
#: main.py:135 main.py:155
|
||||
msgid ""
|
||||
"This is clicker.\n"
|
||||
"\n"
|
||||
msgstr ""
|
||||
"Bu clicker.\n"
|
||||
"\n"
|
||||
|
||||
#: main.py:163
|
||||
msgid "This is ReplyKeyboardMarkup menu example in multilanguage bot."
|
||||
msgstr "Bu multilanguage bot da replykeyboardmarkup menyu misoli."
|
||||
|
||||
#: main.py:203
|
||||
msgid "Seems you confused language"
|
||||
msgstr "Tilni adashtirdiz"
|
||||
|
211
examples/middleware/class_based/i18n_middleware/main.py
Normal file
211
examples/middleware/class_based/i18n_middleware/main.py
Normal file
|
@ -0,0 +1,211 @@
|
|||
"""
|
||||
In this example you will learn how to adapt your bot to different languages
|
||||
Using built-in middleware I18N.
|
||||
|
||||
You need to install babel package 'https://pypi.org/project/Babel/'
|
||||
Babel provides a command-line interface for working with message catalogs
|
||||
After installing babel package you have a script called 'pybabel'
|
||||
Too see all the commands open terminal and type 'pybabel --help'
|
||||
Full description for pybabel commands can be found here: 'https://babel.pocoo.org/en/latest/cmdline.html'
|
||||
|
||||
Create a directory 'locales' where our translations will be stored
|
||||
|
||||
First we need to extract texts:
|
||||
pybabel extract -o locales/{domain_name}.pot --input-dirs .
|
||||
{domain_name}.pot - is the file where all translations are saved
|
||||
The name of this file should be the same as domain which you pass to I18N class
|
||||
In this example domain_name will be 'messages'
|
||||
|
||||
For gettext (singular texts) we use '_' alias and it works perfect
|
||||
You may also you some alias for ngettext (plural texts) but you can face with a problem that
|
||||
your plural texts are not being extracted
|
||||
That is because by default 'pybabel extract' recognizes the following keywords:
|
||||
_, gettext, ngettext, ugettext, ungettext, dgettext, dngettext, N_
|
||||
To add your own keyword you can use '-k' flag
|
||||
In this example for 'ngettext' i will assign double underscore alias '__'
|
||||
|
||||
Full command with pluralization support will look so:
|
||||
pybabel extract -o locales/{domain_name}.pot -k __:1,2 --input-dirs .
|
||||
|
||||
Then create directories with translations (get list of all locales: 'pybabel --list-locales'):
|
||||
pybabel init -i locales/{domain_name}.pot -d locales -l en
|
||||
pybabel init -i locales/{domain_name}.pot -d locales -l ru
|
||||
pybabel init -i locales/{domain_name}.pot -d locales -l uz_Latn
|
||||
|
||||
Now you can translate the texts located in locales/{language}/LC_MESSAGES/{domain_name}.po
|
||||
After you translated all the texts you need to compile .po files:
|
||||
pybabel compile -d locales
|
||||
|
||||
When you delete/update your texts you also need to update them in .po files:
|
||||
pybabel extract -o locales/{domain_name}.pot -k __:1,2 --input-dirs .
|
||||
pybabel update -i locales/{domain_name}.pot -d locales
|
||||
- translate
|
||||
pybabel compile -d locales
|
||||
|
||||
If you have any exceptions check:
|
||||
- you have installed babel
|
||||
- translations are ready, so you just compiled it
|
||||
- in the commands above you replaced {domain_name} to messages
|
||||
- you are writing commands from correct path in terminal
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from typing import Union
|
||||
|
||||
import keyboards
|
||||
from i18n_base_middleware import I18N
|
||||
from telebot import TeleBot
|
||||
from telebot import types, StateMemoryStorage
|
||||
from telebot.custom_filters import TextMatchFilter, TextFilter
|
||||
|
||||
class I18NMiddleware(I18N):
|
||||
|
||||
def process_update_types(self) -> list:
|
||||
"""
|
||||
Here you need to return a list of update types which you want to be processed
|
||||
"""
|
||||
return ['message', 'callback_query']
|
||||
|
||||
def get_user_language(self, obj: Union[types.Message, types.CallbackQuery]):
|
||||
"""
|
||||
This method is called when new update comes (only updates which you return in 'process_update_types' method)
|
||||
Returned language will be used in 'pre_process' method of parent class
|
||||
Returned language will be set to context language variable.
|
||||
If you need to get translation with user's actual language you don't have to pass it manually
|
||||
It will be automatically passed from context language value.
|
||||
However if you need some other language you can always pass it.
|
||||
"""
|
||||
|
||||
user_id = obj.from_user.id
|
||||
|
||||
if user_id not in users_lang:
|
||||
users_lang[user_id] = 'en'
|
||||
|
||||
return users_lang[user_id]
|
||||
|
||||
|
||||
storage = StateMemoryStorage()
|
||||
bot = TeleBot("", state_storage=storage, use_class_middlewares=True)
|
||||
|
||||
i18n = I18NMiddleware(translations_path='locales', domain_name='messages')
|
||||
_ = i18n.gettext # for singular translations
|
||||
__ = i18n.ngettext # for plural translations
|
||||
|
||||
# These are example storages, do not use it in a production development
|
||||
users_lang = {}
|
||||
users_clicks = {}
|
||||
|
||||
@bot.message_handler(commands=['start'])
|
||||
def start_handler(message: types.Message):
|
||||
text = _("Hello, {user_fist_name}!\n"
|
||||
"This is the example of multilanguage bot.\n"
|
||||
"Available commands:\n\n"
|
||||
"/lang - change your language\n"
|
||||
"/plural - pluralization example\n"
|
||||
"/menu - text menu example")
|
||||
|
||||
# remember don't use f string for interpolation, use .format method instead
|
||||
text = text.format(user_fist_name=message.from_user.first_name)
|
||||
bot.send_message(message.from_user.id, text)
|
||||
|
||||
|
||||
@bot.message_handler(commands=['lang'])
|
||||
def change_language_handler(message: types.Message):
|
||||
bot.send_message(message.chat.id, "Choose language\nВыберите язык\nTilni tanlang",
|
||||
reply_markup=keyboards.languages_keyboard())
|
||||
|
||||
|
||||
@bot.callback_query_handler(func=None, text=TextFilter(contains=['en', 'ru', 'uz_Latn']))
|
||||
def language_handler(call: types.CallbackQuery):
|
||||
lang = call.data
|
||||
users_lang[call.from_user.id] = lang
|
||||
|
||||
# When you changed user language, you have to pass it manually beacause it is not changed in context
|
||||
bot.edit_message_text(_("Language has been changed", lang=lang), call.from_user.id, call.message.id)
|
||||
|
||||
|
||||
@bot.message_handler(commands=['plural'])
|
||||
def pluralization_handler(message: types.Message):
|
||||
if not users_clicks.get(message.from_user.id):
|
||||
users_clicks[message.from_user.id] = 0
|
||||
clicks = users_clicks[message.from_user.id]
|
||||
|
||||
text = __(
|
||||
singular="You have {number} click",
|
||||
plural="You have {number} clicks",
|
||||
n=clicks
|
||||
)
|
||||
text = _("This is clicker.\n\n") + text.format(number=clicks)
|
||||
|
||||
bot.send_message(message.chat.id, text, reply_markup=keyboards.clicker_keyboard(_))
|
||||
|
||||
|
||||
@bot.callback_query_handler(func=None, text=TextFilter(equals='click'))
|
||||
def click_handler(call: types.CallbackQuery):
|
||||
if not users_clicks.get(call.from_user.id):
|
||||
users_clicks[call.from_user.id] = 1
|
||||
else:
|
||||
users_clicks[call.from_user.id] += 1
|
||||
|
||||
clicks = users_clicks[call.from_user.id]
|
||||
|
||||
text = __(
|
||||
singular="You have {number} click",
|
||||
plural="You have {number} clicks",
|
||||
n=clicks
|
||||
)
|
||||
text = _("This is clicker.\n\n") + text.format(number=clicks)
|
||||
|
||||
bot.edit_message_text(text, call.from_user.id, call.message.message_id,
|
||||
reply_markup=keyboards.clicker_keyboard(_))
|
||||
|
||||
|
||||
@bot.message_handler(commands=['menu'])
|
||||
def menu_handler(message: types.Message):
|
||||
text = _("This is ReplyKeyboardMarkup menu example in multilanguage bot.")
|
||||
bot.send_message(message.chat.id, text, reply_markup=keyboards.menu_keyboard(_))
|
||||
|
||||
|
||||
# For lazy tranlations
|
||||
# lazy gettext is used when you don't know user's locale
|
||||
# It can be used for example to handle text buttons in multilanguage bot
|
||||
# The actual translation will be delayed until update comes and context language is set
|
||||
l_ = i18n.lazy_gettext
|
||||
|
||||
|
||||
# Handlers below will handle text according to user's language
|
||||
@bot.message_handler(text=l_("My user id"))
|
||||
def return_user_id(message: types.Message):
|
||||
bot.send_message(message.chat.id, str(message.from_user.id))
|
||||
|
||||
|
||||
@bot.message_handler(text=l_("My user name"))
|
||||
def return_user_id(message: types.Message):
|
||||
username = message.from_user.username
|
||||
if not username:
|
||||
username = '-'
|
||||
bot.send_message(message.chat.id, username)
|
||||
|
||||
|
||||
# You can make it case-insensitive
|
||||
@bot.message_handler(text=TextFilter(equals=l_("My first name"), ignore_case=True))
|
||||
def return_user_id(message: types.Message):
|
||||
bot.send_message(message.chat.id, message.from_user.first_name)
|
||||
|
||||
|
||||
all_menu_texts = []
|
||||
for language in i18n.available_translations:
|
||||
for menu_text in ("My user id", "My user name", "My first name"):
|
||||
all_menu_texts.append(_(menu_text, language))
|
||||
|
||||
|
||||
# When user confused language. (handles all menu buttons texts)
|
||||
@bot.message_handler(text=TextFilter(contains=all_menu_texts, ignore_case=True))
|
||||
def missed_message(message: types.Message):
|
||||
bot.send_message(message.chat.id, _("Seems you confused language"), reply_markup=keyboards.menu_keyboard(_))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
bot.setup_middleware(i18n)
|
||||
bot.add_custom_filter(TextMatchFilter())
|
||||
asyncio.run(bot.infinity_polling())
|
|
@ -0,0 +1,77 @@
|
|||
import gettext
|
||||
import os
|
||||
import threading
|
||||
|
||||
|
||||
class I18N:
|
||||
"""
|
||||
This class provides high-level tool for internationalization
|
||||
It is based on gettext util.
|
||||
"""
|
||||
|
||||
context_lang = threading.local()
|
||||
|
||||
def __init__(self, translations_path, domain_name: str):
|
||||
self.path = translations_path
|
||||
self.domain = domain_name
|
||||
self.translations = self.find_translations()
|
||||
|
||||
@property
|
||||
def available_translations(self):
|
||||
return list(self.translations)
|
||||
|
||||
def gettext(self, text: str, lang: str = None):
|
||||
"""
|
||||
Singular translations
|
||||
"""
|
||||
|
||||
if lang is None:
|
||||
lang = self.context_lang.language
|
||||
|
||||
if lang not in self.translations:
|
||||
return text
|
||||
|
||||
translator = self.translations[lang]
|
||||
return translator.gettext(text)
|
||||
|
||||
def ngettext(self, singular: str, plural: str, lang: str = None, n=1):
|
||||
"""
|
||||
Plural translations
|
||||
"""
|
||||
if lang is None:
|
||||
lang = self.context_lang.language
|
||||
|
||||
if lang not in self.translations:
|
||||
if n == 1:
|
||||
return singular
|
||||
return plural
|
||||
|
||||
translator = self.translations[lang]
|
||||
return translator.ngettext(singular, plural, n)
|
||||
|
||||
|
||||
def find_translations(self):
|
||||
"""
|
||||
Looks for translations with passed 'domain' in passed 'path'
|
||||
"""
|
||||
if not os.path.exists(self.path):
|
||||
raise RuntimeError(f"Translations directory by path: {self.path!r} was not found")
|
||||
|
||||
result = {}
|
||||
|
||||
for name in os.listdir(self.path):
|
||||
translations_path = os.path.join(self.path, name, 'LC_MESSAGES')
|
||||
|
||||
if not os.path.isdir(translations_path):
|
||||
continue
|
||||
|
||||
po_file = os.path.join(translations_path, self.domain + '.po')
|
||||
mo_file = po_file[:-2] + 'mo'
|
||||
|
||||
if os.path.isfile(po_file) and not os.path.isfile(mo_file):
|
||||
raise FileNotFoundError(f"Translations for: {name!r} were not compiled!")
|
||||
|
||||
with open(mo_file, 'rb') as file:
|
||||
result[name] = gettext.GNUTranslations(file)
|
||||
|
||||
return result
|
23
examples/middleware/function_based/i18n_gettext/keyboards.py
Normal file
23
examples/middleware/function_based/i18n_gettext/keyboards.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton
|
||||
|
||||
|
||||
def languages_keyboard():
|
||||
return InlineKeyboardMarkup(
|
||||
keyboard=[
|
||||
[
|
||||
InlineKeyboardButton(text="English", callback_data='en'),
|
||||
InlineKeyboardButton(text="Русский", callback_data='ru'),
|
||||
InlineKeyboardButton(text="O'zbekcha", callback_data='uz_Latn')
|
||||
]
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def clicker_keyboard(_):
|
||||
return InlineKeyboardMarkup(
|
||||
keyboard=[
|
||||
[
|
||||
InlineKeyboardButton(text=_("click"), callback_data='click'),
|
||||
]
|
||||
]
|
||||
)
|
|
@ -0,0 +1,50 @@
|
|||
# English translations for PROJECT.
|
||||
# Copyright (C) 2022 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2022-02-18 17:54+0500\n"
|
||||
"PO-Revision-Date: 2022-02-18 16:22+0500\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language: en\n"
|
||||
"Language-Team: en <LL@li.org>\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.9.1\n"
|
||||
|
||||
#: keyboards.py:20
|
||||
msgid "click"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:78
|
||||
msgid ""
|
||||
"Hello, {user_fist_name}!\n"
|
||||
"This is the example of multilanguage bot.\n"
|
||||
"Available commands:\n"
|
||||
"\n"
|
||||
"/lang - change your language\n"
|
||||
"/plural - pluralization example"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:102
|
||||
msgid "Language has been changed"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:114
|
||||
#, fuzzy
|
||||
msgid "You have {number} click"
|
||||
msgid_plural "You have {number} clicks"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: main.py:120
|
||||
msgid ""
|
||||
"This is clicker.\n"
|
||||
"\n"
|
||||
msgstr ""
|
|
@ -0,0 +1,59 @@
|
|||
# Russian translations for PROJECT.
|
||||
# Copyright (C) 2022 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2022-02-18 17:54+0500\n"
|
||||
"PO-Revision-Date: 2022-02-18 16:22+0500\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language: ru\n"
|
||||
"Language-Team: ru <LL@li.org>\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
||||
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.9.1\n"
|
||||
|
||||
#: keyboards.py:20
|
||||
msgid "click"
|
||||
msgstr "Клик"
|
||||
|
||||
#: main.py:78
|
||||
msgid ""
|
||||
"Hello, {user_fist_name}!\n"
|
||||
"This is the example of multilanguage bot.\n"
|
||||
"Available commands:\n"
|
||||
"\n"
|
||||
"/lang - change your language\n"
|
||||
"/plural - pluralization example"
|
||||
msgstr ""
|
||||
"Привет, {user_fist_name}!\n"
|
||||
"Это пример мультиязычного бота.\n"
|
||||
"Доступные команды:\n"
|
||||
"\n"
|
||||
"/lang - изменить язык\n"
|
||||
"/plural - пример плюрализации"
|
||||
|
||||
#: main.py:102
|
||||
msgid "Language has been changed"
|
||||
msgstr "Язык был сменён"
|
||||
|
||||
#: main.py:114
|
||||
msgid "You have {number} click"
|
||||
msgid_plural "You have {number} clicks"
|
||||
msgstr[0] "У вас {number} клик"
|
||||
msgstr[1] "У вас {number} клика"
|
||||
msgstr[2] "У вас {number} кликов"
|
||||
|
||||
#: main.py:120
|
||||
msgid ""
|
||||
"This is clicker.\n"
|
||||
"\n"
|
||||
msgstr ""
|
||||
"Это кликер.\n"
|
||||
"\n"
|
|
@ -0,0 +1,57 @@
|
|||
# Uzbek (Latin) translations for PROJECT.
|
||||
# Copyright (C) 2022 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2022-02-18 17:54+0500\n"
|
||||
"PO-Revision-Date: 2022-02-18 16:22+0500\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language: uz_Latn\n"
|
||||
"Language-Team: uz_Latn <LL@li.org>\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.9.1\n"
|
||||
|
||||
#: keyboards.py:20
|
||||
msgid "click"
|
||||
msgstr "clik"
|
||||
|
||||
#: main.py:78
|
||||
msgid ""
|
||||
"Hello, {user_fist_name}!\n"
|
||||
"This is the example of multilanguage bot.\n"
|
||||
"Available commands:\n"
|
||||
"\n"
|
||||
"/lang - change your language\n"
|
||||
"/plural - pluralization example"
|
||||
msgstr ""
|
||||
"Salom, {user_fist_name}!\n"
|
||||
"Bu multilanguage bot misoli.\n"
|
||||
"Mavjud buyruqlar:\n"
|
||||
"\n"
|
||||
"/lang - tilni ozgartirish\n"
|
||||
"/plural - pluralizatsiya misoli"
|
||||
|
||||
#: main.py:102
|
||||
msgid "Language has been changed"
|
||||
msgstr "Til ozgartirildi"
|
||||
|
||||
#: main.py:114
|
||||
msgid "You have {number} click"
|
||||
msgid_plural "You have {number} clicks"
|
||||
msgstr[0] "Sizda {number}ta clik"
|
||||
msgstr[1] "Sizda {number}ta clik"
|
||||
|
||||
#: main.py:120
|
||||
msgid ""
|
||||
"This is clicker.\n"
|
||||
"\n"
|
||||
msgstr ""
|
||||
"Bu clicker.\n"
|
||||
"\n"
|
134
examples/middleware/function_based/i18n_gettext/main.py
Normal file
134
examples/middleware/function_based/i18n_gettext/main.py
Normal file
|
@ -0,0 +1,134 @@
|
|||
"""
|
||||
In this example you will learn how to adapt your bot to different languages
|
||||
Using built-in class I18N.
|
||||
You need to install babel package 'https://pypi.org/project/Babel/'
|
||||
Babel provides a command-line interface for working with message catalogs
|
||||
After installing babel package you have a script called 'pybabel'
|
||||
Too see all the commands open terminal and type 'pybabel --help'
|
||||
Full description for pybabel commands can be found here: 'https://babel.pocoo.org/en/latest/cmdline.html'
|
||||
Create a directory 'locales' where our translations will be stored
|
||||
First we need to extract texts:
|
||||
pybabel extract -o locales/{domain_name}.pot --input-dirs .
|
||||
{domain_name}.pot - is the file where all translations are saved
|
||||
The name of this file should be the same as domain which you pass to I18N class
|
||||
In this example domain_name will be 'messages'
|
||||
For gettext (singular texts) we use '_' alias and it works perfect
|
||||
You may also you some alias for ngettext (plural texts) but you can face with a problem that
|
||||
your plural texts are not being extracted
|
||||
That is because by default 'pybabel extract' recognizes the following keywords:
|
||||
_, gettext, ngettext, ugettext, ungettext, dgettext, dngettext, N_
|
||||
To add your own keyword you can use '-k' flag
|
||||
In this example for 'ngettext' i will assign double underscore alias '__'
|
||||
Full command with pluralization support will look so:
|
||||
pybabel extract -o locales/{domain_name}.pot -k __:1,2 --input-dirs .
|
||||
Then create directories with translations (get list of all locales: 'pybabel --list-locales'):
|
||||
pybabel init -i locales/{domain_name}.pot -d locales -l en
|
||||
pybabel init -i locales/{domain_name}.pot -d locales -l ru
|
||||
pybabel init -i locales/{domain_name}.pot -d locales -l uz_Latn
|
||||
Now you can translate the texts located in locales/{language}/LC_MESSAGES/{domain_name}.po
|
||||
After you translated all the texts you need to compile .po files:
|
||||
pybabel compile -d locales
|
||||
When you delete/update your texts you also need to update them in .po files:
|
||||
pybabel extract -o locales/{domain_name}.pot -k __:1,2 --input-dirs .
|
||||
pybabel update -i locales/{domain_name}.pot -d locales
|
||||
- translate
|
||||
pybabel compile -d locales
|
||||
If you have any exceptions check:
|
||||
- you have installed babel
|
||||
- translations are ready, so you just compiled it
|
||||
- in the commands above you replaced {domain_name} to messages
|
||||
- you are writing commands from correct path in terminal
|
||||
"""
|
||||
|
||||
from telebot import TeleBot, types, custom_filters
|
||||
from telebot import apihelper
|
||||
from telebot.storage.memory_storage import StateMemoryStorage
|
||||
|
||||
import keyboards
|
||||
from i18n_class import I18N
|
||||
|
||||
apihelper.ENABLE_MIDDLEWARE = True
|
||||
storage = StateMemoryStorage()
|
||||
# IMPORTANT! This example works only if polling is non-threaded.
|
||||
bot = TeleBot("", state_storage=storage, threaded=False)
|
||||
|
||||
i18n = I18N(translations_path='locales', domain_name='messages')
|
||||
_ = i18n.gettext # for singular translations
|
||||
__ = i18n.ngettext # for plural translations
|
||||
|
||||
# These are example storages, do not use it in a production development
|
||||
users_lang = {}
|
||||
users_clicks = {}
|
||||
|
||||
|
||||
@bot.middleware_handler(update_types=['message', 'callback_query'])
|
||||
def set_contex_language(bot_instance, message):
|
||||
i18n.context_lang.language = users_lang.get(message.from_user.id, 'en')
|
||||
|
||||
|
||||
@bot.message_handler(commands=['start'])
|
||||
def start_handler(message: types.Message):
|
||||
text = _("Hello, {user_fist_name}!\n"
|
||||
"This is the example of multilanguage bot.\n"
|
||||
"Available commands:\n\n"
|
||||
"/lang - change your language\n"
|
||||
"/plural - pluralization example")
|
||||
|
||||
# remember don't use f string for interpolation, use .format method instead
|
||||
text = text.format(user_fist_name=message.from_user.first_name)
|
||||
bot.send_message(message.from_user.id, text)
|
||||
|
||||
|
||||
@bot.message_handler(commands=['lang'])
|
||||
def change_language_handler(message: types.Message):
|
||||
bot.send_message(message.chat.id, "Choose language\nВыберите язык\nTilni tanlang",
|
||||
reply_markup=keyboards.languages_keyboard())
|
||||
|
||||
|
||||
@bot.callback_query_handler(func=None, text=custom_filters.TextFilter(contains=['en', 'ru', 'uz_Latn']))
|
||||
def language_handler(call: types.CallbackQuery):
|
||||
lang = call.data
|
||||
users_lang[call.from_user.id] = lang
|
||||
|
||||
# When you change user's language, pass language explicitly coz it's not changed in context
|
||||
bot.edit_message_text(_("Language has been changed", lang=lang), call.from_user.id, call.message.id)
|
||||
bot.delete_state(call.from_user.id)
|
||||
|
||||
|
||||
@bot.message_handler(commands=['plural'])
|
||||
def pluralization_handler(message: types.Message):
|
||||
if not users_clicks.get(message.from_user.id):
|
||||
users_clicks[message.from_user.id] = 0
|
||||
clicks = users_clicks[message.from_user.id]
|
||||
|
||||
text = __(
|
||||
singular="You have {number} click",
|
||||
plural="You have {number} clicks",
|
||||
n=clicks,
|
||||
)
|
||||
text = _("This is clicker.\n\n") + text.format(number=clicks)
|
||||
bot.send_message(message.chat.id, text, reply_markup=keyboards.clicker_keyboard(_))
|
||||
|
||||
|
||||
@bot.callback_query_handler(func=None, text=custom_filters.TextFilter(equals='click'))
|
||||
def click_handler(call: types.CallbackQuery):
|
||||
if not users_clicks.get(call.from_user.id):
|
||||
users_clicks[call.from_user.id] = 1
|
||||
else:
|
||||
users_clicks[call.from_user.id] += 1
|
||||
|
||||
clicks = users_clicks[call.from_user.id]
|
||||
|
||||
text = __(
|
||||
singular="You have {number} click",
|
||||
plural="You have {number} clicks",
|
||||
n=clicks
|
||||
)
|
||||
text = _("This is clicker.\n\n") + text.format(number=clicks)
|
||||
bot.edit_message_text(text, call.from_user.id, call.message.message_id,
|
||||
reply_markup=keyboards.clicker_keyboard(_))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
bot.add_custom_filter(custom_filters.TextMatchFilter())
|
||||
bot.infinity_polling()
|
17
examples/multibot/README.MD
Normal file
17
examples/multibot/README.MD
Normal file
|
@ -0,0 +1,17 @@
|
|||
You probably have seen bots which allow you to send them token of your bot and then handle updates providing some functionality for your bot.
|
||||
<br>
|
||||
This type of bots are called <b>multibots</b>. They are created using webhooks.
|
||||
<br>
|
||||
|
||||
This is the example of simple multibot.<br>
|
||||
In order to reproduce this example you need to have <b>domain and ssl connection</b>.
|
||||
<br>
|
||||
If you have, go to config.py and specify your data.
|
||||
<br>
|
||||
There is also file called <b>nginx_conf.conf</b>, we will use nginx as proxy-server and this file is example nginx.conf file.
|
||||
<br>
|
||||
Make sure that server_name and port are the same in both config and nginx_conf
|
||||
<br>
|
||||
(nginx_conf.conf IS NOT complete, you would probably use tools like certbot to add ssl connection to it)
|
||||
<br>
|
||||
Also, in this example I used dictionary as tokens storage, but in production you should use database so that you can re-set webhooks in case bot restarts.
|
6
examples/multibot/config.py
Normal file
6
examples/multibot/config.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
MAIN_BOT_TOKEN = "your_main_bot_token"
|
||||
|
||||
WEBHOOK_HOST = "your_domain.com"
|
||||
WEBHOOK_PATH = "telegram_webhook"
|
||||
WEBAPP_HOST = "0.0.0.0"
|
||||
WEBAPP_PORT = 3500
|
14
examples/multibot/handlers.py
Normal file
14
examples/multibot/handlers.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
from telebot import types, TeleBot
|
||||
|
||||
|
||||
def hello_handler(message: types.Message, bot: TeleBot):
|
||||
bot.send_message(message.chat.id, "Hi :)")
|
||||
|
||||
|
||||
def echo_handler(message: types.Message, bot: TeleBot):
|
||||
bot.send_message(message.chat.id, message.text)
|
||||
|
||||
|
||||
def register_handlers(bot: TeleBot):
|
||||
bot.register_message_handler(hello_handler, func=lambda message: message.text == 'Hello', pass_bot=True)
|
||||
bot.register_message_handler(echo_handler, pass_bot=True)
|
48
examples/multibot/main.py
Normal file
48
examples/multibot/main.py
Normal file
|
@ -0,0 +1,48 @@
|
|||
from flask import Flask
|
||||
from flask import request, abort
|
||||
from telebot import TeleBot, types, util
|
||||
from handlers import register_handlers
|
||||
|
||||
import config
|
||||
|
||||
main_bot = TeleBot(config.MAIN_BOT_TOKEN)
|
||||
app = Flask(__name__)
|
||||
tokens = {config.MAIN_BOT_TOKEN: True}
|
||||
|
||||
|
||||
@app.route(f"/{config.WEBHOOK_PATH}/<token>", methods=['POST'])
|
||||
def webhook(token: str):
|
||||
if not tokens.get(token):
|
||||
return abort(404)
|
||||
|
||||
if request.headers.get('content-type') != 'application/json':
|
||||
return abort(403)
|
||||
|
||||
json_string = request.get_data().decode('utf-8')
|
||||
update = types.Update.de_json(json_string)
|
||||
if token == main_bot.token:
|
||||
main_bot.process_new_updates([update])
|
||||
return ''
|
||||
|
||||
from_update_bot = TeleBot(token)
|
||||
register_handlers(from_update_bot)
|
||||
from_update_bot.process_new_updates([update])
|
||||
return ''
|
||||
|
||||
|
||||
@main_bot.message_handler(commands=['add_bot'])
|
||||
def add_bot(message: types.Message):
|
||||
token = util.extract_arguments(message.text)
|
||||
tokens[token] = True
|
||||
|
||||
new_bot = TeleBot(token)
|
||||
new_bot.delete_webhook()
|
||||
new_bot.set_webhook(f"{config.WEBHOOK_HOST}/{config.WEBHOOK_PATH}/{token}")
|
||||
|
||||
new_bot.send_message(message.chat.id, "Webhook was set.")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main_bot.delete_webhook()
|
||||
main_bot.set_webhook(f"{config.WEBHOOK_HOST}/{config.WEBHOOK_PATH}/{config.MAIN_BOT_TOKEN}")
|
||||
app.run(host=config.WEBAPP_HOST, port=config.WEBAPP_PORT)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user