mirror of
https://github.com/octoleo/telegram-bot-bash.git
synced 2024-06-01 09:50:53 +00:00
Compare commits
1100 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
8f23bca8a1 | ||
|
420029c7f6 | ||
|
02c73d432e | ||
|
1c2c07397a | ||
|
8f742ff1fb | ||
|
d0c3156e7d | ||
|
d157f61cf2 | ||
|
af7596f69a | ||
|
0c25a11c5c | ||
|
5653582d68 | ||
|
b6dc3a0d93 | ||
|
4b2331b623 | ||
|
38f2cc475b | ||
|
74294f3fb4 | ||
|
4591b357d1 | ||
|
bc71f37a2e | ||
|
0dae2db8ac | ||
|
1a83202a07 | ||
|
58e6d0aaf6 | ||
|
479f41c80e | ||
|
67d75feace | ||
|
1ffa890428 | ||
|
6490f6756f | ||
|
90d3d7551d | ||
|
d06c162f16 | ||
|
89ac61afe7 | ||
|
369d7f8d4d | ||
|
93dc4a09d6 | ||
|
738c5e5f6d | ||
|
aad42a52fb | ||
|
a2a3927117 | ||
|
5205fe3990 | ||
|
783bf30190 | ||
|
a23370645f | ||
|
36d8604cde | ||
|
6e66a2877c | ||
|
52fbb14770 | ||
|
c63f098fb0 | ||
|
69b1871eea | ||
|
45efa80699 | ||
|
b097f088c8 | ||
|
e4c13ddabe | ||
|
f7f55ea45f | ||
|
9b6aba0586 | ||
|
ecaecfee6f | ||
|
4c4ba0ba5e | ||
|
f790d73e66 | ||
|
79fc511bdb | ||
|
3501318d84 | ||
|
443958aa5f | ||
|
12157b380d | ||
|
cbd74a7f72 | ||
|
dedcc00b8c | ||
|
721e433b47 | ||
|
cbde841bae | ||
|
f1ea49426b | ||
|
e60ada0bfe | ||
|
85f7c074f4 | ||
|
43cab461f8 | ||
|
99950e6518 | ||
|
94aefbe4d5 | ||
|
369124bada | ||
|
8adca9beea | ||
|
41e6883817 | ||
|
ae525c47e0 | ||
|
47a032d582 | ||
|
761aa46b66 | ||
|
a5b230646b | ||
|
24638662d3 | ||
|
b1af0f07e7 | ||
|
c4e2981116 | ||
|
235f26a0e9 | ||
|
50777ceff7 | ||
|
fdb2b3ac7b | ||
|
0a296eaaa1 | ||
|
eb0c227615 | ||
|
7500ca0d12 | ||
|
ac16103361 | ||
|
b78431eacd | ||
|
b454827109 | ||
|
e6838d1436 | ||
|
53e936ee65 | ||
|
ec90ce820d | ||
|
859ce92379 | ||
|
fff79d6daf | ||
|
e098aee321 | ||
|
4854d0d051 | ||
|
7b8e391479 | ||
|
24158142f9 | ||
|
a9ac7eaeda | ||
|
a473e25dfd | ||
|
b6e90af4fa | ||
|
0859354be8 | ||
|
5dd24c3958 | ||
|
dda86e3496 | ||
|
941598d01f | ||
|
84ff8cec15 | ||
|
f7842f4f60 | ||
|
34923ddabe | ||
|
2131911625 | ||
|
f4d45d814f | ||
|
f4323e48b5 | ||
|
c57e9273fb | ||
|
6b8ad9783a | ||
|
17efeeb903 | ||
|
ac71000519 | ||
|
1a0642bcce | ||
|
192fae8a37 | ||
|
70724427d9 | ||
|
8b18f25c88 | ||
|
882efa8f1a | ||
|
fdbfcebc7c | ||
|
f7897fd41b | ||
|
473d802aab | ||
|
b1e6e0fc50 | ||
|
aee7bae141 | ||
|
622a394494 | ||
|
3f848ac17d | ||
|
8efbfcaab9 | ||
|
d6f37afa3a | ||
|
9958b5b5e1 | ||
|
77ffbabf22 | ||
|
82a57a77ed | ||
|
b1f6a0b230 | ||
|
785e769460 | ||
|
805a74eb6d | ||
|
6b07242179 | ||
|
e67e43dd2e | ||
|
2f4ef69971 | ||
|
429f271939 | ||
|
193ca1e5b9 | ||
|
a7d85e352c | ||
|
c58fa22b7a | ||
|
d3a1cecf1f | ||
|
f842730645 | ||
|
117255a958 | ||
|
066274c943 | ||
|
897458a37f | ||
|
b2fc4052fc | ||
|
62b6b618d5 | ||
|
069570e4ed | ||
|
a9ed559383 | ||
|
2f6f3bd4d8 | ||
|
eee5458232 | ||
|
52d1ac5618 | ||
|
429c230627 | ||
|
a6ff405cc5 | ||
|
34455c2c4c | ||
|
9d36f23b14 | ||
|
ad1b91f3bc | ||
|
ccac62dd72 | ||
|
5294d00ae3 | ||
|
b91e96dce1 | ||
|
5212df422e | ||
|
0702d58ab0 | ||
|
54673ac396 | ||
|
baa4e14ebc | ||
|
bc40a3fcbb | ||
|
5a689d22de | ||
|
58fb001d1e | ||
|
d15b4f5070 | ||
|
6fe19556b7 | ||
|
f9dab50f84 | ||
|
1440d56f48 | ||
|
969c7a9fbb | ||
|
d876f758ee | ||
|
9ce139a689 | ||
|
3a29a9dc4a | ||
|
737be16b3f | ||
|
91a143ab15 | ||
|
c4d100e0ad | ||
|
e86c8dc116 | ||
|
c1aec9285e | ||
|
e4a983b16f | ||
|
4e7b3052de | ||
|
6754273c6e | ||
|
5b0b121ba5 | ||
|
a7c98d750c | ||
|
0dd5f83d5a | ||
|
342a5da97a | ||
|
8034a5f055 | ||
|
f377e17e44 | ||
|
bc3a3b3def | ||
|
4833712246 | ||
|
2a3663a463 | ||
|
a289cb8e5b | ||
|
9316caa260 | ||
|
c0f1af529e | ||
|
1e49f6c2b1 | ||
|
9cfeab9cdc | ||
|
10d275c557 | ||
|
08b7b85d03 | ||
|
c9daa822bb | ||
|
c693ab5bb9 | ||
|
7c748247d8 | ||
|
cfc4d2eed1 | ||
|
41e2d09067 | ||
|
279a9e7ca3 | ||
|
a3eec98491 | ||
|
e83f4d443f | ||
|
0c0dc01f26 | ||
|
3f331dc8e8 | ||
|
ca9ea1bf31 | ||
|
b45efa3726 | ||
|
079eb1c289 | ||
|
5a0a5712dd | ||
|
5192212782 | ||
|
8c85c81f94 | ||
|
cbf3945e4f | ||
|
fa0cb75c60 | ||
|
75e775606a | ||
|
e4ee88003e | ||
|
b096338c33 | ||
|
2222875e2b | ||
|
b441384d4a | ||
|
08a05242f9 | ||
|
bc414eef5a | ||
|
47cab8021d | ||
|
6b102a728a | ||
|
70a3c194a0 | ||
|
5ceddde4e8 | ||
|
cc4ac1a816 | ||
|
9584068ea3 | ||
|
c90b5658b3 | ||
|
cc7afdb149 | ||
|
aa2c20b37e | ||
|
461e748c92 | ||
|
1fe22a0345 | ||
|
9023b21791 | ||
|
d9b3342c3c | ||
|
f995eeea13 | ||
|
78e4551107 | ||
|
41e956d517 | ||
|
121f131bb4 | ||
|
13052f01da | ||
|
2960e58941 | ||
|
8bb4b7e5ac | ||
|
28328013c7 | ||
|
3378c1a5d1 | ||
|
407194b23f | ||
|
4371050206 | ||
|
db8f32b732 | ||
|
662c6f48cb | ||
|
e9543991ee | ||
|
07f026c6a7 | ||
|
749eee74a4 | ||
|
127cc85a2a | ||
|
85a178d68a | ||
|
f6e319c6eb | ||
|
f95b6c2e7d | ||
|
6c91a327a6 | ||
|
8854e03ece | ||
|
e923e2e8fc | ||
|
f2dd64c900 | ||
|
f66e5702b0 | ||
|
0ee6973143 | ||
|
b0f653b705 | ||
|
427f670a02 | ||
|
62378f7cf6 | ||
|
fe1fb75748 | ||
|
ad532cce54 | ||
|
5f21fcb0dc | ||
|
3266427bcc | ||
|
d8453aad36 | ||
|
172a9e5461 | ||
|
161e883a9a | ||
|
6bfab17170 | ||
|
a545bf1d8e | ||
|
d269f9816d | ||
|
6857a5558f | ||
|
d12ab8600d | ||
|
ef972c5714 | ||
|
277178389a | ||
|
0f27e71b0f | ||
|
0596983056 | ||
|
550a0defb3 | ||
|
541a279f29 | ||
|
0794506753 | ||
|
abe058a53a | ||
|
eab840868e | ||
|
28ab301ce4 | ||
|
83990961a3 | ||
|
8ae30faffc | ||
|
29fa5cfcca | ||
|
0739a51130 | ||
|
ab71f3765b | ||
|
e13b9eb940 | ||
|
5f602a9a14 | ||
|
afade2e2f0 | ||
|
71daed3487 | ||
|
87f618fadb | ||
|
daeffb30e8 | ||
|
f573d63c55 | ||
|
f8d8edef0b | ||
|
cc299a5819 | ||
|
e1f209783f | ||
|
d521d35815 | ||
|
c6c30a4b9d | ||
|
bd664dacfe | ||
|
fb8b022e24 | ||
|
b9c323573c | ||
|
b2eecc56e2 | ||
|
427e4df6ca | ||
|
41ce9cc486 | ||
|
171b196bbf | ||
|
88a24cb2a3 | ||
|
8253a53994 | ||
|
2a3ab2a145 | ||
|
168584d693 | ||
|
eac21375e8 | ||
|
de24dede53 | ||
|
37e4539ef8 | ||
|
4a9d1f0a29 | ||
|
bd2d2e1e58 | ||
|
1eafc91452 | ||
|
f0a2843f2a | ||
|
58e789a079 | ||
|
fa8e8a267c | ||
|
da214ab819 | ||
|
04e3c18cc4 | ||
|
d3253fdf76 | ||
|
6f8515d701 | ||
|
efca2e013b | ||
|
ac2e1a96f7 | ||
|
1525ac8231 | ||
|
f08df73ddd | ||
|
c205ae528c | ||
|
cb81f7c8e0 | ||
|
bbc679463a | ||
|
8be95a3abf | ||
|
ac02f5a3d3 | ||
|
3d9f7848cf | ||
|
126f61f00c | ||
|
dd19f0f34e | ||
|
0d3a53a7d2 | ||
|
6408befddd | ||
|
7cf624ff2e | ||
|
4582efd556 | ||
|
2fe6d4b0cc | ||
|
1631b0263b | ||
|
b3c22bcf74 | ||
|
fc5d50e3d5 | ||
|
5f50011891 | ||
|
14fa2c7635 | ||
|
248a065be4 | ||
|
9ef8778f85 | ||
|
641727dc99 | ||
|
a5aa756596 | ||
|
63379de77b | ||
|
53c107d4ee | ||
|
0d678f4234 | ||
|
8162695451 | ||
|
d310805a98 | ||
|
0798f1ae00 | ||
|
5f6476d691 | ||
|
8a095bc79f | ||
|
966ee5d5a7 | ||
|
e072afac41 | ||
|
5ad7be59ba | ||
|
83fc57e46c | ||
|
11daa4890d | ||
|
c85af776ba | ||
|
fc847c3510 | ||
|
e0597ad2c1 | ||
|
bbdeb8ba0f | ||
|
64400cd216 | ||
|
9acb2cd7f4 | ||
|
f95e21428c | ||
|
e8aa80c15a | ||
|
f7b5c19cab | ||
|
7e1c1b51e1 | ||
|
0dfbf7bbac | ||
|
32b99dcf2b | ||
|
9492f9828a | ||
|
16e2077833 | ||
|
d70a4616ca | ||
|
a210da4ffa | ||
|
bbda41b0f3 | ||
|
dad68a95d0 | ||
|
5415f28a38 | ||
|
b423a96b50 | ||
|
ec15b34dc6 | ||
|
d4bb169e6b | ||
|
629d97290c | ||
|
072dfa4213 | ||
|
d1e9ccb652 | ||
|
051e603907 | ||
|
5d9df7b7fd | ||
|
05b81ff31d | ||
|
652398e29f | ||
|
b5f2789dd7 | ||
|
81e4fa6c81 | ||
|
a93dc564f1 | ||
|
9cca55b376 | ||
|
ed1cc4a37f | ||
|
03c8c9ded5 | ||
|
726357ab58 | ||
|
b0578d2541 | ||
|
647492c989 | ||
|
7b6a6ca9c3 | ||
|
74dfdd753f | ||
|
23e04a98ef | ||
|
c296899fda | ||
|
3193169256 | ||
|
bbbf57c5d6 | ||
|
e22fcbf9c3 | ||
|
09859b65df | ||
|
7f032b16e3 | ||
|
cb8ae24756 | ||
|
d13e95ada9 | ||
|
ddb2785f8b | ||
|
b04ee84b1d | ||
|
79f58cd7fd | ||
|
3407b0500b | ||
|
41378f87a9 | ||
|
889fe8e865 | ||
|
bddd52829e | ||
|
29f2ce8418 | ||
|
91419a2691 | ||
|
c6001c200e | ||
|
7ecb836c6d | ||
|
a5307e3a94 | ||
|
d083390dcb | ||
|
2aa5c75fe0 | ||
|
fee0615c28 | ||
|
cf6f3eedd7 | ||
|
13d15f453c | ||
|
43f5536dcb | ||
|
d0f87169f4 | ||
|
be87ba3e23 | ||
|
d496639cbb | ||
|
2ee8c9456a | ||
|
1a0b51d2ab | ||
|
a3efcd2e7f | ||
|
8c67bb76c4 | ||
|
a4dce7bb5a | ||
|
b5e4f53357 | ||
|
249dbb0471 | ||
|
8c9298d548 | ||
|
eedd0b3ab3 | ||
|
a1f7215aa4 | ||
|
3f8841b8f1 | ||
|
0d7fee3bd2 | ||
|
21afd4e62e | ||
|
e8173281a8 | ||
|
9bfc27a678 | ||
|
90c5d87761 | ||
|
c0bce91937 | ||
|
b123c3dbce | ||
|
cae6288598 | ||
|
874e37e408 | ||
|
cd5cbfd5ef | ||
|
0bda9d9feb | ||
|
79402eca27 | ||
|
de31231a24 | ||
|
03bdecb056 | ||
|
2e878fd864 | ||
|
1bd1727ea0 | ||
|
232a16bc90 | ||
|
00af5b86c8 | ||
|
74ab0c24fc | ||
|
239dd769c2 | ||
|
2ab00a2c57 | ||
|
88d1de2009 | ||
|
ffc1ecf7be | ||
|
f016598054 | ||
|
0b7cd8ac89 | ||
|
f281ae0f6f | ||
|
269cbfb1d2 | ||
|
dca7a6dccb | ||
|
1dd94410fd | ||
|
709e26bc7c | ||
|
c39c1ca8f9 | ||
|
6173d77c4e | ||
|
c93c9ae891 | ||
|
a9852efd0d | ||
|
f4d64f7b0c | ||
|
69ca15a9d2 | ||
|
fa246732c3 | ||
|
eba9216ba6 | ||
|
450d94d4d3 | ||
|
824cf137d9 | ||
|
4d1c237510 | ||
|
928ab057e8 | ||
|
9f3d39d461 | ||
|
4a4f73b7b0 | ||
|
fffa436262 | ||
|
ac877c2f8b | ||
|
20bfef1e6a | ||
|
05bb23a49f | ||
|
cecc39fc2b | ||
|
f56b7ae5c5 | ||
|
0d50c8df6e | ||
|
9c319f84fd | ||
|
82f7939132 | ||
|
873169b029 | ||
|
f548b0e1a3 | ||
|
f43fb72a4c | ||
|
62f2a0d469 | ||
|
c88f76796d | ||
|
3324ecdf26 | ||
|
bd155f8cb5 | ||
|
0db0215d9b | ||
|
53c7879c9f | ||
|
8b9cb1a77e | ||
|
16a22995d6 | ||
|
c356143be4 | ||
|
1dd546b037 | ||
|
f762d22958 | ||
|
16448a9f60 | ||
|
e6223b6645 | ||
|
85ee75705a | ||
|
5b94265b09 | ||
|
32a6ef2cc6 | ||
|
9d39fe181b | ||
|
c084005106 | ||
|
d7d61a411f | ||
|
8379a624e3 | ||
|
2e24918beb | ||
|
4442382a10 | ||
|
d1f2bc8137 | ||
|
5ca6afc496 | ||
|
84b893cc6d | ||
|
dfe9c7ec85 | ||
|
3c1ea93168 | ||
|
3496a21d62 | ||
|
78ddc1f4e6 | ||
|
c8f61afda9 | ||
|
da7b1bccbf | ||
|
a25f876a06 | ||
|
4f600e26de | ||
|
898a794cb2 | ||
|
74e0aa36a0 | ||
|
931598f558 | ||
|
975d0147f4 | ||
|
eda77f8b55 | ||
|
da7a3f1f21 | ||
|
22741d9a0c | ||
|
cdb63b8c76 | ||
|
401a31a172 | ||
|
b9cfd4b5e8 | ||
|
336f00bb3c | ||
|
5db2ef6f30 | ||
|
10c104d471 | ||
|
62cab32da5 | ||
|
04ec4baab2 | ||
|
d6e1c222f7 | ||
|
59c51afb52 | ||
|
658fac607c | ||
|
40106ee163 | ||
|
b0281f1f32 | ||
|
1b8a1d4253 | ||
|
d30a700b33 | ||
|
c50499c7ff | ||
|
aac3ddf45f | ||
|
ef80aa5690 | ||
|
95b2b9a79d | ||
|
282448772a | ||
|
11c1d55322 | ||
|
b5caff0a32 | ||
|
a1773cce84 | ||
|
b4dcb52793 | ||
|
6dc8f1b267 | ||
|
b4c83c141a | ||
|
0b64af7423 | ||
|
de31d7731f | ||
|
6948ecd778 | ||
|
1cf1dfff00 | ||
|
a749d2907e | ||
|
352ef813e2 | ||
|
6ec00d49b3 | ||
|
2a5d47df8d | ||
|
8df7a3b8bf | ||
|
55e4ae7f45 | ||
|
5a3e68370d | ||
|
9bb94e2ab6 | ||
|
5854e836fc | ||
|
269d18507f | ||
|
dd47dd6626 | ||
|
da837bcf94 | ||
|
d667ecc262 | ||
|
d64ba40b63 | ||
|
676a69465d | ||
|
9c8b4f9611 | ||
|
de7d363abc | ||
|
7488d52922 | ||
|
34ea573d9f | ||
|
12579c8712 | ||
|
a52116280a | ||
|
e835bbc408 | ||
|
d9d360e772 | ||
|
b941d06f10 | ||
|
c0eb399869 | ||
|
c20eef461d | ||
|
c479c80362 | ||
|
1153d654d8 | ||
|
6718d24133 | ||
|
c292292709 | ||
|
c2a110a74d | ||
|
9b3d689b9f | ||
|
0e030aa670 | ||
|
4812540e61 | ||
|
d9620c7de6 | ||
|
1b7f64db6b | ||
|
8e4623acea | ||
|
4d17016a2b | ||
|
7e2f5a8495 | ||
|
f2ff9471d9 | ||
|
aa1ca143d6 | ||
|
22372f10fa | ||
|
5212a990b1 | ||
|
6de7be098e | ||
|
cf0c489987 | ||
|
7b2ca2efdc | ||
|
d57940dd2d | ||
|
65e9775ad6 | ||
|
d8c10ef069 | ||
|
25a33b3731 | ||
|
99217c4e25 | ||
|
682f3941e3 | ||
|
9d7f1455e5 | ||
|
d6de66d634 | ||
|
25578bf603 | ||
|
2d6468cf6c | ||
|
6a6410e8e6 | ||
|
f53e9ced17 | ||
|
3e10396e2e | ||
|
b9c8dc0ff8 | ||
|
4ab8ebd298 | ||
|
6011444a3c | ||
|
afbdb1e7a5 | ||
|
c4ab7ff4ee | ||
|
aec73450af | ||
|
15eb3116b7 | ||
|
c9e5c0fe27 | ||
|
acf9d8432f | ||
|
5ef858f538 | ||
|
3daf84dad8 | ||
|
2775000072 | ||
|
38a6198198 | ||
|
50e661aa50 | ||
|
f3bb5d9a9a | ||
|
6e0242368e | ||
|
1952610282 | ||
|
2dc1f385f2 | ||
|
c5ce29a586 | ||
|
3a658ea1ab | ||
|
905410f93d | ||
|
0d3778fae0 | ||
|
e1084a8047 | ||
|
b641a1888f | ||
|
4d5b79283c | ||
|
80b94f4cb4 | ||
|
d181e9d98a | ||
|
78088d6472 | ||
|
ef4d21f6f4 | ||
|
08540ee298 | ||
|
2b104716df | ||
|
35528760fd | ||
|
f4f6c2c501 | ||
|
9799db4cb9 | ||
|
d85c7794a9 | ||
|
d8cff8f70e | ||
|
a12738734b | ||
|
487deee08c | ||
|
ca765afa32 | ||
|
6481cb5452 | ||
|
9b1119d51d | ||
|
28de99eaeb | ||
|
2d48670680 | ||
|
550387bdbc | ||
|
5b5447e4bb | ||
|
358f95a766 | ||
|
9e89627ae9 | ||
|
10f0dea98d | ||
|
595d21ff84 | ||
|
9e3d301d37 | ||
|
12b4696e80 | ||
|
928dfa27be | ||
|
4883c18974 | ||
|
517e600681 | ||
|
9f5f061c22 | ||
|
63b9c283a2 | ||
|
d24ef50fd4 | ||
|
1666cac184 | ||
|
4b3363f603 | ||
|
0e6712a599 | ||
|
456e86b932 | ||
|
e6de3828d3 | ||
|
ae4610a742 | ||
|
2dafbd9d63 | ||
|
a64ec1afa9 | ||
|
a656533693 | ||
|
3569a761e1 | ||
|
bee55fec78 | ||
|
c517129559 | ||
|
724f36b4df | ||
|
423bf35411 | ||
|
7618b38ee3 | ||
|
c79031f604 | ||
|
a597303115 | ||
|
24e9ec6e75 | ||
|
5afe05aa44 | ||
|
a69204596e | ||
|
e3151626c0 | ||
|
01a72e8a26 | ||
|
86f8fbe994 | ||
|
18065b119e | ||
|
571fb9c3c8 | ||
|
ea92c55c0c | ||
|
af156a4e1b | ||
|
d904371fb9 | ||
|
5ec83bbc2f | ||
|
03700cdbc2 | ||
|
48f314eaaa | ||
|
3d760b3319 | ||
|
e7739b8333 | ||
|
fb61a488c6 | ||
|
d2a578a757 | ||
|
694ee6185d | ||
|
afa8d874e3 | ||
|
80a6dbbe9f | ||
|
4fe969766b | ||
|
d52ea8c240 | ||
|
25cc9a5015 | ||
|
cac1ea44c2 | ||
|
0b8c0476db | ||
|
8f03835ccc | ||
|
30a72eb853 | ||
|
fa6ad3e6a8 | ||
|
21f29a496f | ||
|
e4d13fd92d | ||
|
4d8c2054a6 | ||
|
f119c447ce | ||
|
1cba3aaf53 | ||
|
f1d71a0771 | ||
|
11b5aab9b9 | ||
|
75024a1726 | ||
|
cf536c9ca3 | ||
|
fa5be1eafb | ||
|
5dcc7ef3f6 | ||
|
9adc62d6ec | ||
|
ba614b71fd | ||
|
67f2dcd498 | ||
|
30eedcffb1 | ||
|
02715e4128 | ||
|
8b3e92d233 | ||
|
eea1de6cbd | ||
|
d221fb698e | ||
|
344167e259 | ||
|
35d5e05ea9 | ||
|
215667b3ef | ||
|
3cd8dc91ae | ||
|
2dbe63b79e | ||
|
ea27513706 | ||
|
91ced1fa35 | ||
|
18f0ace928 | ||
|
6e3655fc2b | ||
|
7694df5ecc | ||
|
413779dede | ||
|
5dcbccd236 | ||
|
70e7ee4bc1 | ||
|
b33132ea5e | ||
|
8991cc98f0 | ||
|
4b18757779 | ||
|
4990f70bce | ||
|
834f5ba200 | ||
|
6439d435c2 | ||
|
c943280034 | ||
|
24a7eaa8dd | ||
|
3e4e90443c | ||
|
4e043c5717 | ||
|
852ab9de16 | ||
|
dda5b6d10e | ||
|
2af9d76ea7 | ||
|
bc44331183 | ||
|
cc69310a7e | ||
|
2281943940 | ||
|
de811c173a | ||
|
656389182f | ||
|
74caa49ab1 | ||
|
e0b9f6f870 | ||
|
cdc6dd323d | ||
|
ca0509556a | ||
|
e0470aadc0 | ||
|
2397f0d0b4 | ||
|
8838d93e9c | ||
|
5baab14cd2 | ||
|
f32833ccf9 | ||
|
a901cc78d4 | ||
|
eb4fa6840b | ||
|
8affc94813 | ||
|
a8fe17882c | ||
|
f2a1d9f32f | ||
|
79056bc517 | ||
|
15e6c7bcbe | ||
|
3871ca9656 | ||
|
737d54d365 | ||
|
471ad21e90 | ||
|
38164ba9a2 | ||
|
15f6da85dc | ||
|
e663979206 | ||
|
b6e9f9ed16 | ||
|
15928bd58f | ||
|
6c02bab1bd | ||
|
81c8771898 | ||
|
2bc8f398c0 | ||
|
f968c8b92d | ||
|
de21079d2f | ||
|
d70656db68 | ||
|
e64d066db4 | ||
|
2e237e2f70 | ||
|
769d07d151 | ||
|
aec4e71dc8 | ||
|
c2f47535cc | ||
|
ec7fce72ac | ||
|
848219d82c | ||
|
f4c1657270 | ||
|
5b2582129b | ||
|
eb89aee3d5 | ||
|
0c0a4cc3c9 | ||
|
72c8531cee | ||
|
1133f25f35 | ||
|
7790e47a7e | ||
|
6d940c7cc8 | ||
|
deeef7edc5 | ||
|
a792048dfe | ||
|
eace5e18a4 | ||
|
4fd6f98f77 | ||
|
a71d68ee43 | ||
|
dba4f95e9a | ||
|
7644c6c14c | ||
|
f96625ef9d | ||
|
b23aaddf17 | ||
|
82a0c18bf4 | ||
|
30b5b1a79a | ||
|
b01e3e91b6 | ||
|
eb4924122e | ||
|
78c066e1e5 | ||
|
de745719dc | ||
|
9b138eecbd | ||
|
b189191b85 | ||
|
02e776c426 | ||
|
19c45c4771 | ||
|
6f86036809 | ||
|
bd22e2aa17 | ||
|
8792e8353c | ||
|
3e4008844f | ||
|
720dc59713 | ||
|
d11598e082 | ||
|
3fcb8547e8 | ||
|
5fc4d01a51 | ||
|
601fe0ea51 | ||
|
3f85134d2f | ||
|
515e07de5d | ||
|
4407ccf8ad | ||
|
313ff03e17 | ||
|
d42429efad | ||
|
0ad70fda87 | ||
|
d0e9bd874b | ||
|
407e1476a3 | ||
|
bc74141db7 | ||
|
9c96e3eb80 | ||
|
c729cf428b | ||
|
8e7583d3b7 | ||
|
2a66ee928f | ||
|
dddd1ce2de | ||
|
31b3203483 | ||
|
e366633ebd | ||
|
ed373a8a03 | ||
|
ed14e850a4 | ||
|
46748ee4b8 | ||
|
6d1e7cc065 | ||
|
ff5fb2d337 | ||
|
da98b09d6b | ||
|
578056b57d | ||
|
9c7a203fb3 | ||
|
20a969c1fe | ||
|
2a3dcaa471 | ||
|
975f99a4b0 | ||
|
a7997f21b5 | ||
|
2e9587a11d | ||
|
67b9039d51 | ||
|
cbad54036d | ||
|
a2f10bf70e | ||
|
feddcabf9c | ||
|
53bab25459 | ||
|
8f29907442 | ||
|
e63590b9b4 | ||
|
01539286d1 | ||
|
7e83e5dd1c | ||
|
037b1ea326 | ||
|
ab863af08b | ||
|
a4636668a7 | ||
|
0841633dd9 | ||
|
b6f36c6e7a | ||
|
4b36432d09 | ||
|
a72d56a1c6 | ||
|
d5606098c7 | ||
|
f8f59a3cab | ||
|
a055b775d7 | ||
|
c86efb1e07 | ||
|
46af6348a7 | ||
|
876361f562 | ||
|
3d92bf3ca8 | ||
|
dcf6534c1f | ||
|
7b34db46e1 | ||
|
1dc0211890 | ||
|
f0a7d85351 | ||
|
df53191838 | ||
|
ca803c0a47 | ||
|
ced78d3656 | ||
|
7aa409fbc8 | ||
|
bdb50c8716 | ||
|
6531fecfed | ||
|
cbce60a3b0 | ||
|
96fda449b5 | ||
|
93f49665aa | ||
|
f13a2d05cc | ||
|
aaa71c80d6 | ||
|
e721a1aaa3 | ||
|
c02327f7a1 | ||
|
52bde30271 | ||
|
b1d569a679 | ||
|
ac9ca6049e | ||
|
23a3d4b8f4 | ||
|
d1f509a00f | ||
|
284172fc10 | ||
|
64efe96117 | ||
|
1e0de91a2d | ||
|
6c6b312f47 | ||
|
d28f9752d2 | ||
|
0e75138548 | ||
|
c0a633f42d | ||
|
4aa7561f7c | ||
|
ac2ec02a98 | ||
|
a5975d93c4 | ||
|
bf8a9117aa | ||
|
8a119f8806 | ||
|
eef955abf3 | ||
|
fa1afc4aa9 | ||
|
2e446d91f6 | ||
|
b3d7918a15 | ||
|
fdc28e97f6 | ||
|
a710e0cc33 | ||
|
43dce860ef | ||
|
11acaaaa1a | ||
|
daa2dfadda | ||
|
4f90215465 | ||
|
3d636f77e6 | ||
|
f9c107850a | ||
|
e3ba1a053c | ||
|
b84ab57f6f | ||
|
91ad865c17 | ||
|
3531eb9565 | ||
|
7843de5647 | ||
|
c5caf937cc | ||
|
d4f415f7d9 | ||
|
a7769add6a | ||
|
ce605551c9 | ||
|
aec6de0304 | ||
|
0497513eb9 | ||
|
9b9125c9cc | ||
|
55c9d8bb4d | ||
|
aad0bfecd8 | ||
|
4594e057a3 | ||
|
1e851bd296 | ||
|
db03e23be8 | ||
|
31808a9e4f | ||
|
e2c998c5b9 | ||
|
5819b5cac4 | ||
|
6128c8956f | ||
|
6302ef4795 | ||
|
9a81e440f1 | ||
|
274f5d84ad | ||
|
5ebfaccfa1 | ||
|
7029f7f93d | ||
|
dbb6caf667 | ||
|
4297fc164b | ||
|
ffec76a830 | ||
|
46271cc1a2 | ||
|
93b49141e8 | ||
|
3a2f58c535 | ||
|
e80b98ac85 | ||
|
501b308532 | ||
|
fc36de9fa0 | ||
|
d5f9b1c4fb | ||
|
b240edee41 | ||
|
1c5594a5c2 | ||
|
2a28e7f0c9 | ||
|
9148dc5f04 | ||
|
405276bbbc | ||
|
60b1a59a8e | ||
|
5779accfe8 | ||
|
a1a4829109 | ||
|
ce6749e8df | ||
|
74cb204d1a | ||
|
6651cf4f0a | ||
|
afc669c915 | ||
|
cb3f3e32f3 | ||
|
f2f5e11610 | ||
|
59aa9fca8b | ||
|
9e020a9644 | ||
|
bbbc8aece1 | ||
|
9b05ae0220 | ||
|
cfdcb41a38 | ||
|
3c6b2d3b35 | ||
|
d23bb28ebc | ||
|
b60f33afac | ||
|
483da5a797 | ||
|
c6deadd446 | ||
|
981c0eec01 | ||
|
ec856365ed | ||
|
bee9f33022 | ||
|
64b4055dda | ||
|
7bad01b258 | ||
|
9f74bcfec4 | ||
|
43372f5278 | ||
|
68bee46383 | ||
|
25c9b62a76 | ||
|
15e7f014bd | ||
|
f019ab190f | ||
|
6b886562f7 | ||
|
b268e4dafe | ||
|
48022e4ed2 | ||
|
0f6864f763 | ||
|
83892b7924 | ||
|
5296820753 | ||
|
ad98a6c908 | ||
|
5fa7b2e15c | ||
|
31c6c4b111 | ||
|
5d57e2bbdd | ||
|
abcc410c9a | ||
|
856b831736 | ||
|
f74e95ddcb | ||
|
3808496b32 | ||
|
cb77d411a8 | ||
|
b1fb35d421 | ||
|
e0bb9f85e1 | ||
|
80a47780ce | ||
|
51aa2ed4b3 | ||
|
58cf9017ea | ||
|
5e6d62f19f | ||
|
75691dc685 | ||
|
5bce3f7151 | ||
|
d8e0b5c975 | ||
|
9ef99ee1b8 | ||
|
e08b52e043 | ||
|
b096ea3e98 | ||
|
5b2d0e1e8f | ||
|
8669cfb785 | ||
|
fd7ca77cc1 | ||
|
8dfdf2e168 | ||
|
f1ebdbb72d | ||
|
300553f8ba | ||
|
d34c22f156 | ||
|
e5f7b2da50 | ||
|
d1a3372d39 | ||
|
3c5ffdb506 | ||
|
9482bd62bf | ||
|
b8ae9eca87 | ||
|
dd7c66d823 | ||
|
7190c6e330 | ||
|
beb77a4b65 | ||
|
83623ece2e | ||
|
e7d2effc27 | ||
|
a3c0d3165c | ||
|
a1a823b4b6 | ||
|
bccd064516 | ||
|
792dde9a91 | ||
|
31a5d00a64 | ||
|
61a1f6f626 | ||
|
e8a1fd0bf1 | ||
|
6d497d5f5e | ||
|
085d85da35 | ||
|
a72f24ac9c | ||
|
d01addf0a9 | ||
|
412173cf85 | ||
|
417bc376db | ||
|
bcd62dca36 | ||
|
46ec7c28e9 | ||
|
d5994166c0 | ||
|
eb0cde55df | ||
|
aacdc76af2 | ||
|
bce7f1a6dc | ||
|
df03727e14 | ||
|
b55c171233 | ||
|
5f945e5e0a | ||
|
a79f97fdd6 | ||
|
e9cf8d25e5 | ||
|
92f022d038 | ||
|
acee08deff | ||
|
5b10e75b94 | ||
|
d08d91205d | ||
|
b7df57a085 | ||
|
e492da05f7 | ||
|
0c5e3dd597 | ||
|
0b36bc517b | ||
|
dbba89cd1d | ||
|
b8414b3d05 |
33
.github/ISSUE_TEMPLATE/bug_report.md
vendored
33
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
@ -1,33 +0,0 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Enter text / Run command '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Bashbot (please complete the following information):**
|
||||
- Version [ grep 'VERSION' bashbot.sh ]
|
||||
- OS: [ uname -a]
|
||||
- Shell [ bash --version]
|
||||
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
|
@ -1,20 +0,0 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
17
.github/ISSUE_TEMPLATE/others.md
vendored
17
.github/ISSUE_TEMPLATE/others.md
vendored
|
@ -1,17 +0,0 @@
|
|||
---
|
||||
name: Others
|
||||
about: Anything else not a Bug or Feature
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your issue is related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe your idea or complaint**
|
||||
A clear and concise description of what you want to talk about.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about your idea or complaint here.
|
15
.gitignore
vendored
15
.gitignore
vendored
|
@ -1,9 +1,18 @@
|
|||
*~
|
||||
/.github/
|
||||
/count
|
||||
/token
|
||||
/count*
|
||||
/token*
|
||||
/blocked*
|
||||
/botconf*
|
||||
/botacl*
|
||||
/botown*
|
||||
*.jssh
|
||||
*.save
|
||||
*.log
|
||||
*.swp
|
||||
*.swo
|
||||
/logs/
|
||||
/JSON.sh/
|
||||
/data-bot-bash/
|
||||
/dist/
|
||||
/DIST/
|
||||
/STANDALONE/
|
||||
|
|
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -1,3 +0,0 @@
|
|||
[submodule "JSON.sh"]
|
||||
path = JSON.sh
|
||||
url = http://github.com/dominictarr/JSON.sh
|
270
README.html
270
README.html
|
@ -1,44 +1,117 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta http-equiv="Content-Style-Type" content="text/css" />
|
||||
<meta charset="utf-8" />
|
||||
<meta name="generator" content="pandoc" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
<title>Bashbot README</title>
|
||||
<style type="text/css">code{white-space: pre;}</style>
|
||||
<style>
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
span.underline{text-decoration: underline;}
|
||||
div.column{display: inline-block; vertical-align: top; width: 50%;}
|
||||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||||
ul.task-list{list-style: none;}
|
||||
pre > code.sourceCode { white-space: pre; position: relative; }
|
||||
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
|
||||
pre > code.sourceCode > span:empty { height: 1.2em; }
|
||||
code.sourceCode > span { color: inherit; text-decoration: inherit; }
|
||||
div.sourceCode { margin: 1em 0; }
|
||||
pre.sourceCode { margin: 0; }
|
||||
@media screen {
|
||||
div.sourceCode { overflow: auto; }
|
||||
}
|
||||
@media print {
|
||||
pre > code.sourceCode { white-space: pre-wrap; }
|
||||
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
|
||||
}
|
||||
pre.numberSource code
|
||||
{ counter-reset: source-line 0; }
|
||||
pre.numberSource code > span
|
||||
{ position: relative; left: -4em; counter-increment: source-line; }
|
||||
pre.numberSource code > span > a:first-child::before
|
||||
{ content: counter(source-line);
|
||||
position: relative; left: -1em; text-align: right; vertical-align: baseline;
|
||||
border: none; display: inline-block;
|
||||
-webkit-touch-callout: none; -webkit-user-select: none;
|
||||
-khtml-user-select: none; -moz-user-select: none;
|
||||
-ms-user-select: none; user-select: none;
|
||||
padding: 0 4px; width: 4em;
|
||||
color: #aaaaaa;
|
||||
}
|
||||
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
|
||||
div.sourceCode
|
||||
{ }
|
||||
@media screen {
|
||||
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
|
||||
}
|
||||
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
|
||||
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
|
||||
code span.at { color: #7d9029; } /* Attribute */
|
||||
code span.bn { color: #40a070; } /* BaseN */
|
||||
code span.bu { } /* BuiltIn */
|
||||
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
|
||||
code span.ch { color: #4070a0; } /* Char */
|
||||
code span.cn { color: #880000; } /* Constant */
|
||||
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
|
||||
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
|
||||
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
|
||||
code span.dt { color: #902000; } /* DataType */
|
||||
code span.dv { color: #40a070; } /* DecVal */
|
||||
code span.er { color: #ff0000; font-weight: bold; } /* Error */
|
||||
code span.ex { } /* Extension */
|
||||
code span.fl { color: #40a070; } /* Float */
|
||||
code span.fu { color: #06287e; } /* Function */
|
||||
code span.im { } /* Import */
|
||||
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
|
||||
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
|
||||
code span.op { color: #666666; } /* Operator */
|
||||
code span.ot { color: #007020; } /* Other */
|
||||
code span.pp { color: #bc7a00; } /* Preprocessor */
|
||||
code span.sc { color: #4070a0; } /* SpecialChar */
|
||||
code span.ss { color: #bb6688; } /* SpecialString */
|
||||
code span.st { color: #4070a0; } /* String */
|
||||
code span.va { color: #19177c; } /* Variable */
|
||||
code span.vs { color: #4070a0; } /* VerbatimString */
|
||||
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
|
||||
</style>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div id="header">
|
||||
<header id="title-block-header">
|
||||
<h1 class="title">Bashbot README</h1>
|
||||
</div>
|
||||
<h1 id="bashbot">bashbot</h1>
|
||||
<p>A Telegram bot written in bash.</p>
|
||||
<p>Written by Drew (<span class="citation">@topkecleon</span>), Daniil Gentili (<span class="citation">@danogentili</span>), and Kay M (<span class="citation">@gnadelwartz</span>).</p>
|
||||
<p>Contributions by JuanPotato, BigNerd95, TiagoDanin, and iicc1.</p>
|
||||
</header>
|
||||
<h2><img align="middle" src="https://raw.githubusercontent.com/odb/official-bash-logo/master/assets/Logos/Icons/PNG/64x64.png" >
|
||||
Bashbot - A Telegram bot written in bash.
|
||||
</h2>
|
||||
Written by Drew (@topkecleon) and Kay M (@gnadelwartz).
|
||||
|
||||
<p>Contributions by Daniil Gentili (@danog), JuanPotato, BigNerd95, TiagoDanin, iicc1 and dcoomber.</p>
|
||||
<p>Released to the public domain wherever applicable. Elsewhere, consider it released under the <a href="http://www.wtfpl.net/txt/copying/">WTFPLv2</a>.</p>
|
||||
<h2 id="prerequisites">Prerequisites</h2>
|
||||
<p>Depends on <a href="http://github.com/tmux/tmux">tmux</a>. Uses <a href="http://github.com/dominictarr/JSON.sh">JSON.sh</a>.</p>
|
||||
<p>Most complete <a href="doc/4_expert.md#Bashbot-UTF-8-Support">UTF-8 support for bashbot</a> is availible if phyton is installed (optional).</p>
|
||||
<p>Bashbot <a href="https://github.com/topkecleon/telegram-bot-bash">Documentation</a> and <a href="https://github.com/topkecleon/telegram-bot-bash/releases">Downloads</a> are availible on www.github.com</p>
|
||||
<h2 id="documentation">Documentation</h2>
|
||||
<p>Linted by <a href="https://github.com/koalaman/shellcheck">#ShellCheck</a></p>
|
||||
<h2>Prerequisites</h2>
|
||||
<p>Uses <a href="http://github.com/dominictarr/JSON.sh">JSON.sh</a>/<a href="https://github.com/step-/JSON.awk">JSON.awk</a> and the magic of sed.</p>
|
||||
<p>Bashbot is written in bash. It depends on commands typically available in a Linux/Unix Environment. For more information on commands provided by recent versions of <a href="https://en.wikipedia.org/wiki/List_of_GNU_Core_Utilities_commands">coreutils</a>, <a href="https://en.wikipedia.org/wiki/BusyBox#Commands">busybox</a> or <a href="https://landley.net/toybox/help.html">toybox</a>, see <a href="doc/7_develop.md#common-commands">Developer Notes</a>.</p>
|
||||
<p><strong>Note for MacOS and BSD Users:</strong> Bashbot will not run without installing additional software as it uses modern bash and (gnu) grep/sed features. See <a href="doc/0_install.md">Install Bashbot</a>.</p>
|
||||
<p><strong>Note for embedded systems:</strong> You need to install a "real" bash as the vanilla installation of busybox or toybox is not sufficient. See <a href="doc/0_install.md">Install Bashbot</a>.</p>
|
||||
<p>Bashbot <a href="https://github.com/topkecleon/telegram-bot-bash">Documentation</a> and <a href="https://github.com/topkecleon/telegram-bot-bash/releases">Downloads</a> are available on <a href="https://www.github.com">www.github.com</a>.</p>
|
||||
<h2>Documentation</h2>
|
||||
<ul>
|
||||
<li><a href="https://core.telegram.org/bots">Introdution to Telegram Bots</a>
|
||||
<ul>
|
||||
<li><a href="https://core.telegram.org/bots#3-how-do-i-create-a-bot">One Bot to rule them all</a></li>
|
||||
<li><a href="https://core.telegram.org/bots#commands">Bot commands</a></li>
|
||||
</ul></li>
|
||||
<li><a href="https://core.telegram.org/bots">Introduction to Telegram Bots</a></li>
|
||||
<li><a href="doc/0_install.md">Install Bashbot</a>
|
||||
<ul>
|
||||
<li>Install release</li>
|
||||
<li>Install from githup</li>
|
||||
<li>Install from github</li>
|
||||
<li>Update Bashbot</li>
|
||||
<li>Notes on Updates</li>
|
||||
</ul></li>
|
||||
<li><a href="doc/1_firstbot.md">Create a new Telegram Bot with botfather</a></li>
|
||||
<li><a href="doc/1_firstbot.md">Get Bottoken from Botfather</a></li>
|
||||
<li><a href="doc/2_usage.md">Getting Started</a>
|
||||
<ul>
|
||||
<li>Managing your Bot</li>
|
||||
<li>Recieve data</li>
|
||||
<li>Receive data</li>
|
||||
<li>Send messages</li>
|
||||
<li>Send files, locations, keyboards</li>
|
||||
</ul></li>
|
||||
|
@ -48,17 +121,21 @@
|
|||
<li>Interactive Chats</li>
|
||||
<li>Background Jobs</li>
|
||||
<li>Inline queries</li>
|
||||
<li>Send message errors</li>
|
||||
</ul></li>
|
||||
<li><a href="doc/4_expert.md">Expert Use</a>
|
||||
<ul>
|
||||
<li>Handling UTF-8 character sets</li>
|
||||
<li>Run as other user or system service</li>
|
||||
<li>Scedule bashbot from Cron</li>
|
||||
<li>Schedule bashbot from Cron</li>
|
||||
<li>Use from CLI and Scripts</li>
|
||||
<li>Customize Bashbot Environment</li>
|
||||
</ul></li>
|
||||
<li><a href="doc/5_practice.md">Best Practices</a>
|
||||
<ul>
|
||||
<li>Customize commands.sh</li>
|
||||
<li>Seperate logic from commands</li>
|
||||
<li>Customize mycommands.sh</li>
|
||||
<li>Overwrite/disable commands</li>
|
||||
<li>Separate logic from commands</li>
|
||||
<li>Test your Bot with shellcheck</li>
|
||||
</ul></li>
|
||||
<li><a href="doc/6_reference.md">Function Reference</a>
|
||||
|
@ -66,43 +143,126 @@
|
|||
<li>Sending Messages, Files, Keyboards</li>
|
||||
<li>User Access Control</li>
|
||||
<li>Inline Queries</li>
|
||||
<li>jsshDB Bashbot key-value storage</li>
|
||||
<li>Background and Interactive Jobs</li>
|
||||
</ul></li>
|
||||
<li><a href="doc/7_develop.md">Deveoper Notess</a>
|
||||
<li><a href="doc/7_develop.md">Developer Notes</a>
|
||||
<ul>
|
||||
<li>Debug bashbot</li>
|
||||
<li>Modules, addons, events</li>
|
||||
<li>Setup your environment</li>
|
||||
<li>Test, Add, Push changes</li>
|
||||
<li>Prepare a new version</li>
|
||||
<li>Bashbot testsuite</li>
|
||||
<li>Bashbot test suite</li>
|
||||
</ul></li>
|
||||
<li><a href="doc/8_custom.md">Customize bashbot environment</a></li>
|
||||
<li><a href="examples/README.md">Examples</a></li>
|
||||
<li><a href="examples">Examples Directory</a></li>
|
||||
<li><a href="examples/webhook">Webhook Example</a></li>
|
||||
</ul>
|
||||
<h2 id="security-considerations">Security Considerations</h2>
|
||||
<p>Running a Telegram Bot means it is connected to the public and you never know whats send to your Bot.</p>
|
||||
<p>Bash scripts in general are not designed to be bullet proof, so consider this Bot as a proof of concept. Bash programmers often struggle with ‘quoting hell’ and globbing, see <a href="https://unix.stackexchange.com/questions/171346/security-implications-of-forgetting-to-quote-a-variable-in-bash-posix-shells">Implications of wrong quoting</a></p>
|
||||
<p>Whenever you are processing input from from untrusted sources (messages, files, network) you must be as carefull as possible, e.g. set IFS appropriate, disable globbing (set -f) and quote everthing. In addition delete unused scripts and examples from your Bot, e.g. scripts ‘notify’, ‘calc’, ‘question’, and disable all not used commands.</p>
|
||||
<p>A powerful tool to improve your scripts is <code>shellcheck</code>. You can <a href="https://www.shellcheck.net/">use it online</a> or <a href="https://github.com/koalaman/shellcheck#installing">install shellcheck locally</a>. Shellcheck is used extensive in bashbot development to enshure a high code quality, e.g. it’s not allowed to push changes without passing all shellcheck tests. In addition bashbot has a <a href="doc/7_develop.md">test suite</a> to check if important functionality is working as expected.</p>
|
||||
<h3 id="run-your-bot-as-a-restricted-user">Run your Bot as a restricted user</h3>
|
||||
<p><strong>I recommend to run your bot as a user, with almost no access rights.</strong> All files your Bot have write access to are in danger to be overwritten/deleted if your bot is hacked. For the same reason ervery file your Bot can read is in danger to be disclosed. Restict your Bots access rigths to the absolute minimum.</p>
|
||||
<p><strong>Never run your Bot as root, this is the most dangerous you can do!</strong> Usually the user ‘nobody’ has almost no rights on Unix/Linux systems. See <a href="doc/4_expert.md">Expert use</a> on how to run your Bot as an other user.</p>
|
||||
<h3 id="secure-your-bot-installation">Secure your Bot installation</h3>
|
||||
<p><strong>Your Bot configuration must no be readable from other users.</strong> Everyone who can read your Bots token can act as your Bot and has access to all chats your Bot is in!</p>
|
||||
<p>Everyone with read access to your Bot files can extract your Bots data. Especially your Bot Token in <code>token</code> must be protected against other users. No one exept you must have write access to the Bot files. The Bot must be restricted to have write access to <code>count</code> and <code>tmp-bot-bash</code> only, all other files must be write protected.</p>
|
||||
<h3>Your very first bashbot in a nutshell</h3>
|
||||
<p>To install and run bashbot you need access to a Linux/Unix command line with bash, a <a href="https://telegram.org">Telegram client</a> and a mobile phone <a href="https://telegramguide.com/create-a-telegram-account/">with a Telegram account</a>.</p>
|
||||
<p>First you need to <a href="doc/1_firstbot.md">create a new Telegram Bot token</a> for your bot and write it down.</p>
|
||||
<p>Now open a Linux/Unix terminal with bash, create a new directory, change to it and install telegram-bot-bash:</p>
|
||||
<div class="sourceCode" id="cb1"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1"></a><span class="co"># create bot dir</span></span>
|
||||
<span id="cb1-2"><a href="#cb1-2"></a><span class="fu">mkdir</span> mybot</span>
|
||||
<span id="cb1-3"><a href="#cb1-3"></a><span class="bu">cd</span> mybot</span>
|
||||
<span id="cb1-4"><a href="#cb1-4"></a></span>
|
||||
<span id="cb1-5"><a href="#cb1-5"></a><span class="co"># download latest release with wget or from https://github.com/topkecleon/telegram-bot-bash/releases/latest</span></span>
|
||||
<span id="cb1-6"><a href="#cb1-6"></a><span class="fu">wget</span> <span class="st">"https://github.com/</span><span class="va">$(</span><span class="fu">wget</span> -q <span class="st">"https://github.com/topkecleon/telegram-bot-bash/releases/latest"</span> -O - <span class="kw">|</span> <span class="fu">egrep</span> <span class="st">'/.*/download/.*/.*tar.gz'</span> -o<span class="va">)</span><span class="st">"</span></span>
|
||||
<span id="cb1-7"><a href="#cb1-7"></a></span>
|
||||
<span id="cb1-8"><a href="#cb1-8"></a><span class="co"># Extract the tar archive and go into bot dir</span></span>
|
||||
<span id="cb1-9"><a href="#cb1-9"></a><span class="fu">tar</span> -xzf *.tar.gz</span>
|
||||
<span id="cb1-10"><a href="#cb1-10"></a><span class="bu">cd</span> telegram-bot-bash</span>
|
||||
<span id="cb1-11"><a href="#cb1-11"></a></span>
|
||||
<span id="cb1-12"><a href="#cb1-12"></a><span class="co"># initialize your bot</span></span>
|
||||
<span id="cb1-13"><a href="#cb1-13"></a><span class="co"># Enter your bot token when asked, all other questions can be answered by hitting the \<Return\> key.</span></span>
|
||||
<span id="cb1-14"><a href="#cb1-14"></a><span class="ex">./bashbot.sh</span> init</span>
|
||||
<span id="cb1-15"><a href="#cb1-15"></a></span>
|
||||
<span id="cb1-16"><a href="#cb1-16"></a><span class="co"># Now start your bot</span></span>
|
||||
<span id="cb1-17"><a href="#cb1-17"></a><span class="ex">./bashbot.sh</span> start</span>
|
||||
<span id="cb1-18"><a href="#cb1-18"></a></span>
|
||||
<span id="cb1-19"><a href="#cb1-19"></a><span class="ex">Bottoken</span> is valid ...</span>
|
||||
<span id="cb1-20"><a href="#cb1-20"></a><span class="ex">Bot</span> Name: yourbotname_bot</span>
|
||||
<span id="cb1-21"><a href="#cb1-21"></a><span class="ex">Session</span> Name: yourbotname_bot-startbot</span>
|
||||
<span id="cb1-22"><a href="#cb1-22"></a><span class="ex">Bot</span> started successfully.</span></code></pre></div>
|
||||
<p>Now open the Telegram App on your mobile phone and start a chat with your bot (<em>your bot's username is shown after 'Bot Name:'</em>):</p>
|
||||
<pre><code>/start
|
||||
|
||||
You are Botadmin
|
||||
Available commands:
|
||||
/start: _Start bot and get this message_.
|
||||
/help: _Get this message_.
|
||||
/info: _Get shorter info message about this bot_....
|
||||
|
||||
/info
|
||||
|
||||
This is bashbot, the Telegram bot written entirely in bash.
|
||||
It features background tasks and interactive chats, and can serve as an interface for CLI programs.
|
||||
</code></pre>
|
||||
<p>For more Information on how to install, customize and use your new bot, read the <a href="#Documentation">Documentation</a>.</p>
|
||||
<h3>Log files</h3>
|
||||
<p>Bashbot actions are logged to <code>BASHBOT.log</code>. Telegram send/receive errors are logged to <code>ERROR.log</code>. Start bashbot in debug mode to see all messages sent to / received from Telegram, as well as bash command error messages.</p>
|
||||
<p>To enable debug mode, start bashbot with debug as third argument: <code>bashbot start debug</code></p>
|
||||
<pre><code>|__ logs
|
||||
| |__ BASHBOT.log # log what your bot is doing ...
|
||||
| |__ ERROR.log # connection errors from / to Telegram API
|
||||
| |
|
||||
| |__ DEBUG.log # stdout/stderr of you bot (debug mode enabled)
|
||||
| |__ MESSAGE.log # full text of all message send/received (debug mode enabled)
|
||||
</code></pre>
|
||||
<hr />
|
||||
<h2>Security Considerations</h2>
|
||||
<p>Running a Telegram Bot means it is connected to the public and you never know what's send to your Bot.</p>
|
||||
<p>Bash scripts in general are not designed to be bulletproof, so consider this Bot as a proof of concept. Bash programmers often struggle with 'quoting hell' and globbing, see <a href="https://unix.stackexchange.com/questions/171346/security-implications-of-forgetting-to-quote-a-variable-in-bash-posix-shells">Implications of wrong quoting</a>.</p>
|
||||
<p>Whenever you are processing input from untrusted sources (messages, files, network) you must be as careful as possible (e.g. set IFS appropriately, disable globbing with <code>set -f</code> and quote everything). In addition remove unused scripts and examples from your Bot (e.g. everything in <code>example/</code>) and disable/remove all unused bot commands.</p>
|
||||
<p>It's important to escape or remove <code>$</code> and ` in input from user, files or network (<em>as bashbot does</em>). One of the powerful features of Unix shells is variable and command substitution using <code>${var}</code>, <code>$(cmd)</code> and `cmd` can lead to remote code execution (RCE) or remote information disclosure (RID) bugs if unescaped <code>$</code> or ` is included in untrusted input (e.g. <code>$$</code> or <code>$(rm -rf /*)</code>).</p>
|
||||
<p>A powerful tool to improve your scripts is <code>shellcheck</code>. You can <a href="https://www.shellcheck.net/">use it online</a> or <a href="https://github.com/koalaman/shellcheck#installing">install shellcheck locally</a>. Shellcheck is used extensively in bashbot development to ensure a high code quality (e.g. it's not allowed to push changes without passing all shellcheck tests). In addition bashbot has a <a href="doc/7_develop.md">test suite</a> to check if important functionality is working as expected.</p>
|
||||
<h3>Use printf whenever possible</h3>
|
||||
<p>If you're writing a script that accepts external input (e.g. from the user as arguments or the file system), you shouldn't use echo to display it. <a href="https://unix.stackexchange.com/a/6581">Use printf whenever possible</a>.</p>
|
||||
<h3>Run your Bot as a restricted user</h3>
|
||||
<p><strong>I recommend running your bot as a user with almost no access rights.</strong> All files your Bot has write access to are in danger of being overwritten/deleted if your bot is hacked. For the same reason every file your Bot can read is in danger of being disclosed. Restrict your Bots access rights to the absolute minimum.</p>
|
||||
<p><strong>Never run your Bot as root, this is the most dangerous you can do!</strong> Usually the user 'nobody' has almost no rights on Linux/Unix systems. See <a href="doc/4_expert.md">Expert use</a> on how to run your Bot as an other user.</p>
|
||||
<h3>Secure your Bot installation</h3>
|
||||
<p><strong>Your Bot configuration must not be readable by other users.</strong> Everyone who can read your Bots token is able to act as your Bot and has access to all chats the Bot is in!</p>
|
||||
<p>Everyone with read access to your Bot files can extract your Bots data. Especially your Bot config in <code>config.jssh</code> must be protected against other users. No one except you should have write access to the Bot files. The Bot should be restricted to have write access to <code>count.jssh</code>, <code>data-bot-bash/</code> and <code>logs/</code> only, all other files must be write protected.</p>
|
||||
<p>To set access rights for your bashbot installation to a reasonable default run <code>sudo ./bashbot.sh init</code> after every update or change to your installation directory.</p>
|
||||
<h3 id="is-this-bot-insecure">Is this Bot insecure?</h3>
|
||||
<p>Bashbot is not more (in)secure as any other Bot written in any other language, we have done our best to make it as secure as possible. But YOU are responsible for the bot commands you wrote and you should know about the risks …</p>
|
||||
<h3 id="why-bash-and-not-the-much-better-xyz">Why Bash and not the much better xyz?</h3>
|
||||
<p>Well, thats a damn good question … may be because I’m an Unix/Linux admin from stone age. Nevertheless there are more reasons from my side:</p>
|
||||
<p><em>Note</em>: Keep old log files in a safe place or even better delete them, they are GDPR relevant and <a href="https://github.com/topkecleon/telegram-bot-bash/issues/174">may contain information</a> you don't want to be public.</p>
|
||||
<h2>FAQ</h2>
|
||||
<h3>Is this Bot insecure?</h3>
|
||||
<p>Bashbot is not more (in)secure than a Bot written in another language. We have done our best to make it as secure as possible. But YOU are responsible for the bot commands you wrote and you should know about the risks ...</p>
|
||||
<p><strong>Note:</strong> Up to version 0.941 (mai/22/2020) telegram-bot-bash had a remote code execution bug, please update if you use an older version!</p>
|
||||
<h3>Why Bash and not the much better xyz?</h3>
|
||||
<p>Well, that's a damn good question... maybe because I'm a Unix admin from the stone age. Nevertheless there are more reasons from my side:</p>
|
||||
<ul>
|
||||
<li>bashbot will run everywhere where bash is availible, from ebedded linux to mainframe</li>
|
||||
<li>easy to integrate with other shell script, e.g. for sending system message / health status</li>
|
||||
<li>bashbot will run wherever bash and (gnu) sed is available, from embedded Linux to mainframe</li>
|
||||
<li>easy to integrate with other shell scripts, e.g. for sending system message / health status</li>
|
||||
<li>no need to install or learn a new programming language, library or framework</li>
|
||||
<li>no database, not event driven, not OO …</li>
|
||||
<li>no database, not event driven, not object oriented ...</li>
|
||||
</ul>
|
||||
<p><span class="citation">@Gnadelwartz</span></p>
|
||||
<h2 id="thats-it">That’s it!</h2>
|
||||
<p>If you feel that there’s something missing or if you found a bug, feel free to submit a pull request!</p>
|
||||
<h4 id="version-v0.72-1-g67c47ac"><br /><span class="math display"><em>V</em><em>E</em><em>R</em><em>S</em><em>I</em><em>O</em><em>N</em></span><br /> v0.72-1-g67c47ac</h4>
|
||||
<h3>Can I have the single bashbot.sh file back?</h3>
|
||||
<p>At the beginning bashbot was simply the file <code>bashbot.sh</code> that you could copy everywhere and run the bot. Now we have 'commands.sh', 'mycommands.sh', 'modules/*.sh' and much more.</p>
|
||||
<p>Hey no problem, if you are finished with your cool bot, run <code>dev/make-standalone.sh</code> to create a stripped down version of your bot containing only 'bashbot.sh' and 'commands.sh'! For more information see <a href="doc/7_develop.md">Create a stripped down version of your Bot</a>.</p>
|
||||
<h3>Can I send messages from CLI and scripts?</h3>
|
||||
<p>Of course you can send messages from command line and scripts! Simply install bashbot as <a href="#Your-really-first-bashbot-in-a-nutshell">described here</a>, send the message '/start' to set yourself as botadmin and then stop the bot with <code>./bashbot.sh stop</code>.</p>
|
||||
<p>Bashbot provides some ready to use scripts for sending messages from command line in <code>bin/</code> dir, e.g. <code>send_message.sh</code>.</p>
|
||||
<div class="sourceCode" id="cb4"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1"></a><span class="ex">bin/send_message.sh</span> BOTADMIN <span class="st">"This is my first message send from CLI"</span></span>
|
||||
<span id="cb4-2"><a href="#cb4-2"></a></span>
|
||||
<span id="cb4-3"><a href="#cb4-3"></a><span class="ex">bin/send_message.sh</span> --help</span></code></pre></div>
|
||||
<p>You can also source bashbot for use in your scripts, for more information see <a href="doc/4_expert.md">Expert Use</a>.</p>
|
||||
<h3>Blocked by telegram?</h3>
|
||||
<p>This may happen if too many or wrong requests are sent to api.telegram.org, e.g. using a invalid token or invalid API calls. If the block stay for longer time you can ask telegram service to unblock your IP-Address.</p>
|
||||
<p>You can check with curl or wget if you are blocked by Telegram:</p>
|
||||
<div class="sourceCode" id="cb5"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1"></a><span class="ex">curl</span> -m 10 https://api.telegram.org/bot</span>
|
||||
<span id="cb5-2"><a href="#cb5-2"></a><span class="co">#curl: (28) Connection timed out after 10001 milliseconds</span></span>
|
||||
<span id="cb5-3"><a href="#cb5-3"></a></span>
|
||||
<span id="cb5-4"><a href="#cb5-4"></a><span class="fu">wget</span> -t 1 -T 10 https://api.telegram.org/bot</span>
|
||||
<span id="cb5-5"><a href="#cb5-5"></a><span class="co">#Connecting to api.telegram.org (api.telegram.org)|46.38.243.234|:443... failed: Connection timed out.</span></span>
|
||||
<span id="cb5-6"><a href="#cb5-6"></a></span>
|
||||
<span id="cb5-7"><a href="#cb5-7"></a><span class="ex">nc</span> -w 2 api.telegram.org 443 <span class="kw">||</span> <span class="bu">echo</span> <span class="st">"your IP seems blocked by telegram"</span></span>
|
||||
<span id="cb5-8"><a href="#cb5-8"></a><span class="co">#your IP seems blocked by telegram</span></span></code></pre></div>
|
||||
<p>Bashbot offers the option to recover from broken connections (blocked). Therefore you can provide a function named <code>bashbotBlockRecover()</code> in <code>mycommands.sh</code>, the function is called every time when a broken connection is detected.</p>
|
||||
<p>Possible actions are: Check if network is working, change IP-Address or simply wait some time. See <code>mycommnds.sh.dist</code> for an example.</p>
|
||||
<hr />
|
||||
<p>@Gnadelwartz</p>
|
||||
<h2>That's it all guys!</h2>
|
||||
<p>If you feel that there's something missing or if you found a bug, feel free to submit a pull request!</p>
|
||||
<h4>$$VERSION$$ v1.52-0-g1a83202</h4>
|
||||
</body>
|
||||
</html>
|
||||
|
|
238
README.md
238
README.md
|
@ -1,34 +1,46 @@
|
|||
# bashbot
|
||||
A Telegram bot written in bash.
|
||||
<h2><img align="middle" src="https://raw.githubusercontent.com/odb/official-bash-logo/master/assets/Logos/Icons/PNG/64x64.png" >
|
||||
Bashbot - A Telegram bot written in bash.
|
||||
</h2>
|
||||
Written by Drew (@topkecleon) and Kay M (@gnadelwartz).
|
||||
|
||||
Written by Drew (@topkecleon), Daniil Gentili (@danogentili), and Kay M (@gnadelwartz).
|
||||
|
||||
Contributions by JuanPotato, BigNerd95, TiagoDanin, and iicc1.
|
||||
Contributions by Daniil Gentili (@danog), JuanPotato, BigNerd95, TiagoDanin, iicc1 and dcoomber.
|
||||
|
||||
Released to the public domain wherever applicable.
|
||||
Elsewhere, consider it released under the [WTFPLv2](http://www.wtfpl.net/txt/copying/).
|
||||
|
||||
Linted by [#ShellCheck](https://github.com/koalaman/shellcheck)
|
||||
|
||||
---
|
||||
**Bashbot** is created by old-fashioned shell hackers to show that it's possible to write a bot in Bash.
|
||||
|
||||
It is designed for **simple** use cases and easily integrates with Linux tasks.
|
||||
For bots that serve a lot of users or a heavy workload, I strongly recommend using a dedicated bot framework.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
Depends on [tmux](http://github.com/tmux/tmux).
|
||||
Uses [JSON.sh](http://github.com/dominictarr/JSON.sh).
|
||||
Uses [JSON.sh](http://github.com/dominictarr/JSON.sh)/[JSON.awk](https://github.com/step-/JSON.awk) and the magic of sed.
|
||||
|
||||
Most complete [UTF-8 support for bashbot](doc/4_expert.md#Bashbot-UTF-8-Support) is availible if phyton is installed (optional).
|
||||
Bashbot is written in bash. It depends on commands typically available in a Linux/Unix Environment.
|
||||
For more information on commands provided by recent versions of [coreutils](https://en.wikipedia.org/wiki/List_of_GNU_Core_Utilities_commands), [busybox](https://en.wikipedia.org/wiki/BusyBox#Commands) or [toybox](https://landley.net/toybox/help.html), see [Developer Notes](doc/7_develop.md#common-commands).
|
||||
|
||||
Bashbot [Documentation](https://github.com/topkecleon/telegram-bot-bash) and [Downloads](https://github.com/topkecleon/telegram-bot-bash/releases) are availible on www.github.com
|
||||
**Note for MacOS and BSD Users:** Bashbot will not run without installing additional software as it uses modern bash and (gnu) grep/sed features. See [Install Bashbot](doc/0_install.md).
|
||||
|
||||
**Note for embedded systems:** You need to install a "real" bash as the vanilla installation of busybox or toybox is not sufficient. See [Install Bashbot](doc/0_install.md).
|
||||
|
||||
Bashbot [Documentation](https://github.com/topkecleon/telegram-bot-bash) and [Downloads](https://github.com/topkecleon/telegram-bot-bash/releases) are available on [www.github.com](https://www.github.com).
|
||||
|
||||
## Documentation
|
||||
* [Introdution to Telegram Bots](https://core.telegram.org/bots)
|
||||
* [One Bot to rule them all](https://core.telegram.org/bots#3-how-do-i-create-a-bot)
|
||||
* [Bot commands](https://core.telegram.org/bots#commands)
|
||||
* [Introduction to Telegram Bots](https://core.telegram.org/bots)
|
||||
* [Install Bashbot](doc/0_install.md)
|
||||
* Install release
|
||||
* Install from githup
|
||||
* Install from github
|
||||
* Update Bashbot
|
||||
* Notes on Updates
|
||||
* [Create a new Telegram Bot with botfather](doc/1_firstbot.md)
|
||||
* [Get Bottoken from Botfather](doc/1_firstbot.md)
|
||||
* [Getting Started](doc/2_usage.md)
|
||||
* Managing your Bot
|
||||
* Recieve data
|
||||
* Receive data
|
||||
* Send messages
|
||||
* Send files, locations, keyboards
|
||||
* [Advanced Features](doc/3_advanced.md)
|
||||
|
@ -36,66 +48,206 @@ Bashbot [Documentation](https://github.com/topkecleon/telegram-bot-bash) and [Do
|
|||
* Interactive Chats
|
||||
* Background Jobs
|
||||
* Inline queries
|
||||
* Send message errors
|
||||
* [Expert Use](doc/4_expert.md)
|
||||
* Handling UTF-8 character sets
|
||||
* Run as other user or system service
|
||||
* Scedule bashbot from Cron
|
||||
* Schedule bashbot from Cron
|
||||
* Use from CLI and Scripts
|
||||
* Customize Bashbot Environment
|
||||
* [Best Practices](doc/5_practice.md)
|
||||
* Customize commands.sh
|
||||
* Seperate logic from commands
|
||||
* Customize mycommands.sh
|
||||
* Overwrite/disable commands
|
||||
* Separate logic from commands
|
||||
* Test your Bot with shellcheck
|
||||
* [Function Reference](doc/6_reference.md)
|
||||
* Sending Messages, Files, Keyboards
|
||||
* User Access Control
|
||||
* Inline Queries
|
||||
* jsshDB Bashbot key-value storage
|
||||
* Background and Interactive Jobs
|
||||
* [Deveoper Notess](doc/7_develop.md)
|
||||
* [Developer Notes](doc/7_develop.md)
|
||||
* Debug bashbot
|
||||
* Modules, addons, events
|
||||
* Setup your environment
|
||||
* Test, Add, Push changes
|
||||
* Prepare a new version
|
||||
* Bashbot testsuite
|
||||
* [Customize bashbot environment](doc/8_custom.md)
|
||||
* [Examples](examples/README.md)
|
||||
* Bashbot test suite
|
||||
* [Examples Directory](examples)
|
||||
* [Webhook Example](examples/webhook)
|
||||
|
||||
### Your very first bashbot in a nutshell
|
||||
|
||||
To install and run bashbot you need access to a Linux/Unix command line with bash, a [Telegram client](https://telegram.org) and a mobile phone [with a Telegram account](https://telegramguide.com/create-a-telegram-account/).
|
||||
|
||||
First you need to [create a new Telegram Bot token](doc/1_firstbot.md) for your bot and write it down.
|
||||
|
||||
Now open a Linux/Unix terminal with bash, create a new directory, change to it and install telegram-bot-bash:
|
||||
|
||||
```bash
|
||||
# create bot dir
|
||||
mkdir mybot
|
||||
cd mybot
|
||||
|
||||
# download latest release with wget or from https://github.com/topkecleon/telegram-bot-bash/releases/latest
|
||||
wget "https://github.com/$(wget -q "https://github.com/topkecleon/telegram-bot-bash/releases/latest" -O - | egrep '/.*/download/.*/.*tar.gz' -o)"
|
||||
|
||||
# Extract the tar archive and go into bot dir
|
||||
tar -xzf *.tar.gz
|
||||
cd telegram-bot-bash
|
||||
|
||||
# initialize your bot
|
||||
# Enter your bot token when asked, all other questions can be answered by hitting the \<Return\> key.
|
||||
./bashbot.sh init
|
||||
|
||||
# Now start your bot
|
||||
./bashbot.sh start
|
||||
|
||||
Bottoken is valid ...
|
||||
Bot Name: yourbotname_bot
|
||||
Session Name: yourbotname_bot-startbot
|
||||
Bot started successfully.
|
||||
```
|
||||
|
||||
Now open the Telegram App on your mobile phone and start a chat with your bot (_your bot's username is shown after 'Bot Name:'_):
|
||||
|
||||
```
|
||||
/start
|
||||
|
||||
You are Botadmin
|
||||
Available commands:
|
||||
/start: _Start bot and get this message_.
|
||||
/help: _Get this message_.
|
||||
/info: _Get shorter info message about this bot_....
|
||||
|
||||
/info
|
||||
|
||||
This is bashbot, the Telegram bot written entirely in bash.
|
||||
It features background tasks and interactive chats, and can serve as an interface for CLI programs.
|
||||
```
|
||||
For more Information on how to install, customize and use your new bot, read the [Documentation](#Documentation).
|
||||
|
||||
### Log files
|
||||
|
||||
Bashbot actions are logged to `BASHBOT.log`. Telegram send/receive errors are logged to `ERROR.log`.
|
||||
Start bashbot in debug mode to see all messages sent to / received from Telegram, as well as bash command error messages.
|
||||
|
||||
To enable debug mode, start bashbot with debug as third argument: `bashbot start debug`
|
||||
|
||||
```
|
||||
|__ logs
|
||||
| |__ BASHBOT.log # log what your bot is doing ...
|
||||
| |__ ERROR.log # connection errors from / to Telegram API
|
||||
| |
|
||||
| |__ DEBUG.log # stdout/stderr of you bot (debug mode enabled)
|
||||
| |__ MESSAGE.log # full text of all message send/received (debug mode enabled)
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
## Security Considerations
|
||||
Running a Telegram Bot means it is connected to the public and you never know whats send to your Bot.
|
||||
Running a Telegram Bot means it is connected to the public and you never know what's send to your Bot.
|
||||
|
||||
Bash scripts in general are not designed to be bullet proof, so consider this Bot as a proof of concept. Bash programmers often struggle with 'quoting hell' and globbing, see [Implications of wrong quoting](https://unix.stackexchange.com/questions/171346/security-implications-of-forgetting-to-quote-a-variable-in-bash-posix-shells)
|
||||
Bash scripts in general are not designed to be bulletproof, so consider this Bot as a proof of concept.
|
||||
Bash programmers often struggle with 'quoting hell' and globbing,
|
||||
see [Implications of wrong quoting](https://unix.stackexchange.com/questions/171346/security-implications-of-forgetting-to-quote-a-variable-in-bash-posix-shells).
|
||||
|
||||
Whenever you are processing input from from untrusted sources (messages, files, network) you must be as carefull as possible, e.g. set IFS appropriate, disable globbing (set -f) and quote everthing. In addition delete unused scripts and examples from your Bot, e.g. scripts 'notify', 'calc', 'question', and disable all not used commands.
|
||||
Whenever you are processing input from untrusted sources (messages, files, network) you must be as careful as possible
|
||||
(e.g. set IFS appropriately, disable globbing with `set -f` and quote everything). In addition remove unused scripts and examples
|
||||
from your Bot (e.g. everything in `example/`) and disable/remove all unused bot commands.
|
||||
|
||||
A powerful tool to improve your scripts is ```shellcheck```. You can [use it online](https://www.shellcheck.net/) or [install shellcheck locally](https://github.com/koalaman/shellcheck#installing). Shellcheck is used extensive in bashbot development to enshure a high code quality, e.g. it's not allowed to push changes without passing all shellcheck tests.
|
||||
It's important to escape or remove `$` and \` in input from user, files or network (_as bashbot does_).
|
||||
One of the powerful features of Unix shells is variable and command substitution using `${var}`, `$(cmd)` and \`cmd\` can lead to remote
|
||||
code execution (RCE) or remote information disclosure (RID) bugs if unescaped `$` or \` is included in untrusted input (e.g. `$$` or `$(rm -rf /*)`).
|
||||
|
||||
A powerful tool to improve your scripts is `shellcheck`. You can [use it online](https://www.shellcheck.net/) or
|
||||
[install shellcheck locally](https://github.com/koalaman/shellcheck#installing). Shellcheck is used extensively in bashbot development
|
||||
to ensure a high code quality (e.g. it's not allowed to push changes without passing all shellcheck tests).
|
||||
In addition bashbot has a [test suite](doc/7_develop.md) to check if important functionality is working as expected.
|
||||
|
||||
### Run your Bot as a restricted user
|
||||
**I recommend to run your bot as a user, with almost no access rights.**
|
||||
All files your Bot have write access to are in danger to be overwritten/deleted if your bot is hacked.
|
||||
For the same reason ervery file your Bot can read is in danger to be disclosed. Restict your Bots access rigths to the absolute minimum.
|
||||
### Use printf whenever possible
|
||||
|
||||
**Never run your Bot as root, this is the most dangerous you can do!** Usually the user 'nobody' has almost no rights on Unix/Linux systems. See [Expert use](doc/4_expert.md) on how to run your Bot as an other user.
|
||||
If you're writing a script that accepts external input (e.g. from the user as arguments or the file system),
|
||||
you shouldn't use echo to display it. [Use printf whenever possible](https://unix.stackexchange.com/a/6581).
|
||||
|
||||
### Run your Bot as a restricted user
|
||||
**I recommend running your bot as a user with almost no access rights.**
|
||||
All files your Bot has write access to are in danger of being overwritten/deleted if your bot is hacked.
|
||||
For the same reason every file your Bot can read is in danger of being disclosed. Restrict your Bots access rights to the absolute minimum.
|
||||
|
||||
**Never run your Bot as root, this is the most dangerous you can do!** Usually the user 'nobody' has almost no rights on Linux/Unix systems. See [Expert use](doc/4_expert.md) on how to run your Bot as an other user.
|
||||
|
||||
### Secure your Bot installation
|
||||
**Your Bot configuration must no be readable from other users.** Everyone who can read your Bots token can act as your Bot and has access to all chats your Bot is in!
|
||||
**Your Bot configuration must not be readable by other users.** Everyone who can read your Bots token is able to act as your Bot and has access to all chats the Bot is in!
|
||||
|
||||
Everyone with read access to your Bot files can extract your Bots data. Especially your Bot Token in ```token``` must be protected against other users. No one exept you must have write access to the Bot files. The Bot must be restricted to have write access to ```count``` and ```tmp-bot-bash``` only, all other files must be write protected.
|
||||
Everyone with read access to your Bot files can extract your Bots data. Especially your Bot config in `config.jssh` must be protected against other users. No one except you should have write access to the Bot files. The Bot should be restricted to have write access to `count.jssh`, `data-bot-bash/` and `logs/` only, all other files must be write protected.
|
||||
|
||||
To set access rights for your bashbot installation to a reasonable default run ```sudo ./bashbot.sh init``` after every update or change to your installation directory.
|
||||
To set access rights for your bashbot installation to a reasonable default run `sudo ./bashbot.sh init` after every update or change to your installation directory.
|
||||
|
||||
*Note*: Keep old log files in a safe place or even better delete them, they are GDPR relevant and [may contain information](https://github.com/topkecleon/telegram-bot-bash/issues/174) you don't want to be public.
|
||||
|
||||
## FAQ
|
||||
|
||||
### Is this Bot insecure?
|
||||
Bashbot is not more (in)secure as any other Bot written in any other language, we have done our best to make it as secure as possible. But YOU are responsible for the bot commands you wrote and you should know about the risks ...
|
||||
Bashbot is not more (in)secure than a Bot written in another language. We have done our best to make it as secure as possible. But YOU are responsible for the bot commands you wrote and you should know about the risks ...
|
||||
|
||||
**Note:** Up to version 0.941 (mai/22/2020) telegram-bot-bash had a remote code execution bug, please update if you use an older version!
|
||||
|
||||
### Why Bash and not the much better xyz?
|
||||
Well, thats a damn good question ... may be because I'm an Unix/Linux admin from stone age. Nevertheless there are more reasons from my side:
|
||||
Well, that's a damn good question... maybe because I'm a Unix admin from the stone age. Nevertheless there are more reasons from my side:
|
||||
|
||||
- bashbot will run everywhere where bash is availible, from ebedded linux to mainframe
|
||||
- easy to integrate with other shell script, e.g. for sending system message / health status
|
||||
- bashbot will run wherever bash and (gnu) sed is available, from embedded Linux to mainframe
|
||||
- easy to integrate with other shell scripts, e.g. for sending system message / health status
|
||||
- no need to install or learn a new programming language, library or framework
|
||||
- no database, not event driven, not OO ...
|
||||
- no database, not event driven, not object oriented ...
|
||||
|
||||
### Can I have the single bashbot.sh file back?
|
||||
At the beginning bashbot was simply the file `bashbot.sh` that you could copy everywhere and run the bot. Now we have 'commands.sh', 'mycommands.sh', 'modules/*.sh' and much more.
|
||||
|
||||
Hey no problem, if you are finished with your cool bot, run `dev/make-standalone.sh` to create a stripped down version of your bot containing only
|
||||
'bashbot.sh' and 'commands.sh'! For more information see [Create a stripped down version of your Bot](doc/7_develop.md).
|
||||
|
||||
### Can I send messages from CLI and scripts?
|
||||
Of course you can send messages from command line and scripts! Simply install bashbot as [described here](#Your-really-first-bashbot-in-a-nutshell),
|
||||
send the message '/start' to set yourself as botadmin and then stop the bot with `./bashbot.sh stop`.
|
||||
|
||||
Bashbot provides some ready to use scripts for sending messages from command line in `bin/` dir, e.g. `send_message.sh`.
|
||||
|
||||
```bash
|
||||
bin/send_message.sh BOTADMIN "This is my first message send from CLI"
|
||||
|
||||
bin/send_message.sh --help
|
||||
```
|
||||
|
||||
You can also source bashbot for use in your scripts, for more information see [Expert Use](doc/4_expert.md).
|
||||
|
||||
|
||||
### Blocked by telegram?
|
||||
This may happen if too many or wrong requests are sent to api.telegram.org, e.g. using a invalid token or invalid API calls.
|
||||
If the block stay for longer time you can ask telegram service to unblock your IP-Address.
|
||||
|
||||
You can check with curl or wget if you are blocked by Telegram:
|
||||
```bash
|
||||
curl -m 10 https://api.telegram.org/bot
|
||||
#curl: (28) Connection timed out after 10001 milliseconds
|
||||
|
||||
wget -t 1 -T 10 https://api.telegram.org/bot
|
||||
#Connecting to api.telegram.org (api.telegram.org)|46.38.243.234|:443... failed: Connection timed out.
|
||||
|
||||
nc -w 2 api.telegram.org 443 || echo "your IP seems blocked by telegram"
|
||||
#your IP seems blocked by telegram
|
||||
```
|
||||
|
||||
Bashbot offers the option to recover from broken connections (blocked). Therefore you can provide a function
|
||||
named `bashbotBlockRecover()` in `mycommands.sh`, the function is called every time when a broken connection is detected.
|
||||
|
||||
Possible actions are: Check if network is working, change IP-Address or simply wait some time.
|
||||
See `mycommnds.sh.dist` for an example.
|
||||
|
||||
---
|
||||
|
||||
@Gnadelwartz
|
||||
|
||||
## That's it!
|
||||
## That's it all guys!
|
||||
|
||||
If you feel that there's something missing or if you found a bug, feel free to submit a pull request!
|
||||
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
|
413
README.txt
413
README.txt
|
@ -1,140 +1,323 @@
|
|||
# bashbot
|
||||
A Telegram bot written in bash.
|
||||
|
||||
Written by Drew (@topkecleon), Daniil Gentili (@danogentili), and Kay M
|
||||
(@gnadelwartz).
|
||||
..
|
||||
****
|
||||
****oooooo*****
|
||||
*****ooooooooooooo*****
|
||||
*****oooooooooooooooooooooo****
|
||||
****oooooooooooooooooooooooooooooooo**
|
||||
*.*oooooooooooooooooooooooooooooooooooo**
|
||||
*.ooooooooooooooooooooooooooooooooo**....
|
||||
*.oooooooooooooooooooooooooooo**.........
|
||||
*.oooooooooooooooooooooooo**.............
|
||||
*.ooooooooooooooooooo**.................. ____ _ _ _
|
||||
*.ooooooooooooooooo*.......,............. | _ \ | | | | | |
|
||||
*.ooooooooooooooooo*.....,***,........... | |_) | __ _ ___ | |__ | |__ ___ | |_
|
||||
*.ooooooooooooooooo*....o*............... | _ < / _` |/ __|| '_ \ | '_ \ / _ \ | __|
|
||||
*.ooooooooooooooooo*....*o***,........... | |_) || (_| |\__ \| | | || |_) || (_) || |_
|
||||
*.*oooooooooooooooo*........o*.....oo.... |____/ \__,_||___/|_| |_||_.__/ \___/ \__|
|
||||
****ooooooooooooo*....`***....oo.....*
|
||||
*****oooooooo*......*..oo.....**
|
||||
******ooo*.............*
|
||||
***o*........**
|
||||
**...**
|
||||
|
||||
Contributions by JuanPotato, BigNerd95, TiagoDanin, and iicc1.
|
||||
|
||||
Released to the public domain wherever applicable.
|
||||
Elsewhere, consider it released under the
|
||||
[WTFPLv2](http://www.wtfpl.net/txt/copying/).
|
||||
|
||||
## Prerequisites
|
||||
Depends on [tmux](http://github.com/tmux/tmux).
|
||||
Uses [JSON.sh](http://github.com/dominictarr/JSON.sh).
|
||||
|
||||
Most complete [UTF-8 support for
|
||||
bashbot](doc/4_expert.md#Bashbot-UTF-8-Support) is availible if phyton is
|
||||
installed (optional).
|
||||
|
||||
Bashbot [Documentation](https://github.com/topkecleon/telegram-bot-bash) and
|
||||
[Downloads](https://github.com/topkecleon/telegram-bot-bash/releases) are
|
||||
availible on www.github.com
|
||||
Bashbot README
|
||||
|
||||
## Documentation
|
||||
* [Introdution to Telegram Bots](https://core.telegram.org/bots)
|
||||
* [One Bot to rule them
|
||||
all](https://core.telegram.org/bots#3-how-do-i-create-a-bot)
|
||||
* [Bot commands](https://core.telegram.org/bots#commands)
|
||||
* [Install Bashbot](doc/0_install.md)
|
||||
* Install release
|
||||
* Install from githup
|
||||
* Update Bashbot
|
||||
* Notes on Updates
|
||||
* [Create a new Telegram Bot with botfather](doc/1_firstbot.md)
|
||||
* [Getting Started](doc/2_usage.md)
|
||||
* Managing your Bot
|
||||
* Recieve data
|
||||
* Send messages
|
||||
* Send files, locations, keyboards
|
||||
* [Advanced Features](doc/3_advanced.md)
|
||||
* Access Control
|
||||
* Interactive Chats
|
||||
* Background Jobs
|
||||
* Inline queries
|
||||
* [Expert Use](doc/4_expert.md)
|
||||
* Handling UTF-8 character sets
|
||||
* Run as other user or system service
|
||||
* Scedule bashbot from Cron
|
||||
* [Best Practices](doc/5_practice.md)
|
||||
* Customize commands.sh
|
||||
* Seperate logic from commands
|
||||
* Test your Bot with shellcheck
|
||||
* [Function Reference](doc/6_reference.md)
|
||||
* Sending Messages, Files, Keyboards
|
||||
* User Access Control
|
||||
* Inline Queries
|
||||
* Background and Interactive Jobs
|
||||
* [Deveoper Notess](doc/7_develop.md)
|
||||
* Setup your environment
|
||||
* Test, Add, Push changes
|
||||
* Prepare a new version
|
||||
* Bashbot testsuite
|
||||
* [Customize bashbot environment](doc/8_custom.md)
|
||||
* [Examples](examples/README.md)
|
||||
|
||||
## Security Considerations
|
||||
Running a Telegram Bot means it is connected to the public and you never know
|
||||
whats send to your Bot.
|
||||
Bashbot - A Telegram bot written in bash.
|
||||
|
||||
Bash scripts in general are not designed to be bullet proof, so consider this
|
||||
Bot as a proof of concept. Bash programmers often struggle with 'quoting hell'
|
||||
and globbing, see [Implications of wrong
|
||||
quoting](https://unix.stackexchange.com/questions/171346/security-implications-o
|
||||
f-forgetting-to-quote-a-variable-in-bash-posix-shells)
|
||||
Written by Drew (@topkecleon) and Kay M (@gnadelwartz).
|
||||
Contributions by Daniil Gentili (@danog), JuanPotato, BigNerd95, TiagoDanin, iicc1 and
|
||||
dcoomber.
|
||||
Released to the public domain wherever applicable. Elsewhere, consider it released under
|
||||
the WTFPLv2 [http://www.wtfpl.net/txt/copying/].
|
||||
Linted by #ShellCheck
|
||||
|
||||
Whenever you are processing input from from untrusted sources (messages, files,
|
||||
network) you must be as carefull as possible, e.g. set IFS appropriate, disable
|
||||
globbing (set -f) and quote everthing. In addition delete unused scripts and
|
||||
examples from your Bot, e.g. scripts 'notify', 'calc', 'question', and disable
|
||||
all not used commands.
|
||||
Prerequisites
|
||||
|
||||
A powerful tool to improve your scripts is ```shellcheck```. You can [use it
|
||||
online](https://www.shellcheck.net/) or [install shellcheck
|
||||
locally](https://github.com/koalaman/shellcheck#installing). Shellcheck is used
|
||||
extensive in bashbot development to enshure a high code quality, e.g. it's not
|
||||
allowed to push changes without passing all shellcheck tests.
|
||||
In addition bashbot has a [test suite](doc/7_develop.md) to check if important
|
||||
Uses JSON.sh [http://github.com/dominictarr/JSON.sh]/JSON.awk [https://github.com/step-/
|
||||
JSON.awk] and the magic of sed.
|
||||
Bashbot is written in bash. It depends on commands typically available in a Linux/Unix
|
||||
Environment. For more information on commands provided by recent versions of coreutils
|
||||
[https://en.wikipedia.org/wiki/List_of_GNU_Core_Utilities_commands], busybox [https://
|
||||
en.wikipedia.org/wiki/BusyBox#Commands] or toybox [https://landley.net/toybox/help.html],
|
||||
see Developer Notes [doc/7_develop.md#common-commands].
|
||||
Note for MacOS and BSD Users: Bashbot will not run without installing additional software
|
||||
as it uses modern bash and (gnu) grep/sed features. See Install Bashbot [doc/
|
||||
0_install.md].
|
||||
Note for embedded systems: You need to install a "real" bash as the vanilla installation
|
||||
of busybox or toybox is not sufficient. See Install Bashbot [doc/0_install.md].
|
||||
Bashbot Documentation [https://github.com/topkecleon/telegram-bot-bash] and Downloads
|
||||
[https://github.com/topkecleon/telegram-bot-bash/releases] are available on www.github.com
|
||||
[https://www.github.com].
|
||||
|
||||
Documentation
|
||||
|
||||
|
||||
* Introduction to Telegram Bots [https://core.telegram.org/bots]
|
||||
* Install Bashbot [doc/0_install.md]
|
||||
|
||||
o Install release
|
||||
o Install from github
|
||||
o Update Bashbot
|
||||
o Notes on Updates
|
||||
|
||||
* Get Bottoken from Botfather [doc/1_firstbot.md]
|
||||
* Getting Started [doc/2_usage.md]
|
||||
|
||||
o Managing your Bot
|
||||
o Receive data
|
||||
o Send messages
|
||||
o Send files, locations, keyboards
|
||||
|
||||
* Advanced Features [doc/3_advanced.md]
|
||||
|
||||
o Access Control
|
||||
o Interactive Chats
|
||||
o Background Jobs
|
||||
o Inline queries
|
||||
o Send message errors
|
||||
|
||||
* Expert Use [doc/4_expert.md]
|
||||
|
||||
o Handling UTF-8 character sets
|
||||
o Run as other user or system service
|
||||
o Schedule bashbot from Cron
|
||||
o Use from CLI and Scripts
|
||||
o Customize Bashbot Environment
|
||||
|
||||
* Best Practices [doc/5_practice.md]
|
||||
|
||||
o Customize mycommands.sh
|
||||
o Overwrite/disable commands
|
||||
o Separate logic from commands
|
||||
o Test your Bot with shellcheck
|
||||
|
||||
* Function Reference [doc/6_reference.md]
|
||||
|
||||
o Sending Messages, Files, Keyboards
|
||||
o User Access Control
|
||||
o Inline Queries
|
||||
o jsshDB Bashbot key-value storage
|
||||
o Background and Interactive Jobs
|
||||
|
||||
* Developer Notes [doc/7_develop.md]
|
||||
|
||||
o Debug bashbot
|
||||
o Modules, addons, events
|
||||
o Setup your environment
|
||||
o Bashbot test suite
|
||||
|
||||
* Examples Directory [examples]
|
||||
* Webhook Example [examples/webhook]
|
||||
|
||||
|
||||
Your very first bashbot in a nutshell
|
||||
|
||||
To install and run bashbot you need access to a Linux/Unix command line with bash, a
|
||||
Telegram client [https://telegram.org] and a mobile phone with a Telegram account [https:/
|
||||
/telegramguide.com/create-a-telegram-account/].
|
||||
First you need to create a new Telegram Bot token [doc/1_firstbot.md] for your bot and
|
||||
write it down.
|
||||
Now open a Linux/Unix terminal with bash, create a new directory, change to it and install
|
||||
telegram-bot-bash:
|
||||
|
||||
# create bot dir
|
||||
mkdir mybot
|
||||
cd mybot
|
||||
|
||||
# download latest release with wget or from https://github.com/topkecleon/telegram-bot-
|
||||
bash/releases/latest
|
||||
wget "https://github.com/$(wget -q "https://github.com/topkecleon/telegram-
|
||||
bot-bash/releases/latest" -O - | egrep '/.*/download/.*/.*tar.gz' -o)"
|
||||
|
||||
# Extract the tar archive and go into bot dir
|
||||
tar -xzf *.tar.gz
|
||||
cd telegram-bot-bash
|
||||
|
||||
# initialize your bot
|
||||
# Enter your bot token when asked, all other questions can be answered by hitting the
|
||||
\<Return\> key.
|
||||
./bashbot.sh init
|
||||
|
||||
# Now start your bot
|
||||
./bashbot.sh start
|
||||
|
||||
Bottoken is valid ...
|
||||
Bot Name: yourbotname_bot
|
||||
Session Name: yourbotname_bot-startbot
|
||||
Bot started successfully.
|
||||
|
||||
Now open the Telegram App on your mobile phone and start a chat with your bot (your bot's
|
||||
username is shown after 'Bot Name:'):
|
||||
|
||||
/start
|
||||
|
||||
You are Botadmin
|
||||
Available commands:
|
||||
/start: _Start bot and get this message_.
|
||||
/help: _Get this message_.
|
||||
/info: _Get shorter info message about this bot_....
|
||||
|
||||
/info
|
||||
|
||||
This is bashbot, the Telegram bot written entirely in bash.
|
||||
It features background tasks and interactive chats, and can serve as an interface for
|
||||
CLI programs.
|
||||
|
||||
For more Information on how to install, customize and use your new bot, read the
|
||||
Documentation [#Documentation].
|
||||
|
||||
Log files
|
||||
|
||||
Bashbot actions are logged to BASHBOT.log. Telegram send/receive errors are logged to
|
||||
ERROR.log. Start bashbot in debug mode to see all messages sent to / received from
|
||||
Telegram, as well as bash command error messages.
|
||||
To enable debug mode, start bashbot with debug as third argument: bashbot start debug
|
||||
|
||||
|__ logs
|
||||
| |__ BASHBOT.log # log what your bot is doing ...
|
||||
| |__ ERROR.log # connection errors from / to Telegram API
|
||||
| |
|
||||
| |__ DEBUG.log # stdout/stderr of you bot (debug mode enabled)
|
||||
| |__ MESSAGE.log # full text of all message send/received (debug mode enabled)
|
||||
|
||||
------------------------------------------------------------------------------------------
|
||||
|
||||
Security Considerations
|
||||
|
||||
Running a Telegram Bot means it is connected to the public and you never know what's send
|
||||
to your Bot.
|
||||
Bash scripts in general are not designed to be bulletproof, so consider this Bot as a
|
||||
proof of concept. Bash programmers often struggle with 'quoting hell' and globbing, see
|
||||
Implications of wrong quoting [https://unix.stackexchange.com/questions/171346/security-
|
||||
implications-of-forgetting-to-quote-a-variable-in-bash-posix-shells].
|
||||
Whenever you are processing input from untrusted sources (messages, files, network) you
|
||||
must be as careful as possible (e.g. set IFS appropriately, disable globbing with set -
|
||||
f and quote everything). In addition remove unused scripts and examples from your Bot
|
||||
(e.g. everything in example/) and disable/remove all unused bot commands.
|
||||
It's important to escape or remove $ and ` in input from user, files or network (as
|
||||
bashbot does). One of the powerful features of Unix shells is variable and command
|
||||
substitution using ${var}, $(cmd) and `cmd` can lead to remote code execution (RCE) or
|
||||
remote information disclosure (RID) bugs if unescaped $ or ` is included in untrusted
|
||||
input (e.g. $$ or $(rm -rf /*)).
|
||||
A powerful tool to improve your scripts is shellcheck. You can use it online [https://
|
||||
www.shellcheck.net/] or install shellcheck locally [https://github.com/koalaman/
|
||||
shellcheck#installing]. Shellcheck is used extensively in bashbot development to ensure a
|
||||
high code quality (e.g. it's not allowed to push changes without passing all shellcheck
|
||||
tests). In addition bashbot has a test suite [doc/7_develop.md] to check if important
|
||||
functionality is working as expected.
|
||||
|
||||
### Run your Bot as a restricted user
|
||||
**I recommend to run your bot as a user, with almost no access rights.**
|
||||
All files your Bot have write access to are in danger to be overwritten/deleted
|
||||
if your bot is hacked.
|
||||
For the same reason ervery file your Bot can read is in danger to be disclosed.
|
||||
Restict your Bots access rigths to the absolute minimum.
|
||||
Use printf whenever possible
|
||||
|
||||
**Never run your Bot as root, this is the most dangerous you can do!** Usually
|
||||
the user 'nobody' has almost no rights on Unix/Linux systems. See [Expert
|
||||
use](doc/4_expert.md) on how to run your Bot as an other user.
|
||||
If you're writing a script that accepts external input (e.g. from the user as arguments or
|
||||
the file system), you shouldn't use echo to display it. Use printf whenever possible
|
||||
[https://unix.stackexchange.com/a/6581].
|
||||
|
||||
### Secure your Bot installation
|
||||
**Your Bot configuration must no be readable from other users.** Everyone who
|
||||
can read your Bots token can act as your Bot and has access to all chats your
|
||||
Bot is in!
|
||||
Run your Bot as a restricted user
|
||||
|
||||
Everyone with read access to your Bot files can extract your Bots data.
|
||||
Especially your Bot Token in ```token``` must be protected against other users.
|
||||
No one exept you must have write access to the Bot files. The Bot must be
|
||||
restricted to have write access to ```count``` and ```tmp-bot-bash``` only,
|
||||
all other files must be write protected.
|
||||
I recommend running your bot as a user with almost no access rights. All files your Bot
|
||||
has write access to are in danger of being overwritten/deleted if your bot is hacked. For
|
||||
the same reason every file your Bot can read is in danger of being disclosed. Restrict
|
||||
your Bots access rights to the absolute minimum.
|
||||
Never run your Bot as root, this is the most dangerous you can do! Usually the user
|
||||
'nobody' has almost no rights on Linux/Unix systems. See Expert use [doc/4_expert.md] on
|
||||
how to run your Bot as an other user.
|
||||
|
||||
To set access rights for your bashbot installation to a reasonable default run
|
||||
```sudo ./bashbot.sh init``` after every update or change to your installation
|
||||
directory.
|
||||
Secure your Bot installation
|
||||
|
||||
### Is this Bot insecure?
|
||||
Bashbot is not more (in)secure as any other Bot written in any other language,
|
||||
we have done our best to make it as secure as possible. But YOU are responsible
|
||||
for the bot commands you wrote and you should know about the risks ...
|
||||
Your Bot configuration must not be readable by other users. Everyone who can read your
|
||||
Bots token is able to act as your Bot and has access to all chats the Bot is in!
|
||||
Everyone with read access to your Bot files can extract your Bots data. Especially your
|
||||
Bot config in config.jssh must be protected against other users. No one except you should
|
||||
have write access to the Bot files. The Bot should be restricted to have write access to
|
||||
count.jssh, data-bot-bash/ and logs/ only, all other files must be write protected.
|
||||
To set access rights for your bashbot installation to a reasonable default run sudo ./
|
||||
bashbot.sh init after every update or change to your installation directory.
|
||||
Note: Keep old log files in a safe place or even better delete them, they are GDPR
|
||||
relevant and may contain information [https://github.com/topkecleon/telegram-bot-bash/
|
||||
issues/174] you don't want to be public.
|
||||
|
||||
### Why Bash and not the much better xyz?
|
||||
Well, thats a damn good question ... may be because I'm an Unix/Linux admin
|
||||
from stone age. Nevertheless there are more reasons from my side:
|
||||
FAQ
|
||||
|
||||
- bashbot will run everywhere where bash is availible, from ebedded linux to
|
||||
mainframe
|
||||
- easy to integrate with other shell script, e.g. for sending system message /
|
||||
health status
|
||||
- no need to install or learn a new programming language, library or framework
|
||||
- no database, not event driven, not OO ...
|
||||
|
||||
Is this Bot insecure?
|
||||
|
||||
Bashbot is not more (in)secure than a Bot written in another language. We have done our
|
||||
best to make it as secure as possible. But YOU are responsible for the bot commands you
|
||||
wrote and you should know about the risks ...
|
||||
Note: Up to version 0.941 (mai/22/2020) telegram-bot-bash had a remote code execution bug,
|
||||
please update if you use an older version!
|
||||
|
||||
Why Bash and not the much better xyz?
|
||||
|
||||
Well, that's a damn good question... maybe because I'm a Unix admin from the stone age.
|
||||
Nevertheless there are more reasons from my side:
|
||||
|
||||
* bashbot will run wherever bash and (gnu) sed is available, from embedded Linux to
|
||||
mainframe
|
||||
* easy to integrate with other shell scripts, e.g. for sending system message / health
|
||||
status
|
||||
* no need to install or learn a new programming language, library or framework
|
||||
* no database, not event driven, not object oriented ...
|
||||
|
||||
|
||||
Can I have the single bashbot.sh file back?
|
||||
|
||||
At the beginning bashbot was simply the file bashbot.sh that you could copy everywhere and
|
||||
run the bot. Now we have 'commands.sh', 'mycommands.sh', 'modules/*.sh' and much more.
|
||||
Hey no problem, if you are finished with your cool bot, run dev/make-standalone.sh to
|
||||
create a stripped down version of your bot containing only 'bashbot.sh' and 'commands.sh'!
|
||||
For more information see Create a stripped down version of your Bot [doc/7_develop.md].
|
||||
|
||||
Can I send messages from CLI and scripts?
|
||||
|
||||
Of course you can send messages from command line and scripts! Simply install bashbot as
|
||||
described here [#Your-really-first-bashbot-in-a-nutshell], send the message '/start' to
|
||||
set yourself as botadmin and then stop the bot with ./bashbot.sh stop.
|
||||
Bashbot provides some ready to use scripts for sending messages from command line in bin/
|
||||
dir, e.g. send_message.sh.
|
||||
|
||||
bin/send_message.sh BOTADMIN "This is my first message send from CLI"
|
||||
|
||||
bin/send_message.sh --help
|
||||
|
||||
You can also source bashbot for use in your scripts, for more information see Expert Use
|
||||
[doc/4_expert.md].
|
||||
|
||||
Blocked by telegram?
|
||||
|
||||
This may happen if too many or wrong requests are sent to api.telegram.org, e.g. using a
|
||||
invalid token or invalid API calls. If the block stay for longer time you can ask telegram
|
||||
service to unblock your IP-Address.
|
||||
You can check with curl or wget if you are blocked by Telegram:
|
||||
|
||||
curl -m 10 https://api.telegram.org/bot
|
||||
#curl: (28) Connection timed out after 10001 milliseconds
|
||||
|
||||
wget -t 1 -T 10 https://api.telegram.org/bot
|
||||
#Connecting to api.telegram.org (api.telegram.org)|46.38.243.234|:443... failed:
|
||||
Connection timed out.
|
||||
|
||||
nc -w 2 api.telegram.org 443 || echo "your IP seems blocked by telegram"
|
||||
#your IP seems blocked by telegram
|
||||
|
||||
Bashbot offers the option to recover from broken connections (blocked). Therefore you can
|
||||
provide a function named bashbotBlockRecover() in mycommands.sh, the function is called
|
||||
every time when a broken connection is detected.
|
||||
Possible actions are: Check if network is working, change IP-Address or simply wait some
|
||||
time. See mycommnds.sh.dist for an example.
|
||||
------------------------------------------------------------------------------------------
|
||||
@Gnadelwartz
|
||||
|
||||
## That's it!
|
||||
That's it all guys!
|
||||
|
||||
If you feel that there's something missing or if you found a bug, feel free to
|
||||
submit a pull request!
|
||||
If you feel that there's something missing or if you found a bug, feel free to submit a
|
||||
pull request!
|
||||
|
||||
$$VERSION$$ v1.52-0-g1a83202
|
||||
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
|
|
147
addons/antiFlood.sh
Normal file
147
addons/antiFlood.sh
Normal file
|
@ -0,0 +1,147 @@
|
|||
#!/bin/bash
|
||||
# file: addons/antiFlood.sh.dist
|
||||
#
|
||||
# this addon counts how many files, e.g. stickers, are sent to
|
||||
# a chat and takes actions if threshold is reached
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
# used events:
|
||||
#
|
||||
# BASHBOT_EVENT_TEXT message containing message text received
|
||||
# BASHBOT_EVENT_CMD a command is received
|
||||
# BASHBOT_EVENT_FILE file received
|
||||
#
|
||||
# all global variables and functions can be used in registered functions.
|
||||
#
|
||||
# parameters when loaded
|
||||
# $1 event: init, startbot ...
|
||||
# $2 debug: use "[[ "$2" = *"debug"* ]]" if you want to output extra diagnostic
|
||||
#
|
||||
# parameters on events
|
||||
# $1 event: inline, message, ..., file
|
||||
# $2 debug: use "[[ "$2" = *"debug"* ]]" if you want to output extra diagnostic
|
||||
#
|
||||
# shellcheck disable=SC2140
|
||||
|
||||
# export used events
|
||||
export BASHBOT_EVENT_TEXT BASHBOT_EVENT_CMD BASHBOT_EVENT_FILE BASHBOT_EVENT_TIMER
|
||||
|
||||
# any global variable defined by addons MUST be prefixed by addon name
|
||||
ANTIFL_ME="antiFlood"
|
||||
|
||||
declare -Ax ANTIFL_CHATS ANTIFL_ACTUALS
|
||||
|
||||
ANTIFL_DEFAULT="5" # 5 files per minute
|
||||
ANTIFL_BAN="5" # 5 minutes
|
||||
|
||||
# initialize after installation or update
|
||||
if [[ "$1" = "init"* ]]; then
|
||||
jssh_newDB "addons/${ANTIFL_ME}"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# register on startbot
|
||||
if [[ "$1" = "start"* ]]; then
|
||||
ANTIFL_ADMIN="$(getConfigKey "botadmin")"
|
||||
#load existing chat settings on start
|
||||
jssh_readDB "ANTIFL_CHATS" "addons/${ANTIFL_ME}"
|
||||
|
||||
# register to CMD
|
||||
BASHBOT_EVENT_CMD["${ANTIFL_ME}"]="${ANTIFL_ME}_cmd"
|
||||
|
||||
antiFlood_cmd(){
|
||||
# shellcheck disable=SC2153
|
||||
local chat="${CHAT[ID]}"
|
||||
|
||||
case "${CMD[0]}" in
|
||||
# command /afstart starts detection, $1 floodlevel
|
||||
"/afstart")
|
||||
# allow bot admin to activate for other chats
|
||||
[[ "${CMD[3]}" =~ ^[-0-9]+$ ]] && user_is_botadmin "${USER[ID]}" && chat="$3"
|
||||
[[ "${CMD[1]}" =~ ^[0-9]+$ ]] && ANTIFL_CHATS["${chat}","level"]="${CMD[1]}" \
|
||||
|| ANTIFL_CHATS["${chat}","level"]="${ANTIFL_DEFAULT}"
|
||||
[[ "${CMD[2]}" =~ ^[0-9]+$ ]] && ANTIFL_CHATS["${chat}","ban"]="${CMD[2]}" \
|
||||
|| ANTIFL_CHATS["${chat}","ban"]="${ANTIFL_BAN}"
|
||||
antiFlood_timer
|
||||
send_normal_message "${USER[ID]}" "Antiflood set for chat ${chat}" &
|
||||
;;
|
||||
# command /afactive starts counter meausares
|
||||
"/afdo" | "/afactive")
|
||||
[[ "${CMD[1]}" =~ ^[-0-9]+$ ]] && user_is_botadmin "${USER[ID]}" && chat="$3"
|
||||
ANTIFL_CHATS["${chat}","active"]="yes"
|
||||
jssh_writeDB "ANTIFL_CHATS" "addons/${ANTIFL_ME}" &
|
||||
send_normal_message "${USER[ID]}" "Antiflood activated for chat ${chat}" &
|
||||
;;
|
||||
# command /afactive starts counter meausares
|
||||
"/afstop")
|
||||
[[ "${CMD[1]}" =~ ^[-0-9]+$ ]] && user_is_botadmin "${USER[ID]}" && chat="$3"
|
||||
ANTIFL_CHATS["${chat}","active"]="no"
|
||||
jssh_writeDB "ANTIFL_CHATS" "addons/${ANTIFL_ME}" &
|
||||
send_normal_message "${USER[ID]}" "Antiflood stopped for chat ${chat}" &
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# register to timer
|
||||
BASHBOT_EVENT_TIMER["${ANTIFL_ME}","${ANTIFL_BAN}"]="antiFlood_timer"
|
||||
|
||||
# save settings and reset flood level every BAN Min
|
||||
antiFlood_timer(){
|
||||
ANTIFL_ACTUALS=( )
|
||||
jssh_writeDB "ANTIFL_CHATS" "addons/${ANTIFL_ME}" &
|
||||
}
|
||||
|
||||
# register to inline and command
|
||||
BASHBOT_EVENT_TEXT["${ANTIFL_ME}"]="${ANTIFL_ME}_multievent"
|
||||
BASHBOT_EVENT_FILE["${ANTIFL_ME}"]="${ANTIFL_ME}_multievent"
|
||||
|
||||
antiFlood_multievent(){
|
||||
# not started
|
||||
[ -z "${ANTIFL_CHATS["${CHAT[ID]}","level"]}" ] && return
|
||||
# count user flood text
|
||||
if [ "$1" = "text" ]; then
|
||||
if [ "${#MESSAGE[0]}" -gt "${ANTIFL_CHATS["${CHAT[ID]}","level"]}" ]; then
|
||||
(( ANTIFL_ACTUALS["${CHAT[ID]}","${USER[ID]}"]-- ))
|
||||
# shellcheck disable=SC2154
|
||||
(( ANTIFL_ACTUALS["${CHAT[ID]}","${USER[ID]}","file"]-- ))
|
||||
else
|
||||
# shellcheck disable=SC2154
|
||||
(( ANTIFL_ACTUALS["${CHAT[ID]}","${USER[ID]}"]++ ))
|
||||
fi
|
||||
fi
|
||||
# count user chat flood
|
||||
if [ "$1" = "file" ]; then
|
||||
# shellcheck disable=SC2154
|
||||
(( ANTIFL_ACTUALS["${CHAT[ID]}","${USER[ID]}","file"]++ ))
|
||||
# shellcheck disable=SC2154
|
||||
(( ANTIFL_ACTUALS["${CHAT[ID]}","file"]++ ))
|
||||
antiFlood_action & # do actions in subshell
|
||||
fi
|
||||
}
|
||||
|
||||
# check and handle actions
|
||||
antiFlood_action() {
|
||||
# check flood level of user
|
||||
if [ "$(( ANTIFL_ACTUALS["${CHAT[ID]}","${USER[ID]}","file"] +1))" -gt "${ANTIFL_CHATS["${CHAT[ID]}","level"]}" ]; then
|
||||
if [ "${ANTIFL_CHATS["${CHAT[ID]}","active"]}" = "yes" ]; then
|
||||
# remove message
|
||||
delete_message "${CHAT[ID]}" "${MESSAGE[ID]}"
|
||||
else
|
||||
# inform admin
|
||||
send_markdown_message "${ANTIFL_ADMIN}" "User ${USER[USERNAME]} reached flood level in chat ${CHAT[USERNAME]}!"
|
||||
fi
|
||||
fi
|
||||
# check flood level of chat
|
||||
if [ "$(( ANTIFL_ACTUALS["${CHAT[ID]}","file"] +1))" -gt "$(( ANTIFL_CHATS["${CHAT[ID]}","level"] * ANTIFL_BAN ))" ]; then
|
||||
if [ "${ANTIFL_CHATS["${CHAT[ID]}","active"]}" = "yes" ]; then
|
||||
# remove message
|
||||
delete_message "${CHAT[ID]}" "${MESSAGE[ID]}"
|
||||
else
|
||||
# inform admin
|
||||
send_markdown_message "${ANTIFL_ADMIN}" "Chat ${CHAT[USERNAME]} reached max flood level!"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
fi
|
115
addons/example.sh
Normal file
115
addons/example.sh
Normal file
|
@ -0,0 +1,115 @@
|
|||
#!/bin/bash
|
||||
# file: addons/example.sh.dist
|
||||
#
|
||||
# Addons can register to bashbot events at startup
|
||||
# by providing their name and a callback per event
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#
|
||||
# If an event occurs each registered event function is called.
|
||||
#
|
||||
# Events run in the same context as the main bashbot event loop
|
||||
# so variables set here are persistent as long bashbot is running.
|
||||
#
|
||||
# Note: For the same reason event function MUST return imideatly!
|
||||
# compute intensive tasks must be run in a nonblocking subshell,
|
||||
# e.g. "(long running) &"
|
||||
#
|
||||
|
||||
# Available events:
|
||||
# on events startbot and init, this file is sourced
|
||||
#
|
||||
# BASHBOT_EVENT_INLINE inline query received
|
||||
# BASHBOT_EVENT_MESSAGE any type of message received
|
||||
# BASHBOT_EVENT_TEXT message containing message text received
|
||||
# BASHBOT_EVENT_CMD a command is received
|
||||
# BASHBOT_EVENT_REPLYTO reply to message received
|
||||
# BASHBOT_EVENT_FORWARD forwarded message received
|
||||
# BASHBOT_EVENT_CONTACT contact received
|
||||
# BASHBOT_EVENT_LOCATION location or venue received
|
||||
# BASHBOT_EVENT_FILE file received
|
||||
#
|
||||
# BASHBOT_EVENT_TIMER this event is a bit special as it fires every Minute
|
||||
# and has 3 meanings: oneshot, every time, every X minutes.
|
||||
#
|
||||
# all global variables and functions can be used in registered functions.
|
||||
#
|
||||
# parameters when loaded
|
||||
# $1 event: init, startbot ...
|
||||
# $2 debug: use "[[ "$2" = *"debug"* ]]" if you want to output extra diagnostic
|
||||
#
|
||||
# parameters on events
|
||||
# $1 event: inline, message, ..., file
|
||||
# $2 key: key of array BASHBOT_EVENT_xxx
|
||||
# $3 debug: use "[[ "$2" = *"debug"* ]]" if you want to output extra diagnostic
|
||||
#
|
||||
|
||||
# export used events
|
||||
export BASHBOT_EVENT_INLINE BASHBOT_EVENT_CMD BASHBOT_EVENT_REPLY BASHBOT_EVENT_TIMER BASHBOT_EVENT_SEND
|
||||
|
||||
# any global variable defined by addons MUST be prefixed by addon name
|
||||
EXAMPLE_ME="example"
|
||||
|
||||
# initialize after installation or update
|
||||
if [[ "$1" = "init"* ]]; then
|
||||
: # nothing to do
|
||||
fi
|
||||
|
||||
|
||||
# register on startbot
|
||||
if [[ "$1" = "start"* ]]; then
|
||||
# register to reply
|
||||
BASHBOT_EVENT_REPLY["${EXAMPLE_ME}"]="${EXAMPLE_ME}_reply"
|
||||
EXAMPLE_ADMIN="$(getConfigKey "botadmin")"
|
||||
|
||||
# any function defined by addons MUST be prefixed by addon name
|
||||
# function local variables can have any name, but must be LOCAL
|
||||
example_reply(){
|
||||
local msg="message" event="$1" key="$2"
|
||||
send_markdown_message "${CHAT[ID]}" "User *${USER[USERNAME]}* replied to ${msg} from *${REPLYTO[USERNAME]}* (Event: ${event} Key:{${key})" &
|
||||
}
|
||||
|
||||
# register to inline and command
|
||||
BASHBOT_EVENT_INLINE["${EXAMPLE_ME}"]="${EXAMPLE_ME}_multievent"
|
||||
BASHBOT_EVENT_CMD["${EXAMPLE_ME}"]="${EXAMPLE_ME}_multievent"
|
||||
|
||||
# any function defined by addons MUST be prefixed by addon name
|
||||
# function local variables can have any name, but must be LOCAL
|
||||
example_multievent(){
|
||||
local event="$1" key="$2"
|
||||
local msg="${MESSAGE[0]}"
|
||||
# shellcheck disable=SC2154
|
||||
[ "${type}" = "inline" ] && msg="${iQUERY[0]}"
|
||||
send_normal_message "${CHAT[ID]}" "${event} from ${key} received: ${msg}" &
|
||||
}
|
||||
|
||||
BASHBOT_EVENT_TIMER["${EXAMPLE_ME}after5min","-5"]="${EXAMPLE_ME}_after5min"
|
||||
|
||||
# any function defined by addons MUST be prefixed by addon name
|
||||
# function local variables can have any name, but must be LOCAL
|
||||
example_after5min(){
|
||||
send_markdown_message "${EXAMPLE_ADMIN}" "This is a one time event after 5 Minutes!" &
|
||||
}
|
||||
|
||||
BASHBOT_EVENT_TIMER["${EXAMPLE_ME}every2min","2"]="${EXAMPLE_ME}_every2min"
|
||||
|
||||
# any function defined by addons MUST be prefixed by addon name
|
||||
# function local variables can have any name, but must be LOCAL
|
||||
example_every2min(){
|
||||
send_markdown_message "${EXAMPLE_ADMIN}" "This a a every 2 minute event ..." &
|
||||
}
|
||||
|
||||
# register to send
|
||||
BASHBOT_EVENT_SEND["${EXAMPLE_ME}"]="${EXAMPLE_ME}_log"
|
||||
EXAMPLE_LOG="${BASHBOT_ETC:-.}/addons/${EXAMPLE_ME}.log"
|
||||
|
||||
# any function defined by addons MUST be prefixed by addon name
|
||||
# function local variables can have any name, but must be LOCAL
|
||||
# $1 = send / upload
|
||||
# $* remaining args are from sendJson and sendUpload
|
||||
# Note: do not call any send message functions from EVENT_SEND!
|
||||
example_log(){
|
||||
local send="$1"; shift
|
||||
printf "%s: Type: %s Args: %s\n" "$(date)" "${send}" "$*" >>"${EXAMPLE_LOG}"
|
||||
}
|
||||
fi
|
130
bashbot.rc
130
bashbot.rc
|
@ -1,9 +1,14 @@
|
|||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
# description: Start or stop telegram-bash-bot
|
||||
#
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
# example service script to run bashbot in background as specified user
|
||||
#
|
||||
# tested on: ubuntu, opensuse, debian
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
# shellcheck disable=SC2009
|
||||
# shellcheck disable=SC2181
|
||||
# shellcheck disable=SC2250
|
||||
|
||||
#
|
||||
### BEGIN INIT INFO
|
||||
|
@ -17,70 +22,133 @@
|
|||
|
||||
# save default values
|
||||
TERM="" # disable bashbot clear and color output
|
||||
runas="nobody"
|
||||
runcmd="echo Dry run:" # not actived until you edit lines below
|
||||
runcmd="echo Dry run:" # not activated until you edit lines below
|
||||
|
||||
#######################
|
||||
# Configuration Section
|
||||
|
||||
# edit the next line to fit the user you want to run bashbot, e.g. nobody:
|
||||
# runas="nobody"
|
||||
runas="nobody"
|
||||
|
||||
# uncomment one of the following lines to fit your system
|
||||
# runcmd="su $runas -s /bin/bash -c " # runasuser with *su*
|
||||
# runcmd="runuser $runas -s /bin/bash -c " # runasuser with *runuser*
|
||||
# uncomment one of the example lines to fit your system
|
||||
# runcmd="su ${runas} -s /bin/bash -c " # runasuser with *su*
|
||||
# runcmd="/usr/sbin/runuser ${runas} -s /bin/bash -c " # runasuser with *runuser*
|
||||
|
||||
# edit the values of the following lines to fit your config:
|
||||
start="/usr/local/telegram-bot-bash/bashbot.sh" # location of your bashbot.sh script
|
||||
name='' # your bot name as given to botfather, e.g. mysomething_bot
|
||||
# your bot name as given to botfather, e.g. mysomething_bot
|
||||
name=""
|
||||
[ -z "${name}" ] && name="unknown"
|
||||
|
||||
# your bot installation dir
|
||||
bashbotdir="/usr/local/telegram-bot-bash"
|
||||
databotdir="${bashbotdir}/data-bot-bash"
|
||||
FIFO="${databotdir}/webhook-fifo-${name}"
|
||||
|
||||
# programs to run
|
||||
bashbot="cd ${bashbotdir}; ${bashbotdir}/bashbot.sh"
|
||||
webhook="cd ${bashbotdir}; nohup ${bashbotdir}/bin/process_batch.sh --startbot --watch ${FIFO}"
|
||||
# set additionl parameter, e.g. debug
|
||||
mode=""
|
||||
|
||||
# select logfile for webhook start stop and script errors
|
||||
hooklog="DEBUG"
|
||||
hooklog="WEBHOOK"
|
||||
|
||||
# END Configuration
|
||||
#######################
|
||||
|
||||
lockfile="$(dirname $start)/lockfile"
|
||||
[ "$name" = "" ] && name="$runas"
|
||||
|
||||
# check for bot status
|
||||
stat=""
|
||||
ps -f -u "${runas}" | grep "${name}" | grep -qF "bashbot.sh startbot"
|
||||
if [ "$?" = "0" ]; then
|
||||
# printf "bashbot (%s) is running in poll mode\n" "${name}"
|
||||
stat="${stat} polling"
|
||||
fi
|
||||
ps -f -u "${runas}" | grep "${name}" | grep -qF "process_batch.sh --startbot"
|
||||
if [ "$?" = "0" ]; then
|
||||
#printf "bashbot (%s) is running in webhook mode\n" "${name}"
|
||||
stat="${stat} webhook"
|
||||
elif [ "${name}" != "unknown" ]; then
|
||||
#printf "bashbot (%s) is stopped\n" "${name}"
|
||||
stat="stop"
|
||||
else
|
||||
stat="unknown"
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
'start')
|
||||
$runcmd "$start start" # >/dev/null 2>&1 </dev/null
|
||||
[ "${stat}" != "stop" ] && printf "Warning, bot is already running in mode: %s\n" "${stat}"
|
||||
$runcmd "$bashbot start $mode" # >/dev/null 2>&1 </dev/null
|
||||
RETVAL=$?
|
||||
;;
|
||||
'starthook')
|
||||
[ -p "${FIFO}" ] || printf "Warning, webhook pipe not found: %s\n" "${FIFO##*/}"
|
||||
[ "${stat}" != "stop" ] && printf "Warning, bot is already running in mode: %s\n" "${stat}"
|
||||
printf "Starting bashbot in webhook mode ... "
|
||||
$runcmd "$webhook $mode </dev/null &>>${bashbotdir}/logs/${hooklog}.log &" # >/dev/null 2>&1 </dev/null
|
||||
sleep 1
|
||||
$0 status
|
||||
RETVAL=$?
|
||||
if [ "$RETVAL" = "0" ]; then
|
||||
touch "$lockfile" >/dev/null 2>&1
|
||||
fi
|
||||
;;
|
||||
'stop')
|
||||
$runcmd "$start kill"
|
||||
[[ "${stat}" != *"poll"* ]] && printf "Warning, bot is not in poll mode: %s\n" "${stat}"
|
||||
$runcmd "$bashbot stop $mode"
|
||||
RETVAL=$?
|
||||
if [ "$RETVAL" = "0" ]; then
|
||||
rm -f "$lockfile"
|
||||
;;
|
||||
'stophook')
|
||||
[[ "${stat}" != *"hook"* ]] && printf "Warning, bot is not in webhook mode: %s\n" "${stat}"
|
||||
printf "Stopping bashbot webhook mode ... "
|
||||
KILLID="$(ps -f -u "${runas}" | grep "process_batch.sh --startbot" | sed -E 's/[^0-9]+([0-9]+).*/\1/' | tr -s "\r\n" " ")"
|
||||
if [ -n "${KILLID}" ]; then
|
||||
$runcmd "kill ${KILLID} 2>/dev/null; wait ${KILLID} 2>/dev/null"
|
||||
sleep 1
|
||||
fi
|
||||
RETVAL=$?
|
||||
$0 status
|
||||
;;
|
||||
'status')
|
||||
ps -f -u "$runas" | grep "$name" | grep -qF "bashbot.sh startbot"
|
||||
if [ "$?" = "0" ]; then
|
||||
echo "bashbot ($name) is running"
|
||||
RETVAL=0
|
||||
else
|
||||
echo "bashbot ($name) is stopped"
|
||||
RETVAL=1
|
||||
fi
|
||||
case "${stat}" in
|
||||
*"poll"*) printf "bashbot (%s) is running in polling mode\n" "${name}"
|
||||
RETVAL=0
|
||||
;;&
|
||||
*"hook"*) printf "bashbot (%s) is running in webhook mode\n" "${name}"
|
||||
RETVAL=0
|
||||
;;
|
||||
*"stop"*) printf "bashbot (%s) is not running\n" "${name}"
|
||||
RETVAL=1
|
||||
;;
|
||||
*) printf "bashbot (%s) status is %s\n" "${name}" "${stat}"
|
||||
RETVAL=2
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
'restart'|'reload')
|
||||
$0 stop; $0 start
|
||||
RETVAL=$?
|
||||
;;
|
||||
'restarthook'|'reloadhook')
|
||||
$0 stophook; $0 starthook
|
||||
RETVAL=$?
|
||||
;;
|
||||
'restartback')
|
||||
$0 suspendback; $0 resumeback
|
||||
RETVAL=$?
|
||||
;;
|
||||
'suspendback'|'resumeback'|'killback')
|
||||
$runcmd "$start $1"
|
||||
# shellcheck disable=SC2250
|
||||
$runcmd "$bashbot $1"
|
||||
RETVAL=$?
|
||||
# kill inotifywait from runuser
|
||||
if [ "$1" != "resumeback" ]; then
|
||||
# shellcheck disable=SC2046
|
||||
kill -9 $(ps -u "${runas}" | grep inotifywait | sed 's/ .*//') >/dev/null 2>&1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 { start | stop | restart | reload | restartback | suspendback | resumeback | killback }"
|
||||
printf "%s\n" "Usage: $0 [ start | stop | restart | starthook | stophook | restarthook ]"
|
||||
printf "%s\n" " $0 [ status | restartback | suspendback | resumeback | killback ]"
|
||||
RETVAL=1
|
||||
;;
|
||||
esac
|
||||
exit $RETVAL
|
||||
|
||||
exit "${RETVAL}"
|
||||
|
|
1447
bashbot.sh
1447
bashbot.sh
File diff suppressed because it is too large
Load Diff
85
bin/any_command.sh
Executable file
85
bin/any_command.sh
Executable file
|
@ -0,0 +1,85 @@
|
|||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034,SC2059
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/any_command.sh
|
||||
#
|
||||
USAGE='any_command.sh [-h|--help] [--force|--reference] bot_command args ...'
|
||||
#
|
||||
# DESCRIPTION: execute (almost) any bashbot command/function
|
||||
# can be used for testing commands while bot development
|
||||
#
|
||||
# OPTIONS: -- force - execute unknown commands/functions
|
||||
# by default only commands in 6_reference.md are allowed
|
||||
#
|
||||
# -h - display short help
|
||||
# --help - this help
|
||||
#
|
||||
# Set BASHBOT_HOME to your installation directory
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 30.01.2021 10:24
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
COMMAND=""
|
||||
|
||||
# set bashbot environment
|
||||
source "${0%/*}/bashbot_env.inc.sh" "debug" # debug
|
||||
print_help "$1"
|
||||
|
||||
|
||||
error=""
|
||||
# check options
|
||||
if [[ "$1" = "--force" ]]; then
|
||||
# skip checks
|
||||
shift
|
||||
else
|
||||
# check for --ref
|
||||
ref="$1"; [[ "$1" == "--ref"* ]] && shift
|
||||
if [ "${#1}" -lt 11 ];then
|
||||
printf "${RED}Command must be minimum 11 characters!${NC}\n"
|
||||
error=3
|
||||
fi
|
||||
if [[ "$1" != *"_"* ]];then
|
||||
printf "${RED}Command must contain _ (underscore)!${NC}\n"
|
||||
error=3
|
||||
fi
|
||||
# simple hack to get allowed commands from doc
|
||||
if grep -q "^##### $1" <<<"$(sed -n -e '/^##### _is_/,$ d' -e '/^##### /p' "${BASHBOT_HOME:-..}doc/"6_*)"; then
|
||||
# oiutput reference and exit
|
||||
if [[ "${ref}" == "--ref"* ]]; then
|
||||
sed -n -e '/^##### '"$1"'/,/^##/ p' "${BASHBOT_HOME:-..}doc/"6_*
|
||||
exit
|
||||
fi
|
||||
else
|
||||
printf "Command ${GREY}%s${NC} not found in 6_reference.md, use ${GREY}--force${NC} to execute!\n" "$1"
|
||||
error=4
|
||||
fi
|
||||
[ -n "${error}" ] && exit "${error}"
|
||||
fi
|
||||
|
||||
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
COMMAND="$1"
|
||||
if [ "$2" == "BOTADMIN" ]; then
|
||||
ARG1="${BOTADMIN}"
|
||||
else
|
||||
ARG1="$2"
|
||||
fi
|
||||
|
||||
# clear result and response
|
||||
BOTSENT=()
|
||||
UPD=()
|
||||
|
||||
# send message in selected format
|
||||
"${COMMAND}" "${ARG1}" "${@:3}"
|
||||
|
||||
# output result an telegram response
|
||||
print_result
|
||||
print_response
|
91
bin/bashbot_env.inc.sh
Normal file
91
bin/bashbot_env.inc.sh
Normal file
|
@ -0,0 +1,91 @@
|
|||
#!/bin/bash
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bashbot_env.inc.sh
|
||||
#
|
||||
# USAGE: source bashbot_env.inc.sh [debug]
|
||||
#
|
||||
# DESCRIPTION: set bashbot environment for all scripts in this directory
|
||||
#
|
||||
# OPTIONS: $1 - will be forwarded ro bashbot, e.g. debug
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 18.12.2020 12:27
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
############
|
||||
# set where your bashbot lives
|
||||
export BASHBOT_HOME BASHBOT_ETC BASHBOT_VAR FILE_REGEX ME
|
||||
|
||||
# default: one dir up
|
||||
BASHBOT_HOME="$(cd "${BASH_SOURCE[0]%/*}/../" >/dev/null 2>&1 && pwd)"
|
||||
[ "${BASHBOT_HOME}" = "" ] && BASHBOT_HOME="../"
|
||||
|
||||
# set you own BASHBOT_HOME if different, e.g.
|
||||
# BASHBOT_HOME="/usr/local/telegram-bot-bash"
|
||||
BASHBOT_VAR="${BASHBOT_HOME}"
|
||||
BASHBOT_ETC="${BASHBOT_HOME}"
|
||||
|
||||
#####
|
||||
# if files are not readable, eviroment is wrong or bashbot is not initialized
|
||||
|
||||
# check for bashbot
|
||||
if [ ! -r "${BASHBOT_HOME}/bashbot.sh" ]; then
|
||||
printf "%s\n" "Bashbot.sh not found in \"${BASHBOT_HOME}\""
|
||||
exit 4
|
||||
fi
|
||||
|
||||
dev=" Are we in dev or did you forget to run init?"
|
||||
# check for botconfig.jssh readable
|
||||
if [ ! -r "${BASHBOT_ETC}/botconfig.jssh" ]; then
|
||||
printf "%s\n" "Bashbot config file in \"${BASHBOT_ETC}\" does not exist or is not readable. ${dev}"
|
||||
exit 3
|
||||
fi
|
||||
# check for count.jssh readable
|
||||
if [ ! -r "${BASHBOT_VAR}/count.jssh" ]; then
|
||||
printf "%s\n" "Bashbot count file in \"${BASHBOT_VAR}\" does not exist or is not readable. ${dev}"
|
||||
exit 3
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC1090
|
||||
source "${BASHBOT_HOME}/bashbot.sh" source "$1"
|
||||
|
||||
# overwrite bot FILE regex to BASHBOT_VAR
|
||||
# change this to the location you want to allow file uploads from
|
||||
UPLOADDIR="${BASHBOT_VAR%/bin*}"
|
||||
FILE_REGEX="${UPLOADDIR}/.*"
|
||||
|
||||
# get and check ADMIN and NAME
|
||||
BOTNAME="$(getConfigKey "botname")"
|
||||
ME="${BOTNAME}"
|
||||
[[ -z "${BOTADMIN}" || "${BOTADMIN}" == "?" ]] && printf "%s\n" "${ORANGE}Warning: Botadmin not set, send bot command${NC} /start"
|
||||
[[ -z "${BOTNAME}" ]] && printf "%s\n" "${ORANGE}Warning: Botname not set, run bashbot.sh botname"
|
||||
|
||||
# default webhook pipe
|
||||
export WEBHOOK="${DATADIR}/webhook-fifo-${ME}"
|
||||
|
||||
|
||||
# output command result or Telegram response
|
||||
print_result() { jssh_printDB "BOTSENT" | sort -r; }
|
||||
print_response() { jssh_printDB "UPD"; }
|
||||
|
||||
# check and output help
|
||||
print_help() {
|
||||
case "$1" in
|
||||
'')
|
||||
printf "missing arguments\n"
|
||||
;&
|
||||
"-h"*)
|
||||
printf 'usage: %s\n' "${USAGE}"
|
||||
exit 1
|
||||
;;
|
||||
'--h'*)
|
||||
sed -n '/^#====/,/^#====/p' <"$0"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
149
bin/bashbot_init.inc.sh
Normal file
149
bin/bashbot_init.inc.sh
Normal file
|
@ -0,0 +1,149 @@
|
|||
#!/bin/bash
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bashbot_init.inc.sh
|
||||
#
|
||||
# USAGE: source bashbot_init.inc.sh
|
||||
#
|
||||
# DESCRIPTION: extend / overwrite bashbot initialisation
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 27.01.2021 13:42
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
# shellcheck disable=SC2059
|
||||
|
||||
##########
|
||||
# commands to execute before bot_init() is called
|
||||
|
||||
|
||||
########
|
||||
# called after default init is finished
|
||||
my_init() {
|
||||
: # your init here
|
||||
}
|
||||
|
||||
|
||||
#########
|
||||
#
|
||||
# extended initialisation:
|
||||
#
|
||||
# - uograde old config
|
||||
# - backup of botconfig.jssh
|
||||
# - running bot as service or other user
|
||||
# - copy clean and dist files if not exist
|
||||
# - configure bot for INLINE CALLBACK MEONLY SILENCER
|
||||
#
|
||||
# delete from here to disable extended initialisation
|
||||
bot_init() {
|
||||
if [ -n "${BASHBOT_HOME}" ] && ! cd "${BASHBOT_HOME}"; then
|
||||
printf "Can't change to BASHBOT_HOME"
|
||||
exit 1
|
||||
fi
|
||||
local runuser chown touser botname DEBUG="$1"
|
||||
# upgrade from old version
|
||||
# currently no action
|
||||
printf "Check for Update actions ...\n"
|
||||
printf "Done.\n"
|
||||
# load addons on startup
|
||||
printf "Initialize modules and addons ...\n"
|
||||
for addons in "${ADDONDIR:-.}"/*.sh ; do
|
||||
# shellcheck source=./modules/aliases.sh
|
||||
[ -r "${addons}" ] && source "${addons}" "init" "${DEBUG}"
|
||||
done
|
||||
printf "Done.\n"
|
||||
# guess bashbot from botconfig.jssh owner:group
|
||||
[ -f "${BOTCONFIG}.jssh" ] && runuser="$(stat -c '%U' "${BOTCONFIG}.jssh"):$(stat -c '%G' "${BOTCONFIG}.jssh")"
|
||||
# empty or ":" use user running init, nobody for root
|
||||
if [ "${#runuser}" -lt 3 ]; then
|
||||
# shellcheck disable=SC2153
|
||||
runuser="${RUNUSER}"
|
||||
[ "${UID}" = "0" ] && runuser="nobody"
|
||||
fi
|
||||
printf "Enter User to run bashbot [${runuser}]: "
|
||||
read -r chown
|
||||
[ -z "${chown}" ] && chown="${runuser}"
|
||||
touser="${chown%:*}"
|
||||
# check user ...
|
||||
if ! id "${touser}" &>/dev/null; then
|
||||
printf "${RED}User \"${touser}\" does not exist!${NN}"
|
||||
exit 3
|
||||
elif [ "${UID}" != "0" ]; then
|
||||
# different user but not root ...
|
||||
printf "${ORANGE}You are not root, adjusting permissions may fail. Try \"sudo ./bashbot.sh init\"${NN}Press <CTRL+C> to stop or <Enter> to continue..." 1>&2
|
||||
[ -n "${INTERACTIVE}" ] && read -r runuser
|
||||
fi
|
||||
# check if mycommands exist
|
||||
if [[ ! -r "${BASHBOT_ETC:-.}/mycommands.sh" && -r ${BASHBOT_ETC:-.}/mycommands.sh.dist ]]; then
|
||||
printf "Mycommands.sh not found, copy ${GREY}<C>lean file, <E>xamples or <N>one${NC} to mycommands.sh? (c/e/N) N\b"
|
||||
read -r ANSWER
|
||||
[[ "${ANSWER}" =~ ^[cC] ]] && cp -f "${BASHBOT_ETC:-.}/mycommands.sh.clean" "${BASHBOT_ETC:-.}/mycommands.sh"
|
||||
[[ "${ANSWER}" =~ ^[eE] ]] && cp -f "${BASHBOT_ETC:-.}/mycommands.sh.dist" "${BASHBOT_ETC:-.}/mycommands.sh"
|
||||
# offer to copy config also
|
||||
if [ ! -r "${BASHBOT_ETC:-.}/mycommands.conf" ]; then
|
||||
printf "Mycommands config file not found, copy ${GREY}mycommands.conf.dist${NC} to mycommands.conf? (Y/n) Y\b"
|
||||
read -r ANSWER
|
||||
[[ "${ANSWER}" =~ ^[nN] ]] || cp -f "${BASHBOT_ETC:-.}/mycommands.conf.dist" "${BASHBOT_ETC:-.}/mycommands.conf"
|
||||
fi
|
||||
# adjust INLINE CALLBACK MEONLY SILENCER
|
||||
if [ -w "${BASHBOT_ETC:-.}/mycommands.conf" ]; then
|
||||
printf "Activate processing for ${GREY}<I>nline queries, <C>allback buttons, <B>oth or <N>one${NC} in mycommands.sh? (i/c/b/N) N\b"
|
||||
read -r ANSWER
|
||||
[[ "${ANSWER}" =~ ^[iIbB] ]] && sed -i '/INLINE="/ s/^.*$/export INLINE="1"/' "${BASHBOT_ETC:-.}/mycommands.conf"
|
||||
[[ "${ANSWER}" =~ ^[cCbB] ]] && sed -i '/CALLBACK="/ s/^.*$/export CALLBACK="1"/' "${BASHBOT_ETC:-.}/mycommands.conf"
|
||||
printf "Always ignore commands for other Bots in chat ${GREY}(/cmd@other_bot)${NC}? (y/N) N\b"
|
||||
read -r ANSWER
|
||||
[[ "${ANSWER}" =~ ^[yY] ]] && sed -i '/MEONLY="/ s/^.*$/export MEONLY="1"/' "${BASHBOT_ETC:-.}/mycommands.conf"
|
||||
printf "Delete administrative messages in chats ${GREY}(pinned, user join/leave, ...)${NC}? (y/N) N\b"
|
||||
read -r ANSWER
|
||||
[[ "${ANSWER}" =~ ^[yY] ]] && sed -i '/SILENCER="/ s/^.*$/export SILENCER="yes"/' "${BASHBOT_ETC:-.}/mycommands.conf"
|
||||
fi
|
||||
printf "Done.\n"
|
||||
fi
|
||||
# adjust permissions
|
||||
printf "Adjusting files and permissions for user \"${touser}\" ...\n"
|
||||
chown -Rf "${chown}" . ./*
|
||||
chmod 711 .
|
||||
chmod -R o-w ./*
|
||||
chmod -R u+w "${COUNTFILE}"* "${BLOCKEDFILE}"* "${DATADIR}" logs "${LOGDIR}/"*.log 2>/dev/null
|
||||
chmod -R o-r,o-w "${COUNTFILE}"* "${BLOCKEDFILE}"* "${DATADIR}" "${BOTACL}" 2>/dev/null
|
||||
# jsshDB must writeable by owner
|
||||
find . -name '*.jssh*' -exec chmod u+w \{\} +
|
||||
printf "Done.\n"
|
||||
# adjust values in bashbot.rc
|
||||
if [ -w "bashbot.rc" ]; then
|
||||
printf "Adjust user and botname in bashbot.rc ...\n"
|
||||
sed -i '/^[# ]*runas=/ s|runas=.*$|runas="'"${touser}"'"|' "bashbot.rc"
|
||||
sed -i '/^[# ]*bashbotdir=/ s|bashbotdir=.*$|bashbotdir="'"${PWD}"'"|' "bashbot.rc"
|
||||
botname="$(getConfigKey "botname")"
|
||||
[ -n "${botname}" ] && sed -i '/^[# ]*name=/ s|name=.*$|name="'"${botname}"'"|' "bashbot.rc"
|
||||
printf "Done.\n"
|
||||
fi
|
||||
# ask to check bottoken online
|
||||
if [ -z "$(getConfigKey "botid")" ]; then
|
||||
printf "Seems to be your first init. Should I verify your bot token online? (y/N) N\b"
|
||||
read -r ANSWER
|
||||
if [[ "${ANSWER}" =~ ^[Yy] ]]; then
|
||||
printf "${GREEN}Contacting telegram to verify your bot token ...${NN}"
|
||||
$0 botname
|
||||
fi
|
||||
fi
|
||||
# check if botconf seems valid
|
||||
printf "${GREEN}This is your bot config:${NN}${GREY}"
|
||||
sed 's/^/\t/' "${BOTCONFIG}.jssh" | grep -vF '["bot_config_key"]'; printf "${NC}"
|
||||
if check_token "$(getConfigKey "bottoken")" && [[ "$(getConfigKey "botadmin")" =~ ^[${o9o9o9}]+$ ]]; then
|
||||
printf "Bot config seems to be valid. Should I make a backup copy? (Y/n) Y\b"
|
||||
read -r ANSWER
|
||||
if [[ -z "${ANSWER}" || "${ANSWER}" =~ ^[^Nn] ]]; then
|
||||
printf "Copy bot config to ${BOTCONFIG}.jssh.ok ...\n"
|
||||
cp "${BOTCONFIG}.jssh" "${BOTCONFIG}.jssh.ok"
|
||||
fi
|
||||
else
|
||||
printf "${ORANGE}Bot config may incomplete, pls check.${NN}"
|
||||
fi
|
||||
# show result
|
||||
printf "${GREY}"; ls -ldp "${DATADIR}" "${LOGDIR}" ./*.jssh* ./*.sh ./*.conf 2>/dev/null; printf "${NC}"
|
||||
_exec_if_function my_init
|
||||
}
|
62
bin/bashbot_stats.sh
Executable file
62
bin/bashbot_stats.sh
Executable file
|
@ -0,0 +1,62 @@
|
|||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/bashbot_stats.sh
|
||||
#
|
||||
USAGE='bashbot_stats.sh [-h|--help] [debug]'
|
||||
#
|
||||
# DESCRIPTION: output bashbot user stats
|
||||
#
|
||||
# OPTIONS: -h - display short help
|
||||
# --help - this help
|
||||
#
|
||||
# Set BASHBOT_HOME to your installation directory
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 23.12.2020 20:34
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
# set bashbot environment
|
||||
source "${0%/*}/bashbot_env.inc.sh" "$1"
|
||||
[ -n "$1" ] && print_help "$1"
|
||||
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
|
||||
echo -e "${GREEN}Hi I'm ${BOTNAME}.${NC}"
|
||||
declare -A STATS
|
||||
jssh_readDB_async "STATS" "${COUNTFILE}"
|
||||
for MSG in ${!STATS[*]}
|
||||
do
|
||||
[[ ! "${MSG}" =~ ^[0-9-]*$ ]] && continue
|
||||
(( USERS++ ))
|
||||
done
|
||||
for MSG in ${STATS[*]}
|
||||
do
|
||||
(( MESSAGES+=MSG ))
|
||||
done
|
||||
if [ "${USERS}" != "" ]; then
|
||||
echo -e "${GREY}A total of ${NC}${MESSAGES}${GREY} messages from ${NC}${USERS}${GREY} users are processed.${NC}"
|
||||
else
|
||||
echo -e "${ORANGE}No one used your bot so far ...${NC}"
|
||||
fi
|
||||
jssh_readDB_async "STATS" "${BLOCKEDFILE}"
|
||||
for MSG in ${!STATS[*]}
|
||||
do
|
||||
[[ ! "${MSG}" =~ ^[0-9-]*$ ]] && continue
|
||||
(( BLOCKS++ ))
|
||||
done
|
||||
if [ "${BLOCKS}" != "" ]; then
|
||||
echo -e "${ORANGE}${BLOCKS} user(s) are blocked:${NC}${GREY}"
|
||||
sort -r "${BLOCKEDFILE}.jssh"
|
||||
echo -e "${NC}\c"
|
||||
else
|
||||
echo -e "${GREEN}No user is blocked currently ...${NC}"
|
||||
fi
|
||||
# show user created bot stats
|
||||
_exec_if_function my_bashbot_stats "$@"
|
||||
|
48
bin/delete_message.sh
Executable file
48
bin/delete_message.sh
Executable file
|
@ -0,0 +1,48 @@
|
|||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/delete_message.sh
|
||||
#
|
||||
USAGE='delete_message.sh [-h|--help] "CHAT[ID]" "MESSAGE[ID]" [debug]'
|
||||
#
|
||||
# DESCRIPTION: delete a message in the given user/group
|
||||
#
|
||||
# OPTIONS: CHAT[ID] - ID number of CHAT or BOTADMIN
|
||||
# MESSAGE[ID] - message to delete
|
||||
#
|
||||
# -h - display short help
|
||||
# --help - this help
|
||||
#
|
||||
# Set BASHBOT_HOME to your installation directory
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 03.01.2021 15:37
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
DELETE="delete_message"
|
||||
|
||||
# set bashbot environment
|
||||
source "${0%/*}/bashbot_env.inc.sh" "${3:-debug}" # $3 debug
|
||||
print_help "$1"
|
||||
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
if [ "$1" == "BOTADMIN" ]; then
|
||||
CHAT="${BOTADMIN}"
|
||||
else
|
||||
CHAT="$1"
|
||||
fi
|
||||
|
||||
# delete message
|
||||
"${DELETE}" "${CHAT}" "$2"
|
||||
|
||||
[ "${BOTSENT[OK]}" = "true" ] && BOTSENT[ID]="$2"
|
||||
|
||||
# output send message result
|
||||
print_result
|
54
bin/edit_buttons.sh
Executable file
54
bin/edit_buttons.sh
Executable file
|
@ -0,0 +1,54 @@
|
|||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/edit_buttons.sh
|
||||
#
|
||||
USAGE='send_message.sh [-h|--help] "CHAT[ID]" "MESSAGE[ID]" "text|url" ...'
|
||||
#
|
||||
# DESCRIPTION: send a send buttons in a row to the given user/group
|
||||
#
|
||||
# OPTIONS: CHAT[ID] - ID number of CHAT or BOTADMIN to send to yourself
|
||||
# MESSAGE[ID] - ID of MESSAGE with buttons to edit
|
||||
# text|url - buttons to send, each button as "text|url" pair or
|
||||
# "url" only to show url as text also, "" starts new row
|
||||
# "url" not http(s):// or tg:// is sent as callback_data
|
||||
#
|
||||
# -h - display short help
|
||||
# --help - this help
|
||||
#
|
||||
# EXAMPLE: 2 buttons on 2 rows, first shows Amazon, second the url as text
|
||||
# send_buttons.sh "Amazon|https://www.amazon.com" "" "https://mydealz.de" ...
|
||||
#
|
||||
# Set BASHBOT_HOME to your installation directory
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 21.01.2021 08:10
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
SEND="edit_inline_keyboard"
|
||||
|
||||
# set bashbot environment
|
||||
source "${0%/*}/bashbot_env.inc.sh" "debug"
|
||||
print_help "$1"
|
||||
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
if [ "$1" == "BOTADMIN" ]; then
|
||||
CHAT="${BOTADMIN}"
|
||||
else
|
||||
CHAT="$1"
|
||||
fi
|
||||
MESSAGE_ID="$2"
|
||||
shift 2
|
||||
|
||||
# send message in selected format
|
||||
"${SEND}" "${CHAT}" "${MESSAGE_ID}" "$(_button_row "$@")"
|
||||
|
||||
# output send message result
|
||||
print_result
|
67
bin/edit_message.sh
Executable file
67
bin/edit_message.sh
Executable file
|
@ -0,0 +1,67 @@
|
|||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/edit_message.sh
|
||||
#
|
||||
USAGE='send_edit_message.sh [-h|--help] [format|caption] "CHAT[ID]" "MESSAGE[ID]" "message ...." [debug]'
|
||||
#
|
||||
# DESCRIPTION: replace a message in the given user/group
|
||||
#
|
||||
# OPTIONS: format - normal, markdown, html or caption for file caption (optional)
|
||||
# CHAT[ID] - ID number of CHAT or BOTADMIN to send to yourself
|
||||
# MESSAGE[ID] - message to replace
|
||||
# message - message to send in specified format
|
||||
# if no format is given send_normal_message() format is used
|
||||
#
|
||||
# -h - display short help
|
||||
# --help - this help
|
||||
#
|
||||
# Set BASHBOT_HOME to your installation directory
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 23.12.2020 16:52
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
SEND="edit_normal_message"
|
||||
case "$1" in
|
||||
"nor"*|"tex"*)
|
||||
SEND="edit_normal_message"
|
||||
shift
|
||||
;;
|
||||
"mark"*)
|
||||
SEND="edit_markdownv2_message"
|
||||
shift
|
||||
;;
|
||||
"htm"*)
|
||||
SEND="edit_html_message"
|
||||
shift
|
||||
;;
|
||||
"cap"*)
|
||||
SEND="edit_message_caption"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
|
||||
# set bashbot environment
|
||||
source "${0%/*}/bashbot_env.inc.sh" "${4:-debug}" # $4 debug
|
||||
print_help "$1"
|
||||
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
if [ "$1" == "BOTADMIN" ]; then
|
||||
CHAT="${BOTADMIN}"
|
||||
else
|
||||
CHAT="$1"
|
||||
fi
|
||||
|
||||
# send message in selected format
|
||||
"${SEND}" "${CHAT}" "$2" "$3"
|
||||
|
||||
# output send message result
|
||||
print_result
|
47
bin/kickban_user.sh
Executable file
47
bin/kickban_user.sh
Executable file
|
@ -0,0 +1,47 @@
|
|||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/kickban_user.sh
|
||||
#
|
||||
USAGE='kickban_user.sh [-h|--help] [-u|--unban] "CHAT[ID]" "USER[ID]" [debug]'
|
||||
#
|
||||
# DESCRIPTION: kickban or unban a user from the given group
|
||||
#
|
||||
# OPTIONS: -u | --unban - unban user
|
||||
# CHAT[ID] - ID number of CHAT or BOTADMIN to send to yourself
|
||||
# USER[ID] - user to (un)ban
|
||||
#
|
||||
# -h - display short help
|
||||
# --help - this help
|
||||
#
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 25.01.2021 20:34
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
BAN="kick_chat_member"
|
||||
case "$1" in
|
||||
"-u"|"--unban")
|
||||
BAN="unban_chat_member"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
|
||||
# set bashbot environment
|
||||
source "${0%/*}/bashbot_env.inc.sh" "${3:-debug}" # $3 debug
|
||||
print_help "$1"
|
||||
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
|
||||
# send message in selected format
|
||||
"${BAN}" "$1" "$2"
|
||||
|
||||
# output send message result
|
||||
print_result
|
98
bin/process_batch.sh
Executable file
98
bin/process_batch.sh
Executable file
|
@ -0,0 +1,98 @@
|
|||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034,SC2059
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/process_batch.sh
|
||||
#
|
||||
USAGE='process_batch.sh [-h|--help] [-s|--startbot] [-w|--watch] [-n|--lines n] [file] [debug]'
|
||||
#
|
||||
# DESCRIPTION: processes last 10 telegram updates in file, one update per line
|
||||
#
|
||||
# -s --startbot load addons, start TIMER, trigger startup actions
|
||||
# -w --watch watch for new updates added to file
|
||||
# -n --lines read only last "n" lines
|
||||
# file to read updates from
|
||||
# empty means read from webhook pipe
|
||||
#
|
||||
# -h - display short help
|
||||
# --help - this help
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 27.02.2021 13:14
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
COMMAND="process_multi_updates"
|
||||
lines="-n 10"
|
||||
mode="batch"
|
||||
|
||||
opt=0
|
||||
while [[ "${opt}" -lt 5 && "$1" == "-"* ]]
|
||||
do
|
||||
(( opt++ ))
|
||||
case "$1" in
|
||||
"-s"|"--startbot")
|
||||
startbot="yes"
|
||||
shift
|
||||
;;
|
||||
"-w"|"--watch")
|
||||
follow="-f"
|
||||
mode="webhook"
|
||||
shift
|
||||
;;
|
||||
"-n"|"--lines")
|
||||
lines="-n $2"
|
||||
shift 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# set bashbot environment
|
||||
source "${0%/*}/bashbot_env.inc.sh" "debug" # debug
|
||||
print_help "${1:-nix}"
|
||||
|
||||
# empty file is webhook
|
||||
file="${WEBHOOK}"
|
||||
[ -n "$1" ] && file="$1"
|
||||
|
||||
# start bot
|
||||
if [ -n "${startbot}" ]; then
|
||||
# warn when starting bot without pipe
|
||||
[ -p "${file}" ] || printf "%(%c)T: %b\n" -1 "${ORANGE}Warning${NC}: File is not a pipe:${GREY} ${file##*/}${NC}"
|
||||
start_bot "$2" "${mode}"
|
||||
printf "%(%c)T: %b\n" -1 "${GREEN}Bot startup actions done, start ${mode} updates ...${NC}"
|
||||
fi
|
||||
# check file exist
|
||||
if [[ ! -r "${file}" || -d "${file}" ]]; then
|
||||
printf "%(%c)T: %b\n" -1 "${RED}Error${NC}: File not readable:${GREY} ${file}${NC}."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
|
||||
# kill all sub processes on exit
|
||||
trap 'printf "%(%c)T: %s\n" -1 "Bot in '"${mode}"' mode stopped"; kill $(jobs -p) 2>/dev/null; wait $(jobs -p) 2>/dev/null; send_normal_message "'"${BOTADMIN}"'" "Bot '"${BOTNAME} ${mode}"' stopped ..."' EXIT HUP QUIT
|
||||
|
||||
# wait after (first) update to avoid processing to many in parallel
|
||||
UPDWAIT="0.5"
|
||||
# use tail to read appended updates
|
||||
# shellcheck disable=SC2086,SC2248
|
||||
tail ${follow} ${lines} "${file}" 2>/dev/null |\
|
||||
while IFS="" read -r input 2>/dev/null
|
||||
do
|
||||
# read json from stdin and convert update format
|
||||
# replace any ID named BOTADMIN with ID of bot admin
|
||||
: "${input//\"id\":BOTADMIN,/\"id\":${BOTADMIN},}"
|
||||
json='{"result": ['"${_}"']}'
|
||||
UPDATE="$(${JSONSHFILE} -b -n <<<"${json}" 2>/dev/null)"
|
||||
|
||||
# process telegram update
|
||||
"${COMMAND}" "$2"
|
||||
sleep "${UPDWAIT}"
|
||||
UPDWAIT="0.05"
|
||||
done
|
41
bin/process_update.sh
Executable file
41
bin/process_update.sh
Executable file
|
@ -0,0 +1,41 @@
|
|||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034,SC2059
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/process_update.sh
|
||||
#
|
||||
USAGE='process_update.sh [-h|--help] [debug] [<file]'
|
||||
#
|
||||
# DESCRIPTION: processes ONE telegram update read from stdin, e.g. form file or webhook
|
||||
#
|
||||
# -h - display short help
|
||||
# --help - this help
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 30.01.2021 19:14
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
COMMAND="process_multi_updates"
|
||||
|
||||
# set bashbot environment
|
||||
source "${0%/*}/bashbot_env.inc.sh" "debug" # debug
|
||||
print_help "${1:-nix}"
|
||||
|
||||
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
|
||||
# read json from stdin and convert update format
|
||||
# replace any ID named BOTADMIN with ID of bot admin
|
||||
json='{"result": ['"$(cat)"']}'
|
||||
json="${json//\"id\":BOTADMIN,/\"id\":${BOTADMIN},}"
|
||||
UPDATE="$(${JSONSHFILE} -b -n <<<"${json}" 2>/dev/null)"
|
||||
|
||||
# process telegram update
|
||||
"${COMMAND}" "$1"
|
||||
|
46
bin/promote_user.sh
Executable file
46
bin/promote_user.sh
Executable file
|
@ -0,0 +1,46 @@
|
|||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/promote_user.sh
|
||||
#
|
||||
USAGE='promote_user.sh [-h|--help] "CHAT[ID]" "USER[ID]" "right[:true|false]" ..'
|
||||
#
|
||||
# DESCRIPTION: promote / denote user rights in given group
|
||||
#
|
||||
# OPTIONS: CHAT[ID] - ID number of CHAT or BOTADMIN to send to yourself
|
||||
# USER[ID] - user to (un)ban
|
||||
# rights[:true|false] - rights to grant in long or short form,
|
||||
# followed by :true to grant or :false to renove
|
||||
# long: is_anonymous can_change_info can_post_messages can_edit_messages
|
||||
# can_delete_messages can_invite_users can_restrict_members
|
||||
# can_pin_messages can_promote_member`
|
||||
# short: anon change post edit delete invite restrict pin promote
|
||||
#
|
||||
# -h - display short help
|
||||
# --help - this help
|
||||
#
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 25.01.2021 22:34
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
PROMOTE="promote_chat_member"
|
||||
|
||||
# set bashbot environment
|
||||
source "${0%/*}/bashbot_env.inc.sh" "debug" # debug
|
||||
print_help "$1"
|
||||
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
|
||||
# send message in selected format
|
||||
"${PROMOTE}" "$@"
|
||||
|
||||
# output send message result
|
||||
print_result
|
127
bin/send_broadcast.sh
Executable file
127
bin/send_broadcast.sh
Executable file
|
@ -0,0 +1,127 @@
|
|||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034
|
||||
#===============================================================================
|
||||
# shellcheck disable=SC2059
|
||||
#
|
||||
# FILE: bin/broadcast_message.sh
|
||||
#
|
||||
USAGE='broadcast_message.sh [-h|--help] [--doit] [--groups|--both|--db=file] [format] "message ...." [debug]'
|
||||
#
|
||||
# DESCRIPTION: send a message to all users listed in a jsonDB (default count db)
|
||||
#
|
||||
# OPTIONS: --doit - broadcast is dangerous, simulate run without --doit
|
||||
# --groups - send to groups instead of users
|
||||
# --both - send to users and groups (default with --db)
|
||||
# --db name - send to all user/groups in jsonDB database (e.g. blocked)
|
||||
# db file: name.jssh, db keys are user/chat id, values are ignored
|
||||
#
|
||||
# format - normal, markdown, html (optional)
|
||||
# message - message to send in specified format
|
||||
# if no format is givern send_message() format is used
|
||||
#
|
||||
# -h - display short help
|
||||
# --help - this help
|
||||
#
|
||||
# Set BASHBOT_HOME to your installation directory
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 16.12.2020 16:14
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# minimum messages seen in a chat before send a broadcast to it
|
||||
MINCOUNT=2
|
||||
USERDB=""
|
||||
|
||||
####
|
||||
# broadcast is dangerous, without --doit we do a dry run ...
|
||||
if [ "$1" = "--doit" ]; then
|
||||
DOIT="yes"
|
||||
shift
|
||||
fi
|
||||
|
||||
####
|
||||
# send to users by default, --group sends groups, --both to both
|
||||
SENDTO="users"
|
||||
if [ "$1" = "--both" ]; then
|
||||
GROUPSALSO=" and groups"
|
||||
shift
|
||||
elif [ "$1" = "--groups" ]; then
|
||||
SENDTO="groups"
|
||||
GROUPSALSO=" only"
|
||||
shift
|
||||
elif [ "$1" = "--db" ]; then
|
||||
USERDB="${2%.jssh}"
|
||||
MINCOUNT=""
|
||||
GROUPSALSO=" and groups"
|
||||
shift 2
|
||||
fi
|
||||
|
||||
####
|
||||
# parse args -----------------
|
||||
SEND="send_message"
|
||||
case "$1" in
|
||||
"nor"*|"tex"*)
|
||||
SEND="send_normal_message"
|
||||
shift
|
||||
;;
|
||||
"mark"*)
|
||||
SEND="send_markdownv2_message"
|
||||
shift
|
||||
;;
|
||||
"html")
|
||||
SEND="send_html_message"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
|
||||
# set bashbot environment
|
||||
source "${0%/*}/bashbot_env.inc.sh" "$2" # $3 debug
|
||||
print_help "$1"
|
||||
|
||||
# read in users from given DB or count.jssh
|
||||
database="${USERDB:-${COUNTFILE}}"
|
||||
declare -A SENDALL
|
||||
jssh_readDB_async "SENDALL" "${database}"
|
||||
if [ -z "${SENDALL[*]}" ]; then
|
||||
printf "${ORANGE}User database not found or empty: ${NC}${database}\n"
|
||||
fi
|
||||
|
||||
# loop over users
|
||||
printf "${GREEN}Sending broadcast message to ${SENDTO}${GROUPSALSO} of ${BOTNAME} using database:${NC}${GREY} ${database##*/}"
|
||||
|
||||
{ # dry run
|
||||
[ -z "${DOIT}" ] && printf "${NC}\n${ORANGE}DRY RUN! use --doit as first argument to execute broadcast...${NC}\n"
|
||||
|
||||
for USER in ${!SENDALL[*]}
|
||||
do
|
||||
# send to users, groups or both ...
|
||||
[[ -z "${GROUPSALSO}" && "${USER}" == *"-"* ]] && continue
|
||||
[[ "${SENDTO}" != "users" && "${USER}" != *"-"* ]] && continue
|
||||
# ignore everything not a user or group
|
||||
[[ ! "${USER}" =~ ^[0-9-]*$ ]] && continue
|
||||
# ignore chats with no count or lower MINCOUNT
|
||||
[[ -n "${MINCOUNT}" && ( ! "${SENDALL[${USER}]}" =~ ^[0-9]*$ || "${SENDALL[${USER}]}" -lt "${MINCOUNT}" ) ]] && continue
|
||||
(( COUNT++ ))
|
||||
if [ -z "${DOIT}" ]; then
|
||||
printf "${SEND} ${USER} $1 $2\n"
|
||||
else
|
||||
"${SEND}" "${USER}" "$1" "$2"
|
||||
printf "." 1>&2
|
||||
# ups, kicked or banned ...
|
||||
if [ "${BOTSENT[ERROR]}" = "403" ]; then
|
||||
# remove chat from future broadcasts
|
||||
jssh_insertKeyDB "${USER}" "${SENDALL[${USER}]} banned" "${COUNTFILE}"
|
||||
printf "${ORANGE}Warning: bot banned from chat${NC} %s ${ORANGE}after${NC} %s ${ORANGE}commands${NC}\n"\
|
||||
"${USER}" "${SENDALL[${USER}]}"
|
||||
fi
|
||||
sleep 0.1
|
||||
fi
|
||||
done
|
||||
# printout final stats message
|
||||
printf "${NC}\n${GREEN}Message${NC} $1 ${GREEN}sent to${NC} ${COUNT} ${GREEN}${SENDTO}${GROUPSALSO}.${NC}\n"
|
||||
} | more
|
||||
|
54
bin/send_buttons.sh
Executable file
54
bin/send_buttons.sh
Executable file
|
@ -0,0 +1,54 @@
|
|||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/send_message.sh
|
||||
#
|
||||
USAGE='send_message.sh [-h|--help] "CHAT[ID]" "message" "text|url" ...'
|
||||
#
|
||||
# DESCRIPTION: send a send buttons in a row to the given user/group
|
||||
#
|
||||
# OPTIONS: CHAT[ID] - ID number of CHAT or BOTADMIN to send to yourself
|
||||
# message - message to send
|
||||
# text|url - buttons to send, each button as "text|url" pair or
|
||||
# "url" not http(s):// or tg:// is sent as callback_data
|
||||
# "url" only to show url as text also, "" starts new row
|
||||
#
|
||||
# -h - display short help
|
||||
# --help - this help
|
||||
#
|
||||
# EXAMPLE: 2 buttons on 2 rows, first shows Amazon, second the url as text
|
||||
# send_buttons.sh "Amazon|https://www.amazon.com" "" "https://mydealz.de" ...
|
||||
#
|
||||
# Set BASHBOT_HOME to your installation directory
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 18.01.2021 11:34
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
SEND="send_inline_keyboard"
|
||||
|
||||
# set bashbot environment
|
||||
source "${0%/*}/bashbot_env.inc.sh" "debug"
|
||||
print_help "$1"
|
||||
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
if [ "$1" == "BOTADMIN" ]; then
|
||||
CHAT="${BOTADMIN}"
|
||||
else
|
||||
CHAT="$1"
|
||||
fi
|
||||
MESSAGE="$2"
|
||||
shift 2
|
||||
|
||||
# send message in selected format
|
||||
"${SEND}" "${CHAT}" "${MESSAGE}" "$(_button_row "$@")"
|
||||
|
||||
# output send message result
|
||||
print_result
|
47
bin/send_dice.sh
Executable file
47
bin/send_dice.sh
Executable file
|
@ -0,0 +1,47 @@
|
|||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/send_dice.sh
|
||||
#
|
||||
USAGE='send_dice.sh [-h|--help] "CHAT[ID]" "emoji" [debug]'
|
||||
#
|
||||
# DESCRIPTION: send an animated emoji (dice) to given chat
|
||||
#
|
||||
# OPTIONS: CHAT[ID] - ID number of CHAT or BOTADMIN to send to yourself
|
||||
# emoji - must be one of: “🎲”, “🎯”, “🏀”, “⚽” “🎰” "🎳"
|
||||
# :game_die: :dart: :basketball: :soccer: :slot_machine: :bowling:
|
||||
#
|
||||
# -h - display short help
|
||||
# --help - this help
|
||||
#
|
||||
# Set BASHBOT_HOME to your installation directory
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 07.02.2021 18:45
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
SEND="send_dice"
|
||||
|
||||
# set bashbot environment
|
||||
source "${0%/*}/bashbot_env.inc.sh" "${3:-debug}" # $5 debug
|
||||
print_help "$1"
|
||||
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
if [ "$1" == "BOTADMIN" ]; then
|
||||
CHAT="${BOTADMIN}"
|
||||
else
|
||||
CHAT="$1"
|
||||
fi
|
||||
|
||||
# send message in selected format
|
||||
"${SEND}" "${CHAT}" "$2"
|
||||
|
||||
# output send message result
|
||||
print_result
|
55
bin/send_file.sh
Executable file
55
bin/send_file.sh
Executable file
|
@ -0,0 +1,55 @@
|
|||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/send_file.sh
|
||||
#
|
||||
USAGE='send_file.sh [-h|--help] "CHAT[ID]" "file|URL" "caption ...." [type] [debug]'
|
||||
#
|
||||
# DESCRIPTION: send a file to the given user/group
|
||||
#
|
||||
# OPTIONS: CHAT[ID] - ID number of CHAT or BOTADMIN to send to yourself
|
||||
# file - local file to send, must be an absolute path or relative to pwd
|
||||
# Note: must not contain .. or . and located below BASHBOT_ETC
|
||||
# URL - send an URL instead local file
|
||||
#
|
||||
# caption - message to send with file
|
||||
# type - photo, video, sticker, voice, document (optional)
|
||||
#
|
||||
# -h - display short help
|
||||
# --help - this help
|
||||
#
|
||||
# Set BASHBOT_HOME to your installation directory
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 25.12.2020 20:24
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
SEND="send_file"
|
||||
|
||||
# set bashbot environment
|
||||
source "${0%/*}/bashbot_env.inc.sh" "${5:-debug}" # $5 debug
|
||||
print_help "$1"
|
||||
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
if [ "$1" == "BOTADMIN" ]; then
|
||||
CHAT="${BOTADMIN}"
|
||||
else
|
||||
CHAT="$1"
|
||||
fi
|
||||
|
||||
FILE="$2"
|
||||
# convert to absolute path if not start with / or http://
|
||||
[[ ! ( "$2" == "/"* || "$2" =~ ^https*:// || "$2" == "file_id://"*) ]] && FILE="${PWD}/$2"
|
||||
|
||||
# send message in selected format
|
||||
"${SEND}" "${CHAT}" "${FILE}" "$3" "$4"
|
||||
|
||||
# output send message result
|
||||
print_result
|
73
bin/send_message.sh
Executable file
73
bin/send_message.sh
Executable file
|
@ -0,0 +1,73 @@
|
|||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/send_message.sh
|
||||
#
|
||||
USAGE='send_message.sh [-h|--help] [format] "CHAT[ID]" "message ...." [debug]'
|
||||
#
|
||||
# DESCRIPTION: send a message to the given user/group
|
||||
#
|
||||
# OPTIONS: format - normal, markdown, html, stdin, - (optional)
|
||||
# CHAT[ID] - ID number of CHAT or BOTADMIN to send to yourself
|
||||
# message - message to send in specified format
|
||||
# if no format is givern send_message() format is used
|
||||
#
|
||||
# use format "stdin" to read message from stdin or from a file:
|
||||
# send_message.sh stdin "CHAT[ID]" <file
|
||||
# df -h | send_message.sh - "CHAT[ID]"
|
||||
#
|
||||
# -h - display short help
|
||||
# --help - this help
|
||||
#
|
||||
# Set BASHBOT_HOME to your installation directory
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 16.12.2020 11:34
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
SEND="send_message"
|
||||
case "$1" in
|
||||
"nor"*|"tex"*)
|
||||
SEND="send_normal_message"
|
||||
shift
|
||||
;;
|
||||
"mark"*)
|
||||
SEND="send_markdownv2_message"
|
||||
shift
|
||||
;;
|
||||
"html")
|
||||
SEND="send_html_message"
|
||||
shift
|
||||
;;
|
||||
"stdin"|"-")
|
||||
FILE="stdin"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
|
||||
# set bashbot environment
|
||||
source "${0%/*}/bashbot_env.inc.sh" "${3:-debug}" # $3 debug
|
||||
print_help "$1"
|
||||
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
if [ "$1" == "BOTADMIN" ]; then
|
||||
CHAT="${BOTADMIN}"
|
||||
else
|
||||
CHAT="$1"
|
||||
fi
|
||||
|
||||
# send message in selected format
|
||||
if [ "${FILE}" = "stdin" ]; then
|
||||
"${SEND}" "${CHAT}" "$(cat)"
|
||||
else
|
||||
"${SEND}" "${CHAT}" "$2"
|
||||
fi
|
||||
# output send message result
|
||||
print_result
|
170
commands.sh
170
commands.sh
|
@ -1,17 +1,24 @@
|
|||
#!/bin/bash
|
||||
# file: commands.sh
|
||||
# do not edit this file, instead place all your commands in mycommands.sh
|
||||
|
||||
# _____ _______ _ _ _
|
||||
# (____ \ _ (_______) | (_)_ | |
|
||||
# _ \ \ ___ ____ ___ | |_ _____ _ | |_| |_ | |
|
||||
# | | | / _ \ | _ \ / _ \| _) | ___) / || | | _)|_|
|
||||
# | |__/ / |_| | | | | | |_| | |__ | |____( (_| | | |__ _
|
||||
# |_____/ \___/ |_| |_|\___/ \___) |_______)____|_|\___)_|
|
||||
#
|
||||
# this file *MUST* not edited! place your config in the file "mycommands.conf"
|
||||
# and commands in "mycommands.sh", a clean version is provided as "mycommands.sh.clean"
|
||||
#
|
||||
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#
|
||||
# shellcheck disable=SC2154
|
||||
# shellcheck disable=SC2034
|
||||
|
||||
# adjust your language setting here, e.g.when run from other user or cron.
|
||||
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
|
||||
# bashbot locale defaults to c.UTF-8, adjust locale in mycommands.sh if needed
|
||||
export 'LC_ALL=C.UTF-8'
|
||||
export 'LANG=C.UTF-8'
|
||||
export 'LANGUAGE=C.UTF-8'
|
||||
|
@ -19,104 +26,133 @@ export 'LANGUAGE=C.UTF-8'
|
|||
unset IFS
|
||||
# set -f # if you are paranoid use set -f to disable globbing
|
||||
|
||||
# to change the default info message overwrite bashbot_info in mycommands.sh
|
||||
#-----------------------------
|
||||
# this file *MUST* not edited!
|
||||
# copy "mycommands.sh.dist" to "mycommands.sh" and change the strings there
|
||||
bashbot_info='This is bashbot, the Telegram bot written entirely in bash.
|
||||
It features background tasks and interactive chats, and can serve as an interface for CLI programs.
|
||||
It currently can send, recieve and forward messages, custom keyboards, photos, audio, voice, documents, locations and video files.
|
||||
It currently can send, receive and forward messages, custom keyboards, photos, audio, voice, documents, locations and video files.
|
||||
'
|
||||
|
||||
# to change the default help messages overwrite in mycommands.sh
|
||||
bashbot_help='*Available commands*:
|
||||
#-----------------------------
|
||||
# this file *MUST* not edited!
|
||||
# copy "mycommands.sh.dist" to "mycommands.sh" and change the strings there
|
||||
bashbot_help='
|
||||
*Available commands*:
|
||||
*• /start*: _Start bot and get this message_.
|
||||
*• /help*: _Get this message_.
|
||||
*• /info*: _Get shorter info message about this bot_.
|
||||
*• /question*: _Start interactive chat_.
|
||||
*• /cancel*: _Cancel any currently running interactive chats_.
|
||||
*• /kickme*: _You will be autokicked from the chat_.
|
||||
*• /kickme*: _You will be autokicked from the group_.
|
||||
*• /leavechat*: _The bot will leave the group with this command _.
|
||||
Written by Drew (@topkecleon), Daniil Gentili (@danogentili) and KayM(@gnadelwartz).
|
||||
Get the code in my [GitHub](http://github.com/topkecleon/telegram-bot-bash)
|
||||
Additional commands from mycommands.dist ...
|
||||
*• /game*: _throw a die_.
|
||||
*• /question*: _Start interactive chat_.
|
||||
*• /cancel*: _Cancel any currently running interactive chat_.
|
||||
*• /run_notify*: _Start background job_.
|
||||
*• /stop_notify*: _Stop notify background job_.
|
||||
Written by Drew (@topkecleon) and KayM (@gnadelwartz).
|
||||
Get the code on [GitHub](http://github.com/topkecleon/telegram-bot-bash)
|
||||
'
|
||||
|
||||
if [ "${1}" != "source" ]; then
|
||||
# load modules needed for commands.sh only
|
||||
# shellcheck source=./modules/aliases.sh
|
||||
[ -r "${MODULEDIR:-.}/aliases.sh" ] && source "${MODULEDIR:-.}/aliases.sh"
|
||||
# shellcheck source=./modules/background.sh
|
||||
[ -r "${MODULEDIR:-.}/background.sh" ] && source "${MODULEDIR:-.}/background.sh"
|
||||
else
|
||||
# defaults to no inline and nonsense home dir
|
||||
INLINE="0"
|
||||
FILE_REGEX='/home/user/allowed/.*'
|
||||
|
||||
# load modules needed for bashbot.sh also
|
||||
# shellcheck source=./modules/background.sh
|
||||
[ -r "${MODULEDIR:-.}/inline.sh" ] && source "${MODULEDIR:-.}/inline.sh"
|
||||
# load modules on startup and always on on debug
|
||||
if [ -n "$1" ]; then
|
||||
# load all readable modules
|
||||
for modules in "${MODULEDIR:-.}"/*.sh ; do
|
||||
if [[ "$1" == *"debug"* ]] || ! _is_function "$(basename "${modules}")"; then
|
||||
# shellcheck source=./modules/aliases.sh
|
||||
[ -r "${modules}" ] && source "${modules}" "$1"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
#----------------------------
|
||||
# this file *MUST* not edited!
|
||||
# copy "mycommands.sh.dist" to "mycommands.sh" and change the values there
|
||||
# defaults to no inline, all commands and nonsense home dir
|
||||
export INLINE="0"
|
||||
export CALLBACK="0"
|
||||
export MEONLY="0"
|
||||
export FILE_REGEX="${BASHBOT_ETC}/.*"
|
||||
|
||||
|
||||
# load mycommands
|
||||
# shellcheck source=./commands.sh
|
||||
[ -r "${BASHBOT_ETC:-.}/mycommands.sh" ] && source "${BASHBOT_ETC:-.}/mycommands.sh" "${1}"
|
||||
[ -r "${BASHBOT_ETC:-.}/mycommands.sh" ] && source "${BASHBOT_ETC:-.}/mycommands.sh" "$1"
|
||||
|
||||
|
||||
if [ "${1}" != "source" ];then
|
||||
if ! tmux ls 2>/dev/null | grep -v send | grep -q "$copname"; then
|
||||
# interactive running?
|
||||
[ ! -z "${URLS[*]}" ] && {
|
||||
curl -s "${URLS[*]}" -o "$NAME"
|
||||
send_file "${CHAT[ID]}" "$NAME" "$CAPTION"
|
||||
rm -f "$NAME"
|
||||
}
|
||||
[ ! -z "${LOCATION[*]}" ] && send_location "${CHAT[ID]}" "${LOCATION[LATITUDE]}" "${LOCATION[LONGITUDE]}"
|
||||
if [ -z "$1" ] || [[ "$1" == *"debug"* ]];then
|
||||
#################
|
||||
# detect inline and callback query
|
||||
if [ -n "${iQUERY[ID]}" ]; then
|
||||
# forward inline query to optional dispatcher
|
||||
[ "${INLINE:-0}" != "0" ] && _exec_if_function myinlines
|
||||
|
||||
fi
|
||||
elif [ -n "${iBUTTON[ID]}" ]; then
|
||||
# forward inline query to optional dispatcher
|
||||
[ "${CALLBACK:-0}" != "0" ] && _exec_if_function mycallbacks
|
||||
|
||||
if [ "$INLINE" != "0" ] && [ "${iQUERY[ID]}" != "" ]; then
|
||||
if _is_function process_inline; then
|
||||
# forward iinline query to optional dispatcher
|
||||
_is_function myinlines && myinlines
|
||||
fi
|
||||
#################
|
||||
# regular command
|
||||
else
|
||||
|
||||
case "${MESSAGE}" in
|
||||
###################
|
||||
# if is bashbot is group admin it get commands sent to other bots
|
||||
# set MEONLY=1 to ignore commands for other bots
|
||||
if [[ "${MEONLY}" != "0" && "${MESSAGE}" == "/"*"@"* ]]; then
|
||||
# here we have a command with @xyz_bot added, check if it's our bot
|
||||
[ "${MESSAGE%%@*}" != "${MESSAGE%%@${ME}}" ] && return
|
||||
fi
|
||||
|
||||
###################
|
||||
# user defined commands must placed in mycommands
|
||||
! _is_function mycommands || mycommands
|
||||
|
||||
# run commands if true (0) is returned or if mycommands dose not exist
|
||||
# shellcheck disable=SC2181
|
||||
if [ "$?" = "0" ]; then
|
||||
case "${MESSAGE}" in
|
||||
################################################
|
||||
# this file *MUST* not edited!
|
||||
# copy "mycommands.sh.dist" to "mycommands.sh" and change the values and add your commands there
|
||||
#
|
||||
# GLOBAL commands start here, edit messages only
|
||||
'/info'*)
|
||||
_markdown_message "${bashbot_info}"
|
||||
send_markdown_message "${CHAT[ID]}" "${bashbot_info}"
|
||||
;;
|
||||
'/start'*)
|
||||
send_action "${CHAT[ID]}" "typing"
|
||||
_is_botadmin && _markdown_message "You are *BOTADMIN*."
|
||||
if _is_botadmin || _is_allowed "start" ; then
|
||||
_markdown_message "${bashbot_help}"
|
||||
MYCOMMANDS="*Note*: MISSING mycommands.sh: copy _mycommands.dist_ or _mycommands.clean_."
|
||||
[ -r "${BASHBOT_ETC:-.}/mycommands.sh" ] && MYCOMMANDS="Place your commands and messages in _mycommands.sh_"
|
||||
user_is_botadmin "${USER[ID]}" &&\
|
||||
send_markdownv2_message "${CHAT[ID]}" "You are *BOTADMIN*.\n${MYCOMMANDS}"
|
||||
if user_is_admin "${CHAT[ID]}" "${USER[ID]}" || user_is_allowed "${USER[ID]}" "start" ; then
|
||||
send_markdown_message "${CHAT[ID]}" "${bashbot_help}"
|
||||
else
|
||||
_message "You are not allowed to start Bot."
|
||||
send_normal_message "${CHAT[ID]}" "You are not allowed to start Bot."
|
||||
fi
|
||||
;;
|
||||
|
||||
'/help'*)
|
||||
_markdown_message "${bashbot_help}"
|
||||
send_markdown_message "${CHAT[ID]}" "${bashbot_help}"
|
||||
;;
|
||||
'/leavechat'*) # bot leave chat if user is admin in chat
|
||||
if _is_admin ; then
|
||||
_markdown_message "*LEAVING CHAT...*"
|
||||
_leave
|
||||
'/leavechat'*) # bot leave chat if user is admin in chat
|
||||
if user_is_admin "${CHAT[ID]}" "${USER[ID]}" || user_is_allowed "${USER[ID]}" "leave" ; then
|
||||
send_markdown_message "${CHAT[ID]}" "*LEAVING CHAT...*"
|
||||
leave_chat "${CHAT[ID]}"
|
||||
fi
|
||||
;;
|
||||
|
||||
'/kickme'*)
|
||||
_kick_user "${USER[ID]}"
|
||||
_unban_user "${USER[ID]}"
|
||||
kick_chat_member "${CHAT[ID]}" "${USER[ID]}"
|
||||
unban_chat_member "${CHAT[ID]}" "${USER[ID]}"
|
||||
;;
|
||||
|
||||
'/cancel'*)
|
||||
checkproc
|
||||
if [ "$res" -eq 0 ] ; then killproc && _message "Command canceled.";else _message "No command is currently running.";fi
|
||||
'/'*) # discard all unknown commands
|
||||
: ;;
|
||||
*) # forward message to interactive chats
|
||||
_exec_if_function send_interactive "${CHAT[ID]}" "${MESSAGE}"
|
||||
;;
|
||||
*) # forward messages to optional dispatcher
|
||||
_is_function startproc && if tmux ls | grep -v send | grep -q "$copname"; then inproc; fi # interactive running
|
||||
_is_function mycommands && mycommands
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
|
30
db.json
Normal file
30
db.json
Normal file
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"usage":
|
||||
{
|
||||
"ok":true,
|
||||
"url":"https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/usage?",
|
||||
"description":"Testing of JSON responses for github.com/topkecleon/telegram-bot-bash, replace usage with the dataset you want to query"
|
||||
} ,
|
||||
"false":
|
||||
{
|
||||
"ok":false,
|
||||
"error_code":404,
|
||||
"description":"Not Found"
|
||||
} ,
|
||||
"true":
|
||||
{
|
||||
"ok":true,
|
||||
"description":"Test for ok"
|
||||
} ,
|
||||
"getMe":
|
||||
{
|
||||
"ok":true,
|
||||
"result":
|
||||
{
|
||||
"id":123456789,
|
||||
"is_bot":true,
|
||||
"first_name":"bashbot",
|
||||
"username":"TestBotBash"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,57 +1,79 @@
|
|||
#!/usr/bin/env bash
|
||||
# this has to run once atfer git clone
|
||||
# and every time we create new hooks
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#############################################################
|
||||
#
|
||||
# File: dev/all-tests.sh
|
||||
#
|
||||
# Description: run all tests, exit after failed test
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#############################################################
|
||||
|
||||
# magic to ensure that we're always inside the root of our application,
|
||||
# no matter from which directory we'll run script
|
||||
GIT_DIR=$(git rev-parse --git-dir)
|
||||
cd "${GIT_DIR}/.." || exit 1
|
||||
#shellcheck disable=SC1090
|
||||
source "${0%/*}/dev.inc.sh"
|
||||
|
||||
##########################
|
||||
# create test environment
|
||||
TESTENV="/tmp/bashbot.test$$"
|
||||
mkdir "${TESTENV}"
|
||||
cp -r ./* "${TESTENV}"
|
||||
cd "test" || exit 1
|
||||
|
||||
# delete possible config
|
||||
rm -f "${TESTENV}/botconfig.jssh" "${TESTENV}/botacl" 2>/dev/null
|
||||
|
||||
# mkdir needed dirs
|
||||
mkdir "${TESTENV}/data-bot-bash"
|
||||
|
||||
# inject JSON.sh
|
||||
mkdir "${TESTENV}/JSON.sh"
|
||||
curl -sL "https://cdn.jsdelivr.net/gh/dominictarr/JSON.sh/JSON.sh" >"${TESTENV}/JSON.sh/JSON.sh"
|
||||
chmod +x "${TESTENV}/JSON.sh/JSON.sh"
|
||||
|
||||
########################
|
||||
#prepare and run tests
|
||||
#set -e
|
||||
fail=0
|
||||
tests=0
|
||||
passed=0
|
||||
#all_tests=${__dirname:}
|
||||
#echo PLAN ${#all_tests}
|
||||
#printf PLAN ${#all_tests}
|
||||
for test in $(find ./*-test.sh | sort -u) ;
|
||||
do
|
||||
[ "${test}" = "test/all-tests.sh" ] && continue
|
||||
[ "${test}" = "dev/all-tests.sh" ] && continue
|
||||
[ ! -x "${test}" ] && continue
|
||||
tests=$((tests+1))
|
||||
echo "TEST: ${test}"
|
||||
printf "TEST: %s\n" "${test}"
|
||||
"${test}" "${TESTENV}"
|
||||
ret=$?
|
||||
if [ "$ret" -eq 0 ] ; then
|
||||
echo "OK: ---- ${test}"
|
||||
set +e
|
||||
if [ "${ret}" -eq 0 ] ; then
|
||||
printf "OK: ---- %s\n" "${test}"
|
||||
passed=$((passed+1))
|
||||
else
|
||||
echo "FAIL: $test $fail"
|
||||
printf "FAIL: %s\n" "${test} ${fail}"
|
||||
fail=$((fail+ret))
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$fail" -eq 0 ]; then
|
||||
/bin/echo -n 'SUCCESS '
|
||||
###########################
|
||||
# cleanup depending on test state
|
||||
if [ "${fail}" -eq 0 ]; then
|
||||
printf 'SUCCESS '
|
||||
exitcode=0
|
||||
rm -rf "${TESTENV}"
|
||||
else
|
||||
/bin/echo -n 'FAILURE '
|
||||
printf 'FAILURE '
|
||||
exitcode=1
|
||||
rm -rf "${TESTENV}/test"
|
||||
find "${TESTENV}/"* ! -name '[a-z]-*' -delete
|
||||
fi
|
||||
|
||||
echo -e "${passed} / ${tests}\\n"
|
||||
[ -d "${TESTENV}" ] && echo "Logfiles from run are in ${TESTENV}"
|
||||
#########################
|
||||
# show test result and test logs
|
||||
printf "%s\n\n" "${passed} / ${tests}"
|
||||
[ -d "${TESTENV}" ] && printf "Logfiles from run are in %s\n" "${TESTENV}"
|
||||
|
||||
ls -ld /tmp/bashbot.test* 2>/dev/null && echo "Don not forget to deleted bashbot test files in /tmp!!"
|
||||
ls -ld /tmp/bashbot.test* 2>/dev/null && printf "Do not forget to delete bashbot test files in /tmp!!\n"
|
||||
|
||||
exit ${exitcode}
|
||||
exit "${exitcode}"
|
||||
|
|
24
dev/dev.inc.sh
Normal file
24
dev/dev.inc.sh
Normal file
|
@ -0,0 +1,24 @@
|
|||
#!/usr/bin/env bash
|
||||
#############################################################
|
||||
#
|
||||
# File: dev/dev.inc.sh
|
||||
#
|
||||
# Description: common stuff for all dev scripts
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#############################################################
|
||||
|
||||
# magic to ensure that we're always inside the root of our application,
|
||||
# no matter from which directory we'll run script
|
||||
|
||||
# shellcheck disable=SC2034
|
||||
GIT_DIR=$(git rev-parse --git-dir 2>/dev/null)
|
||||
BASE_DIR=$(git rev-parse --show-toplevel 2>/dev/null)
|
||||
if [ "${BASE_DIR}" != "" ] ; then
|
||||
cd "${BASE_DIR}" || exit 1
|
||||
else
|
||||
printf "Sorry, no git repository %s\n" "$(pwd)" && exit 1
|
||||
fi
|
||||
|
||||
HOOKDIR="dev/hooks"
|
||||
LASTCOMMIT=".git/.lastcommit"
|
|
@ -3,28 +3,37 @@
|
|||
#
|
||||
# works together with git pre-push.sh and ADD all changed files since last push
|
||||
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
# magic to ensure that we're always inside the root of our application,
|
||||
# no matter from which directory we'll run script
|
||||
GIT_DIR=$(git rev-parse --git-dir)
|
||||
cd "$GIT_DIR/.." || exit 1
|
||||
#shellcheck disable=SC1090
|
||||
source "${0%/*}/dev.inc.sh"
|
||||
|
||||
[ ! -f .git/.lastpush ] && echo "No push or hooks not installed, use \"git add\" instead ... Abort" && exit
|
||||
# check for last commit date
|
||||
if [ ! -f "${LASTCOMMIT}" ]; then
|
||||
if ! touch -d "$(git log -1 --format=%cD)" "${LASTCOMMIT}"; then
|
||||
printf "No previous commit found, use \"git add\" instead ... Abort\n"
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
|
||||
FILES="$(find ./* -newer .git/.lastpush)"
|
||||
[ "${FILES}" = "" ] && echo "Noting changed since last push ... Abort" && exit
|
||||
set +f
|
||||
FILES="$(find ./* -newer "${LASTCOMMIT}" | grep -v -e 'DIST\/' -e 'STANDALONE\/' -e 'JSON.sh')"
|
||||
set -f
|
||||
# FILES="$(find ./* -newer .git/.lastpush)"
|
||||
[ "${FILES}" = "" ] && printf "Nothing changed since last commit ...\n" && exit
|
||||
|
||||
# run pre_commit on files
|
||||
dev/hooks/pre-commit.sh
|
||||
|
||||
echo -n "Add files to repo: "
|
||||
printf "Add files to repo: "
|
||||
# shellcheck disable=SC2086
|
||||
for file in ${FILES}
|
||||
do
|
||||
[ -d "${file}" ] && continue
|
||||
echo -n "${file} "
|
||||
printf "%s" "${file} "
|
||||
done
|
||||
git add .
|
||||
echo "done."
|
||||
printf " - Done.\n"
|
||||
|
||||
# stay with "." for (re)moved files!
|
||||
git add .
|
||||
|
||||
|
|
23
dev/hooks/post-commit.sh
Executable file
23
dev/hooks/post-commit.sh
Executable file
|
@ -0,0 +1,23 @@
|
|||
#!/usr/bin/env bash
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
############
|
||||
# NOTE: you MUST run install-hooks.sh again when updating this file!
|
||||
|
||||
# magic to ensure that we're always inside the root of our application,
|
||||
# no matter from which directory we'll run script
|
||||
GIT_DIR=$(git rev-parse --git-dir)
|
||||
cd "${GIT_DIR}/.." || exit 1
|
||||
|
||||
export HOOKDIR="dev/hooks"
|
||||
LASTPUSH='.git/.lastcommit'
|
||||
|
||||
# if any command inside script returns error, exit and return that error
|
||||
set -e
|
||||
|
||||
#printf "Running post-commit hook\n............................\n"
|
||||
|
||||
unset IFS; set -f
|
||||
|
||||
# note date of last push for version
|
||||
touch "${LASTPUSH}"
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env bash
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
############
|
||||
# NOTE: you MUST run install-hooks.sh again when updating this file!
|
||||
|
@ -7,7 +7,7 @@
|
|||
# magic to ensure that we're always inside the root of our application,
|
||||
# no matter from which directory we'll run script
|
||||
GIT_DIR=$(git rev-parse --git-dir)
|
||||
cd "$GIT_DIR/.." || exit 1
|
||||
cd "${GIT_DIR}/.." || exit 1
|
||||
|
||||
export HOOKDIR="dev/hooks"
|
||||
LASTPUSH='.git/.lastpush'
|
||||
|
@ -15,50 +15,60 @@ LASTPUSH='.git/.lastpush'
|
|||
# if any command inside script returns error, exit and return that error
|
||||
set -e
|
||||
|
||||
echo "Running pre-commit hook"
|
||||
echo "............................"
|
||||
printf "Running pre-commit hook\n............................\n"
|
||||
|
||||
unset IFS; set -f
|
||||
|
||||
# check for shellcheck
|
||||
if which shellcheck >/dev/null 2>&1; then
|
||||
echo " Test all scripts with shellcheck ..."
|
||||
if command -v shellcheck >/dev/null 2>&1; then
|
||||
printf "Test all scripts with shellcheck\n"
|
||||
else
|
||||
echo "Error: shellcheck is not installed. Install shellcheck or delete $0"
|
||||
printf "Error: shellcheck is not installed. Please install shellcheck\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# run shellcheck before commit
|
||||
set +f
|
||||
FILES="$(find ./* -name '*.sh' | grep -v 'dist\/' )"
|
||||
FILES="$(find ./* -name '*.sh' | grep -v -e 'DIST\/' -e 'STANDALONE\/' -e 'JSON.sh')"
|
||||
set -f
|
||||
FILES="${FILES} $(sed '/^#/d' <"dev/shellcheck.files")"
|
||||
if [ "$FILES" != "" ]; then
|
||||
if [ "${FILES}" != "" ]; then
|
||||
# shellcheck disable=SC2086
|
||||
shellcheck -x ${FILES} || exit 1
|
||||
echo " OK"
|
||||
shellcheck -o all -e SC2249,SC2154 -x ${FILES} || exit 1
|
||||
printf " OK\n............................\n"
|
||||
else
|
||||
# something went wrong
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# get version strings
|
||||
REMOTEVER="$(git ls-remote -t --refs 2>/dev/null | tail -1 | sed -e 's/.*\/v//' -e 's/-.*//')"
|
||||
VERSION="$(git describe --tags | sed -e 's/-.*//' -e 's/v//')"
|
||||
|
||||
VERSION="$(git describe --tags | sed -e 's/-.*//' -e 's/v//' -e 's/,/./')"
|
||||
[ -z "${REMOTEVER}" ] && REMOTEVER="${VERSION}"
|
||||
|
||||
# LOCAL version must greater than latest REMOTE release version
|
||||
if (( $(echo "${VERSION} >= ${REMOTEVER}" | bc -l) )); then
|
||||
printf "Update Version of modified files\n"
|
||||
if ! command -v bc &> /dev/null || (( $(printf "%s\n" "${VERSION} >= ${REMOTEVER}" | bc -l) )); then
|
||||
# update version in bashbot files on push
|
||||
set +f
|
||||
[ -f "${LASTPUSH}" ] && LASTFILES="$(find ./* -newer "${LASTPUSH}")"
|
||||
[ -f "${LASTPUSH}" ] && LASTFILES="$(find ./* -newer "${LASTPUSH}" ! -path "./DIST/*" ! -path "./STANDALONE/*")"
|
||||
[ "${LASTFILES}" = "" ] && exit
|
||||
echo -n " "
|
||||
printf " "
|
||||
# shellcheck disable=SC2086
|
||||
dev/version.sh ${LASTFILES} 2>/dev/null || exit 1
|
||||
echo " OK"
|
||||
printf " OK\n............................\n"
|
||||
else
|
||||
echo "Error: local version ${VERSION} must be greater or equal to release version ${REMOTEVER}."
|
||||
echo "use \"git tag ...\" to create a new local version"
|
||||
printf "Error: local version %s must be equal to or greater then release version%s\n" "${VERSION}" "${REMOTEVER}."
|
||||
printf "use \"git tag vx.zz\" to create a new local version\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if command -v codespell &>/dev/null; then
|
||||
printf "Running codespell\n............................\n"
|
||||
codespell -q 3 --skip="*.zip,*gz,*.log,*.html,*.txt,.git*,jsonDB-keyboard,DIST,STANDALONE" -L "ba"
|
||||
printf "if there are (to many) typo's shown, consider running:\ncodespell -i 3 -w --skip=\"*.log,*.html,*.txt,.git*,examples\" -L \"ba\"\n"
|
||||
else
|
||||
printf "consider installing codespell: pip install codespell\n"
|
||||
fi
|
||||
printf "............................\n"
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env bash
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
############
|
||||
# NOTE: you MUST run install-hooks.sh again when updating this file!
|
||||
|
@ -7,7 +7,7 @@
|
|||
# magic to ensure that we're always inside the root of our application,
|
||||
# no matter from which directory we'll run script
|
||||
GIT_DIR=$(git rev-parse --git-dir)
|
||||
cd "$GIT_DIR/.." || exit 1
|
||||
cd "${GIT_DIR}/.." || exit 1
|
||||
|
||||
export HOOKDIR="dev/hooks"
|
||||
LASTPUSH='.git/.lastpush'
|
||||
|
@ -15,8 +15,7 @@ LASTPUSH='.git/.lastpush'
|
|||
# if any command inside script returns error, exit and return that error
|
||||
set -e
|
||||
|
||||
echo "Running pre-push hook"
|
||||
echo "............................"
|
||||
printf "Running pre-push hook\n............................\n"
|
||||
|
||||
unset IFS; set -f
|
||||
|
||||
|
|
35
dev/inject-json.sh
Normal file
35
dev/inject-json.sh
Normal file
|
@ -0,0 +1,35 @@
|
|||
#!/usr/bin/env bash
|
||||
##############################################################
|
||||
#
|
||||
# File: inject-json.sh
|
||||
#
|
||||
# Description: download and prepare JSON.sh and JSON.awk
|
||||
#
|
||||
# Usage: source inject-json.sh
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
##############################################################
|
||||
|
||||
# download JSON.sh
|
||||
JSONSHFILE="JSON.sh/JSON.sh"
|
||||
if [ ! -r "${JSONSHFILE}" ]; then
|
||||
printf "Inject JSON.sh ... "
|
||||
mkdir "JSON.sh" 2>/dev/null
|
||||
curl -sL -o "${JSONSHFILE}" "https://cdn.jsdelivr.net/gh/dominictarr/JSON.sh/JSON.sh"
|
||||
chmod +x "${JSONSHFILE}"
|
||||
printf "Done!\n"
|
||||
fi
|
||||
|
||||
# download JSON.awk
|
||||
JSONSHFILE="JSON.sh/JSON.awk.dist"
|
||||
if [ ! -r "${JSONSHFILE}" ]; then
|
||||
printf "Inject JSON.awk ... "
|
||||
curl -sL -o "${JSONSHFILE}" "https://cdn.jsdelivr.net/gh/step-/JSON.awk/JSON.awk"
|
||||
curl -sL -o "${JSONSHFILE%/*}/awk-patch.sh" "https://cdn.jsdelivr.net/gh/step-/JSON.awk/tool/patch-for-busybox-awk.sh"
|
||||
chmod +x "${JSONSHFILE}"
|
||||
printf "Done!\n"
|
||||
bash "${JSONSHFILE%/*}/awk-patch.sh" "${JSONSHFILE}"
|
||||
fi
|
||||
# delete backup files
|
||||
rm -f "${JSONSHFILE%/*}"/*.bak
|
||||
|
|
@ -1,22 +1,18 @@
|
|||
#!/usr/bin/env bash
|
||||
# this has to run once atfer git clone
|
||||
# and every time we create new hooks
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
# magic to ensure that we're always inside the root of our application,
|
||||
# no matter from which directory we'll run script
|
||||
GIT_DIR=$(git rev-parse --git-dir)
|
||||
cd "$GIT_DIR/.." || exit 1
|
||||
#shellcheck disable=SC1090
|
||||
source "${0%/*}/dev.inc.sh"
|
||||
|
||||
HOOKDIR="dev/hooks"
|
||||
|
||||
echo -n "Installing hooks..."
|
||||
for hook in pre-commit pre-push
|
||||
printf "Installing hooks..."
|
||||
for hook in pre-commit post-commit pre-push
|
||||
do
|
||||
rm -f "${GIT_DIR}/hooks/${hook}"
|
||||
if [ -f "${HOOKDIR}/${hook}.sh" ]; then
|
||||
echo -n " $hook"
|
||||
printf "%s"" ${hook}"
|
||||
ln -s "../../${HOOKDIR}/${hook}.sh" "${GIT_DIR}/hooks/${hook}"
|
||||
fi
|
||||
done
|
||||
echo " Done!"
|
||||
printf " Done!\n"
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
# this has to run once atfer git clone
|
||||
# and every time we create new hooks
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
|
||||
# magic to ensure that we're always inside the root of our application,
|
||||
# no matter from which directory we'll run script
|
||||
GIT_DIR=$(git rev-parse --git-dir)
|
||||
cd "$GIT_DIR/.." || exit 1
|
||||
|
||||
VERSION="$(git describe --tags | sed -e 's/-[0-9].*//' -e 's/v//')"
|
||||
|
||||
DISTNAME="telegram-bot-bash"
|
||||
DISTDIR="./dist/${DISTNAME}"
|
||||
DISTFILES="bashbot.rc bashbot.sh commands.sh mycommands.sh doc examples modules LICENSE README.md README.txt README.html"
|
||||
|
||||
# run tests first!
|
||||
|
||||
for test in "dev/all-tests.sh"
|
||||
do
|
||||
if ! "${test}" ; then
|
||||
echo "Test ${test} failed, can't create dist!"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# create dir for distribution and copy files
|
||||
mkdir -p "${DISTDIR}" 2>/dev/null
|
||||
# shellcheck disable=SC2086
|
||||
cp -r ${DISTFILES} "${DISTDIR}"
|
||||
cd "${DISTDIR}" || exit 1
|
||||
|
||||
# additional stuff
|
||||
mv "commands.sh" "commands.sh.dist"
|
||||
mv "mycommands.sh" "mycommands.sh.dist"
|
||||
|
||||
JSONSHFILE="JSON.sh/JSON.sh"
|
||||
if [ ! -f "${JSONSHFILE}" ]; then
|
||||
mkdir "JSON.sh" 2>/dev/null
|
||||
curl -sL -o "${JSONSHFILE}" "https://cdn.jsdelivr.net/gh/dominictarr/JSON.sh/JSON.sh"
|
||||
chmod +x "${JSONSHFILE}"
|
||||
fi
|
||||
|
||||
# make html doc
|
||||
mkdir html 2>/dev/null
|
||||
cp README.html html/index.html
|
||||
find doc -iname "*.md" -type f -exec sh -c 'pandoc -s -S -M "title=Bashobot Documentation - ${0%.md}.html" "${0}" -o "./html/$(basename ${0%.md}.html)"' {} \;
|
||||
find examples -iname "*.md" -type f -exec sh -c 'pandoc -s -S -M "title=Bashobot Documentation - ${0%.md}.html" "${0}" -o "${0%.md}.html"' {} \;
|
||||
find README.html html examples -iname "*.html" -type f -exec sh -c 'sed -i -E "s/href=\"(\.\.\/)*doc\//href=\"\1html\//g;s/href=\"(.*).md(#.*)*\"/href=\"\1.html\"/g" ${0}' {} \;
|
||||
|
||||
# create archive
|
||||
cd .. || exit 1
|
||||
zip -rq "${DISTNAME}-${VERSION}.zip" "${DISTNAME}"
|
||||
tar -czf "${DISTNAME}-${VERSION}.tar.gz" "${DISTNAME}"
|
||||
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
ls -ld ${DISTNAME}-${VERSION}.*
|
||||
|
||||
|
85
dev/make-distribution.sh
Executable file
85
dev/make-distribution.sh
Executable file
|
@ -0,0 +1,85 @@
|
|||
#!/usr/bin/env bash
|
||||
##############################################################
|
||||
#
|
||||
# File: make-distribution.sh
|
||||
#
|
||||
# Description: creates files and arcchives to distribute bashbot
|
||||
#
|
||||
# Options: --notest - skip tests
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
##############################################################
|
||||
|
||||
#shellcheck disable=SC1090
|
||||
source "${0%/*}/dev.inc.sh"
|
||||
|
||||
VERSION="$(git describe --tags | sed -e 's/-[0-9].*//' -e 's/v//')"
|
||||
|
||||
DISTNAME="telegram-bot-bash"
|
||||
DISTDIR="./DIST/${DISTNAME}"
|
||||
DISTMKDIR="data-bot-bash logs bin bin/logs addons"
|
||||
|
||||
DISTFILES="bashbot.sh commands.sh mycommands.sh.clean bin doc examples scripts modules LICENSE README.md README.txt README.html"
|
||||
DISTFILESDEV="dev/make-standalone.sh dev/inject-json.sh dev/make-html.sh dev/obfuscate.sh"
|
||||
DISTFILESDIST="mycommands.sh mycommands.conf bashbot.rc $(echo "addons/"*.sh)"
|
||||
|
||||
# run tests first!
|
||||
for test in $1 dev/all-test*.sh
|
||||
do
|
||||
[[ "${test}" == "--notest"* ]] && break
|
||||
[ ! -x "${test}" ] && continue
|
||||
if ! "${test}" ; then
|
||||
printf "ERROR: Test %s failed, can't create dist!\n" "${test}"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# create dir for distribution and copy files
|
||||
mkdir -p "${DISTDIR}" 2>/dev/null
|
||||
|
||||
printf "Copy files\n"
|
||||
# shellcheck disable=SC2086
|
||||
cp -r ${DISTFILES} "${DISTDIR}"
|
||||
mkdir -p "${DISTDIR}/dev"
|
||||
# shellcheck disable=SC2086
|
||||
cp ${DISTFILESDEV} "${DISTDIR}/dev"
|
||||
cd "${DISTDIR}" || exit 1
|
||||
|
||||
printf "Create directories\n"
|
||||
# shellcheck disable=SC2250
|
||||
for dir in $DISTMKDIR
|
||||
do
|
||||
[ ! -d "${dir}" ] && mkdir "${dir}"
|
||||
done
|
||||
|
||||
# do not overwrite on update
|
||||
printf "Create .dist files\n"
|
||||
for file in ${DISTFILESDIST}
|
||||
do
|
||||
[ "${file}" = "addons/*.sh" ] && continue
|
||||
cp "${BASE_DIR}/${file}" "${file}.dist"
|
||||
done
|
||||
|
||||
# inject JSON.sh into distribution
|
||||
# shellcheck disable=SC1090
|
||||
source "${BASE_DIR}/dev/inject-json.sh"
|
||||
|
||||
# make html doc
|
||||
printf "Create html doc\n"
|
||||
# shellcheck disable=SC1090,SC1091
|
||||
source "../../dev/make-html.sh"
|
||||
|
||||
# create archive
|
||||
cd .. || exit 1
|
||||
printf "Create dist archives\n"
|
||||
# shellcheck disable=SC2046
|
||||
zip -rq - "${DISTNAME}" --exclude $(cat "${BASE_DIR}/dev/${0##*/}.exclude") >"${DISTNAME}-${VERSION}.zip"
|
||||
tar --exclude-ignore="${BASE_DIR}/dev/${0##*/}.exclude" -czf "${DISTNAME}-${VERSION}.tar.gz" "${DISTNAME}"
|
||||
|
||||
printf "%s Done!\n" "$0"
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
ls -ld "${DISTNAME}-${VERSION}".*
|
||||
|
||||
# an empty DEBUG.log is created ... :-(
|
||||
rm -f "${BASE_DIR}/test/"*.log
|
23
dev/make-distribution.sh.exclude
Normal file
23
dev/make-distribution.sh.exclude
Normal file
|
@ -0,0 +1,23 @@
|
|||
STANDALONE
|
||||
data-bot-bash/*
|
||||
test
|
||||
webhook-fifo*
|
||||
JSON.awk
|
||||
bashbot.rc
|
||||
mycommands.sh
|
||||
mycommands.conf
|
||||
awk-patch.sh
|
||||
make-standalone.sh.include
|
||||
*.jssh*
|
||||
botacl
|
||||
*.flock
|
||||
*.log
|
||||
*.last
|
||||
*.ok
|
||||
*.bad
|
||||
*.bak
|
||||
*.jpg
|
||||
*.jpeg
|
||||
*.png
|
||||
*.zip
|
||||
*.gz
|
44
dev/make-html.sh
Normal file
44
dev/make-html.sh
Normal file
|
@ -0,0 +1,44 @@
|
|||
#!/usr/bin/env bash
|
||||
##############################################################
|
||||
#
|
||||
# File: make-html.sh
|
||||
#
|
||||
# Description: creates html version from *.md files
|
||||
#
|
||||
# Usage: source make-hmtl
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
##############################################################
|
||||
|
||||
# check for correct dir
|
||||
if [[ ! ( -f README.html && -f README.md ) ]]; then
|
||||
printf "Error: Can't create html, script must run where README.md and README.html is!\n"
|
||||
|
||||
else
|
||||
# check if pandoc installed
|
||||
if [ "$(type -t pandoc)" != "file" ]; then
|
||||
printf "pandoc not found, skipping html generation ...\n"
|
||||
|
||||
else
|
||||
########
|
||||
# everything seems ok, start html generation
|
||||
printf "Start hmtl conversion "
|
||||
# create dir for html doc and index.html there
|
||||
mkdir html 2>/dev/null
|
||||
cp README.html html/index.html
|
||||
# convert *.md files in doc to *.hmtl in html
|
||||
find doc -iname "*.md" -type f -exec sh -c\
|
||||
'printf "."; pandoc -s -f commonmark -M "title=Bashobot Documentation - ${0%.md}.html" "$0" -o "./html/$(basename ${0%.md}.html)"' {} \;
|
||||
# html for examples dir
|
||||
if [ -d "examples" ]; then
|
||||
EXAMPLES="examples" # add to final conversion job
|
||||
find examples -iname "*.md" -type f -exec sh -c\
|
||||
'printf "."; pandoc -s -f commonmark -M "title=Bashobot Documentation - ${0%.md}.html" "$0" -o "${0%.md}.html"' {} \;
|
||||
fi
|
||||
# final: convert links from *.md to *.html
|
||||
# shellcheck disable=SC2248
|
||||
find README.html html ${EXAMPLES} -iname "*.html" -type f -exec sh -c\
|
||||
'sed -i -E "s/href=\"(\.\.\/)*doc\//href=\"\1html\//g;s/href=\"(.*).md(#.*)*\"/href=\"\1.html\"/g" $0' {} \;
|
||||
printf " Done!\n"
|
||||
fi
|
||||
fi
|
136
dev/make-standalone.sh
Executable file
136
dev/make-standalone.sh
Executable file
|
@ -0,0 +1,136 @@
|
|||
#!/usr/bin/env bash
|
||||
###################################################################
|
||||
#
|
||||
# File: make-standalone.sh
|
||||
#
|
||||
# Description:
|
||||
# even after make-distribution.sh bashbot is not self contained as it was in the past.
|
||||
#
|
||||
# Options: --notest
|
||||
#
|
||||
# If you your bot is finished you can use make-standalone.sh to create the
|
||||
# the old all-in-one bashbot: bashbot.sh and commands.sh only!
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
###################################################################
|
||||
|
||||
# include git config and change to base dir
|
||||
incfile="${0%/*}/dev.inc.sh"
|
||||
#shellcheck disable=SC1090
|
||||
[ -f "${incfile}" ] && source "${incfile}"
|
||||
|
||||
# seems we are not in a dev env
|
||||
if [ -z "${BASE_DIR}" ]; then
|
||||
BASE_DIR="$(pwd)"
|
||||
[[ "${BASE_DIR}" == *"/dev" ]] && BASE_DIR="${BASE_DIR%/*}"
|
||||
# go to basedir
|
||||
cd "${BASE_DIR}" || exit 1
|
||||
fi
|
||||
|
||||
# see if if bashbot is in base dir
|
||||
[ ! -f "bashbot.sh" ] && printf "bashbot.sh not found in %s\n" " $(pwd)" && exit 1
|
||||
|
||||
# run pre_commit if exist
|
||||
[[ -f "dev/dev.inc.sh" && "$1" != "--notest" ]] && dev/hooks/pre-commit.sh
|
||||
|
||||
# files and dirs to copy
|
||||
#DISTNAME="telegram-bot-bash"
|
||||
DISTDIR="./STANDALONE"
|
||||
DISTMKDIR="data-bot-bash logs bin/logs addons"
|
||||
DISTFILES="bashbot.sh commands.sh mycommands.sh modules scripts LICENSE README.* doc addons"
|
||||
DISTBINFILES="bin/bashbot_env.inc.sh bin/bashbot_stats.sh bin/process_batch.sh bin/process_update.sh bin/send_broadcast.sh bin/send_message.sh"
|
||||
|
||||
# add extra files, minimum mycommands.conf
|
||||
extrafile="${BASE_DIR}/dev/${0##*/}.include"
|
||||
[ ! -f "${extrafile}" ] && printf "bashbot.rc\nbotacl\nbotconfig.jssh\nmycommands.conf\ndev/obfuscate.sh\n" >"${extrafile}"
|
||||
DISTFILES+=" $(<"${extrafile}")"
|
||||
|
||||
# create dir for distribution and copy files
|
||||
printf "Create directories and copy files\n"
|
||||
mkdir -p "${DISTDIR}/bin" 2>/dev/null
|
||||
# shellcheck disable=SC2086
|
||||
cp -rp ${DISTFILES} "${DISTDIR}" 2>/dev/null
|
||||
# shellcheck disable=SC2086
|
||||
cp -p ${DISTBINFILES} "${DISTDIR}/bin" 2>/dev/null
|
||||
|
||||
cd "${DISTDIR}" || exit 1
|
||||
|
||||
# remove log files
|
||||
find . -name '*.log' -delete
|
||||
|
||||
# shellcheck disable=SC2250
|
||||
for dir in $DISTMKDIR
|
||||
do
|
||||
[ ! -d "${dir}" ] && mkdir "${dir}"
|
||||
done
|
||||
|
||||
# inject JSON.sh into distribution
|
||||
# shellcheck disable=SC1090
|
||||
source "${BASE_DIR}/dev/inject-json.sh"
|
||||
|
||||
#######################
|
||||
# here the magic starts
|
||||
# create all in one bashbot.sh file
|
||||
|
||||
printf "OK, now lets do the magic ...\n\t... create unified commands.sh\n"
|
||||
|
||||
{
|
||||
# first head of commands.sh
|
||||
sed -n '0,/^if / p' commands.sh | grep -v -F -e "___" -e "*MUST*" -e "mycommands.sh.dist" -e "mycommands.sh.clean"| head -n -2
|
||||
|
||||
# then mycommands from first non comment line on
|
||||
printf '\n##############################\n# my commands starts here ...\n'
|
||||
sed -n '/^$/,$ p' mycommands.sh
|
||||
|
||||
# last tail of commands.sh
|
||||
printf '\n##############################\n# default commands starts here ...\n'
|
||||
sed -n '/source .*\/mycommands.sh"/,$ p' commands.sh | tail -n +2
|
||||
|
||||
} >>$$commands.sh
|
||||
|
||||
mv $$commands.sh commands.sh
|
||||
rm -f mycommands.sh
|
||||
|
||||
printf "\t... create unified bashbot.sh\n"
|
||||
|
||||
{
|
||||
# first head of bashbot.sh
|
||||
sed -n '0,/for module in/ p' bashbot.sh | head -n -3
|
||||
|
||||
# then modules without shebang
|
||||
printf '\n##############################\n# bashbot modules starts here ...\n'
|
||||
# shellcheck disable=SC2016
|
||||
cat modules/*.sh | sed -e 's/^#\!\/bin\/bash.*//' -e '/^#.*\$\$VERSION\$\$/d'
|
||||
|
||||
# last remaining commands.sh
|
||||
printf '\n##############################\n'
|
||||
sed -n '/^# read commands file/,$ p' bashbot.sh
|
||||
|
||||
} >>$$bashbot.sh
|
||||
|
||||
mv $$bashbot.sh bashbot.sh
|
||||
chmod +x bashbot.sh
|
||||
|
||||
rm -rf modules
|
||||
|
||||
printf "Create minimized Version of bashbot.sh and commands.sh\n"
|
||||
# shellcheck disable=SC2016
|
||||
sed -E -e '/(shellcheck)|(^#!\/)|(\$\$VERSION\$\$)/! s/^[[:space:]]*#.*//' -e '/shellcheck/! s/\t+#.*//' -e 's/^[[:space:]]*//'\
|
||||
-e '/^$/d' bashbot.sh | sed 'N;s/\\\n/ /;P;D' | sed 'N;s/\\\n/ /;P;D' > bashbot.sh.min
|
||||
# shellcheck disable=SC2016
|
||||
sed -E -e '/(shellcheck)|(^#!\/)|(\$\$VERSION\$\$)/! s/^[[:space:]]*#.*//' -e '/shellcheck/! s/\t+#.*//' -e 's/^[[:space:]]*//'\
|
||||
-e '/^$/d' commands.sh | sed 'N;s/\\\n/ /;P;D' > commands.sh.min
|
||||
chmod +x bashbot.sh.min
|
||||
|
||||
# make html doc
|
||||
printf "Create html doc\n"
|
||||
#shellcheck disable=SC1090
|
||||
source "${BASE_DIR}/dev/make-html.sh"
|
||||
|
||||
printf "%s Done!\n" "$0"
|
||||
|
||||
cd .. || exit 1
|
||||
|
||||
printf "\nStandalone bashbot files are now available in %s:\n\n" "${DISTDIR}"
|
||||
ls -l "${DISTDIR}"
|
||||
|
5
dev/make-standalone.sh.include
Normal file
5
dev/make-standalone.sh.include
Normal file
|
@ -0,0 +1,5 @@
|
|||
bashbot.rc
|
||||
botacl
|
||||
botconfig.jssh
|
||||
mycommands.conf
|
||||
dev/obfuscate.sh
|
24
dev/obfuscate.sh
Executable file
24
dev/obfuscate.sh
Executable file
|
@ -0,0 +1,24 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# joke hack to obfuscate bashbot.min.sh
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
# shellcheck disable=SC2028,SC2016,SC1117
|
||||
|
||||
infile="bashbot.sh"
|
||||
outfile="./bashbot.obf.sh"
|
||||
|
||||
if [ ! -f "${infile}" ]; then
|
||||
printf "This is a hack to obfuscate %s, run me in STANDALONE after running make-standalone.sh\n" "${infile}"
|
||||
exit 1
|
||||
fi
|
||||
# create gzipped base64 encoded file plus commands to decode
|
||||
{
|
||||
# shellcheck disable=SC2183
|
||||
printf '#!/bin/bash\na="$PWD";cd "$(mktemp -d)"||exit;%s'\
|
||||
'printf '"'$(gzip -9 <"${infile}" | base64)'"'|base64 -d|gunzip >a;export BASHBOT_HOME="$a";chmod +x a;./a "$@";a="$PWD";cd ..;rm -rf "$a"'
|
||||
} >"${outfile}"
|
||||
|
||||
chmod +x "${outfile}"
|
||||
ls -l "${outfile}"
|
||||
printf "Try to run %s init ;-)\n" "${outfile}"
|
|
@ -1,3 +1,5 @@
|
|||
# list of additional files to check from shellcheck
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
bashbot.rc
|
||||
mycommands.conf
|
||||
mycommands.sh.clean
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
# shellcheck disable=SC2016
|
||||
#
|
||||
# Easy Versioning in git:
|
||||
|
@ -34,30 +34,48 @@
|
|||
# run this script to (re)place Version number in files
|
||||
#
|
||||
|
||||
# magic to ensure that we're always inside the root of our application,
|
||||
# no matter from which directory we'll run script
|
||||
GIT_DIR=$(git rev-parse --git-dir)
|
||||
cd "$GIT_DIR/.." || exit 1
|
||||
#shellcheck disable=SC1090
|
||||
source "${0%/*}/dev.inc.sh"
|
||||
|
||||
unset IFS
|
||||
# set -f # if you are paranoid use set -f to disable globbing
|
||||
|
||||
VERSION="$(git describe --tags --long)"
|
||||
echo "Update to version $VERSION ..."
|
||||
printf "Update to version %s ...\n" "${VERSION}"
|
||||
|
||||
FILES="$(find ./*)"
|
||||
[ "$1" != "" ] && FILES="$*"
|
||||
# only regular files, ignore .dot files/dirs, e.g. .git .gitinore in BASEDIR
|
||||
if [ -n "$1" ]; then
|
||||
FILES="$*"
|
||||
else
|
||||
printf "Update version string in all files? (y/N)\b\b"
|
||||
read -r answer
|
||||
[[ "${answer}" != "y" && "${answer}" != "Y" ]] && exit
|
||||
FILES="$(find ./* -type f ! -path "./DIST/*" ! -path "./STANDALONE/*")"
|
||||
fi
|
||||
|
||||
for file in $FILES
|
||||
# autogenerate REMADME.html REMADE.txt
|
||||
if [[ "${FILES}" == *"README.md"* ]]; then
|
||||
FILES+=" README.html README.txt"
|
||||
type -f pandoc >/dev/null && pandoc -s -f commonmark -M "title=Bashbot README" README.md >README.html
|
||||
cat "doc/bashbot.ascii" >"README.txt"
|
||||
if [ -r "README.html" ] && type -f html2text >/dev/null; then
|
||||
# convert html links to text [link]
|
||||
sed -E 's/<a href="([^>]+)">([^<#]+)<\/a>/\2 [\1]/g' <README.html |\
|
||||
html2text -style pretty -width 90 - >>README.txt
|
||||
else
|
||||
type -f fold >/dev/null && fold -s -w 90 README.md >>README.txt
|
||||
fi
|
||||
fi
|
||||
|
||||
# change version string in given files
|
||||
for file in ${FILES}
|
||||
do
|
||||
[ ! -f "$file" ] && continue
|
||||
#[ "$file" == "version" ] && continue
|
||||
echo -n " $file" >&2
|
||||
sed -i 's/^#### $$VERSION$$.*/#### \$\$VERSION\$\$ '"$VERSION"'/' "$file"
|
||||
# symlink is a file :-(
|
||||
[[ -L "${file}" || ! -f "${file}" ]] && continue
|
||||
#[ "${file}" == "version" ] && continue
|
||||
printf "%s" " ${file}" >&2
|
||||
sed -i 's/^#### $$VERSION$$.*/#### \$\$VERSION\$\$ '"${VERSION}"'/' "${file}"
|
||||
done
|
||||
# try to compile README.txt
|
||||
echo -n " README.txt" >&2
|
||||
type -f pandoc >/dev/null && pandoc -s -S -M "title=Bashbot README" README.md >README.html
|
||||
fold -s README.md >README.txt
|
||||
echo " done."
|
||||
|
||||
printf " done.\n"
|
||||
|
||||
|
|
155
doc/0_install.md
155
doc/0_install.md
|
@ -1,67 +1,136 @@
|
|||
#### [Home](../README.md)
|
||||
|
||||
## Check bash installation
|
||||
|
||||
There may systems where bash seems to be installed but it is not (_e.g. embedded systems_) or where bash is to old.
|
||||
Bashbot has some builtin checks but it may better to check before installing bashbot.
|
||||
|
||||
Run the following commands to see if your bash looks ok ...
|
||||
|
||||
```bash
|
||||
# system say bash is there?
|
||||
if which bash; then echo "bash seems available..."; else echo "NO bash"; fi
|
||||
|
||||
# real bash supports ARRAY
|
||||
bash -c 'if eval "a[1]=1"; then echo "Shell support arrays..."; else echo "Shell has NO arrays"; fi'
|
||||
|
||||
# check for bash version by feature
|
||||
bash -c 'if [ "$(LANG=C.UTF-8 echo -e "\u1111")" != "\u1111" ]; then echo "Bash version ok ..."; else echo "Bash version may to old ..."; fi'
|
||||
|
||||
# display bash version, must be greater than 4.3
|
||||
bash --version | grep "bash"
|
||||
```
|
||||
|
||||
## Install bashbot
|
||||
|
||||
1. Go to the directory you want to install bashbot, e.g.
|
||||
* your $HOME directory (install and run with your user-ID)
|
||||
* /usr/local if you want to run as service
|
||||
2. [Download latest release zip from github](https://github.com/topkecleon/telegram-bot-bash/releases) and extract all files.
|
||||
3. Change into the directory ```telegram-bot-bash```
|
||||
4. Create default commands with ```cp commands.sh.dist commands.sh; cp mycommands.sh.dist mycommands.sh```
|
||||
5. Run ```./bashbot.sh init``` to setup the environment and enter your Bots token given by botfather.
|
||||
Installing bashbot is very simple: Download and extract the installation archive.
|
||||
|
||||
1. Choose a directory to install bashbot (_e.g.your HOME or /usr/local_)
|
||||
2. Download [latest release zip / tar archive](https://github.com/topkecleon/telegram-bot-bash/releases/latest) and extract all files.
|
||||
3. Change into the directory `telegram-bot-bash`
|
||||
4. Copy `mycommands.conf.dist` `mycommands.conf`
|
||||
4. Copy `mycommands.sh.dist` or `mycommands.sh.clean` to `mycommands.sh`
|
||||
5. Run `./bashbot.sh init`\* to setup the environment and enter your Bots token given by botfather.
|
||||
|
||||
Edit config in `mycommands.conf` and commands in `mycommands.sh` to fit your need.
|
||||
Now your Bot is ready to start ...
|
||||
|
||||
**If you are new to Bot development read [Bots: An introduction for developers](https://core.telegram.org/bots)**
|
||||
*If you are new to Bot development read [Bots: An introduction for developers](https://core.telegram.org/bots)*
|
||||
|
||||
### Install from Github
|
||||
\* _Run with sudo if you want to run bashbot from different user, e.g. from `bashbot.rc`._
|
||||
|
||||
As an alternative to download the zip files, you can clone the github repository to get the latest improvements/fixes.
|
||||
### Update bashbot
|
||||
|
||||
1. Go to the directory you want to install bashbot, e.g.
|
||||
* your $HOME directory (install and run with your user-ID)
|
||||
* /usr/local if you want to run as service
|
||||
2. Run ```git clone https://github.com/topkecleon/telegram-bot-bash.git```
|
||||
3. Change into the directory ```telegram-bot-bash```
|
||||
4. Run ``` test/ALL-tests.sh``` and if everthing finish OK ...
|
||||
5. Run ```sudo ./bashbot.sh init``` to setup the environment and enter your Bots token given by botfather.
|
||||
Update bashbot is almost identical to installing bashbot: Download and extract the installation archive.
|
||||
|
||||
### Update bashbot
|
||||
**Important: All files may overwritten, make a backup!**
|
||||
|
||||
1. Go to the directory where you had installed bashbot, e.g.
|
||||
* your $HOME directory
|
||||
* /usr/local
|
||||
2. [Download latest release zip from github](https://github.com/topkecleon/telegram-bot-bash/releases)
|
||||
3. Extract all files to your existing bashbot dir
|
||||
**Note: all files execpt 'mycommands.sh' and 'commands.sh' may overwritten!**
|
||||
4. Run ```sudo ./bashbot.sh init``` to setup your environment after the update
|
||||
1. Go to the directory where bashbot is installed (_e.g.$HOME/telegram-bot-bash or /usr/local/telegram-bot-bash_)
|
||||
2. Download [latest release zip / tar archive](https://github.com/topkecleon/telegram-bot-bash/releases/latest)
|
||||
3. Stop all running instances of bashbot `./bashbot.sh stop`
|
||||
4. Change to parent directory of bashbot installation and extract all files from archive.
|
||||
5. Run `./bashbot.sh init`\* to setup your environment after the update
|
||||
6. Restart your bot `./bashbot.sh start`
|
||||
|
||||
### Notes on Updates
|
||||
`mycommands.conf` and `mycommands.sh` will not overwritten, this avoids losing your bot config and commands on updates.
|
||||
|
||||
#### Location of tmp / data dir
|
||||
From version 0.70 on the tmp dir is renamed to 'data-bot-bash' to reflect the fact that not only temporary files are stored. an existing 'tmp-bot-bash' will be automatically renamed after update.
|
||||
*Note*: If you are updating from a pre-1.0 version, update to [Version 1.20](https://github.com/topkecleon/telegram-bot-bash/releases/tags/v1.20) first!
|
||||
|
||||
From version 0.50 on the temporary files are no more placed in '/tmp'. instead a dedicated tmp dir is used.
|
||||
### Use JSON.awk
|
||||
|
||||
#### Changes to send_keyboard in v0.6
|
||||
From Version 0.60 on keybord format for ```send_keyboard``` and ```send_message "mykeyboardstartshere ..."``` was changed.
|
||||
Keybords are now defined in JSON Array notation e.g. "[ \\"yes\\" , \\"no\\" ]".
|
||||
This has the advantage that you can create any type of keyboard supported by Telegram.
|
||||
The old format is supported for backward compatibility, but may fail for corner cases.
|
||||
[JSON.awk](https://github.com/step-/JSON.awk) is an awk port of `JSON.sh`, it provides the same functionality but is 5 times faster.
|
||||
On most systems you can use `JSON.awk` with system default awk installation.
|
||||
( [gnu awk, posix awk, mawk, busybox akw](https://github.com/step-/JSON.awk#compatibility-with-awk-implementations) ).
|
||||
|
||||
*Example Keyboards*:
|
||||
After you have checked that `JSON.awk.dist` is working on your system copy it to `JSON.awk` and (re)start bashbot.
|
||||
|
||||
- yes no in two rows:
|
||||
- OLD format: 'yes' 'no' *(two strings)*
|
||||
- NEW format: '[ "yes" ] , [ "no" ]' *(two arrays with a string)*
|
||||
- new layouts made easy with NEW format:
|
||||
- Yes No in one row: '[ "yes" , "no" ]'
|
||||
- Yes No plus Maybe in 2.row: '[ "yes" , "no" ] , [ "maybe" ]'
|
||||
- numpad style keyboard: '[ "1" , "2" , "3" ] , [ "4" , "5" , "6" ] , [ "7" , "8" , "9" ] , [ "0" ]'
|
||||
BSD and MacOS users must install `gnu awk` and adjust the shebang, see below
|
||||
|
||||
*Note*: To install or update `JSON.awk` manually execute the following commands in the directory `JSON.sh/`:
|
||||
|
||||
wget https://cdn.jsdelivr.net/gh/step-/JSON.awk/JSON.awk
|
||||
wget https://cdn.jsdelivr.net/gh/step-/JSON.awk/tool/patch-for-busybox-awk.sh
|
||||
bash patch-for-busybox-awk.sh
|
||||
chmod +x JSON.awk
|
||||
|
||||
|
||||
### Install bashbot from git repo
|
||||
|
||||
Installation and updates should be done using the zip / tar archives provided on github to avoid
|
||||
problems and not overwriting your bot config and `mycommands.sh`.
|
||||
|
||||
Nevertheless you can install or update bashbot from a git repo, see next chapter ...
|
||||
|
||||
|
||||
### Create Installation / Update archives
|
||||
|
||||
To install or update bashbot from git repo execute `dev/make-distribution.sh`.
|
||||
This creates the installation archives in `DIST/` and a ready to run test installation in `DIST/telegram.bot-bash`.
|
||||
|
||||
*Note:* You should be familiar with `git`.
|
||||
|
||||
1. Run `git clone https://github.com/topkecleon/telegram-bot-bash.git`
|
||||
2. Change into the directory `telegram-bot-bash`
|
||||
3. Optional: Run ` git checkout develop` for latest develop version
|
||||
4. Run ` dev/make-distribution.sh` (_add --notest to skip tests_)
|
||||
5. Change to dir `DIST/`
|
||||
|
||||
Use the installation archives to install or update bashbot as described above.
|
||||
|
||||
To run a test bot, e.g. while development or testing latest changes, you can use the bashbot installation provided in `DIST/telegram-bot-bash`.
|
||||
To update the test installation (_after git pull, local changes or switch master/develop_) run `dev/make-distribution.sh` again.
|
||||
|
||||
|
||||
### Note for BSD and MacOS
|
||||
|
||||
**On MacOS** you must install a more recent version of bash, as the default bash is way to old,
|
||||
see e.g. [Install Bash on Mac](http://macappstore.org/bash/)
|
||||
|
||||
**On BSD and MacOS** I recommend to install gnu coreutils and include them in your PATH
|
||||
environment variable before running bashbot, e.g. the gnu versions of sed, grep, find, awk ...
|
||||
|
||||
On BSD and MacOS you must adjust the shebang line of the scripts `bashbot.sh` and `json.sh` to point to to the correct bash
|
||||
or use the script: `examples/bash2env *.sh */*.sh` to convert them for you.
|
||||
|
||||
Bashbot will stay with `#!/bin/bash` shebang, as using a fixed path is IMHO more secure than the portable '!/usr/bin/env bash` variant.
|
||||
|
||||
Compatibility with BSD/MacOS will result in a rewrite of all grep/sed commands with an uncertain outcome,
|
||||
see [BSD/MacOS vs. GNU sed](https://riptutorial.com/sed/topic/9436/bsd-macos-sed-vs--gnu-sed-vs--the-posix-sed-specification)
|
||||
to get an impression how different they are.
|
||||
|
||||
|
||||
### Notes on Changes
|
||||
|
||||
#### Config moved to mycommands.conf
|
||||
|
||||
From Version 1.30 on config for new bots is moved to `mycommands.conf`.
|
||||
|
||||
#### Support for update from pre-1.0 removed
|
||||
|
||||
From Version 1.21 on updating from a pre-1.0 version (_no \*.jssh config_) is no more supported!
|
||||
You must update to [Version 1.20](https://github.com/topkecleon/telegram-bot-bash/releases/tags/v1.20) first!
|
||||
|
||||
#### [Next Create Bot](1_firstbot.md)
|
||||
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#### [Home](../README.md)
|
||||
## Create a Telegram Bot with botfather
|
||||
## Create a Telegram Bot with Botfather
|
||||
**[BotFather is the one bot to rule them all](https://core.telegram.org/bots#3-how-do-i-create-a-bot). It will help you create new bots and change settings for existing ones.** [Commands known by Botfather](https://core.telegram.org/bots#generating-an-authorization-token)
|
||||
|
||||
### Creating a new Bot
|
||||
|
@ -9,7 +9,7 @@ text: `/newbot`
|
|||
If you don't know how to message by username, click the search
|
||||
field on your Telegram app and type `@botfather`, you should be able
|
||||
to initiate a conversation. Be careful not to send it to the wrong
|
||||
contact, because some users has similar usernames to `botfather`.
|
||||
contact, because there are users with a similar username.
|
||||
|
||||
![botfather initial conversation](http://i.imgur.com/aI26ixR.png)
|
||||
|
||||
|
@ -65,5 +65,5 @@ group. This step is up to you actually.
|
|||
#### [Prev Installation](0_install.md)
|
||||
#### [Next Getting started](2_usage.md)
|
||||
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
|
|
384
doc/2_usage.md
384
doc/2_usage.md
|
@ -1,19 +1,91 @@
|
|||
#### [Home](../README.md)
|
||||
## Gettting Started
|
||||
## Getting Started
|
||||
|
||||
The Bots standard commands are in ```commands.sh``` file. You must not add your commands to 'commands.sh', instead place them in ```mycommands.sh```, there you also find examples how to process messages and send out text. See [Best practices](5_practice.md) for more information.
|
||||
The Bots default commands are in `commands.sh`. Do not edit this file! Instead copy `mycommands.sh.clean` to `mycommands.sh` and place you commands there.
|
||||
Have a look at `mycommands.sh.dist` for examples on how to write commands or overwrite existing ones. See [Best practices](5_practice.md) for more information.
|
||||
|
||||
Once you're done with editing 'mycommands.sh' start the Bot with ```./bashbot.sh start```.
|
||||
To stop the Bot run ```./bashbot.sh kill```
|
||||
Once you're done with editing run the Bot with `./bashbot.sh start`. To stop running the Bot use `./bashbot.sh stop`
|
||||
|
||||
If some thing doesn't work as it should, you can debug with ```./bashbot.sh startbot DEBUG``` where DEBUG can be 'debug', 'xdebug' or 'xdebugx'.
|
||||
If something doesn't work as expected, debug with `./bashbot.sh startbot DEBUG &`, where DEBUG can be 'debug', 'xdebug' or 'xdebugx'.
|
||||
See [Bashbot Development](7_develop.md) for more information.
|
||||
|
||||
To use the functions provided in this script in other scripts simply source bashbot: ```source bashbot.sh```
|
||||
To use the functions provided in this script in other scripts simply source bashbot: `source bashbot.sh source`. see [Expert Use](8_expert.md#Expert-use)
|
||||
|
||||
Have FUN!
|
||||
|
||||
## Managing your own Bot
|
||||
----
|
||||
|
||||
### Files
|
||||
```
|
||||
.
|
||||
├── mycommands.sh # THIS is your bot, place logic and commands here!
|
||||
├── mycommands.conf # place your bot config and bot messages here!
|
||||
│
|
||||
├── mycommands.conf.dist # copy to "mycommands.conf" if not exist
|
||||
├── mycommands.sh.clean # copy to "mycommands.sh" to start developing a new bot
|
||||
├── mycommands.sh.dist # example bot, also used for testing bashbot internally
|
||||
│
|
||||
├── count.jssh # count bashbot usage in jssh key-value store
|
||||
├── blocked.jssh # list of blocked USER[ID] in jssh key-value store
|
||||
│
|
||||
├── bashbot.sh # main bashbot script - DO NOT EDIT!
|
||||
├── commands.sh # command dispatcher - DO NOT EDIT!
|
||||
├── JSON.sh # bashbot JSON parsers
|
||||
│ ├── JSON.sh # sh implementation, https://github.com/dominictarr/JSON.sh
|
||||
│ └── JSON.awk.dist # faster awk version, https://github.com/step-/JSON.awk
|
||||
│
|
||||
├── bin # ready to use scripts, use `scriptname --help` for help
|
||||
│ ├── bashbot_stats.sh # does what it says ...
|
||||
│ ├── send_broadcast.sh # send message to all known chats
|
||||
│ ├── send_message.sh # send message to given chat
|
||||
│ ├── edit_message.sh # replace given message id in given chat
|
||||
│ ├── send_file.sh # send file to given chat
|
||||
│ ├── delete_message.sh # delete given message id in given chat
|
||||
│ ├── send_buttons.sh # send message with attached button
|
||||
│ ├── edit_buttons.sh # attach/edit message buttons
|
||||
│ ├── kickban_user.sh # kick/unban user from given chat
|
||||
│ ├── promote_user.sh # promote/dente user rights in given chat
|
||||
│ │
|
||||
│ ├── bashbot_env.inc.sh # sourced from scripts, adapt locations if needed
|
||||
│ └── bashbot_init.inc.sh # sourced from bashbot.sh init
|
||||
│
|
||||
├── scripts # place your bashbot interactive and background scripts here
|
||||
│ └── interactive.sh.clean # interactive script template for new scripts
|
||||
│
|
||||
├── logs # here you'll find BASHBOT, ERROR, DEBUG and MESSAGE.log
|
||||
│
|
||||
├── modules # optional functions, sourced by commands.sh
|
||||
│ ├── aliases.sh # to disable modules rename them xxx.sh.off
|
||||
│ ├── answerInline.sh
|
||||
│ ├── background.sh # interactive and background functions
|
||||
│ ├── chatMember.sh # manage chat mambers
|
||||
│ ├── jsshDB.sh # read and store JSON.sh style JSON, mandatory
|
||||
│ ├── processUpdates.sh # process updates from telegram, mandatory (run bot)
|
||||
│ └── sendMessage.sh # send message functions, mandatory
|
||||
│
|
||||
├── addons # optional addons, disabled by default
|
||||
│ ├── example.sh # to enable addons change their XXX_ENABLE to true
|
||||
│ └── antiFlood.sh # simple addon taking actions based on # files and text sent to chat
|
||||
│
|
||||
├── bashbot.rc # start/stop script if you run bashbot as service
|
||||
│
|
||||
├── examples # example scripts and configs for bashbot
|
||||
│ ├── README.md # description of files and examples
|
||||
│ ├── bash2env.sh # script to convert shebang to /usr/bin/env, see [Security Considerations](../README.md#Security-Considerations)
|
||||
│ └── bashbot.cron # example crontab
|
||||
│
|
||||
├── doc # Documentation and License
|
||||
├── html
|
||||
├── LICENSE
|
||||
├── README.html
|
||||
├── README.md
|
||||
└── README.txt
|
||||
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
## Managing your Bot
|
||||
#### Note: running bashbot as root is highly danger and not recommended. See Expert use.
|
||||
|
||||
### Start / Stop
|
||||
|
@ -22,96 +94,233 @@ Start or Stop your Bot use the following commands:
|
|||
./bashbot.sh start
|
||||
```
|
||||
```bash
|
||||
./bashbot.sh kill
|
||||
./bashbot.sh stop
|
||||
```
|
||||
|
||||
### User count
|
||||
To count the total number of users that ever used the bot run the following command:
|
||||
### Scripts in bin/
|
||||
Use `script.sh -h` or `script --help` to get short/long help for script.
|
||||
|
||||
To count the total number of users and messages run the following command:
|
||||
|
||||
```bash
|
||||
./bashbot.sh count
|
||||
bin/bashbot_stats.sh
|
||||
```
|
||||
|
||||
### Sending broadcasts to all users
|
||||
To send a broadcast to all of users that ever used the bot run the following command:
|
||||
|
||||
```bash
|
||||
./bashbot.sh broadcast "Hey! I just wanted to let you know that the bot's been updated!"
|
||||
bin/send_broadcast.sh "Hey, I just wanted to let you know that the bot's been updated!"
|
||||
|
||||
Sending broadcast message to all users of Deal_O_Mat_bot
|
||||
DRY RUN! use --doit as first argument to execute broadcast...
|
||||
...
|
||||
Message "Hey, ..." sent to xxx users.
|
||||
```
|
||||
|
||||
## Recieve data
|
||||
Evertime a Message is recieved, you can read incoming data using the following variables:
|
||||
To send a message to one user or chat run the following command:
|
||||
|
||||
### Regular Messages
|
||||
```bash
|
||||
bin/send_message.sh "CHAT[ID]" "Hey, I just wanted to let you know that the bot's been updated!"
|
||||
|
||||
* ```${MESSAGE}```: Current message
|
||||
* ```${MESSAGE[ID]}```: ID of current message
|
||||
* ```$CAPTION```: Captions
|
||||
* ```$REPLYTO```: Original message wich was replied to
|
||||
* ```$USER```: This array contains the First name, last name, username and user id of the sender of the current message.
|
||||
* ```${USER[ID]}```: User id
|
||||
* ```${USER[FIRST_NAME]}```: User's first name
|
||||
* ```${USER[LAST_NAME]}```: User's last name
|
||||
* ```${USER[USERNAME]}```: Username
|
||||
* ```$CHAT```: This array contains the First name, last name, username, title and user id of the chat of the current message.
|
||||
* ```${CHAT[ID]}```: Chat id
|
||||
* ```${CHAT[FIRST_NAME]}```: Chat's first name
|
||||
* ```${CHAT[LAST_NAME]}```: Chat's last name
|
||||
* ```${CHAT[USERNAME]}```: Username
|
||||
* ```${CHAT[TITLE]}```: Title
|
||||
* ```${CHAT[TYPE]}```: Type
|
||||
* ```${CHAT[ALL_MEMBERS_ARE_ADMINISTRATORS]}```: All members are administrators (true if true)
|
||||
* ```$REPLYTO```: This array contains the First name, last name, username and user id of the ORIGINAL sender of the message REPLIED to.
|
||||
* ```${REPLYTO[ID]}```: ID of message wich was replied to
|
||||
* ```${REPLYTO[UID]}```: Original user's id
|
||||
* ```${REPLYTO[FIRST_NAME]}```: Original user's first name
|
||||
* ```${REPLYTO[LAST_NAME]}```: Original user's' last name
|
||||
* ```${REPLYTO[USERNAME]}```: Original user's username
|
||||
* ```$FORWARD```: This array contains the First name, last name, username and user id of the ORIGINAL sender of the FORWARDED message.
|
||||
* ```${FORWARD[ID]}```: Same as MESSAGE[ID] if message is forwarded
|
||||
* ```${FORWARD[UID]}```: Original user's id
|
||||
* ```${FORWARD[FIRST_NAME]}```: Original user's first name
|
||||
* ```${FORWARD[LAST_NAME]}```: Original user's' last name
|
||||
* ```${FORWARD[USERNAME]}```: Original user's username
|
||||
* ```$URLS```: This array contains documents, audio files, voice recordings and stickers as URL.
|
||||
* ```${URLS[AUDIO]}```: Audio files
|
||||
* ```${URLS[VIDEO]}```: Videos
|
||||
* ```${URLS[PHOTO]}```: Photos (maximum quality)
|
||||
* ```${URLS[VOICE]}```: Voice recordings
|
||||
* ```${URLS[STICKER]}```: Stickers
|
||||
* ```${URLS[DOCUMENT]}```: Any other file
|
||||
* ```$CONTACT```: This array contains info about contacts sent in a chat.
|
||||
* ```${CONTACT[ID]}```: User id
|
||||
* ```${CONTACT[NUMBER]}```: Phone number
|
||||
* ```${CONTACT[FIRST_NAME]}```: First name
|
||||
* ```${CONTACT[LAST_NAME]}```: Last name
|
||||
* ```${CONTACT[VCARD]}```: User's complete Vcard
|
||||
* ```$LOCATION```: This array contains info about locations sent in a chat.
|
||||
* ```${LOCATION[LONGITUDE]}```: Longitude
|
||||
* ```${LOCATION[LATITUDE]}```: Latitude
|
||||
* ```$VENUE```: This array contains info about venue (a place) sent in a chat.
|
||||
* ```${VENUE[TITLE]}```: Name of the place
|
||||
* ```${VENUE[ADDRESS]}```: Address of the place
|
||||
* ```${VENUE[LONGITUDE]}```: Longitude
|
||||
* ```${VENUE[LATITUDE]}```: Latitude
|
||||
* ```${VENUE[FOURSQUARE]}```: Fouresquare ID
|
||||
["OK"] "true"
|
||||
["ID"] "12345"
|
||||
```
|
||||
|
||||
To replace a message already sent to one user or chat run the following command:
|
||||
|
||||
```bash
|
||||
bin/edit_message.sh "CHAT[ID]" "12345" "Done!"
|
||||
|
||||
["OK"] "true"
|
||||
["ID"] "12345"
|
||||
```
|
||||
|
||||
To send a file to one user or chat run the following command:
|
||||
|
||||
```bash
|
||||
bin/send_file.sh "CHAT[ID]" "funny-pic.jpg" "enjoy this picture"
|
||||
|
||||
["OK"] "true"
|
||||
["ID"] "12346"
|
||||
```
|
||||
|
||||
Note: to get help about a script in bin/ run `scriptname.sh --help`
|
||||
|
||||
----
|
||||
|
||||
## Receive data
|
||||
Evertime a Telegram update is received, you can read incoming data using the following variables:
|
||||
In case you need other update values, the array `UPD` contains complete Telegram response.
|
||||
|
||||
### Processing Messages
|
||||
|
||||
If an update is received from Telegram, the message is pre processed by Bashbot and the following bash variables are set for use in `mycommands.sh`.
|
||||
|
||||
These variables are always present if a message is pre processed:
|
||||
|
||||
* `${ME}`: Name of your bot
|
||||
* `${BOTADMIN}`: User id of bot administrator
|
||||
|
||||
* `${MESSAGE}`: Current message text
|
||||
* `${MESSAGE[ID]}`: ID of current message
|
||||
* `$USER`: This array contains the First name, last name, username and user id of the sender of the current message.
|
||||
* `${USER[ID]}`: User id
|
||||
* `${USER[FIRST_NAME]}`: User's first name
|
||||
* `${USER[LAST_NAME]}`: User's last name
|
||||
* `${USER[USERNAME]}`: Username
|
||||
* `$CHAT`: This array contains the First name, last name, username, title and user id of the chat of the current message.
|
||||
* `${CHAT[ID]}`: Chat id
|
||||
* `${CHAT[FIRST_NAME]}`: Chat's first name
|
||||
* `${CHAT[LAST_NAME]}`: Chat's last name
|
||||
* `${CHAT[USERNAME]}`: Username
|
||||
* `${CHAT[TITLE]}`: Title
|
||||
* `${CHAT[TYPE]}`: Type
|
||||
* `${CHAT[ALL_MEMBERS_ARE_ADMINISTRATORS]}`: All members are administrators (true if true)
|
||||
|
||||
The following variables are set if the message contains optional parts:
|
||||
|
||||
* `MESSAGE[CAPTION]`: Picture, Audio, Video, File Captions
|
||||
* `MESSAGE[DICE]`: Animated DICE Emoji DICE values is contained in `MESSAGE[RESULT]`
|
||||
* `$REPLYTO`: Original message which was replied to
|
||||
* `$REPLYTO`: This array contains the First name, last name, username and user id of the ORIGINAL sender of the message REPLIED to.
|
||||
* `${REPLYTO[ID]}`: ID of message which was replied to
|
||||
* `${REPLYTO[UID]}`: Original user's id
|
||||
* `${REPLYTO[FIRST_NAME]}`: Original user's first name
|
||||
* `${REPLYTO[LAST_NAME]}`: Original user's' last name
|
||||
* `${REPLYTO[USERNAME]}`: Original user's username
|
||||
* `$FORWARD`: This array contains the First name, last name, username and user id of the ORIGINAL sender of the FORWARDED message.
|
||||
* `${FORWARD[ID]}`: Same as MESSAGE[ID] if message is forwarded
|
||||
* `${FORWARD[UID]}`: Original user's id
|
||||
* `${FORWARD[FIRST_NAME]}`: Original user's first name
|
||||
* `${FORWARD[LAST_NAME]}`: Original user's' last name
|
||||
* `${FORWARD[USERNAME]}`: Original user's username
|
||||
* `$URLS`: This array contains the `path` on Telegram server for files send to chat, e.g. photo, video, audio file.
|
||||
* `${URLS[AUDIO]}`: Path to audio file
|
||||
* `${URLS[VIDEO]}`: Path to video
|
||||
* `${URLS[PHOTO]}`: Path to photo (maximum quality)
|
||||
* `${URLS[VOICE]}`: Path to voice recording
|
||||
* `${URLS[STICKER]}`: Path to sticker
|
||||
* `${URLS[DOCUMENT]}`: Path to any other file
|
||||
**Important:** This is NOT a full URL, you must use `download_file "${URLS[xxx]}"` or prefix path with telegram api url for manual download
|
||||
(_e.g. `getJson "${URL}/${URLS[xxx]}" >file`_).
|
||||
* `$CONTACT`: This array contains info about contacts sent in a chat.
|
||||
* `${CONTACT[ID]}`: User id
|
||||
* `${CONTACT[NUMBER]}`: Phone number
|
||||
* `${CONTACT[FIRST_NAME]}`: First name
|
||||
* `${CONTACT[LAST_NAME]}`: Last name
|
||||
* `${CONTACT[VCARD]}`: User's complete Vcard
|
||||
* `$LOCATION`: This array contains info about locations sent in a chat.
|
||||
* `${LOCATION[LONGITUDE]}`: Longitude
|
||||
* `${LOCATION[LATITUDE]}`: Latitude
|
||||
* `$VENUE`: This array contains info about venue (a place) sent in a chat.
|
||||
* `${VENUE[TITLE]}`: Name of the place
|
||||
* `${VENUE[ADDRESS]}`: Address of the place
|
||||
* `${VENUE[LONGITUDE]}`: Longitude
|
||||
* `${VENUE[LATITUDE]}`: Latitude
|
||||
* `${VENUE[FOURSQUARE]}`: Fouresquare ID
|
||||
|
||||
|
||||
### Service Messages
|
||||
|
||||
Service Messages are updates not itended for end users, instead they signal special events in a chat, e.g. new users.
|
||||
|
||||
If a service message is received bashbot pre processing sets `${MESSAGE}` according to the service message type,
|
||||
e.g. if a new user joins a chat MESSAGE is set to `/_new_chat_user ...`.
|
||||
|
||||
* `$SERVICE`: This array contains info about received service messages.
|
||||
* `${SERVICE}`: "yes" if service message is received
|
||||
* `${SERVICE[NEWMEMBER]}}`: New user's id
|
||||
* `${MESSAGE}`: /_new_chat_member ID NAME
|
||||
* `${NEWMEMBER[ID]}`: New user's id
|
||||
* `${NEWMEMBER[FIRST_NAME]}`: New user's first name
|
||||
* `${NEWMEMBER[LAST_NAME]}`: New user's last name
|
||||
* `${NEWMEMBER[USERNAME]}`: New user's username
|
||||
* `${NEWMEMBER[ISBOT]}`: New user is a bot
|
||||
* `${SERVICE[LEFTMEMBER]}`: Id of user left
|
||||
* `${MESSAGE}`: /_left_chat_member ID NAME
|
||||
* `${LEFTMEMBER[ID]}`: Left user's id
|
||||
* `${LEFTMEMBER[FIRST_NAME]}`: Left user's first name
|
||||
* `${LEFTMEMBER[LAST_NAME]}`: Left user's last name
|
||||
* `${LEFTMEMBER[USERNAME]}`: Left user's username
|
||||
* `${LEFTMEMBER[ISBOT]}`: Left user is a bot
|
||||
* `${SERVICE[NEWTITLE]}`: Text of new title
|
||||
* `${MESSAGE}`: /_new_chat_title SENDER TEXT
|
||||
* `${SERVICE[NEWPHOTO]}`: New Chat Picture
|
||||
* `${MESSAGE}`: /_new_chat_picture SENDER URL
|
||||
**Important:** SERVICE[NEWPHOTO] is NOT a full URL, you must use `download_file "${SERVICE[NEWPHOTO]}"` or prefix path with telegram api url for manual download
|
||||
(_e.g. `getJson "${FILEURL}/${SERVICE[NEWPHOTO]}" >file`_).
|
||||
* `${SERVICE[PINNED]}`: Pinned MESSAGE ID
|
||||
* `${MESSAGE}`: /_new_pinned_message SENDER ID
|
||||
* `${PINNED[ID]}`: Id of pinned message
|
||||
* `${PINNED[MESSAGE]}`: Message text of pinned message
|
||||
* `${SERVICE[MIGRATE]}`: Old and new group id
|
||||
* `${MESSAGE}`: /_migrate_group MIGRATE_FROM MIGRATE_TO
|
||||
* `${MIGRATE[FROM]}`: Old group id
|
||||
* `${MIGRATE[TO]}`: New group id
|
||||
|
||||
|
||||
|
||||
### Inline query messages
|
||||
Inline query messages are special messages for direct interaction with your bot.
|
||||
If an user starts an inline conversation an inline query is sent after each user keystroke.
|
||||
|
||||
To receive inline messages you must set `inline=1` in `mycommands.conf` and in botfather.
|
||||
THe message contatains all characters so far typed from the user.
|
||||
|
||||
An received inline query must be anserwered with `answer_inline_query`, see also (Inline Query)[6_reference.md#inline-query]
|
||||
|
||||
If an inline query is received only the following variables are available:
|
||||
|
||||
* `${iQUERY}`: Inline message typed so far by user
|
||||
* `$iQUERY`: This array contains the ID, First name, last name, username and user id of the sender of the current inline query.
|
||||
* `${iQUERY[ID]}`: Inline query ID
|
||||
* `${iQUERY[USER_ID]}`: User's id
|
||||
* `${iQUERY[FIRST_NAME]}`: User's first name
|
||||
* `${iQUERY[LAST_NAME]}`: User's last name
|
||||
|
||||
|
||||
|
||||
### Callback button messages
|
||||
Callback button messages special messages swend from callback buttons, they contain the following variables only:
|
||||
|
||||
* `$iBUTTON`: This array contains the ID, First name, last name, username and user id of the user clicked on the button
|
||||
* `${iBUTTON[ID]}`: Callback query ID
|
||||
* `${iBUTTON[DATA]`: Data attached to button, hopefully unique
|
||||
* `${iBUTTON[CHAT_ID]`: Chat where button was pressed
|
||||
* `${iBUTTON[MESSAGE_ID]`: Message to which button is attached
|
||||
* `${iBUTTON[MESSAGE]`: Text of message
|
||||
* `${iBUTTON[USER_ID]}`: User's id
|
||||
* `${iBUTTON[FIRST_NAME]}`: User's first name
|
||||
* `${iBUTTON[LAST_NAME]}`: User's last name
|
||||
* `${iBUTTON[USERNAME]}`: User's @username
|
||||
|
||||
|
||||
## Send data / get response
|
||||
|
||||
After every `send_xxx` `get_xxx` call the array BOTSENT contains the most important values from Telegram response.
|
||||
In case you need other response values , the array `UPD` contains complete Telegram response.
|
||||
|
||||
You can use the array values to check if a commands was successful and get returned values from Telegram.
|
||||
|
||||
### BOTSENT array
|
||||
|
||||
* `$BOTSENT`: This array contains the parsed results from the last transmission to telegram.
|
||||
* `${BOTSENT[OK]}`: contains the string `true`: after a successful transmission
|
||||
* `${BOTSENT[ID]}`: Message ID of sent message, image, file etc., if OK is true
|
||||
* `${BOTSENT[FILE_ID]}`: unique identifier returned for an uploaded file or URL
|
||||
* `${BOTSENT[FILE_TYPE]}`: file type: photo, audio, video, sticker, voice, document
|
||||
|
||||
### Inline queries
|
||||
Evertime a Message is recieved, you can read incoming data using the following variables:
|
||||
|
||||
* ```${iQUERY}```: Current inline query
|
||||
* ```$iQUERY```: This array contains the ID, First name, last name, username and user id of the sender of the current inline query.
|
||||
* ```${iQUERY[ID]}```: Inline query ID
|
||||
* ```${iQUERY[USER_ID]}```: User's id
|
||||
* ```${iQUERY[FIRST_NAME]}```: User's first name
|
||||
* ```${iQUERY[LAST_NAME]}```: User's last name
|
||||
|
||||
## Usage of bashbot functions
|
||||
|
||||
#### sending messages
|
||||
To send messages use the ```send_xxx_message``` functions.
|
||||
To send messages use the `send_xxx_message` functions.
|
||||
To insert line brakes in a message place `\n` in the text.
|
||||
|
||||
To send regular text without any markdown use:
|
||||
```bash
|
||||
send_text_message "${CHAT[ID]}" "lol"
|
||||
send_normal_message "${CHAT[ID]}" "lol"
|
||||
```
|
||||
To send text with markdown:
|
||||
```bash
|
||||
|
@ -122,7 +331,7 @@ To send text with html:
|
|||
send_html_message "${CHAT[ID]}" "lol <b>bold</b>"
|
||||
```
|
||||
|
||||
To forward messages use the ```forward``` function:
|
||||
To forward messages use the `forward` function:
|
||||
```bash
|
||||
forward "${CHAT[ID]}" "from_chat_id" "message_id"
|
||||
```
|
||||
|
@ -155,24 +364,25 @@ send_message "${CHAT[ID]}" "lol" "safe"
|
|||
|
||||
|
||||
#### Send files, locations, keyboards.
|
||||
To send images, videos, voice files, photos etc. use the ```send_photo``` function (remember to change the safety Regex @ line 14 of command.sh to allow sending files only from certain directories):
|
||||
To send local files or URL's (photo, video, voice, sticker, documents) use the `send_file` function.
|
||||
```bash
|
||||
send_file "${CHAT[ID]}" "/home/user/doge.jpg" "Lool"
|
||||
send_file "${CHAT[ID]}" "/home/user/dog.jpg" "Lool" "photo"
|
||||
send_file "${CHAT[ID]}" "https://images-na.ssl-images-amazon.com/images/I/81DQ0FpoSNL._AC_SL1500_.jpg"
|
||||
```
|
||||
To send custom keyboards use the ```send_keyboard``` function:
|
||||
To send custom keyboards use the `send_keyboard` function:
|
||||
```bash
|
||||
send_keyboard "${CHAT[ID]}" "Text that will appear in chat?" '[ "Yep" , "No" ]' # note the simgle quotes!
|
||||
send_keyboard "${CHAT[ID]}" "Text that will appear in chat?" "[ \\"Yep\\" , \\"No\\" ]" # within double quotes you must excape the inside double quots
|
||||
send_keyboard "${CHAT[ID]}" "Text that will appear in chat?" '[ "Yep" , "No" ]' # note the single quotes!
|
||||
send_keyboard "${CHAT[ID]}" "Text that will appear in chat?" "[ \\"Yep\\" , \\"No\\" ]" # within double quotes you must escape the inside double quots
|
||||
```
|
||||
To send locations use the ```send_location``` function:
|
||||
To send locations use the `send_location` function:
|
||||
```bash
|
||||
send_location "${CHAT[ID]}" "Latitude" "Longitude"
|
||||
```
|
||||
To send venues use the ```send_venue``` function:
|
||||
To send venues use the `send_venue` function:
|
||||
```bash
|
||||
send_venue "${CHAT[ID]}" "Latitude" "Longitude" "Title" "Address" "optional foursquare id"
|
||||
```
|
||||
To send a chat action use the ```send_action``` function.
|
||||
To send a chat action use the `send_action` function.
|
||||
Allowed values: typing for text messages, upload_photo for photos, record_video or upload_video for videos, record_audio or upload_audio for audio files, upload_document for general files, find_location for locations.
|
||||
```bash
|
||||
send_action "${CHAT[ID]}" "action"
|
||||
|
@ -182,5 +392,5 @@ send_action "${CHAT[ID]}" "action"
|
|||
#### [Prev Create Bot](1_firstbot.md)
|
||||
#### [Next Advanced Usage](3_advanced.md)
|
||||
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
|
|
|
@ -2,11 +2,10 @@
|
|||
## Advanced Features
|
||||
|
||||
### Access control
|
||||
Bashbot offers functions to check what Telegram capabilities like 'chat admin' or 'chat creator' the given user has:
|
||||
Bashbot offers functions to check what Telegram capabilities like `chat admin` or `chat creator` the given user has:
|
||||
|
||||
```bash
|
||||
# return true if user is admin/owner of the bot
|
||||
# -> botadmin is stored in file './botadmin'
|
||||
user_is_botadmin "user"
|
||||
|
||||
# return true if user is creator or admin of a chat
|
||||
|
@ -21,13 +20,15 @@ user_is_botadmin "${USER[ID]}" && send_markdown_message "${CHAT[ID]}" "You are *
|
|||
user_is_admin "${CHAT[ID]}" "${USER[ID]}" && send_markdown_message "${CHAT[ID]}" "You are *CHATADMIN*."
|
||||
|
||||
```
|
||||
In addition you can check individual capabilities of users as you must define in the file ```./botacl```:
|
||||
|
||||
In addition you can check individual capabilities of users as you must define in the file `./botacl`:
|
||||
|
||||
```bash
|
||||
# file: botacl
|
||||
# a user not listed here, will return false from 'user_is_allowed'
|
||||
#
|
||||
# Format:
|
||||
# user:ressource:chat
|
||||
# user:resource:chat
|
||||
|
||||
# allow user 123456789 access to all resources in all chats
|
||||
123456789:*:*
|
||||
|
@ -38,19 +39,30 @@ In addition you can check individual capabilities of users as you must define in
|
|||
# allow user 987654321 only to start bot in chat 98979695
|
||||
987654321:start:98979695
|
||||
|
||||
# special case allow ALL users ONE action in all groups or in one group
|
||||
ALL:search:*
|
||||
ALL:search:98979695
|
||||
|
||||
# not valid, ALL must have an action!
|
||||
ALL:*:*
|
||||
|
||||
# * are only allowed on the right hand side and not for user!
|
||||
# the following exaples are NOT valid!
|
||||
# the following examples are NOT valid!
|
||||
*:*:*
|
||||
*:start:*
|
||||
*:*:98979695
|
||||
|
||||
|
||||
```
|
||||
You must use the function ```user_is_allowed``` to check if a user has the capability to do something. Example: Check if user has capability to start bot.
|
||||
You must use the function `user_is_allowed` to check if a user has the capability to do something. Example: Check if user has capability to start bot.
|
||||
|
||||
```bash
|
||||
case "$MESSAGE" in
|
||||
################################################
|
||||
# GLOBAL commands start here, only edit messages
|
||||
'/start'*)
|
||||
user_is_botadmin "${USER[ID]}" && send_markdown_message "${CHAT[ID]}" "You are *BOTADMIN*."
|
||||
# true if: user is botadmin, user is group admin, user is allowed
|
||||
if user_is_allowed "${USER[ID]}" "start" "${CHAT[ID]}" ; then
|
||||
bot_help "${CHAT[ID]}"
|
||||
else
|
||||
|
@ -61,13 +73,54 @@ You must use the function ```user_is_allowed``` to check if a user has the capab
|
|||
**See also [Bashbot User Access Control functions](6_reference.md#User-Access-Control)**
|
||||
|
||||
### Interactive Chats
|
||||
To create interactive chats, write *(or edit the 'exmaples/question.sh' script)* a bash *(or C or python)* script, make it executable
|
||||
and then use the 'startproc' function to start the script.
|
||||
The output of the script will be sent to the user and user input will be sent to the script.
|
||||
To stop the script use the function 'killprog'
|
||||
Interactive chats are simple Bash scripts, reading user input as TEXT and output TEXT to the user.
|
||||
|
||||
The output of the script will be processed by 'send_messages' to enable you to not only send text, but also keyboards, files, locations and more.
|
||||
Each newline in the output will start an new message to the user, to have line breaks in your message you can use 'mynewlinestartshere'.
|
||||
To create a new interactive chat script copy `scripts/interactive.sh.clean` to e.g. `scripts/mynewinteractive.sh`, make it executable
|
||||
and then use `start_proc` function from your bot, it's possible to pass two arguments. You find more examples for interactive scripts in 'examples'
|
||||
|
||||
**Important**: The script runs standalone in a [pipeline](https://www.geeksforgeeks.org/piping-in-unix-or-linux/), it's **not possible** to use bashbot functions and variables!
|
||||
|
||||
```bash
|
||||
commands.sh send user input as TEXT | script reads TEXT | bashbot.sh recieve output as formated TEXT (see below)
|
||||
```
|
||||
|
||||
In case you want to process any other data then message TEXT, I recommend to switch to a more advanced bot framework.
|
||||
In Bashbot you have to implement methods yourself to pass additional information in the message TEXT to the script.
|
||||
(only recommended for advanced bash experts).
|
||||
|
||||
#### Example script
|
||||
|
||||
*usage*: start_proc chat_id script arg1 arg2
|
||||
|
||||
*usage*: kill_proc chat_id
|
||||
|
||||
*usage*: check_prog chat_id
|
||||
|
||||
|
||||
**Note:** Scripts must read user input from '$3' instead of stdin!
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
######
|
||||
# parameters
|
||||
# $1 $2 args as given to start_proc chat script arg1 arg2
|
||||
# $3 path to named pipe
|
||||
|
||||
#######################
|
||||
# place your commands here
|
||||
#
|
||||
INPUT="${3:-/dev/stdin}" # read from stdin if run in terminal
|
||||
|
||||
echo "Enter a message:"
|
||||
read -r test <"${INPUT}"
|
||||
echo -e "Your Message: ${test}\nbye!"
|
||||
```
|
||||
|
||||
#### message formatting and keyboards
|
||||
|
||||
The output of the script will be processed by `send_messages`, so you can not only send text, but also keyboards, files, locations and more.
|
||||
Each newline in the output will start an new message to the user. To have line breaks in your message you must insert `\n` instead.
|
||||
|
||||
To open up a keyboard in an interactive script, print out the keyboard layout in the following way:
|
||||
```bash
|
||||
|
@ -75,11 +128,14 @@ echo "Text that will appear in chat? mykeyboardstartshere [ \"Yep, sure\" , \"No
|
|||
```
|
||||
Same goes for files:
|
||||
```bash
|
||||
echo "Text that will appear in chat? myfilelocationstartshere /home/user/doge.jpg"
|
||||
echo "Text that will appear in chat? myfilestartshere /home/user/dog.jpg"
|
||||
```
|
||||
*Note*: Use an _absolute path name_ (starting with `/`), a relative path name is relative to `data-bot-bash/upload`!
|
||||
See [send_file documentation](6_reference.md#send_file) for more information.
|
||||
|
||||
And buttons:
|
||||
```bash
|
||||
echo "Text that will appear in chat. mybtextstartshere Klick me myburlstartshere https://dealz.rrr.de"
|
||||
echo "Text that will appear in chat. mybtextstartshere Click me myburlstartshere https://dealz.rrr.de"
|
||||
```
|
||||
And locations:
|
||||
```bash
|
||||
|
@ -91,55 +147,65 @@ echo "Text that will appear in chat. mylatstartshere 45 mylongstartshere 45 myti
|
|||
```
|
||||
You can combine them:
|
||||
```bash
|
||||
echo "Text that will appear in chat? mykeyboardstartshere [ \"Yep, sure\" , \"No, highly unlikely\" ] myfilelocationstartshere /home/user/doge.jpg mylatstartshere 45 mylongstartshere 45"
|
||||
echo "Text that will appear in chat? mykeyboardstartshere [ \"Yep, sure\" , \"No, highly unlikely\" ] myfilestartshere /home/user/doge.jpg mylatstartshere 45 mylongstartshere 45"
|
||||
```
|
||||
Please note that you can either send a location or a venue, not both. To send a venue add the mytitlestartshere and the myaddressstartshere keywords.
|
||||
|
||||
New in v0.6: To insert a linebreak in your message you can insert ```mynewlinestartshere``` in your echo command:
|
||||
To insert a line break in your message you can insert `\n` in your echo command:
|
||||
```bash
|
||||
echo "Text that will appear in one message mynewlinestartshere with this text on a new line"
|
||||
echo "Text that will appear in one message \nwith this text on a new line"
|
||||
```
|
||||
|
||||
New in v0.7: In case you must extend a message already containing a location, a file, a keyboard etc.,
|
||||
with additionial text simply add ``` mytextstartshere additional text``` at the end of the string:
|
||||
In case you want extend a message already containing a location, a file, a keyboard etc.,
|
||||
with an additionial text simply add ` mytextstartshere additional text` at the end of the string:
|
||||
```bash
|
||||
out="Text that will appear mylatstartshere 45 mylongstartshere 45"
|
||||
[[ "$out" != *'in chat'* ]] && out="$out mytextstartshere in chat."
|
||||
echo "$out"
|
||||
```
|
||||
Note: Interactive Chats run independent from main bot and continue running until your script exits or you /cancel if from your Bot.
|
||||
|
||||
### Background Jobs
|
||||
|
||||
A background job is similar to an interactive chat, but runs in the background and does only output massages and does not get user input. In contrast to interactive chats it's possible to run multiple background jobs. To create a background job write a script or edit 'examples/notify.sh' script and use the funtion ```background``` to start it:
|
||||
A background job is similar to an interactive chat, but can be a long running job and does only output massages, user input is ignored.
|
||||
It's possible to run multiple background jobs from the same chat.
|
||||
|
||||
To create a new interactive chat script copy 'scripts/interactive.sh.clean' to e.g. 'scripts/mynewbackground.sh', make it executable
|
||||
and then use 'start_back' function from your bot, it's possible to pass two arguments. You find more examples for background scripts in 'examples'
|
||||
|
||||
*usage*: start_back chat_id script jobname arg1 arg2
|
||||
|
||||
*usage*: kill_back chat_id jobname
|
||||
|
||||
*usage*: check_back chat_id jobname
|
||||
|
||||
```bash
|
||||
background "examples/notify.sh" "jobname"
|
||||
start_back "examples/notify.sh" "${CHAT[ID]}" "jobname"
|
||||
```
|
||||
All output of the script will be sent to the user, to stop a background job use:
|
||||
```bash
|
||||
killback "jobname"
|
||||
kill_back "${CHAT[ID]}" "jobname"
|
||||
```
|
||||
You can also suspend and resume the last running background jobs from outside bashbot, e.g. in your startup schripts:
|
||||
You can also suspend and resume currently running background jobs from outside bashbot, e.g. in your startup scripts:
|
||||
```bash
|
||||
./bashbot.sh suspendback
|
||||
./bashbot.sh resumeback
|
||||
```
|
||||
|
||||
If you want to kill all background jobs permantly run:
|
||||
If you want to kill all background jobs permanently run:
|
||||
```bash
|
||||
./bashbot.sh killback
|
||||
|
||||
```
|
||||
Note: Background Jobs run independent from main bot and continue running until your script exits or you stop if from your Bot. Backgound Jobs will continue running if your Bot is stopeda and must be terminated, e.g. by ```bashbot.sh killback```
|
||||
Note: Background jobs run independent from main bot and continue running until your script exits or you stop it. Background jobs will continue running if your Bot is stopped and must be terminated separately e.g. by `bashbot.sh killback`
|
||||
|
||||
### Inline queries
|
||||
**Inline queries** allow users to send commands to your bot from every chat without going to a private chat. An inline query is started if the user type the bots name, e.g. @myBot. Everything after @myBot is immediatly send to the bot.
|
||||
**Inline queries** allow users to send commands to your bot from every chat without going to a private chat. An inline query is started if the user type the bots name, e.g. @myBot. Everything after @myBot is immediately send to the bot.
|
||||
|
||||
In order to enable **inline mode**, send `/setinline` command to [@BotFather](https://telegram.me/botfather) and provide the placeholder text that the user will see in the input field after typing your bot’s name.
|
||||
|
||||
The following commands allows you to send ansers to *inline queries*. To enable bashbot to process inline queries set ```INLINE="1"``` in 'mycommands.sh'.
|
||||
The following commands allows you to send ansers to *inline queries*. To enable bashbot to process inline queries set `INLINE="1"` in `mycommands.sh`.
|
||||
|
||||
To send messsages or links through an *inline query*:
|
||||
To send messages or links through an *inline query*:
|
||||
```bash
|
||||
answer_inline_query "${iQUERY[ID]}" "article" "Title of the result" "Content of the message to be sent"
|
||||
```
|
||||
|
@ -177,8 +243,77 @@ answer_inline_query "${iQUERY[ID]}" "cached_sticker" "identifier for the sticker
|
|||
```
|
||||
See also [answer_inline_multi, answer_inline_compose](6_reference.md#answer_inline_multi) and [mycommands.sh](../mycommands.sh) for more information.
|
||||
|
||||
|
||||
### Send message results
|
||||
|
||||
Our examples usually do not care about errors happening while sending a message, this is OK as long your bot does not send an
|
||||
massive aoumnt of messages. By default bashbot detects if a message is not sent and try to recover when possible,
|
||||
e.g. resend on throttling. In addition every send error is logged in logs/ERROR.log
|
||||
|
||||
|
||||
#### Transmission results
|
||||
|
||||
On every message send to telegram (transmission) the results are provided in bash variables, like its done when a new message
|
||||
is received.
|
||||
|
||||
**Note**: the values of the variables contains always the result of the LAST transmission to telegram,
|
||||
every send action will overwrite them!
|
||||
|
||||
* `$BOTSENT`: This array contains the parsed results from the last transmission to telegram.
|
||||
* `${BOTSENT[OK]}`: contains the string `true`: after a successful transmission
|
||||
* `${BOTSENT[ID]}`: Message ID if OK is true
|
||||
* `${BOTSENT[ERROR]}`: Error code if an error occurred
|
||||
* `${BOTSENT[DESC]}`: Description text for error
|
||||
* `${BOTSENT[RETRY]}`: Seconds to wait if telegram requests throtteling.
|
||||
* `$res`: temporary variable containing the full transmission result, may be overwritten by any bashbot function.
|
||||
|
||||
By default you don't have to care about retry, as bashbot resend the message after the requested time automatically.
|
||||
Only if the retry fails also an error is returned. The downside is that send_message functions will wait until resend is done.
|
||||
|
||||
If you want to disable automatic error processing and handle all errors manually (or don't care)
|
||||
set `BASHBOT_RETRY` to any no zero value.
|
||||
|
||||
[Telegram Bot API error codes](https://github.com/TelegramBotAPI/errors)
|
||||
|
||||
|
||||
#### Detect bot blocked
|
||||
|
||||
If the we can't connect to telegram, e.g. blocked from telegram server but also any other reason,
|
||||
bashbot set `BOTSENT[ERROR]` to `999`.
|
||||
|
||||
To get a notification on every connection problem create a function named `bashbotBlockRecover` and handle blocks there.
|
||||
If the function returns true (0 or no value) bashbot will retry once and then return to the calling function.
|
||||
In case you return any non 0 value bashbot will return to the calling function without retry.
|
||||
|
||||
Note: If you disable automatic retry, se above, you disable also connection problem notification.
|
||||
|
||||
```bash
|
||||
# somewhere in myfunctions.sh ...
|
||||
MYBLOCKED="0"
|
||||
|
||||
function bashbotBlockRecover() {
|
||||
# ups, we are blocked!
|
||||
(( MYBLOCKED++ ))
|
||||
# log what we got
|
||||
printf "%s: Blocked %d times: %s\n" "$(date)" "${MYBLOCKED}" "$*" >>"${ERRORLOG}"
|
||||
|
||||
if [ "${MYBLOCKED}" -gt 10 ]; then
|
||||
printf "Permanent problem abort current command: %s\n" "${MESSAGE}">>"${ERRORLOG}"
|
||||
exit
|
||||
fi
|
||||
if do_something_to_unblock; then
|
||||
# may be we removed block, e.g. changed IP address, try again
|
||||
return 0
|
||||
fi
|
||||
# do not retry if we can't recover
|
||||
return 1
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
#### [Prev Getting started](2_usage.md)
|
||||
#### [Next Expert Use](4_expert.md)
|
||||
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
|
|
383
doc/4_expert.md
383
doc/4_expert.md
|
@ -5,17 +5,17 @@
|
|||
UTF-8 is a variable length encoding of Unicode. UTF-8 is recommended as the default encoding in JSON, XML and HTML, also Telegram make use of it.
|
||||
|
||||
The first 128 characters are regular ASCII, so it's a superset of and compatible with ASCII environments. The next 1,920 characters need
|
||||
two bytes for encoding and covers almost all ```Latin``` alphabets, also ```Greek```, ```Cyrillic```,
|
||||
```Hebrew```, ```Arabic``` and more. See [Wikipedia](https://en.wikipedia.org/wiki/UTF-8) for more details.
|
||||
two bytes for encoding and covers almost all `Latin` alphabets, also `Greek`, `Cyrillic`,
|
||||
`Hebrew`, `Arabic` and more. See [Wikipedia](https://en.wikipedia.org/wiki/UTF-8) for more details.
|
||||
|
||||
#### Setting up your Environment
|
||||
In general ```bash``` and ```GNU``` utitities are UTF-8 aware if you to setup your environment
|
||||
and your scripts accordingly:
|
||||
In general `bash` and `GNU` utitities are UTF-8 aware if you to setup your environment
|
||||
and your scripts accordingly (_locale setting_):
|
||||
|
||||
1. Your Terminal and Editor must support UTF-8:
|
||||
Set Terminal and Editor locale to UTF-8, eg. in ```Settings/Configuration``` select UTF-8 (Unicode) as Charset.
|
||||
Set Terminal and Editor locale to UTF-8, eg. in `Settings/Configuration` select UTF-8 (Unicode) as Charset.
|
||||
|
||||
2. Set ```Shell``` environment to UTF-8 in your ```.profile``` and your scripts. The usual settings are:
|
||||
2. Set `Shell` locale environment to UTF-8 in your `.profile` and your scripts. The usual settings are:
|
||||
|
||||
```bash
|
||||
export 'LC_ALL=C.UTF-8'
|
||||
|
@ -31,33 +31,88 @@ export 'LANGUAGE=de_DE.UTF-8'
|
|||
```bash
|
||||
export 'LC_ALL=en_US.UTF-8'
|
||||
export 'LANG=de_en_US.UTF-8'
|
||||
export 'LANGUAGE=den_US.UTF-8'
|
||||
export 'LANGUAGE=en_US.UTF-8'
|
||||
```
|
||||
3. make shure your bot scripts use the correct settings, eg. include the lines above at the beginning of your scripts
|
||||
3. make sure your bot scripts use the correct settings, eg. include the lines above at the beginning of your scripts
|
||||
|
||||
To display all availible locales on your system run ```locale -a | more```. [Gentoo Wiki](https://wiki.gentoo.org/wiki/UTF-8)
|
||||
|
||||
#### Known locale pitfalls
|
||||
|
||||
##### Missing C locale
|
||||
|
||||
Even required by POSIX standard some systems (e.g. Manjaro Linux) has `C` and `C.UTF-8` locale not installed.
|
||||
If bashbot display a warning about missing locale you must install `C` and `C.UTF-8` locale.
|
||||
|
||||
If you don't know what locales are installed on your sytsem use `locale -a` to display them.
|
||||
[Gentoo Wiki](https://wiki.gentoo.org/wiki/UTF-8).
|
||||
|
||||
|
||||
##### Character classes
|
||||
|
||||
In ASCII times it was clear `[:lower:]` and `[a-z]` means ONLY the lowercase letters `[abcd...xyz]`.
|
||||
With the introduction of locales, character classes and ranges now contain all characters fitting the class definition.
|
||||
|
||||
This means with a Latin UTF-8 locale `[:lower:]` and `[a-z]` contains also e.g. `á ø ü` etc,
|
||||
see [Unicode Latin lowercase letters](https://www.fileformat.info/info/unicode/category/Ll/list.htm)
|
||||
|
||||
If that's ok for your script you're fine, but many scripts rely on the idea of ASCII ranges and may produce undesired results.
|
||||
|
||||
```bash
|
||||
# try with different locales ...
|
||||
# new bash to not change your current locale!
|
||||
bash
|
||||
lower="abcö"
|
||||
|
||||
echo "$LC_ALL $LC_COLLATE"
|
||||
[[ "$lower" =~ ^[a-z]+$ ]] && echo "Ups, $lower is all lower case!" || echo "OK, not lower case"
|
||||
|
||||
LC_ALL="en_US.UTF-8"
|
||||
[[ "$lower" =~ ^[a-z]+$ ]] && echo "Ups, $lower is all lower case!" || echo "OK, not lower case"
|
||||
|
||||
LC_ALL="C"
|
||||
[[ "$lower" =~ ^[a-z]+$ ]] && echo "Ups, $lower is all lower case!" || echo "OK, not lower case"
|
||||
```
|
||||
|
||||
There are three solutions:
|
||||
|
||||
1. list exactly the characters you want: `[abcd...]`
|
||||
2. instruct bash to use `C` locale for ranges: `shopt -s "globasciiranges"`
|
||||
3. use `LC_COLLATE` to change behavior of all programs: `export LC_COLLATE=C`
|
||||
|
||||
|
||||
To work independent of language and bash settings bashbot uses solution 1.: Own "ranges" if an exact match is mandatory:
|
||||
|
||||
```bash
|
||||
azazaz='abcdefghijklmnopqrstuvwxyz' # a-z :lower:
|
||||
AZAZAZ='ABCDEFGHIJKLMNOPQRSTUVWXYZ' # A-Z :upper:
|
||||
o9o9o9='0123456789' # 0-9 :digit:
|
||||
azAZaz="${azazaz}${AZAZAZ}" # a-zA-Z :alpha:
|
||||
azAZo9="${azAZaz}${o9o9o9}" # a-zA-z0-9 :alnum:
|
||||
|
||||
# e.g. characters allowed for key in key/value pairs
|
||||
JSSH_KEYOK="[-${azAZo9},._]"
|
||||
```
|
||||
|
||||
#### Bashbot UTF-8 Support
|
||||
Bashbot handles all messages transparently, regardless of the charset in use. The only exception is when converting from JSON data to strings.
|
||||
|
||||
Telegram use JSON to send / recieve data. JSON encodes strings as follow: Characters not ASCII *(>127)* are escaped as sequences of ```\uxxxx``` to be regular ASCII. In addition multibyte characters, *e.g. Emoticons or Arabic characters*, are send in double byte UTF-16 notation.
|
||||
The Emoticons ``` 😁 😘 ❤️ 😊 👍 ``` are encoded as: ``` \uD83D\uDE01 \uD83D\uDE18 \u2764\uFE0F \uD83D\uDE0A \uD83D\uDC4D ```
|
||||
Telegram use JSON to send / receive data. JSON encodes strings as follow: Characters not ASCII *(>127)* are escaped as sequences of `\uxxxx` to be regular ASCII. In addition multibyte characters, *e.g. Emoticons or Arabic characters*, are send in double byte UTF-16 notation.
|
||||
The Emoticons ` 😁 😘 ❤️ 😊 👍 ` are encoded as: ` \uD83D\uDE01 \uD83D\uDE18 \u2764\uFE0F \uD83D\uDE0A \uD83D\uDC4D `
|
||||
|
||||
**This "mixed" JSON encoding needs special handling and can not decoded from** ```echo -e``` or ```printf '%s\\n'```
|
||||
**This "mixed" JSON encoding needs special handling and can not decoded from** `echo -e` or `printf '%s\\n'`
|
||||
|
||||
Most complete support for decoding of multibyte characters can only be provided if python is installed on your system.
|
||||
**Without phyton bashbot falls back to an internal, pure bash implementation which may not work for some corner cases**.
|
||||
Bashbot uses an internal, pure bash implementation which is well tested now, even there may some corner cases*.
|
||||
|
||||
|
||||
### Run as other user or system service
|
||||
Bashbot is desingned to run manually by the user who installed it. Nevertheless it's possible to run it by an other user-ID, as a system service or sceduled from cron. This is onyl recommended for experiend linux users.
|
||||
Bashbot is designed to run manually by the user who installed it. Nevertheless it's possible to run it by an other user-ID, as a system service or scheduled from cron. This is recommended if you want to bashbot run as a service.
|
||||
|
||||
Setup the environment for the user you want to run bashbot and enter desired username, e.g. nobody :
|
||||
```bash
|
||||
sudo ./bashbot.sh init
|
||||
```
|
||||
|
||||
Edit the file ```bashbot.rc``` and edit the following lines to fit your configuration:
|
||||
Edit the file `bashbot.rc` and change the following lines to fit your configuration:
|
||||
```bash
|
||||
#######################
|
||||
# Configuration Section
|
||||
|
@ -80,9 +135,9 @@ From now on use 'bashbot.rc' to manage your bot:
|
|||
```bash
|
||||
sudo ./bashbot.rc start
|
||||
```
|
||||
Type ```ps -ef | grep bashbot``` to verify your Bot is running as the desired user.
|
||||
Type `ps -ef | grep bashbot` to verify your Bot is running as the desired user.
|
||||
|
||||
If your Bot is started by 'bashbot.rc', you must use 'bashbot.rc' also to manage your Bot! The following commands are availible:
|
||||
If your Bot is started by 'bashbot.rc', you must use 'bashbot.rc' also to manage your Bot! The following commands are available:
|
||||
```bash
|
||||
sudo ./bashbot.rc start
|
||||
sudo ./bashbot.rc stop
|
||||
|
@ -91,18 +146,294 @@ sudo ./bashbot.rc suspendback
|
|||
sudo ./bashbot.rc resumeback
|
||||
sudo ./bashbot.rc killback
|
||||
```
|
||||
To change back the environment to your user-ID run ```sudo ./bashbot.sh init``` again and enter your user name.
|
||||
To change back the environment to your user-ID run `sudo ./bashbot.sh init` again and enter your user name.
|
||||
|
||||
To use bashbot as a system servive include a working ```bashbot.rc``` in your init system (systemd, /etc/init.d).
|
||||
To use bashbot as a system service include a working `bashbot.rc` in your init system (systemd, /etc/init.d).
|
||||
|
||||
### Scedule bashbot from Cron
|
||||
An example crontab is provided in ```examples/bashbot.cron```.
|
||||
### Schedule bashbot from Cron
|
||||
An example crontab is provided in `examples/bashbot.cron`.
|
||||
|
||||
- If you are running bashbot with your user-ID, copy the examples lines to your crontab and remove username ```nobody```.
|
||||
- if you run bashbot as an other user or a system service edit ```examples/bashbot.cron``` to fit your needs and replace username```nobody``` with the username you want to run bashbot. copy the modified file to ```/etc/cron.d/bashbot```
|
||||
- If you are running bashbot with your user-ID, copy the examples lines to your crontab and remove username `nobody`.
|
||||
- if you run bashbot as an other user or a system service edit `examples/bashbot.cron` to fit your needs and replace username `nobody` with the username you want to run bashbot. Insert the modified lines to systm crontab file or copy to `/etc/cron.d/bashbot`
|
||||
|
||||
#### [Prev Expert Use](4_expert.md)
|
||||
**Warning:** You must use `contab -e` command to modify sytem and user crontabs, see [Cron How-To](https://help.ubuntu.com/community/CronHowto)
|
||||
|
||||
### Use bashbot from CLI and scripts
|
||||
You can use bashbot to send *messages*, *locations*, *venues*, *pictures* etc. from command line and scripts
|
||||
by sourcing it:
|
||||
|
||||
*usage:* . bashbot.sh source
|
||||
|
||||
Before sourcing 'bashbot.sh' for interactive and script use, you should export and set BASHBOT_HOME to bashbots installation dir,
|
||||
e.g. '/usr/local/telegram-bot-bash'. see [Bashbot Environment](#Bashbot-environment)
|
||||
|
||||
**Note:** *If you don't set BASHBOT_HOME bashbot will use the actual directory as NEW home directory
|
||||
which means it will create all needed files and ask for bot token and botadmin if you are not in the real bot home!*
|
||||
|
||||
*Examples:*
|
||||
```bash
|
||||
# if you are in the bashbot directory
|
||||
. bashbot.sh source
|
||||
|
||||
# same, but more readable in scripts
|
||||
source ./bashbot.sh source
|
||||
|
||||
# use bashbot config in BASHBOT_HOME from any directory
|
||||
export BASHBOT_HOME=/usr/local/telegram-bot-bash
|
||||
source ${BASHBOT_HOME}/bashbot.sh source
|
||||
|
||||
# use / create new config in current directory
|
||||
unset BASHBOT_HOME
|
||||
source /path/to/bashbot.sh source
|
||||
|
||||
```
|
||||
|
||||
#### Environment variable exported from bashbot
|
||||
If you have sourced 'bashbot.sh' you have the following bashot internal variables available:
|
||||
```bash
|
||||
COMMANDS # default: ./commands.sh"
|
||||
MODULEDIR # default: ./modules"
|
||||
BOTACL # default: ./botacl"
|
||||
TMPDIR # default: ./data-bot-bash"
|
||||
COUNTFILE # default: ./count" (jsonDB file)
|
||||
|
||||
BOTTOKEN # your token read from bot config
|
||||
URL # telegram api URL - default: https://api.telegram.org/bot${BOTTOKEN}"
|
||||
```
|
||||
|
||||
#### Interactive use
|
||||
For testing your setup or sending messages yourself its possible to use bashbot functions from command line:
|
||||
```bash
|
||||
# are we running bash?
|
||||
echo $SHELL
|
||||
/bin/bash
|
||||
|
||||
# source bashbot.sh WITHOUT BASHBOT_HOME set
|
||||
source ./bashbot.sh source
|
||||
|
||||
# output bashbot internal variables
|
||||
echo $COMMANDS $MODULEDIR $BOTACL $TMPDIR $COUNTFILE
|
||||
./commands.sh ./modules ./botacl ./data-bot-bash ./count
|
||||
|
||||
|
||||
# source bashbot.sh WITH BASHBOT_HOME set
|
||||
export BASHBOT_HOME=/usr/local/telegram-bot-bash
|
||||
source ./bashbot.sh source
|
||||
|
||||
# output bashbot internal variables
|
||||
echo $COMMANDS $MODULEDIR $BOTACL $TMPDIR $COUNTFILE
|
||||
/usr/local/telegram-bot-bash/commands.sh /usr/local/telegram-bot-bash/modules
|
||||
/usr/local/telegram-bot-bash/botacl /usr/local/telegram-bot-bash/data-bot-bash
|
||||
/usr/local/telegram-bot-bash/count
|
||||
|
||||
```
|
||||
After sourcing you can use bashbot functions to send Messages, Locations, Pictures etc. to any Telegram
|
||||
User or Chat you are in. See [Send Messages](2_usage.md#sending-messages).
|
||||
|
||||
*Examples:* You can test this by sending messages to yourself:
|
||||
```bash
|
||||
# first Hello World
|
||||
send_normal_message "$(getConfigKey "botadmin")" "Hello World! This is my first message"
|
||||
|
||||
# now with some markdown and HTML
|
||||
send_markdown_message "$(getConfigKey "botadmin")" '*Hello World!* _This is my first markdown message_'
|
||||
send_html_message "$(getConfigKey "botadmin")" '<b>Hello World!</b> <em>This is my first HTML message</em>'
|
||||
send_keyboard "$(getConfigKey "botadmin")" 'Do you like it?' '[ "Yep" , "No" ]'
|
||||
```
|
||||
Now something more useful ...
|
||||
```bash
|
||||
# sending output from system commands:
|
||||
send_normal_message "$(getConfigKey "botadmin")" "$(date)"
|
||||
|
||||
send_normal_message "$(getConfigKey "botadmin")" "$(uptime)"
|
||||
|
||||
send_normal_message "$(getConfigKey "botadmin")" '`'$(free)'`'
|
||||
|
||||
# same but markdown style 'code' (monospaced)
|
||||
send_markdown_message "$(getConfigKey "botadmin")" "\`$(free)\`"
|
||||
```
|
||||
|
||||
|
||||
### Bashbot environment
|
||||
This section describe how you can customize bashbot to your needs by setting environment variables.
|
||||
|
||||
|
||||
#### Change file locations
|
||||
In standard setup bashbot is self containing, this means you can place 'telegram-bot-bash' any location
|
||||
and run it from there. All files - program, config, data etc - will reside in 'telegram-bot-bash'.
|
||||
|
||||
If you want to have other locations for config, data etc, define and export the following environment variables.
|
||||
**Note: all specified directories and files must exist or running 'bashbot.sh' will fail.**
|
||||
|
||||
##### BASHBOT_ETC
|
||||
Location of the files `commands.sh`, `mycommands.sh`, `botconfig.jssh`, `botacl` ...
|
||||
```bash
|
||||
unset BASHBOT_ETC # keep in telegram-bot-bash (default)
|
||||
export BASHBOT_ETC "" # keep in telegram-bot-bash
|
||||
|
||||
export BASHBOT_ETC "/etc/bashbot" # Unix-like config location
|
||||
|
||||
export BASHBOT_ETC "/etc/bashbot/bot1" # multibot configuration bot 1
|
||||
export BASHBOT_ETC "/etc/bashbot/bot2" # multibot configuration bot 2
|
||||
```
|
||||
|
||||
e.g. /etc/bashbot
|
||||
|
||||
##### BASHBOT_VAR
|
||||
Location of runtime data `data-bot-bash`, `count.jssh`
|
||||
```bash
|
||||
unset BASHBOT_VAR # keep in telegram-bot-bash (default)
|
||||
export BASHBOT_VAR "" # keep in telegram-bot-bash
|
||||
|
||||
export BASHBOT_VAR "/var/spool/bashbot" # Unix-like config location
|
||||
|
||||
export BASHBOT_VAR "/var/spool/bashbot/bot1" # multibot configuration bot 1
|
||||
export BASHBOT_VAR "/var/spool/bashbot/bot2" # multibot configuration bot 2
|
||||
```
|
||||
|
||||
##### BASHBOT_JSONSH
|
||||
Full path to JSON.sh script, default: './JSON.sh/JSON.sh', must end with '/JSON.sh'.
|
||||
```bash
|
||||
unset BASHBOT_JSONSH # telegram-bot-bash/JSON.sh/JSON.sh (default)
|
||||
export BASHBOT_JSONSH "" # telegram-bot-bash/JSON.sh/JSON.sh
|
||||
|
||||
export BASHBOT_JSONSH "/usr/local/bin/JSON.sh" # installed in /usr/local/bin
|
||||
|
||||
```
|
||||
|
||||
##### BASHBOT_HOME
|
||||
Set bashbot home directory, where bashot will look for additional files.
|
||||
If BASHBOT_ETC, BASHBOT_VAR or BASHBOT_JSONSH are set the have precedence over BASHBOT_HOME.
|
||||
|
||||
This is also useful if you want to force bashbot to always use full pathnames instead of relative ones.
|
||||
```bash
|
||||
unset BASHBOT_HOME # autodetection (default)
|
||||
export BASHBOT_HOME "" # autodetection
|
||||
|
||||
export BASHBOT_HOME "/usr/local/telegram-bot-bash" # Unix-like location
|
||||
export BASHBOT_HOME "/usr/local/bin" # Note: you MUST set ETC, VAR and JSONSH to other locations to make this work!
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
#### Change config values
|
||||
|
||||
##### BASHBOT_URL
|
||||
Uses given URL instead of official Telegram API URL, useful if you have your own telegram server or for testing.
|
||||
|
||||
```bash
|
||||
unset BASHBOT_URL # use Telegram URL https://api.telegram.org/bot<token> (default)
|
||||
|
||||
export BASHBOT_URL "" # use use Telegram https://api.telegram.org/bot<token>
|
||||
|
||||
export BASHBOT_URL "https://my.url.com/bot" # use your URL https://my.url.com/bot<token>
|
||||
|
||||
```
|
||||
|
||||
##### BASHBOT_TOKEN
|
||||
If BASHBOT_TOKEN is set, bashbot assumes you know what you are doing and skips environment validation and
|
||||
uses the value of BASHBOT_TOKEN as bot token.
|
||||
|
||||
I recommend to run 'bashbot.sh init' at least one time without BASHBOT_TOKEN set to validate and setup
|
||||
the environment. Afterwards you can delete the token file and provide the bot token in BASHBOT_TOKEN.
|
||||
|
||||
##### BASHBOT_CURL_ARGS
|
||||
The value of BASHBOT_CURL_ARGS is passed to every curl execution.
|
||||
```bash
|
||||
# use socks gateway on localhost
|
||||
export BASHBOT_CURL_ARGS="--socks5-hostname localhost"
|
||||
```
|
||||
|
||||
##### BASHBOT_CURL
|
||||
If BASHBOT_CURL is not set your systems default curl is used. If you want to use an alternative curl executable
|
||||
set BASHBOT_CURL to point to it.
|
||||
```bash
|
||||
# use curl from /usr/local/bin
|
||||
export BASHBOT_CURL="/usr/local/bin/mycurl"
|
||||
```
|
||||
|
||||
##### BASHBOT_WGET
|
||||
Bashbot uses `curl` to communicate with telegram server. if `curl` is not available `wget` is used.
|
||||
If 'BASHBOT_WGET' is set to any value (not undefined or not empty) wget is used even is curl is available.
|
||||
```bash
|
||||
unset BASHBOT_WGET # use curl (default)
|
||||
export BASHBOT_WGET "" # use curl
|
||||
|
||||
export BASHBOT_WGET "yes" # use wget
|
||||
export BASHBOT_WGET "no" # use wget!
|
||||
|
||||
```
|
||||
|
||||
##### BASHBOT_TIMEOUT
|
||||
Bashbot uses a default timeout of 20 seconds for curl and wget. If you want a different timeout, set
|
||||
BASHBOT_TIMEOUT to a numeric value between 1 and 999. Any non numeric or negative value is ignored.
|
||||
```bash
|
||||
# set timeout to 100 seconds
|
||||
export BASHBOT_TIMEOUT="100"
|
||||
|
||||
# 100s is not a numbers
|
||||
export BASHBOT_TIMEOUT="100s" # wrong, default timeout is used
|
||||
|
||||
# -100 is not between 1 and 999s
|
||||
export BASHBOT_TIMEOUT="-100" # wrong, default timeout is used
|
||||
```
|
||||
|
||||
##### BASHBOT_SLEEP
|
||||
Instead of polling permanently or with a fixed delay, bashbot offers a simple adaptive polling.
|
||||
If messages are received bashbot polls with no delay. If no messages are available bashbot add 100ms delay
|
||||
for every poll until the maximum of BASHBOT_SLEEP ms.
|
||||
```bash
|
||||
unset BASHBOT_SLEEP # 5000ms (default)
|
||||
export BASHBOT_SLEEP "" # 5000ms
|
||||
|
||||
export BASHBOT_SLEEP "1000" # 1s maximum sleep
|
||||
export BASHBOT_SLEEP "10000" # 10s maximum sleep
|
||||
export BASHBOT_SLEEP "1" # values < 1000 disables sleep (not recommended)
|
||||
|
||||
```
|
||||
|
||||
#### Tested configs as of v0.90 release
|
||||
|
||||
##### simple Unix like config, for one bot. bashbot is installed in '/usr/local/telegram-bot-bash'
|
||||
```bash
|
||||
# Note: all dirs and files must exist!
|
||||
export BASHBOT_ETC "/etc/bashbot"
|
||||
export BASHBOT_VAR "/var/spool/bashbot"
|
||||
|
||||
/usr/local/telegram-bot-bash/bashbot.sh start
|
||||
```
|
||||
|
||||
##### Unix like config for one bot. bashbot.sh is installed in '/usr/bin'
|
||||
```bash
|
||||
# Note: all dirs and files must exist!
|
||||
export BASHBOT_ETC "/etc/bashbot"
|
||||
export BASHBOT_VAR "/var/spool/bashbot"
|
||||
export BASHBOT_JSONSH "/var/spool/bashbot"
|
||||
|
||||
/usr/local/bin/bashbot.sh start
|
||||
```
|
||||
|
||||
##### simple multibot config, everything is kept inside 'telegram-bot-bash' dir
|
||||
```bash
|
||||
# config for running Bot 1
|
||||
# Note: all dirs and files must exist!
|
||||
export BASHBOT_ETC "./mybot1"
|
||||
export BASHBOT_VAR "./mybot1"
|
||||
|
||||
/usr/local/telegram-bot-bash/bashbot.sh start
|
||||
```
|
||||
|
||||
```bash
|
||||
# config for running Bot 2
|
||||
# Note: all dirs and files must exist!
|
||||
export BASHBOT_ETC "./mybot2"
|
||||
export BASHBOT_VAR "./mybot2"
|
||||
|
||||
/usr/local/telegram-bot-bash/bashbot.sh start
|
||||
```
|
||||
|
||||
#### [Prev Advanced Use](3_advanced.md)
|
||||
#### [Next Best Practice](5_practice.md)
|
||||
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
|
|
|
@ -7,13 +7,15 @@ If you are new to Bot development read [Bots: An introduction for developers](ht
|
|||
|
||||
In addition you should know about [BotFather, the one bot to rule them all](https://core.telegram.org/bots#3-how-do-i-create-a-bot). It will help you create new bots and change settings for existing ones. [Commands known by Botfather](https://core.telegram.org/bots#generating-an-authorization-token)
|
||||
|
||||
If you dont't have a github account, it may time to [sepup a free account now](https://github.com/pricing)
|
||||
If you don't have a github account, it may time to [setup a free account now](https://github.com/pricing)
|
||||
|
||||
### Add commands to mycommands.sh only
|
||||
To ease updates never change ```bashbot.sh```, instead your commands and functions must go to ```mycommands.sh``` . Insert your Bot commands in the ```case ... esac``` block of the 'mycommands()' function:
|
||||
Do not change `bashbot.sh` and `commands.sh`, instead place your commands in to `mycommands.sh`.
|
||||
To start with a clean/minimal bot copy `mycommands.sh.clean` to `mycommands.sh` and start editing
|
||||
the message strings and place commands in the` case ... esac` block of the function mycommands():
|
||||
```bash
|
||||
# file: mycommands.sh
|
||||
# your additional bahsbot commands
|
||||
# your additional bashbot commands
|
||||
|
||||
# uncomment the following lines to overwrite info and help messages
|
||||
bashbot_info='This is *MY* variant of _bashbot_, the Telegram bot written entirely in bash.
|
||||
|
@ -35,50 +37,53 @@ mycommands() {
|
|||
}
|
||||
```
|
||||
|
||||
### Reuse or disable global commands
|
||||
### DIsable, replace and extend global commands
|
||||
|
||||
If you want to disable or reuse a global bashbot command comment it out in 'commands.sh' by placing a '#' in front of
|
||||
every line from ```'/command')``` to ```;;```.
|
||||
Global bashbot command processing, e.g. /start, /info etc. is disabled if you return a non zero value from `mycommands.sh`,
|
||||
see /start example below.
|
||||
|
||||
To replace a global bashbot command add the same command to `mycommands.sh` and place `return 1` at the end of
|
||||
the case block, see /kickme example below.
|
||||
|
||||
If a command is available as a global command and in `mycommands.sh`, plus you return a zero value (nothing or 0)
|
||||
both command sections are processed. Thus you can extend global commands with additional actions, see /info example below
|
||||
|
||||
**Learn more about [Bot commands](https://core.telegram.org/bots#commands).**
|
||||
|
||||
**Note: Never disable the catchall command ```*)``` in 'commands.sh'!!**
|
||||
```bash
|
||||
# file: commands.sh
|
||||
# file: mycommands.sh
|
||||
|
||||
case "$MESSAGE" in
|
||||
################################################
|
||||
# GLOBAL commands start here, edit messages only
|
||||
|
||||
#'/start'*)
|
||||
# send_action "${CHAT[ID]}" "typing"
|
||||
# _is_botadmin && _markdown_message "You are *BOTADMIN*."
|
||||
# if _is_allowed "start" ; then
|
||||
# _markdown_message "${bot_help}"
|
||||
# else
|
||||
# _message "You are not allowed to start Bot."
|
||||
# fi
|
||||
# ;;
|
||||
|
||||
*) # forward other messages to optional dispatcher
|
||||
_is_function startproc && if tmux ls | grep -v send | grep -q "$copname"; then inproc; fi # interactive running
|
||||
_is_function mycommands && mycommands
|
||||
##########
|
||||
# disable start command
|
||||
'/start'*) # disable all commands starting with leave
|
||||
return 1
|
||||
;;
|
||||
# replace command with your own actions
|
||||
'/kickme'*) # this will replace the /kickme command
|
||||
send_markdown_mesage "${CHAT[ID]}" "*This bot will not kick you!*"
|
||||
return 1
|
||||
;;
|
||||
# extend global command
|
||||
'/info'*) # output date in front of regular info
|
||||
send_normal_message "${CHAT[ID]}" "$(date)"
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
```
|
||||
|
||||
|
||||
### Seperate logic from commands
|
||||
### Separate logic from commands
|
||||
|
||||
If a command need more than 2-3 lines of code, you should use a function to seperate logic from command. Place your functions in ```mycommands.sh``` and call the from your command. Example:
|
||||
If a command need more than 2-3 lines of code, you should use a function to separate logic from command. Place your functions in `mycommands.sh` and call the from your command. Example:
|
||||
```bash
|
||||
# file: mycommands.sh
|
||||
# your additional bahsbot commands
|
||||
# your additional bashbot commands
|
||||
|
||||
mycommands() {
|
||||
|
||||
case "$MESSAGE" in
|
||||
'/process'*) # logic for /process is done in process_message
|
||||
'/doit'*) # logic for /doit is done in process_message
|
||||
result="$(process_message "$MESSAGE")"
|
||||
send_normal_message "${CHAT[ID]}" "$result"
|
||||
;;
|
||||
|
@ -128,7 +133,9 @@ Line 17:
|
|||
^-- SC2116: Useless echo? Instead of 'cmd $(echo foo)', just use 'cmd foo'.
|
||||
|
||||
```
|
||||
As you can see my ```mybotcommands.inc.sh``` contains an useless echo command in 'TEXT=' assigment and can be replaced by ```TEXT="${TEXT}${WORD}"```
|
||||
|
||||
As you can see my `mybotcommands.inc.sh` contains an useless echo command in 'TEXT=' assignment and can be replaced by `TEXT="${TEXT}${WORD}"`
|
||||
|
||||
```bash
|
||||
$ shellcheck -x examples/notify
|
||||
OK
|
||||
|
@ -147,11 +154,11 @@ In bashbot.sh line 490:
|
|||
CONTACT[USER_ID]="$(sed -n -e '/\["result",'$PROCESS_NUMBER',"message","contact","user_id"\]/ s/.*\][ \t]"\(.*\)"$/\1/p' <"$TMP")"
|
||||
^-- SC2034: CONTACT appears unused. Verify it or export it.
|
||||
```
|
||||
The example show two warnings in bashbots scripts. The first is a hint you may use shell substitions instead of sed, this is fixed and much faster as the "echo | sed" solution.
|
||||
The example show two warnings in bashbots scripts. The first is a hint you may use shell substitutions instead of sed, this is fixed and much faster as the "echo | sed" solution.
|
||||
The second warning is about an unused variable, this is true because in our examples CONTACT is not used but assigned in case you want to use it :-)
|
||||
|
||||
#### [Prev Best Practice](5_practice.md)
|
||||
#### [Next Functions Reference](6_reference.md)
|
||||
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
|
|
1375
doc/6_reference.md
1375
doc/6_reference.md
File diff suppressed because it is too large
Load Diff
344
doc/7_develop.md
344
doc/7_develop.md
|
@ -1,91 +1,348 @@
|
|||
#### [Home](../README.md)
|
||||
|
||||
## Notes for bashbot developers
|
||||
This section is about help and best practices for new bashbot developers. The main focus on is creating new versions of bashbot, not on develop your individual bot. Nevertheless the rules and tools described here can also help you with your bot development.
|
||||
This section is about help and best practices for new bashbot developers. The main focus on is creating new versions of bashbot, modules and addons, not on developing your individual bot. Nevertheless the information provided here should also help you with your bot development.
|
||||
|
||||
bashbot development is done on github. If you want to provide fixes or new features [fork bashbot on githup](https://help.github.com/en/articles/fork-a-repo) and provide changes as [pull request on github](https://help.github.com/en/articles/creating-a-pull-request).
|
||||
If you want to provide fixes or new features [fork bashbot on github](https://help.github.com/en/articles/fork-a-repo) and provide changes as [pull request on github](https://help.github.com/en/articles/creating-a-pull-request).
|
||||
|
||||
### Debugging Bashbot
|
||||
Usually all bashbot output is discarded.
|
||||
If you want to get error messages (and more) start bashbot `./bashbot.sh startbot debug`.
|
||||
you can the change the level of verbosity of the debug argument:
|
||||
|
||||
### Debuging Bashbot
|
||||
In normal mode of operation all bashbot output is discarded one more correct sent to TMUX console.
|
||||
To get these messages (and more) you can start bashbot in the current shell ```./bashbot.sh startbot```. Now you can see all output or erros from bashbot.
|
||||
In addition you can change the change the level of verbosity by adding a third argument after startbot.
|
||||
```
|
||||
"debug" redirects all output to "DEBUG.log", in addtion every update is logged in "MESSAGE.LOG" and "INLINE.log"
|
||||
"debugterm" same as debug but output and errors are sent to terminal
|
||||
|
||||
"xdebug" same as debug plus set bash option '-x' to log any executed command
|
||||
"xdebugterm" same as xdebug but output and errors are sent to terminal
|
||||
"debug" all output is redirected to `DEBUG.log`, in addition every incoming message is logged in `MESSAGE.log` and `INLINE.log`
|
||||
"xdebug" same as debug plus set bash option '-x' to log any executed command in `DEBUG.log`
|
||||
```
|
||||
|
||||
Use the command `tail` to watch your bot live, e.g. `tail -f DEBUG.log`. To obtain more information place `set -x; ... set +x` around suspected code.
|
||||
|
||||
Sometimes it's useful to watch the bot live in the terminal:
|
||||
|
||||
```
|
||||
"debugx" debug output and errors are sent to terminal
|
||||
"xdebugx" same as debugx plus set bash option '-x' to show any executed command
|
||||
```
|
||||
|
||||
Logging of Telegram update poll is disabled by default, also in `debug` mode. To enable it without using verbose `xdebug` mode
|
||||
set `BASHBOT_UPDATELOG` to an empty value (not unset) `export BASHBOT_UPDATELOG=""`
|
||||
|
||||
### Modules and Addons
|
||||
**Modules** resides in `modules/*.sh` and are colletions of optional bashbot functions grouped by functionality. Main reason for creating modules was
|
||||
to keep 'bashbot.sh' small, while extending functionality. In addition not every function is needed by all bots, so you can
|
||||
disable modules, e.g. by rename the respective module file to 'module.sh.off'.
|
||||
|
||||
Modules must use only functions provided by 'bashbot.sh' or the module itself and should not depend on other modules or addons.
|
||||
The only mandatory module is 'module/sendMessage.sh'.
|
||||
|
||||
If an optional module is used in 'bashbot.sh' or 'commands.sh', the use of `_is_function` or
|
||||
`_execute_if_function` is mandatory to catch absence of the module.
|
||||
|
||||
**Addons** resides in `addons/*.sh.dist` and are not enabled by default. To activate an addon rename it to end with '.sh', e.g. by
|
||||
`cp addons/example.sh.dist addons/example.sh`.
|
||||
|
||||
Addons must register themself to BASHBOT_EVENTS at startup, e.g. to call a function every time a message is received.
|
||||
Addons works similar as 'commands.sh' and 'mycommands.sh' but are much more flexible on when functions/commands are triggered.
|
||||
|
||||
Another major difference is: While regular command processing is done in a new sub shell for every command,
|
||||
**Addons are executed in the context of bashbot event loop!**, This is why event functions are (time) critical
|
||||
and must return as fast as possible. **If an event function call exit, also bashbot exits!**
|
||||
|
||||
*Important*: Spawn a new sub shell in background for your processing commands and when calling bashbot functions, e.g. send_messages.
|
||||
This prevents blocking or exiting bashbots event loop.
|
||||
|
||||
#### Bashbot Events
|
||||
|
||||
Addons must register functions to bashbot events by providing their name, and internal identifier and a callback function.
|
||||
If an event occurs each registered function for the event is called.
|
||||
|
||||
Registered functions run in the same process as bashbot, not as a sub process, so variables set here are persistent as long bashbot is running.
|
||||
|
||||
Note: For the same reason event function MUST return immediately! Time consuming tasks must be run as a background process, e.g. "long running &"
|
||||
|
||||
##### SEND RECEIVE events
|
||||
|
||||
A RECEIVE event is executed when a Message is received, same iQuery / Message variables are available as in commands.sh
|
||||
|
||||
* `BASHBOT_EVENT_INLINE` an inline query is received
|
||||
* `BASHBOT_EVENT_MESSAGE` any of the following message types is received
|
||||
* `BASHBOT_EVENT_TEXT` a message containing text is received
|
||||
* `BASHBOT_EVENT_CMD` a message containing a command is received (starts with /)
|
||||
* `BASHBOT_EVENT_REPLYTO` a reply to a message is received
|
||||
* `BASHBOT_EVENT_FORWARD` a forwarded message is received
|
||||
* `BASHBOT_EVENT_CONTACT` a contact is received
|
||||
* `BASHBOT_EVENT_LOCATION` a location or a venue is received
|
||||
* `BASHBOT_EVENT_FILE` a file is received
|
||||
|
||||
*usage*: BASHBOT_EVENT_xxx[ "unique-name" ]="callback"
|
||||
|
||||
"unique-name" can be every alphanumeric string incl. '-' and '_'. Per convention the name of the addon followed by an internal identyfier should be used.
|
||||
|
||||
"callback" is called as the the parameters "event" "unique-name" "debug", where "event" is the event name in lower case, e.g. inline, messagei, text ... ,
|
||||
and "unique-name" is the name provided when registering the event.
|
||||
|
||||
*Example:* Register a function to echo to any Text sent to the bot
|
||||
|
||||
```bash
|
||||
# register callback:
|
||||
BASHBOT_EVENT_TEXT["example_1"]="example_echo"
|
||||
|
||||
# function called if a text is received
|
||||
example_echo() {
|
||||
local event="$1" key="$2"
|
||||
# all available bashbot functions and variables can be used
|
||||
send_normal_message "${CHAT[ID]}" "Event: ${event} Key: ${key} : ${MESSAGE[0]}" & # run in background!
|
||||
|
||||
( MYTEXT="${MESSAGE[0]}"
|
||||
do_more_processing
|
||||
) & # run as sub shell in background!
|
||||
}
|
||||
```
|
||||
|
||||
An SEND event is executed when a Message is send to telegram.
|
||||
|
||||
* `BASHBOT_EVENT_SEND` is executed if data is send or uploaded to Telegram server
|
||||
|
||||
In contrast to other events, BASHBOT_EVENT_SEND is executed in a sub shell, so there is no need to spawn
|
||||
a background process for longer running commands and changes to variables are not persistent!
|
||||
|
||||
BASHBOT_EVENT_SEND is for logging purposes, you must not send messages while processing this event.
|
||||
To avoid wrong use of EVENT_SEND, e.g. fork bomb, event processing is suspended if recursion is detected.
|
||||
|
||||
*usage*: BASHBOT_EVENT_SEND[ "unique-name" ]="callback"
|
||||
|
||||
"callback" is called with parameter "send" or "upload", followed by the arguments used for 'sendJson' or 'upload' functions.
|
||||
|
||||
*Example:*
|
||||
```bash
|
||||
# register callback:
|
||||
BASHBOT_EVENT_SEND["example_log","1"]="example_log"
|
||||
EXAMPLE_LOG="${BASHBOT_ETC:-.}/addons/${EXAMPLE_ME}.log"
|
||||
|
||||
# Note: do not call any send message functions from EVENT_SEND!
|
||||
example_log(){
|
||||
local send="$1"; shift
|
||||
echo "$(date): Type: ${send} Args: $*" >>"${EXAMPLE_LOG}"
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
##### TIMER events
|
||||
|
||||
Important: Bashbot timer tick is disabled by default and must be enabled by setting BASHBOT_START_TIMER to any value not zero.
|
||||
|
||||
* `BASHBOT_EVENT_TIMER` is executed every minute and can be used in 3 variants: oneshot, once a minute, every X minutes.
|
||||
|
||||
Registering to BASHBOT_EVENT_TIMER works similar as for message events, but you must add a timing argument to the name.
|
||||
EVENT_TIMER is triggered every 60s and waits until the current running command is finished, so it's not exactly every
|
||||
minute, but once a minute.
|
||||
|
||||
Every time EVENT_TIMER is triggered the variable "EVENT_TIMER" is increased. each callback is executed if `EVENT_TIMER % time` is '0' (true).
|
||||
This means if you register an every 5 minutes callback first execution may < 5 Minutes, all subsequent executions are once every 5. Minute.
|
||||
|
||||
*usage:* BASHBOT_EVENT_TIMER[ "name" , "time" ], where time is:
|
||||
|
||||
* 0 ignored
|
||||
* 1 execute once every minute
|
||||
* x execute every x minutes
|
||||
* -x execute once WITHIN the next x Minutes (next 10 Minutes since start "event")
|
||||
|
||||
Note: If you want exact "in x minutes" use "EVENT_TIMER" as reference: `(EVENT_TIMER +x)`
|
||||
|
||||
*Example:*
|
||||
```bash
|
||||
# register callback:
|
||||
BASHBOT_EVENT_TIMER["example_every","1"]="example_everymin"
|
||||
|
||||
# function called every minute
|
||||
example_everymin() {
|
||||
# timer events has no chat id, so send to yourself
|
||||
send_normal_message "$(< "${BOTADMIN})" "$(date)" & # note the &!
|
||||
}
|
||||
|
||||
# register other callback:
|
||||
BASHBOT_EVENT_TIMER["example_every5","5"]="example_every5min"
|
||||
|
||||
# execute once on the next 10 minutes since start "event"
|
||||
BASHBOT_EVENT_TIMER["example_10min","-10"]="example_in10min"
|
||||
|
||||
# once in exact 10 minutes, note the -
|
||||
BASHBOT_EVENT_TIMER["example_10min","-$(( EVENT_TIMER+10 ))"]="example_in10min"
|
||||
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
#### Create a stripped down version of your Bot
|
||||
Currently bashbot is more a bot development environment than a bot, containing examples, developer scripts, modules, documentation and more.
|
||||
You don't need all these files after you're finished with your cool new bot.
|
||||
|
||||
Let's create a stripped down version:
|
||||
|
||||
- delete all modules you do not need from `modules`, e.g. `modules/inline.sh` if you don't use inline queries
|
||||
- delete unused standard commands and messages from `commands.sh`
|
||||
- delete unused commands and functions from `mycommands.sh`
|
||||
- run `dev/make-standalone.sh` to create a a stripped down version of your bot
|
||||
|
||||
Now have a look at the directory `standalone`, here you find the files `bashbot.sh` and `commands.sh` containing everything to run your bot.
|
||||
[Download make-standalone.sh](https://github.com/topkecleon/telegram-bot-bash/blob/master/dev/make-standalone.sh) from github.
|
||||
|
||||
### Setup your develop environment
|
||||
|
||||
1. install git, install [shellcheck](5_practice.md#Test-your-Bot-with-shellcheck)
|
||||
1. install the commands git [shellcheck](5_practice.md#Test-your-Bot-with-shellcheck) bc pandoc zip codespell
|
||||
2. setup your [environment for UTF-8](4_expert.md#Setting-up-your-Environment)
|
||||
3. clone your bashbot fork to a new directory ```git clone https://github.com/<YOURNAME>/telegram-bot-bash.git```, replace ```<YOURNAME>``` with your username on github
|
||||
4. create and change to your develop branch ```git checkout -b <YOURBRANCH>```, replace ```<YOURBRANCH>``` with the name you want to name it, e.g. 'develop'
|
||||
5. give your (dev) fork a new version tag: ```git tag vx.xx```(optional)
|
||||
6. setup github hooks by running ```dev/install-hooks.sh``` (optional)
|
||||
3. clone your bashbot fork to a new directory `git clone https://github.com/<YOURNAME>/telegram-bot-bash.git`, replace `<YOURNAME>` with your username on github
|
||||
4. create and change to your develop branch `git checkout -b develop`
|
||||
5. give your (dev) fork a new version tag: `git tag v1.xx`
|
||||
6. setup github hooks by running `dev/install-hooks.sh`
|
||||
|
||||
### Test, Add, Push changes
|
||||
Run `dev/make-distribution.sh` to create installation archives and a test installation in `DIST/`.
|
||||
To update the test installation, e.g. after git pull, local changes or switch master/develop, run `dev/make-distribution.sh` again.
|
||||
|
||||
Note for Debian: Debian Buster ships older versions of many utilities, pls try to install from [buster-backports](https://backports.debian.org/Instructions/)
|
||||
```bash
|
||||
sudo apt-get -t buster-backports install git shellcheck pandoc codespell curl
|
||||
```
|
||||
|
||||
#### Test, Add, Push changes
|
||||
A typical bashbot develop loop looks as follow:
|
||||
|
||||
1. start developing - *change, copy, edit bashbot files ...*
|
||||
2. after changing a bash sript: ```shellcheck -x scipt.sh```
|
||||
3. ```dev/all-tests.sh``` - *in case if errors back to 2.*
|
||||
4. ```dev/git-add.sh``` - *check for changed files, update version string, run git add*
|
||||
5. ```git commit -m "COMMIT MESSAGE"; git push```
|
||||
2. after changing a bash script: `shellcheck -x script.sh`
|
||||
3. `dev/all-tests.sh` - *in case if errors back to 2.*
|
||||
4. `dev/git-add.sh` - *check for changed files, update version string, run git add*
|
||||
5. `git commit -m "COMMIT MESSAGE"; git push`
|
||||
|
||||
|
||||
**If you setup your dev environment with hooks and use the scripts above, versioning, addding and testing is done automatically.**
|
||||
**If you setup your dev environment with hooks and use the scripts above, versioning, adding and testing is done automatically.**
|
||||
|
||||
### Prepare a new version
|
||||
#### common commands
|
||||
We state bashbot is a bash only bot, but this is not true. bashbot is a bash script using bash features PLUS external commands.
|
||||
Usually bash is used in a Linux/Unix environment where many (GNU) commands are available, but if commands are missing, bashbot may not work.
|
||||
|
||||
To avoid this and make bashbot working on as many platforms as possible - from embedded Linux to mainframe - I recommend to restrict
|
||||
ourself to the common commands provided by bash and coreutils/busybox/toybox.
|
||||
See [Bash Builtins](https://www.gnu.org/software/bash/manual/html_node/Shell-Builtin-Commands.html),
|
||||
[coreutils](https://en.wikipedia.org/wiki/List_of_GNU_Core_Utilities_commands),
|
||||
[busybox](https://en.wikipedia.org/wiki/BusyBox#Commands) and [toybox](https://landley.net/toybox/help.html)
|
||||
|
||||
Available commands in bash, coreutils, busybox and toybox. Do you find curl on the list?
|
||||
```bash
|
||||
.*, [*, [[*, basename, break, builtin*, bzcat, caller*, cat, cd*, chattr,
|
||||
chgrp, chmod, chown, clear, command*, continue *, cp, cut, date, declare*,
|
||||
dc, dd, df, diff, dirname, du, echo*, eval*, exec*, exit *, expr*, find,
|
||||
fuser, getopt*, grep, hash*, head, hexdump, id, kill, killall, last, length,
|
||||
less, let*, ln, local*, logname, ls, lsattr, lsmod, man, mapfile*, md5sum, mkdir,
|
||||
mkfifo, mknod, more, mv, nice, nohup, passwd, patch, printf*, ps, pwd*, read*,
|
||||
readarray*, readonly* return*, rm, rmdir, sed, seq, sha1sum, shift*, sleep,
|
||||
source*, sort, split, stat, strings, su, sync, tail, tar, tee, test,
|
||||
time, times*, timeout, touch, tr, trap*, true, umask*, usleep, uudecode,
|
||||
uuencode, wc, wget, which, who, whoami, xargs, yes
|
||||
```
|
||||
commands marked with \* are bash builtins, all others are external programs. Calling an external program is more expensive then using bulitins
|
||||
or using an internal replacement. Here are some tipps for using builtins.:
|
||||
```bash
|
||||
HOST="$(hostname)" -> HOST="$HOSTNAME"
|
||||
|
||||
DIR="$(pwd)" -> DIR="$PWD""
|
||||
|
||||
seq 1 100 -> {0..100}
|
||||
|
||||
data="$(cat file)" -> data="$(<"file")"
|
||||
|
||||
DIR="$(dirname $0) -> DIR="${0%/*}"
|
||||
|
||||
date -> printf"%(%c)T\n" -1 # 100 times faster!
|
||||
|
||||
PROG="($basename $0)" -> PROG="${0##*/}*
|
||||
|
||||
ADDME="$ADDME something to add" -> ADDME+=" something to add""
|
||||
|
||||
VAR="$(( 1 + 2 ))" -> (( var=1+2 ))
|
||||
|
||||
INDEX="$(( ${INDEX} + 1 ))" -> (( INDEX++ ))
|
||||
```
|
||||
For more examples see [Pure bash bible](https://github.com/dylanaraps/pure-bash-bible)
|
||||
|
||||
The special variable `$_` stores the expanded __last__ argument of the previous command.
|
||||
This allows a nice optimisation in combination with the no-op command `:`, but be aware of `$_` pitfalls.
|
||||
|
||||
```bash
|
||||
# $_ example: mkdir plus cd to it
|
||||
mkdir "somedir-$$" && cd "$_" # somedir-1234 (process id)
|
||||
|
||||
# manipulate a variable multiple times without storing intermediate results
|
||||
foo="1a23_b__x###"
|
||||
...
|
||||
: "${foo//[0-9]}" # a_b__x###
|
||||
: "${_%%#*}" # a_b__x
|
||||
bar="${_/__x/_c}" # a_b_c
|
||||
|
||||
|
||||
# BE AWARE OF ...
|
||||
# pitfall missing quotes: $_ is LAST arg
|
||||
: ${SOMEVAR} # "String in var" $_ -> "var"
|
||||
: $(<"file") # "Content of\n file" $_ -> "file"
|
||||
|
||||
# pitfall [ vs. test command
|
||||
[ -n "xxx" ] && echo "$_" # $_ -> "]"
|
||||
test -n "xxx" && echo "$_" # $_ -> "xxx"
|
||||
|
||||
# pitfall command substitution: globbing and IFS is applied!
|
||||
: "$(echo "a* is born")"# $_ -> a* is globbed even quoted!
|
||||
: "$(echo "a b c")"# $_ -> "a b c"
|
||||
: "$(<"file")" # "Content of\n file" $_ -> "Content of file"
|
||||
```
|
||||
|
||||
#### Prepare a new version
|
||||
After some development it may time to create a new version for the users. a new version can be in sub version upgrade, e.g. for fixes and smaller additions or
|
||||
a new release version for new features. To mark a new version use ```git tag NEWVERSION``` and run ```dev/version.sh``` to update all version strings.
|
||||
a new release version for new features. To mark a new version use `git tag NEWVERSION` and run `dev/version.sh` to update all version strings.
|
||||
|
||||
Usually I start with pre versions and when everything looks good I push out a release candidate (rc) and finally the new version.
|
||||
```
|
||||
v0.x-devx -> v0.x-prex -> v0.x-rc -> v0.x ... 0.x+1-dev ...
|
||||
```
|
||||
|
||||
### Versioning
|
||||
If you release a new Version run `dev/make-distribution.sh` to create the zip and tar.gz archives in the dist directory and attach them to the github release. Do not forget to delete directory dist afterwards.
|
||||
|
||||
#### Versioning
|
||||
|
||||
Bashbot is tagged with version numbers. If you start a new development cycle you can tag your fork with a version higher than the current version.
|
||||
E.g. if you fork 'v0.60' the next develop version should tagged as ```git tag "v0.61-dev"``` for fixes or ```git tag "v0.70-dev"``` for new features.
|
||||
E.g. if you fork 'v0.60' the next develop version should tagged as `git tag "v0.61-dev"` for fixes or `git tag "v0.70-dev"` for new features.
|
||||
|
||||
To get the current version name of your develepment fork run ```git describe --tags```. The output looks like ```v0.70-dev-6-g3fb7796``` where your version tag is followed by the number of commits since you tag your branch and followed by the latest commit hash. see also [comments in version.sh](../dev/version.sh)
|
||||
To get the current version name of your develepment fork run `git describe --tags`. The output looks like `v0.70-dev-6-g3fb7796` where your version tag is followed by the number of commits since you tag your branch and followed by the latest commit hash. see also [comments in version.sh](../dev/version.sh)
|
||||
|
||||
To update the Version Number in files run ```dev/version.sh files```, it will update the line '#### $$VERSION$$ ###' in all files to the current version name.
|
||||
To update the Version Number in files run `dev/version.sh files`, it will update the line '#### $$VERSION$$ ###' in all files to the current version name.
|
||||
To update version in all files run 'dev/version.sh' without parameter.
|
||||
|
||||
|
||||
### Shellcheck
|
||||
#### Shellcheck
|
||||
|
||||
For a shell script running as a service it's important to be paranoid about quoting, globbing and other common problems. So it's a must to run shellchek on all shell scripts before you commit a change. this is automated by a git hook activated in Setup step 6.
|
||||
|
||||
To run shellcheck for a single script run ```shellcheck -x script.sh```, to check all schripts run ```dev/hooks/pre-commit.sh```.
|
||||
To run shellcheck for a single script run `shellcheck -x script.sh`, to check all scripts run `dev/hooks/pre-commit.sh`.
|
||||
|
||||
|
||||
## bashbot tests
|
||||
Starting with version 0.70 bashbot has a test suite. To start testsuite run ```dev/all-tests.sh```. all-tests.sh will return 'SUCCESS' only if all tests pass.
|
||||
### bashbot test suite
|
||||
Starting with version 0.70 bashbot has a test suite. To start the test suite run `dev/all-tests.sh`. all-tests.sh will return 'SUCCESS' if ALL tests pass.
|
||||
|
||||
### enabling / disabling tests
|
||||
#### enabling / disabling tests
|
||||
|
||||
All tests are placed in the directory ```test```. To disable a test remove the execute flag from the '*-test.sh' script, to (re)enable a test make the script executable again.
|
||||
All tests are placed in the directory `test`. To disable a test remove the execute flag from the '*-test.sh' script, to (re)enable a test make the script executable again.
|
||||
|
||||
|
||||
### creating new tests
|
||||
To create a new test run ```test/ADD-test-new.sh``` and answer the questions, it will create the usually needed files and dirs:
|
||||
#### creating new tests
|
||||
To create a new test run `test/ADD-test-new.sh` and answer the questions, it will create the usually needed files and dirs:
|
||||
|
||||
Each test consists of a script script named after ```p-name-test.sh``` *(where p is test pass 'a-z' and name the name
|
||||
of your test)* and an optional dir ```p-name-test/``` *(script name minus '.sh')* for additional files.
|
||||
Each test consists of a script script named after `p-name-test.sh` *(where p is test pass 'a-z' and name the name
|
||||
of your test)* and an optional dir `p-name-test/` *(script name minus '.sh')* for additional files.
|
||||
|
||||
Tests with no dependency to other tests will run in pass 'a', tests which need an initialized bahsbot environment must run in pass 'd' or later.
|
||||
Tests with no dependency to other tests will run in pass 'a', tests which need an initialized bashbot environment must run in pass 'd' or later.
|
||||
A temporary test environment is created when 'ALL-tests.sh' starts and deleted after all tests are finished.
|
||||
|
||||
The file ```ALL-tests.inc.sh``` must be included from all tests and provide the test environment as shell variables:
|
||||
The file `ALL-tests.inc.sh` must be included from all tests and provide the test environment as shell variables:
|
||||
```bash
|
||||
# Test Evironment
|
||||
# Test Environment
|
||||
TESTME="$(basename "$0")"
|
||||
DIRME="$(pwd)"
|
||||
TESTDIR="$1"
|
||||
|
@ -100,7 +357,7 @@ The file ```ALL-tests.inc.sh``` must be included from all tests and provide the
|
|||
ADMINFILE="botadmin"
|
||||
DATADIR="data-bot-bash"
|
||||
|
||||
# SUCCESS NOSUCCES -> echo "${SUCCESS}" or echo "${NOSUCCESS}"
|
||||
# SUCCESS NOSUCCESS -> echo "${SUCCESS}" or echo "${NOSUCCESS}"
|
||||
SUCCESS=" OK"
|
||||
NOSUCCESS=" FAILED!"
|
||||
|
||||
|
@ -129,7 +386,6 @@ fi
|
|||
```
|
||||
|
||||
#### [Prev Function Reference](6_reference.md)
|
||||
#### [Next Bashbot Environment](8_custom.md)
|
||||
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
|
|
121
doc/8_custom.md
121
doc/8_custom.md
|
@ -1,121 +0,0 @@
|
|||
#### [Home](../README.md)
|
||||
## Customize bashbots environment
|
||||
This section describe how you can customize bashbot to your needs by setting environment variables.
|
||||
|
||||
|
||||
### Change file locations
|
||||
In standard setup bashbot is self containing, this means you can place 'telegram-bot-bash' any location
|
||||
and run it from there. All files - programm, config, data etc - will reside in 'telegram-bot-bash'.
|
||||
|
||||
If you want to have other locations for config, data etc, define and export the following environment variables.
|
||||
**Note: all specified directories and files must exist or running 'bashbot.sh' will fail.**
|
||||
|
||||
#### BASHBOT_ETC
|
||||
Location of the files ```commands.sh```, ```mycommands.sh```, ```token```, ```botadmin```, ```botacl``` ...
|
||||
```bash
|
||||
unset BASHBOT_ETC # keep in telegram-bot-bash (default)
|
||||
export BASHBOT_ETC "" # keep in telegram-bot-bash
|
||||
|
||||
export BASHBOT_ETC "/etc/bashbot" # unix like config location
|
||||
|
||||
export BASHBOT_ETC "/etc/bashbot/bot1" # multibot configuration bot 1
|
||||
export BASHBOT_ETC "/etc/bashbot/bot2" # multibot configuration bot 2
|
||||
```
|
||||
|
||||
e.g. /etc/bashbot
|
||||
|
||||
#### BASHBOT_VAR
|
||||
Location of runtime data ```data-bot-bash```, ```count```
|
||||
```bash
|
||||
unset BASHBOT_VAR # keep in telegram-bot-bash (default)
|
||||
export BASHBOT_VAR "" # keep in telegram-bot-bash
|
||||
|
||||
export BASHBOT_VAR "/var/spool/bashbot" # unix like config location
|
||||
|
||||
export BASHBOT_VAR "/var/spool/bashbot/bot1" # multibot configuration bot 1
|
||||
export BASHBOT_VAR "/var/spool/bashbot/bot2" # multibot configuration bot 2
|
||||
```
|
||||
|
||||
#### BASHBOT_JSONSH
|
||||
Full path to JSON.sh script, default: './JSON.sh/JSON.sh', must end with '/JSON.sh'.
|
||||
```bash
|
||||
unset BASHBOT_JSONSH # telegram-bot-bash/JSON.sh/JSON.sh (default)
|
||||
export BASHBOT_JSONSH "" # telegram-bot-bash/JSON.sh/JSON.sh
|
||||
|
||||
export BASHBOT_JSONSH "/usr/local/bin/JSON.sh" # installed in /usr/local/bin
|
||||
|
||||
```
|
||||
|
||||
### Change config values
|
||||
|
||||
#### BASHBOT_DECODE
|
||||
Bashbot offers two variants for decoding JSON UTF format to UTF-8. By default bashbot uses 'json.encode' if python is installed.
|
||||
If 'BASHBOT_DECODE' is set to any value (not undefined or not empty) the bash only implementation will be used.
|
||||
```bash
|
||||
unset BASHBOT_DECODE # autodetect python (default)
|
||||
export BASHBOT_DECODE "" # autodetect python
|
||||
|
||||
export BASHBOT_DECODE "yes" # force internal
|
||||
export BASHBOT_DECODE "no" # also force internal!
|
||||
```
|
||||
|
||||
|
||||
#### BASHBOT_SLEEP
|
||||
Instead of polling permanently or with a fixed delay, bashbot offers a simple adaptive polling.
|
||||
If messages are recieved bashbot polls with no dealy. If no messages are availible bashbot add 100ms delay
|
||||
for every poll until the maximum of BASHBOT_SLEEP ms.
|
||||
```bash
|
||||
unset BASHBOT_SLEEP # 5000ms (default)
|
||||
export BASHBOT_SLEEP "" # 5000ms
|
||||
|
||||
export BASHBOT_SLEEP "1000" # 1s maximum sleep
|
||||
export BASHBOT_SLEEP "10000" # 10s maximum sleep
|
||||
export BASHBOT_SLEEP "1" # values < 1000 disables sleep (not recommended)
|
||||
|
||||
```
|
||||
|
||||
### Testet configs as of v.07 release
|
||||
**Note: Environment variables are not stored, you must setup them before every call to bashbot.sh, e.g. from a script.**
|
||||
|
||||
#### simple Unix like config, for one bot. bashbot is installed in '/usr/local/telegram-bot-bash'
|
||||
```bash
|
||||
# Note: all dirs and files must exist!
|
||||
export BASHBOT_ETC "/etc/bashbot"
|
||||
export BASHBOT_VAR "/var/spool/bashbot"
|
||||
|
||||
/usr/local/telegram-bot-bash/bashbot.sh start
|
||||
```
|
||||
|
||||
#### Unix like config for one bot. bashbot.sh is installed in '/usr/bin'
|
||||
```bash
|
||||
# Note: all dirs and files must exist!
|
||||
export BASHBOT_ETC "/etc/bashbot"
|
||||
export BASHBOT_VAR "/var/spool/bashbot"
|
||||
export BASHBOT_JSONSH "/var/spool/bashbot"
|
||||
|
||||
/usr/local/bin/bashbot.sh start
|
||||
```
|
||||
|
||||
#### simple multibot config, everything is keept inside 'telegram-bot-bash' dir
|
||||
```bash
|
||||
# config for running Bot 1
|
||||
# Note: all dirs and files must exist!
|
||||
export BASHBOT_ETC "./mybot1"
|
||||
export BASHBOT_VAR "./mybot1"
|
||||
|
||||
/usr/local/telegram-bot-bash/bashbot.sh start
|
||||
```
|
||||
|
||||
```bash
|
||||
# config for running Bot 2
|
||||
# Note: all dirs and files must exist!
|
||||
export BASHBOT_ETC "./mybot2"
|
||||
export BASHBOT_VAR "./mybot2"
|
||||
|
||||
/usr/local/telegram-bot-bash/bashbot.sh start
|
||||
```
|
||||
|
||||
#### [Prev Notes for Developers](7_develop.md)
|
||||
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
|
22
doc/bashbot.ascii
Normal file
22
doc/bashbot.ascii
Normal file
|
@ -0,0 +1,22 @@
|
|||
|
||||
..
|
||||
****
|
||||
****oooooo*****
|
||||
*****ooooooooooooo*****
|
||||
*****oooooooooooooooooooooo****
|
||||
****oooooooooooooooooooooooooooooooo**
|
||||
*.*oooooooooooooooooooooooooooooooooooo**
|
||||
*.ooooooooooooooooooooooooooooooooo**....
|
||||
*.oooooooooooooooooooooooooooo**.........
|
||||
*.oooooooooooooooooooooooo**.............
|
||||
*.ooooooooooooooooooo**.................. ____ _ _ _
|
||||
*.ooooooooooooooooo*.......,............. | _ \ | | | | | |
|
||||
*.ooooooooooooooooo*.....,***,........... | |_) | __ _ ___ | |__ | |__ ___ | |_
|
||||
*.ooooooooooooooooo*....o*............... | _ < / _` |/ __|| '_ \ | '_ \ / _ \ | __|
|
||||
*.ooooooooooooooooo*....*o***,........... | |_) || (_| |\__ \| | | || |_) || (_) || |_
|
||||
*.*oooooooooooooooo*........o*.....oo.... |____/ \__,_||___/|_| |_||_.__/ \___/ \__|
|
||||
****ooooooooooooo*....`***....oo.....*
|
||||
*****oooooooo*......*..oo.....**
|
||||
******ooo*.............*
|
||||
***o*........**
|
||||
**...**
|
|
@ -17,10 +17,10 @@ Two examples for interactive scripts are provided as **calc.sh** and **question.
|
|||
Background jobs are an easy way to provide sceduled messages or alerts if something happens.
|
||||
**notify.sh** is a simple example on how to send a message every x seonds, e.g. current time.
|
||||
|
||||
**background-scripts** contains a more useful example on how to start and stop different scripts plus some example backgound scripts.
|
||||
**background-scripts** contains a more useful example on how to start and stop different scripts plus some example background scripts.
|
||||
|
||||
```
|
||||
mycommands.sh - /run_xxx and /kill-xxx wil start any script named run_xxx.sh
|
||||
mycommands.sh - /run_xxx and /kill-xxx will start any script named run_xxx.sh
|
||||
|
||||
run_diskusage.sh - shows disk usage every 100 seconds
|
||||
run_filename.sh - shown the name of new files in a named dir
|
||||
|
@ -40,7 +40,7 @@ convert existing bots.
|
|||
mycommands.sh - commands to show system status
|
||||
botacl - controls who can show system status
|
||||
|
||||
*Availiable commands*:
|
||||
*Available commands*:
|
||||
/se *sensors*
|
||||
/smb *smbstatus*
|
||||
/free *memory status*
|
||||
|
@ -51,10 +51,15 @@ convert existing bots.
|
|||
/ifconfig *ifconfig output*
|
||||
/smart *sda* _smart status for sda drive_
|
||||
```
|
||||
### External scripts
|
||||
### jsonDB and Keyboards
|
||||
|
||||
**external-use** will contain some examples on how to send messages from external scripts to Telegram chats or users.
|
||||
**jsonDB-keybords** contains a stripped down real world example from my bot showing the usage of jsonDB to store and retrieve values
|
||||
plus use of keyboards in private chats. It's an extended version of mycommands.sh.dist. Messages and help are in german.
|
||||
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
### Webhook
|
||||
|
||||
**Webhook** contains instructions on how use webhook API to get updates from telegram instead polling Telegram server.
|
||||
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
|
||||
|
|
|
@ -3,15 +3,15 @@
|
|||
# copy to mycommands.sh and add all your commands an functions here ...
|
||||
export res
|
||||
|
||||
# your additional bahsbot commands ...
|
||||
# your additional bashbot commands ...
|
||||
mycommands() {
|
||||
|
||||
case "$MESSAGE" in
|
||||
case "${MESSAGE}" in
|
||||
'/run_'*)
|
||||
myback="run_${MESSAGE#*_}"
|
||||
if [ -x "./${myback}.sh" ]; then
|
||||
checkback "${myback}"
|
||||
if [ "$res" -gt 0 ] ; then
|
||||
if [ "${res}" -gt 0 ] ; then
|
||||
send_normal_message "${CHAT[ID]}" "Start ${myback}, use /kill${myback} to stop it."
|
||||
background "./${myback}.sh" "${myback}"
|
||||
else
|
||||
|
@ -23,7 +23,7 @@ mycommands() {
|
|||
myback="run_${MESSAGE#*_}"
|
||||
if [ -x "./${myback}.sh" ]; then
|
||||
checkback "${myback}"
|
||||
if [ "$res" -eq 0 ] ; then
|
||||
if [ "${res}" -eq 0 ] ; then
|
||||
killback "${myback}"
|
||||
send_normal_message "${CHAT[ID]}" "Stopping ${myback}, use /run_${myback} to start again."
|
||||
else
|
||||
|
@ -36,12 +36,6 @@ mycommands() {
|
|||
|
||||
# place your additional processing functions here ...
|
||||
|
||||
# returns true if function exist
|
||||
_is_function()
|
||||
{
|
||||
[ "$(LC_ALL=C type -t "$1")" = "function" ]
|
||||
}
|
||||
|
||||
# inifnite loop for waching a given dir for new files
|
||||
# $1 dir to wtach for new files
|
||||
watch_dir_loop() {
|
||||
|
@ -62,7 +56,7 @@ watch_dir_loop() {
|
|||
echo "$(date): new file: ${newfile}" >>"$0.log"
|
||||
# note: loop callback must a function in the calling script!
|
||||
if _is_function loop_callback ; then
|
||||
loop_callback "$1/$newfile"
|
||||
loop_callback "$1/${newfile}"
|
||||
else
|
||||
echo "ERROR: loop_callback not found!" >&2
|
||||
exit 1
|
||||
|
@ -76,7 +70,7 @@ output_telegram() {
|
|||
sed <<< "${1}" -e ':a;N;$!ba;s/\n/ mynewlinestartshere /g'
|
||||
} # 2>>"$0.log"
|
||||
|
||||
# name and localtion of the tml file
|
||||
# name and location of the tml file
|
||||
|
||||
# $1 string to output
|
||||
# $2 file to add file to
|
||||
|
@ -100,8 +94,8 @@ output_file() {
|
|||
sed <<< "${1}" '
|
||||
s/ *mynewlinestartshere */\n/
|
||||
s/ my[a-z]\{3,15}\(start\|ends\)here.*//g
|
||||
' >"$publish$$"
|
||||
cat "$publish" >>"$publish$$"
|
||||
' >"${publish}$$"
|
||||
cat "${publish}" >>"${publish}$$"
|
||||
mv "${publish}$$" "${publish}"
|
||||
} # >>"$0.log" 2>&1
|
||||
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
#!/bin/bash
|
||||
# file: run_diskcusage.sh
|
||||
# file: run_diskusage.sh
|
||||
# example for an background job display a system value
|
||||
|
||||
#
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
######
|
||||
# parameters
|
||||
# $1 $2 args as given to starct_proc chat script arg1 arg2
|
||||
# $3 path to named pipe/log
|
||||
|
||||
|
||||
# adjust your language setting here
|
||||
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
|
||||
|
@ -18,11 +24,12 @@ unset IFS
|
|||
# discard STDIN for background jobs!
|
||||
cat >/dev/null &
|
||||
|
||||
# shellcheck source=examples/background-scripts/mycommands.sh
|
||||
source "./mycommands.sh"
|
||||
|
||||
# check if $1 is a number
|
||||
re='^[0-9]+$'
|
||||
if [[ $1 =~ $re ]] ; then
|
||||
regex='^[0-9]+$'
|
||||
if [[ $1 =~ ${regex} ]] ; then
|
||||
SLEEP="$1"
|
||||
else
|
||||
SLEEP=100 # time between time notifications
|
||||
|
@ -30,13 +37,13 @@ fi
|
|||
|
||||
NEWLINE=$'\n'
|
||||
|
||||
# output disk usgae every $1 seconds
|
||||
# output disk usage every $1 seconds
|
||||
WAIT=0
|
||||
while sleep $WAIT
|
||||
while sleep "${WAIT}"
|
||||
do
|
||||
output_telegram "Current Disk usage ${NEWLINE} $(df -h / /tmp /usr /var /home)"
|
||||
# only for testing, delete echo line for production ...
|
||||
echo "Current Disk usage ${NEWLINE} $(df -h / /tmp /usr /var /home)"
|
||||
WAIT="$SLEEP"
|
||||
WAIT="${SLEEP}"
|
||||
done
|
||||
|
||||
|
|
|
@ -2,7 +2,13 @@
|
|||
# file: run_filename
|
||||
# background job to display content of all new files in WATCHDIR
|
||||
#
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
######
|
||||
# parameters
|
||||
# $1 $2 args as given to starct_proc chat script arg1 arg2
|
||||
# $3 path to named pipe/log
|
||||
|
||||
|
||||
# adjust your language setting here
|
||||
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
|
||||
|
@ -16,8 +22,10 @@ unset IFS
|
|||
# discard STDIN for background jobs!
|
||||
cat >/dev/null &
|
||||
|
||||
# watch for new files created by a trusted programm
|
||||
# watch for new files created by a trusted program
|
||||
WATCHDIR="/my_trusted/dir_to_watch"
|
||||
|
||||
# shellcheck source=examples/background-scripts/mycommands.sh
|
||||
source "./mycommands.sh"
|
||||
|
||||
# test your script and the remove ...
|
||||
|
@ -32,4 +40,4 @@ loop_callback() {
|
|||
output_telegram "Contents of ${1}: ${NEWLINE} $(cat "${1}")"
|
||||
}
|
||||
|
||||
watch_dir_loop "$WATCHDIR"
|
||||
watch_dir_loop "${WATCHDIR}"
|
||||
|
|
|
@ -2,7 +2,13 @@
|
|||
# file: run_filename
|
||||
# background job to display all new files in WATCHDIR
|
||||
#
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
######
|
||||
# parameters
|
||||
# $1 $2 args as given to starct_proc chat script arg1 arg2
|
||||
# $3 path to named pipe/log
|
||||
|
||||
|
||||
# adjust your language setting here
|
||||
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
|
||||
|
@ -13,11 +19,13 @@ export 'LANGUAGE=C.UTF-8'
|
|||
unset IFS
|
||||
# set -f # if you are paranoid use set -f to disable globbing
|
||||
|
||||
# discard STDIN for background jobs!
|
||||
# shellcheck source=examples/background-scripts/mycommands.sh
|
||||
cat >/dev/null &
|
||||
|
||||
# watch for new logfiles
|
||||
WATCHDIR="/var/log"
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
source "./mycommands.sh"
|
||||
|
||||
# test your script and the remove ...
|
||||
|
@ -30,4 +38,5 @@ loop_callback() {
|
|||
echo "New file ${1} created in ${WATCHDIR}!"
|
||||
}
|
||||
|
||||
watch_dir_loop "$WATCHDIR"
|
||||
watch_dir_loop "${WATCHDIR}"
|
||||
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
#!/bin/bash
|
||||
# file: notify.sh
|
||||
# example for an background job, run with startback notify.sh
|
||||
|
||||
#
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
######
|
||||
# parameters
|
||||
# $1 $2 args as given to starct_proc chat script arg1 arg2
|
||||
# $3 path to named pipe/log
|
||||
|
||||
|
||||
# adjust your language setting here
|
||||
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
|
||||
|
@ -19,15 +25,15 @@ unset IFS
|
|||
cat >/dev/null &
|
||||
|
||||
# check if $1 is a number
|
||||
re='^[0-9]+$'
|
||||
if [[ $1 =~ $re ]] ; then
|
||||
regex='^[0-9]+$'
|
||||
if [[ "$1" =~ ${regex} ]] ; then
|
||||
SLEEP="$1"
|
||||
else
|
||||
SLEEP=10 # time between time notifications
|
||||
fi
|
||||
|
||||
# output current time every $1 seconds
|
||||
while sleep $SLEEP
|
||||
while sleep "${SLEEP}"
|
||||
do
|
||||
date "+* It's %k:%M:%S o' clock ..."
|
||||
done
|
||||
|
|
80
examples/bash2env.sh
Executable file
80
examples/bash2env.sh
Executable file
|
@ -0,0 +1,80 @@
|
|||
#!/usr/bin/env bash
|
||||
# file: bash2env.sh
|
||||
# simole helper script to convert bash shebang from
|
||||
# ! /bin/bash TO ! /usr/bin/env bash
|
||||
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
# shellcheck disable=SC1117
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
# adjust your language setting here
|
||||
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
|
||||
export 'LC_ALL=C.UTF-8'
|
||||
export 'LANG=C.UTF-8'
|
||||
export 'LANGUAGE=C.UTF-8'
|
||||
|
||||
unset IFS
|
||||
MYSHEBANG=""
|
||||
|
||||
################
|
||||
# uncomment one of the following lines to make the conversion
|
||||
# Linux/Unix bash
|
||||
# MYSHEBANG="#!/bin/bash"
|
||||
|
||||
# BSD bash
|
||||
# MYSHEBANG="#!/usr/bin/bash"
|
||||
|
||||
# homebrew gnu bash on MacOS
|
||||
# MYSHEBANG="#!/usr/local/opt/bash"
|
||||
|
||||
# use portable /usr/bin/env
|
||||
# MYSHEBANG="#!/usr/bin/env bash"
|
||||
|
||||
# bashbot default bash
|
||||
FROMSHEBANG="#!/bin/bash"
|
||||
|
||||
# uncomment to convert back to bashbot default bash
|
||||
# FROMSHEBANG="#!/usr/bin/env bash"
|
||||
# MYSHEBANG="#!/bin/bash"
|
||||
|
||||
if [ "$1" = "" ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
|
||||
echo "$0: convert bash shebang to point to your local installation"
|
||||
echo "usage: $0 script [script ...]"
|
||||
exit
|
||||
fi
|
||||
|
||||
# loop tomprocess files
|
||||
if [ "${MYSHEBANG}" != "" ]; then
|
||||
echo "Warning, shebang will changed from ${FROMSHEBANG} changed to ${MYSHEBANG}!"
|
||||
else
|
||||
echo "Dry run, demonstration only!"
|
||||
echo "Uncomment one of the MYSHEBANG= lines fitting your environment to make the changes permanent."
|
||||
|
||||
fi
|
||||
|
||||
echo "Press enter to continue ..."
|
||||
#shellcheck disable=SC2034
|
||||
read -r CONTINUE
|
||||
|
||||
|
||||
for file in "$@"
|
||||
do
|
||||
file "${file}"
|
||||
if [[ "$(file -b "${file}")" =~ Bourne.*script.*text ]]; then
|
||||
echo "Processing ${file} ..."
|
||||
if head -n 1 "${file}" | grep -q "^${FROMSHEBANG}"; then
|
||||
if [ "${MYSHEBANG}" != "" ]; then
|
||||
sed -i -e '1 s|^'"${FROMSHEBANG}"'|'"${MYSHEBANG}"'|' "${file}"
|
||||
head -n 1 "${file}"
|
||||
else
|
||||
sed -n -e '1 s|^'"${FROMSHEBANG}"'|#!/some/shebang/bash (dry run)|p' "${file}"
|
||||
fi
|
||||
else
|
||||
echo "Found: $(head -n 1 "${file}") - Nothing to convert."
|
||||
fi
|
||||
echo -e "... done.\n"
|
||||
else
|
||||
echo -e "Not a bash script, skipping ${file} ...\n"
|
||||
fi
|
||||
done
|
|
@ -2,18 +2,18 @@
|
|||
# file. multibot.sh
|
||||
# description: run multiple telegram bots from one installation
|
||||
#
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
if [ "${2}" = "" ] || [ "${2}" = "-h" ]; then
|
||||
if [ "$2" = "" ] || [ "$2" = "-h" ]; then
|
||||
echo "Usage: $0 botname command"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BOT="${1}"
|
||||
[ "${#BOT}" -lt 5 ] && echo "Botname must have a minumum lenth of 5 characters" && exit 1
|
||||
BOT="$1"
|
||||
[ "${#BOT}" -lt 5 ] && echo "Botname must have a minimum length of 5 characters" && exit 1
|
||||
|
||||
# where should the bots live?
|
||||
# true in one dir, false in seperate dirs
|
||||
# true in one dir, false in separate dirs
|
||||
if true; then
|
||||
# example for all in one bashbot dir
|
||||
BINDIR="/usr/local/telegram-bot-bash"
|
||||
|
@ -21,10 +21,10 @@ if true; then
|
|||
VAR="${BINDIR}"
|
||||
|
||||
else
|
||||
# alternative linux like localtions
|
||||
# alternative Linux-like locations
|
||||
BINDIR="/usr/local/bin"
|
||||
ETC="/etc/bahsbot"
|
||||
VAR="/var/bahsbot"
|
||||
ETC="/etc/bashbot"
|
||||
VAR="/var/bashbot"
|
||||
export BASHBOT_JSONSH="/usr/local/bin/JSON.sh"
|
||||
|
||||
fi
|
||||
|
@ -37,7 +37,7 @@ export BASHBOT_VAR="${VAR}/${BOT}"
|
|||
[ ! -d "${BINDIR}" ] && echo "Dir ${BINDIR} does not exist" && exit 1
|
||||
[ ! -d "${BASHBOT_ETC}" ] && echo "Dir ${BASHBOT_ETC} does not exist" && exit 1
|
||||
[ ! -d "${BASHBOT_VAR}" ] && echo "Dir ${BASHBOT_VAR} does not exist" && exit 1
|
||||
[ ! -x "${BINDIR}/bashbot.sh" ] && echo "${BINDIR}/bashbot.sh not executeable or does not exist" && exit 1
|
||||
[ ! -x "${BINDIR}/bashbot.sh" ] && echo "${BINDIR}/bashbot.sh not executable or does not exist" && exit 1
|
||||
[ ! -r "${BASHBOT_ETC}/commands.sh" ] && echo "${BASHBOT_ETC}/commands.sh not readable or does not exist" && exit 1
|
||||
[ ! -r "${BASHBOT_ETC}/mycommands.sh" ] && echo "${BASHBOT_ETC}/mycommands.sh not readable or does not exist" && exit 1
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# this is an exmaple crontab file for telegram-bot-bash
|
||||
# this is an example crontab file for telegram-bot-bash
|
||||
# copy it to /etc/cron.d/bashbot
|
||||
#
|
||||
# (c) https://github.com/gnadelwartz
|
||||
|
@ -7,7 +7,7 @@
|
|||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
|
||||
SHELL=/bin/sh
|
||||
|
@ -23,13 +23,14 @@ MAILTO=root
|
|||
# │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday;
|
||||
# │ │ │ │ │ 7 is also Sunday on some systems)
|
||||
# │ │ │ │ │
|
||||
# │ │ │ │ │
|
||||
# │ │ │ │ │ ┌───────────── run as user (must be omited in users crontab
|
||||
# │ │ │ │ │ |
|
||||
# * * * * * USER command to execute
|
||||
# * * * * * root echo "run every minute!"
|
||||
|
||||
# run as www every day at 0:00
|
||||
0 0 * * * nobody /usr/local/telegram-bot-bash/bashbot.sh start # (re)start bot
|
||||
0 0 * * * nobody /usr/local/telegram-bot-bash/bashbot.sh resumeback # (re)start background jobs
|
||||
# run as www every day at 0:00 plus random sleep between 0-3h
|
||||
0 0 * * * nobody sleep "$((RANDOM \% 180 ))m" ; /usr/local/telegram-bot-bash/bashbot.rc start # (re)start bot
|
||||
0 0 * * * nobody sleep "$((RANDOM \% 180 ))m" ; /usr/local/telegram-bot-bash/bashbot.rc resumeback # (re)start background jobs
|
||||
|
||||
# run as www on 24 of Dec, 12:00
|
||||
0 12 24 12 * nobody /usr/local/telegram-bot-bash/bashbot.sh broadcast "X-Mas shopping is over!" # broadcast a message
|
||||
|
|
|
@ -1,11 +1,25 @@
|
|||
#!/bin/bash
|
||||
# file: calc.sh
|
||||
# example for an interactive chat, run with startproc calc.sh
|
||||
|
||||
########################################################################
|
||||
#
|
||||
# File: calc.sh
|
||||
#
|
||||
# Description: example for an background job, see mycommands.sh.dist
|
||||
#
|
||||
# Usage: runback calc example/calc.sh - or run in terminal
|
||||
# killback calc - to stop background job
|
||||
#
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
########################################################################
|
||||
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
######
|
||||
# parameters
|
||||
# $1 $2 args as given to starct_proc chat script arg1 arg2
|
||||
# $3 path to named pipe/log
|
||||
|
||||
INPUT="${3:-/dev/stdin}"
|
||||
|
||||
# adjust your language setting here
|
||||
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
|
||||
|
@ -16,21 +30,21 @@ export 'LANGUAGE=C.UTF-8'
|
|||
unset IFS
|
||||
# set -f # if you are paranoid use set -f to disable globbing
|
||||
|
||||
echo 'Starting Calculator ...'
|
||||
echo 'Enter first number.'
|
||||
read -r A
|
||||
echo 'Enter second number.'
|
||||
read -r B
|
||||
echo 'Select Operation: mykeyboardstartshere [ "Addition" , "Subtraction" , "Multiplication" , "Division" , "Cancel" ]'
|
||||
read -r opt
|
||||
echo -n 'Result: '
|
||||
case $opt in
|
||||
'add'* | 'Add'* ) res="$(( A + B ))" ;;
|
||||
'sub'* | 'Sub'* ) res="$(( A - B ))" ;;
|
||||
'mul'* | 'Mul'* ) res="$(( A * B ))" ;;
|
||||
'div'* | 'Div'* ) res="$(( A / B ))" ;;
|
||||
'can'* | 'Can'* ) res="abort!" ;;
|
||||
* ) echo "unknown operator!";;
|
||||
printf 'Starting Calculator ...\n'
|
||||
printf 'Enter first number.\n'
|
||||
read -r A <"${INPUT}"
|
||||
printf 'Enter second number.\n'
|
||||
read -r B <"${INPUT}"
|
||||
printf 'Select Operation: mykeyboardstartshere [ "Addition" , "Subtraction" , "Multiplication" , "Division" , "Cancel" ]\n'
|
||||
read -r opt <"${INPUT}"
|
||||
printf 'Result: '
|
||||
case ${opt,,} in
|
||||
'a'*) res="$(( A + B ))" ;;
|
||||
's'*) res="$(( A - B ))" ;;
|
||||
'm'*) res="$(( A * B ))" ;;
|
||||
'd'*) res="$(( A / B ))" ;;
|
||||
'c'*) res="abort!" ;;
|
||||
* ) printf "unknown operator!\n";;
|
||||
esac
|
||||
echo "$res"
|
||||
echo "Bye .."
|
||||
printf "%s\nBye ...\n" "${res}"
|
||||
|
||||
|
|
373
examples/jsonDB-keyboard/mycommands.sh
Normal file
373
examples/jsonDB-keyboard/mycommands.sh
Normal file
|
@ -0,0 +1,373 @@
|
|||
#!/bin/bash
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: mycommands.sh
|
||||
#
|
||||
# USAGE: will be included from commands.sh
|
||||
#
|
||||
# DESCRIPTION: real world example with jsshDB and send_keyboard
|
||||
#
|
||||
# AUTHOR: KayM (), kay@rrr.de
|
||||
# DATE: 19.12.2020 19:03
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
# shellcheck disable=SC2154
|
||||
# shellcheck disable=SC2034
|
||||
|
||||
bashbot_title='*Hallo, ich bin der @'"${ME//_/\\_}"'. Ich suche und finde Dealz!*'
|
||||
|
||||
bashbot_shelp="${bashbot_title}"'
|
||||
|
||||
Schicke mir https://t.me/'"${ME//_/\\_}"' einen Befehl mit *max. 50 Begriffen*. Ein Begriff muss mindesten 4 Zeichen lang sein.
|
||||
|
||||
*Befehle zum Suchen / Tracken von Dealz:*
|
||||
/search /suche _Suche in Deals der letzen 48h,
|
||||
z.B.:_ /suche Apple mavic.\*air
|
||||
|
||||
/newtrack _Tracking mit neuen Begriffen,
|
||||
z.B.:_ /newtrack Apple mavic.\*air
|
||||
/track /addkey _zusätzlicher Begriff zum Tracken_
|
||||
/delkey _lösche Begriff_
|
||||
|
||||
/listtrack _zeigt aktuell getrackte Begriffe_
|
||||
/delkey ALL _löscht alle Begriffe_
|
||||
/stattrack _Infos zum aktiven Tracking_
|
||||
|
||||
'
|
||||
|
||||
bashbot_commands='*Meine Befehle*:
|
||||
/info _- Info zum Bot_
|
||||
/suche _- Suchen und Tracken von Dealz_
|
||||
/hilfe _- Hilfe zu weiteren Befehlen_
|
||||
|
||||
Du hast eine eigene Telegram Dealgruppe? Lade mich ein und alle in der Guppe können mich nutzen:
|
||||
'
|
||||
|
||||
# uncomment the following lines to overwrite info and help messages
|
||||
bashbot_info="${bashbot_title}"'
|
||||
|
||||
*Du willst Dealz suchen oder tracken?*
|
||||
Klicke hier https://t.me/'"${ME//_/\\_}"' und schicke /start
|
||||
|
||||
'"${bashbot_commands}"'
|
||||
|
||||
*Dein '"${ME//_/-}"'*
|
||||
'
|
||||
|
||||
bashbot_help="${bashbot_title}"'
|
||||
|
||||
*Du willst mich weiterempfehlen?*
|
||||
Schicke https://t.me/'"${ME//_/\\_}"' an deinen Telegram Kontakt und sage ihm er soll darauf klicken und /start schicken.
|
||||
|
||||
'"${bashbot_commands}"'
|
||||
|
||||
*Dein '"${ME//_/-}"'*
|
||||
'
|
||||
|
||||
# in a regular message is no need to escape '_'
|
||||
SORRYADMIN="Du bist kein Gruppenadmin, diesen Befehl kannst Du nur im privaten Chat ausführen @${ME} <<- hier klicken"
|
||||
|
||||
# Set INLINE to 1 in order to receive inline queries.
|
||||
# To enable this option in your bot, send the /setinline command to @BotFather.
|
||||
INLINE="0"
|
||||
|
||||
# if your bot is group admin it get commands sent to other bots
|
||||
# Set MEONLY to 1 to ignore commands sent to other bots
|
||||
export MEONLY="1"
|
||||
|
||||
# Set to .* to allow sending files from all locations
|
||||
FILE_REGEX='/this_is_my_bot_path/.*'
|
||||
# run curl over TOR or SOCKS
|
||||
#export BASHBOT_CURL_ARGS="--socks5-hostname localhost"
|
||||
|
||||
# unset BASHBOT_RETRY to enable retry in case of recoverable errors, e.g. throtteling
|
||||
# see logs/ERROR.log for information why send_messages etc. fail
|
||||
unset BOTSEND_RETRY
|
||||
|
||||
# set value for adaptive sleeping while waitingnfor uodates in millisconds
|
||||
# max slepp between polling updates 10s (default 5s)
|
||||
export BASHBOT_SLEEP="10000"
|
||||
# add 0.2s if no update available, up to BASHBOT_SLEEP (default 0.1s)
|
||||
export BASHBOT_SLEEP_STEP="400"
|
||||
|
||||
# uncomment if you use keyboards in your commands
|
||||
# export REMOVEKEYBOARD="yes"
|
||||
export REMOVEKEYBOARD_PRIVATE="yes"
|
||||
|
||||
# uncomment if you want to say welcome to new chat members
|
||||
export WELCOME_NEWMEMBER="yes"
|
||||
WELCOME_MSG="Willkommen"
|
||||
|
||||
# uncomment if you want to be informed about new/left chat members
|
||||
export REPORT_NEWMEMBER="yes"
|
||||
export REPORT_LEFTMEMBER="yes"
|
||||
|
||||
# location of Database files
|
||||
TRACKFILE="${DATADIR}/0-dealtrack"
|
||||
SEARCHFILE="${DATADIR}/0-dealsearch"
|
||||
WATCHFILE="${DATADIR}/0-dealwatch"
|
||||
|
||||
if [ "$1" = "startbot" ];then
|
||||
# mark startup, triggers action on first message
|
||||
setConfigKey "startupaction" "await"
|
||||
# create Database files on startup
|
||||
jssh_newDB "${TRACKFILE}"
|
||||
jssh_newDB "${SEARCHFILE}"
|
||||
jssh_newDB "${WATCHFILE}"
|
||||
else
|
||||
|
||||
# your additional bahsbot commands
|
||||
# NOTE: command can have @botname attached, you must add * in case tests...
|
||||
mycommands() {
|
||||
# action triggered on first message after startup
|
||||
if [[ "$(getConfigKey "startupaction")" != "done"* ]]; then
|
||||
setConfigKey "startupaction" "done $(date)"
|
||||
fi
|
||||
# a service Message was received
|
||||
local SILENCER="yes"
|
||||
if [[ "${SERVICE}" != "" ]]; then
|
||||
# example: dleted service messages
|
||||
if [ "${SILENCER}" = "yes" ] && bot_is_admin "${CHAT[ID]}"; then
|
||||
delete_message "${CHAT[ID]}" "${MESSAGE[ID]}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# remove keyboard if you use keyboards
|
||||
[ -n "${REMOVEKEYBOARD}" ] && remove_keyboard "${CHAT[ID]}" "..." &
|
||||
[[ -n "${REMOVEKEYBOARD_PRIVATE}" && "${CHAT[ID]}" == "${USER[ID]}" ]] && remove_keyboard "${CHAT[ID]}" "..." &
|
||||
|
||||
# fix upper case first letter in commands
|
||||
[[ "${MESSAGE}" =~ ^/[[:upper:]] ]] && MESSAGE="${MESSAGE:0:1}$(tr '[:upper:]' '[:lower:]' <<<"${MESSAGE:1:1}")${MESSAGE:2}"
|
||||
|
||||
######################
|
||||
# default commands
|
||||
case "${MESSAGE}" in
|
||||
'/info'*)
|
||||
send_action "${CHAT[ID]}" "typing"
|
||||
delete_message "${CHAT[ID]}" "${MESSAGE[ID]}"
|
||||
send_markdownv2_message "${CHAT[ID]}" "${bashbot_info}"
|
||||
return 1 # continue with default action
|
||||
;;
|
||||
'/hel'*|'/hil'*)
|
||||
send_action "${CHAT[ID]}" "typing"
|
||||
delete_message "${CHAT[ID]}" "${MESSAGE[ID]}"
|
||||
send_markdownv2_message "${CHAT[ID]}" "${bashbot_help}"
|
||||
return 1 # break, do not continue
|
||||
;;
|
||||
'/start'*)
|
||||
send_markdownv2_message "${CHAT[ID]}" "${bashbot_help}"
|
||||
return 1 # break, do not continue
|
||||
;;
|
||||
'/_edited_message'*)
|
||||
#return 1 # no
|
||||
# but if we do, remove /edited_message
|
||||
MESSAGE="${MESSAGE#/* }"
|
||||
;;
|
||||
'/_new_chat_member'*)
|
||||
if [[ -n "${WELCOME_NEWMEMBER}" && "${NEWMEMBER[ISBOT]}" != "true" ]] && bot_is_admin "${CHAT[ID]}"; then
|
||||
send_normal_message "${CHAT[ID]}"\
|
||||
"${WELCOME_MSG} ${NEWMEMBER[FIRST_NAME]} ${NEWMEMBER[LAST_NAME]} (@${NEWMEMBER[USERNAME]})"
|
||||
MYSENTID="${BOTSENT[ID]}"
|
||||
{ sleep 5; delete_message "${CHAT[ID]}" "${MYSENTID}"; } &
|
||||
fi
|
||||
[ -n "${REPORT_NEWMEMBER}" ] && send_normal_message "$(getConfigKey "botadmin")"\
|
||||
"New member: ${CHAT[TITLE]} (${CHAT[ID]}): ${NEWMEMBER[FIRST_NAME]} ${NEWMEMBER[LAST_NAME]} (@${NEWMEMBER[USERNAME]})"
|
||||
;;
|
||||
'/_left_chat_member'*)
|
||||
[ -n "${REPORT_LEFTMEMBER}" ] && send_normal_message "$(getConfigKey "botadmin")"\
|
||||
"Left member: ${CHAT[TITLE]} (${CHAT[ID]}): ${LEFTMEMBER[FIRST_NAME]} ${LEFTMEMBER[LAST_NAME]} (@${LEFTMEMBER[USERNAME]})"
|
||||
;;
|
||||
esac
|
||||
|
||||
##########
|
||||
# pre test for admin only commands
|
||||
case "${MESSAGE}" in
|
||||
# must be private, group admin, or botadmin
|
||||
'/sea'*|'/su'*|'/add'*|'/new'*|'/del'*|'/tra'*)
|
||||
send_action "${CHAT[ID]}" "typing"
|
||||
if ! user_is_admin "${CHAT[ID]}" "${USER[ID]}" ; then
|
||||
delete_message "${CHAT[ID]}" "${MESSAGE[ID]}"
|
||||
send_normal_message "${CHAT[ID]}" "${SORRYADMIN}"
|
||||
MYSENTID="${BOTSENT[ID]}"
|
||||
{ sleep 5; delete_message "${CHAT[ID]}" "${MYSENTID}"; } &
|
||||
return 1
|
||||
fi
|
||||
# ok, now lets process the real command
|
||||
;;
|
||||
esac
|
||||
|
||||
#################
|
||||
# search commands
|
||||
#local vairable, e.g. read/write Database
|
||||
local FINDKEYS OLDKEYS KEY MYSENTID
|
||||
declare -a KEYARR
|
||||
declare -A SEARCHVALUES
|
||||
|
||||
#################
|
||||
# pre processing of search commands
|
||||
case "${MESSAGE}" in
|
||||
'/add'*|'/tra'*) # add no arg
|
||||
FINDKEYS="${MESSAGE#/* }"
|
||||
if [ "${FINDKEYS}" = "${MESSAGE}" ]; then
|
||||
send_normal_message "${CHAT[ID]}" "Kein Begriff angegeben!"
|
||||
exit
|
||||
fi
|
||||
;;&
|
||||
'/add'[kbt]*|'/tra'*) OLDKEYS="$(jssh_getKeyDB "${CHAT[ID]}" "${TRACKFILE}")"
|
||||
;;&
|
||||
'/addk'*|'/addt'*|'/tra'*) # add track
|
||||
MESSAGE="/newtrack ${FINDKEYS} ${OLDKEYS}"
|
||||
;;
|
||||
'/delk'*) #delete key
|
||||
OLDKEYS="$(jssh_getKeyDB "${CHAT[ID]}" "${TRACKFILE}")"
|
||||
if [ "${OLDKEYS}" = "" ]; then
|
||||
send_markdownv2_message "${CHAT[ID]}" "*Kein Tracking aktiv!*"
|
||||
return
|
||||
fi
|
||||
KEY="${OLDKEYS%%|!*}"
|
||||
FINDKEYS="${MESSAGE#/* }"
|
||||
read -r -a KEYARR <<<"ALL ${KEY//|/ }"
|
||||
if [ "${FINDKEYS}" = "ALL" ]; then
|
||||
jssh_deleteKeyDB "${CHAT[ID]}" "${TRACKFILE}"
|
||||
send_markdownv2_message "${CHAT[ID]}" "*Tracking gelöscht!*"
|
||||
return
|
||||
elif [[ "${FINDKEYS}" =~ ^[0-9]+$ ]]; then
|
||||
if [ "${#KEYARR[@]}" -lt "${FINDKEYS}" ]; then
|
||||
send_normal_message "${CHAT[ID]}" "Es gibt nur $((${#KEYARR[@]}-1)) Keys, bitte nochmal."
|
||||
unset FINDKEYS
|
||||
else
|
||||
send_normal_message "${CHAT[ID]}" "Lösche Key ${KEYARR[${FINDKEYS}]}"
|
||||
unset "KEYARR[0]"
|
||||
unset "KEYARR[${FINDKEYS}]"
|
||||
FINDKEYS="${KEYARR[*]}"
|
||||
if [ -z "${FINDKEYS}" ]; then
|
||||
jssh_deleteKeyDB "${CHAT[ID]}" "${TRACKFILE}"
|
||||
send_markdownv2_message "${CHAT[ID]}" "*Tracking gelöscht!*"
|
||||
return
|
||||
else
|
||||
KEY="${OLDKEYS#*!}"
|
||||
[ "${KEY}" != "${OLDKEYS}" ] && FINDKEYS+="|!${KEY}"
|
||||
MESSAGE="/newt ${FINDKEYS}"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
OUT="$(printKeys "KEYARR")\n\nSchicke \"/delkey <Nr.>\" zum Löschen."
|
||||
# send keyboard in private chats only
|
||||
if [ "${CHAT[ID]}" != "${USER[ID]}" ]; then
|
||||
send_normal_message "${CHAT[ID]}" "${OUT}"
|
||||
else
|
||||
send_keyboard "${CHAT[ID]}" "${OUT}"\
|
||||
'["/delkey 1","/delkey 2","/delkey 3"],["/delkey 4","/delkey 5","/delkey 6"],["/delkey 7","/delkey 8","/delkey 9"],["/delkey ALL","/delblack","/listtrack"]'
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
case "${MESSAGE}" in
|
||||
#######################
|
||||
# deal search commands
|
||||
'/such'*|'/sea'*) # suche
|
||||
FINDKEYS="${MESSAGE#/* }"
|
||||
if [ "${FINDKEYS}" = "${MESSAGE}" ]; then
|
||||
delete_message "${CHAT[ID]}" "${MESSAGE[ID]}"
|
||||
send_markdownv2_message "${CHAT[ID]}" "${bashbot_shelp}"
|
||||
else
|
||||
if user_is_admin "${CHAT[ID]}" "${USER[ID]}" || user_is_allowed "${USER[ID]}" "search" "${CHAT[ID]}"; then
|
||||
set_keys "${FINDKEYS}" "${SEARCHFILE}"
|
||||
else
|
||||
send_normal_message "${CHAT[ID]}" "${SORRYADMIN}"
|
||||
MYSENTID="${BOTSENT[ID]}"
|
||||
{ sleep 5; delete_message "${CHAT[ID]}" "${MYSENTID}"; } &
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
return 1
|
||||
;;
|
||||
|
||||
'/newt'*) # newtrack
|
||||
FINDKEYS="${MESSAGE#/* }"
|
||||
FINDKEYS="${FINDKEYS%[\" ]}"
|
||||
FINDKEYS="${FINDKEYS#[\" ]}"
|
||||
if [ "${FINDKEYS}" = "" ]; then
|
||||
send_markdownv2_message "${CHAT[ID]}" "${bashbot_shelp}"
|
||||
else
|
||||
set_keys "${FINDKEYS}" "${TRACKFILE}"
|
||||
fi
|
||||
;&
|
||||
'/lst'*|'/listt'*) # listtrack
|
||||
send_action "${CHAT[ID]}" "typing"
|
||||
FINDKEYS="$(jssh_getKeyDB "${CHAT[ID]}" "${TRACKFILE}")"
|
||||
if [ "${FINDKEYS}" = "" ]; then
|
||||
send_markdownv2_message "${CHAT[ID]}" "*Kein Tracking aktiv!*"
|
||||
return
|
||||
fi
|
||||
OUT="Tracking nach \"${FINDKEYS}\" ist aktiv."
|
||||
# send keyboard in private chats only
|
||||
if [[ "${CHAT[ID]}" != "${USER[ID]}" ]]; then
|
||||
send_normal_message "${CHAT[ID]}" "${OUT}"
|
||||
else
|
||||
send_keyboard "${CHAT[ID]}" "${OUT}"\
|
||||
'["/delkey 1","/delkey 2","/delkey 3"],["/delkey 4","/delkey 5","/delkey 6"],["/delkey 7","/delkey 8","/delkey 9"],["/delkey ALL","/delblack","/listtrack"]'
|
||||
fi
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
fi
|
||||
|
||||
# place your processing functions here
|
||||
set_keys(){
|
||||
local MYFIND MYKEY MYKEYF MINLEN MYSEARCH
|
||||
declare -A KEYARR
|
||||
MYFIND="$1"
|
||||
MYKEYF="$2"
|
||||
MINLEN="4"
|
||||
# check len of keys
|
||||
for MYKEY in ${MYFIND}; do [ "${#MYKEY}" -lt "${MINLEN}" ] && break; done
|
||||
if [ "${#MYKEY}" -lt "${MINLEN}" ]; then
|
||||
send_markdownv2_message "${CHAT[ID]}" "*Ein Suchbegriff ist kürzer als ${MINLEN} Zeichen!*"
|
||||
else
|
||||
MYFIND="$(create_pattern "${MYFIND}")"
|
||||
[[ "${MESSAGE}" == "/s"* ]] &&\
|
||||
send_normal_message "${CHAT[ID]}" "Suche nach \"${MYFIND//|/ }\" wird gestartet ..."
|
||||
MYKEY="${MYFIND//[^|]}"
|
||||
if [ "${#MYKEY}" -gt 49 ]; then
|
||||
send_markdownv2_message "${CHAT[ID]}" "*Maximale Anzahl von 50 Begriffen erreicht!*"
|
||||
elif [ "${MYFIND}" != "" ]; then
|
||||
KEYARR["${CHAT[ID]}"]="${MYFIND}"
|
||||
jssh_updateDB "KEYARR" "${MYKEYF}"
|
||||
else
|
||||
send_markdownv2_message "${CHAT[ID]}" "*Ein Begriff ist ungültig, z.B. \" , oder leer!*"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
# place your processing functions here
|
||||
|
||||
# $1 ARRAYNAME to print
|
||||
printKeys() {
|
||||
local key
|
||||
declare -n ARRAY="$1"
|
||||
for key in "${!ARRAY[@]}"
|
||||
do
|
||||
printf '%s - %s\n' "${key}" "${ARRAY[${key}]}"
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
# create a regex from space sepeareted keywords
|
||||
# $1 space separated words
|
||||
create_pattern() {
|
||||
local PATTERN KEY
|
||||
set -f
|
||||
for KEY in $1
|
||||
do
|
||||
[ "${PATTERN}" != "" ] && PATTERN="${PATTERN}|"
|
||||
PATTERN="${PATTERN}${KEY}"
|
||||
done
|
||||
set +f
|
||||
echo "${PATTERN}"
|
||||
}
|
||||
|
|
@ -1,10 +1,25 @@
|
|||
#!/bin/bash
|
||||
# file: notify.sh
|
||||
# example for an background job, run with startback notify.sh
|
||||
|
||||
########################################################################
|
||||
#
|
||||
# File: notify.sh
|
||||
#
|
||||
# Description: example for an background job, see mycommands.sh.dist
|
||||
#
|
||||
# Usage: runback notify example/notify.sh [seconds] - or run in terminal
|
||||
# killback notify - to stop background job
|
||||
#
|
||||
# Options: seconds - time to sleep between output, default 10
|
||||
#
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
########################################################################
|
||||
|
||||
######
|
||||
# parameters
|
||||
# $1 $2 args as given to starct_proc chat script arg1 arg2
|
||||
# $3 path to named pipe/log
|
||||
|
||||
# adjust your language setting here
|
||||
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
|
||||
|
@ -18,17 +33,20 @@ unset IFS
|
|||
# discard STDIN for background jobs!
|
||||
cat >/dev/null &
|
||||
|
||||
# check if $1 is a number
|
||||
re='^[0-9]+$'
|
||||
if [[ $1 =~ $re ]] ; then
|
||||
# $1 = time between time notifications
|
||||
# check if $1 is a valid number
|
||||
if [[ "$1" =~ ^[0-9]+$ ]] ; then
|
||||
SLEEP="$1"
|
||||
else
|
||||
SLEEP=10 # time between time notifications
|
||||
SLEEP=10
|
||||
fi
|
||||
|
||||
# output current time every $1 seconds
|
||||
while sleep $SLEEP
|
||||
printf "Output time every %s seconds ...\n" "${SLEEP}"
|
||||
|
||||
while true
|
||||
do
|
||||
date "+* It's %k:%M:%S o' clock ..."
|
||||
date "+* It's %k:%M:%S o'clock ..."
|
||||
sleep "${SLEEP}"
|
||||
done
|
||||
|
||||
|
|
|
@ -1,11 +1,24 @@
|
|||
#!/bin/bash
|
||||
# file: question.sh
|
||||
# example for an interactive chat, run with startproc question.sh
|
||||
|
||||
########################################################################
|
||||
#
|
||||
# File: question.sh
|
||||
#
|
||||
# Usage: runproc example/question.sh - or run in terminal
|
||||
#
|
||||
# Description: example for an interactive chat, see mycommands.sh.dist
|
||||
#
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
########################################################################
|
||||
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
######
|
||||
# parameters
|
||||
# $1 $2 args as given to starct_proc chat script arg1 arg2
|
||||
# $3 path to named pipe
|
||||
|
||||
INPUT="${3:-/dev/stdin}"
|
||||
|
||||
# adjust your language setting here
|
||||
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
|
||||
|
@ -16,17 +29,29 @@ export 'LANGUAGE=C.UTF-8'
|
|||
unset IFS
|
||||
# set -f # if you are paranoid use set -f to disable globbing
|
||||
|
||||
echo "Why hello there.
|
||||
Would you like some tea (y/n)?"
|
||||
read -r answer
|
||||
[[ $answer =~ ^([yY][eE][sS]|[yY])$ ]] && echo "OK then, here you go: http://www.rivertea.com/blog/wp-content/uploads/2013/12/Green-Tea.jpg" || echo "OK then."
|
||||
until [ "$SUCCESS" = "y" ] ;do
|
||||
echo 'Do you like Music? mykeyboardstartshere "Yass!" , "No"'
|
||||
read -r answer
|
||||
case $answer in
|
||||
'Yass!') echo "Goody! mykeyboardendshere";SUCCESS=y;;
|
||||
'No') echo "Well that's weird. mykeyboardendshere";SUCCESS=y;;
|
||||
# kill interactive script if not finished in time, e.g. user away or error
|
||||
MAXWAIT="1m"
|
||||
{ sleep "${MAXWAIT}"; printf "Stopping Questionnaire after %s, you need to much time to finish ... BYE\n" "${MAXWAIT}"; kill $$; wait 2>/dev/null ;} &
|
||||
|
||||
# simple yes/no question, defaults to no
|
||||
printf "Hi, hello there\nWould you like some tea (y/n)?\n"
|
||||
read -r answer <"${INPUT}"
|
||||
if [[ ${answer,,} == "y"* ]]; then
|
||||
printf "OK then, here you go: http://www.rivertea.com/blog/wp-content/uploads/2013/12/Green-Tea.jpg\n"
|
||||
else
|
||||
printf "OK then, no tea ...\n"
|
||||
fi
|
||||
|
||||
# question with Keyboard, repeating until correct answer given
|
||||
until [ "${SUCCESS}" = "y" ] ;do
|
||||
printf 'Do you like Music? mykeyboardstartshere "Yass!" , "No"\n'
|
||||
read -r answer <"${INPUT}"
|
||||
case ${answer,,} in
|
||||
'') printf "empty answer! Try again\n";;
|
||||
'yass'*) printf "Goody! mykeyboardendshere\n";SUCCESS=y;;
|
||||
'no'*) printf "Well that's weird. mykeyboardendshere\n";SUCCESS=y;;
|
||||
*) SUCCESS=n;;
|
||||
esac
|
||||
done
|
||||
exit
|
||||
printf "OK, Done!\n"
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
# file: botacl
|
||||
# a user not listed here, will return false from 'user_is_allowed'
|
||||
#
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
# Format:
|
||||
# user:ressource:chat
|
||||
# user:resource:chat
|
||||
|
||||
# allow user 123456789 access to all resources in all chats
|
||||
123456789:*:*
|
||||
|
@ -12,7 +12,7 @@
|
|||
12131415:systemstatus:*
|
||||
|
||||
# * are only allowed on the right hand side and not for user!
|
||||
# the following exaples are NOT valid!
|
||||
# the following examples are NOT valid!
|
||||
*:*:*
|
||||
*:start:*
|
||||
*:*:98979695
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
# to show how you can customize bashbot by only editing mycommands.sh
|
||||
# NOTE: this is not tested, simply copied from original source and reworked!
|
||||
#
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#
|
||||
# shellcheck disable=SC2154
|
||||
# shellcheck disable=SC2034
|
||||
|
@ -19,7 +19,7 @@
|
|||
bashbot_info='This bot allows you to request status of your system.
|
||||
To begin using the bot, try with the /help command.
|
||||
'
|
||||
bashbot_help='*Availiable commands*:
|
||||
bashbot_help='*Available commands*:
|
||||
/se *sensors*
|
||||
/smb *smbstatus*
|
||||
/free *memory status*
|
||||
|
@ -32,19 +32,13 @@ bashbot_help='*Availiable commands*:
|
|||
'
|
||||
|
||||
|
||||
# your additional bahsbot commands
|
||||
# your additional bashbot commands
|
||||
# NOTE: command can have @botname attached, you must add * in case tests...
|
||||
mycommands() {
|
||||
[[ "$MESSAGE" = '/'* ]] || return
|
||||
set +f
|
||||
# shellcheck disable=SC2206
|
||||
local arg=( $MESSAGE )
|
||||
set -f
|
||||
local cmd="${arg[0]}"
|
||||
local msg=""
|
||||
|
||||
if user_is_botadmin "${USER[ID]}" || user_is_allowed "${USER[ID]}" "systemstatus"; then
|
||||
case "$cmd" in
|
||||
case "${CMD}" in
|
||||
'/md'*) msg="$(cat /proc/mdstat)";;
|
||||
'/smb'*) msg="$(smbstatus)" ;;
|
||||
'/se'*) msg="$(sensors | sed -r 's/\s|\)+//g' | sed -r 's/\(high=|\(min=/\//' | sed -r 's/\,crit=|\,max=/\//')";;
|
||||
|
@ -55,16 +49,16 @@ mycommands() {
|
|||
'/lvm'*) msg="$(lvs | sed -r 's/\s+/\n/g')";;
|
||||
'/lvsd'*) msg="$(lvs -a -o +devices | sed -r 's/\s+/\n/g')";;
|
||||
'/smart'*)
|
||||
[ "${arg[0]}" == "" ] && msg="example \`/smart sda\`" && return
|
||||
drive="$(echo "${arg[0]}" | cut -c 1-3)"
|
||||
echo "smartctl -a /dev/$drive"
|
||||
msg="$(smartctl -a "/dev/$drive")"
|
||||
[ "${CMD[1]}" == "" ] && msg="example \`/smart sda\`" && return
|
||||
drive="$(echo "${CMD[1]}" | cut -c 1-3)"
|
||||
echo "smartctl -a /dev/${drive}"
|
||||
msg="$(smartctl -a "/dev/${drive}")"
|
||||
;;
|
||||
'/df') msg="$(df -h | sed -r 's/^/\n/' | sed -r 's/\s+/\n/g')";;
|
||||
esac
|
||||
|
||||
if [ "$msg" != "" ]; then
|
||||
send_normal_message "${CHAT[ID]}" "$msg"
|
||||
if [ "${msg}" != "" ]; then
|
||||
send_normal_message "${CHAT[ID]}" "${msg}"
|
||||
fi
|
||||
else
|
||||
send_normal_message "${USER[ID]}" "Sorry, you are not allowed to use this bot!"
|
||||
|
|
3
examples/webhook/BASHBOT_HOME
Normal file
3
examples/webhook/BASHBOT_HOME
Normal file
|
@ -0,0 +1,3 @@
|
|||
/usr/local/github/telegram-bot-bash-develop/DIST/telegram-bot-bash
|
||||
/usr/local/github/telegram-bot-bash-develop/STANDALONE
|
||||
/usr/local/telegram-bot-bash
|
100
examples/webhook/README.md
Normal file
100
examples/webhook/README.md
Normal file
|
@ -0,0 +1,100 @@
|
|||
#### [Examples](../README.md)
|
||||
|
||||
## Bashbot webhook example
|
||||
|
||||
### Webhook
|
||||
|
||||
Bashbot default mode is to poll Telegram server for updates but Telegram offers webhook as a more efficient method to deliver updates.
|
||||
If your server is reachable from the Internet its possible to use the method described here.
|
||||
|
||||
Prerequisite for receiving Telegram updates with webhook is a valid SSL certificate, a self signed certificate will not be sufficient.
|
||||
|
||||
Webhook processing require special setup on server and Telegram side, therefore it's implemented as separate scripts and you need at least sudo rights to setup.
|
||||
|
||||
#### Setup Apache webhook
|
||||
|
||||
Prerequisite: An Apache webserver with a valid SLL certificate chain and php enabled.\
|
||||
This should work with other webservers also but it's not testet.
|
||||
|
||||
Setup webhook with Apache:
|
||||
|
||||
- install bashbot as described in [Bashbot Installation](../../doc/0_install.md)
|
||||
- create file `data-bot-bash/webhook-fifo-<botname>` (_\<botname\> as in `botconfig.jssh`_)
|
||||
- run `sudo bashbot.sh init` to setup bashbot to run as same user as web server (_e.g. www_)
|
||||
- create a directory in web root: `telegram/<your_bot_token>` (_<your_bot_token> as `botconfig.jssh`_)
|
||||
- give web server access to directory (_e.g.`chown www:www -R telegram`_)
|
||||
- go into the new directory and copy all files from `examples/webhook` to it
|
||||
- edit file `BASHBOT_HOME` to contain ithe Bashbot installation directory as first line (_other lines are ignored_)
|
||||
- execute `php index.php` with user id of web server to test write access to `data-bot-bash/webhook-fifo-<botname>
|
||||
|
||||
Calling `https://<yourservername>/telegram/<your_bot_token>/` will execute `index.php`
|
||||
thus append received data to the file `data-bot-bash/webhook-fifo-<botname>`.
|
||||
E.g. `https://<yourservername>/telegram/<your_bot_token>/?json={"test":"me"}` will append `{"test":"me"}`.
|
||||
|
||||
Now your Server is ready to receive updates from Telegram.
|
||||
|
||||
|
||||
#### Default webhook processing
|
||||
|
||||
This is the testet and supported default method for processing Telegram updates over webhook.
|
||||
|
||||
To enable update processing delete the file `data-bot-bash/webhook-fifo-<botname>` if webhook is working as described above.
|
||||
Incoming Telegram updates are now forwarded to the script `bin/process_update.sh` for processing.
|
||||
|
||||
On incoming Telegram updates the script is executed, it sources bashbot.sh and forward the update to Bashbot for processing.
|
||||
Even it seems overhead to source Bashbot for every update, it's more responsive and create less load than Bashbot polling mode.
|
||||
|
||||
Nevertheles there are some limitations compared to polling mode:
|
||||
- no startup actions
|
||||
- `addons` and `TIMER_EVENTS` are not working
|
||||
|
||||
Interactive and background jobs are working as of Bashbot Version 1.51.
|
||||
|
||||
#### Full webhook processing
|
||||
|
||||
Full webhook processing use an external script to imitate Bashbot polling mode with webhook.
|
||||
|
||||
1. Default webook method must work first!
|
||||
2. run `bashbot.sh init` to setup bashbot to run with your user id
|
||||
2. Create a named pipe: `mkfifo data-bot-bash/webhook-fifo-botname` and give the web server write access to it
|
||||
3. execute `php index.php` with user id of web server to test write access to `data-bot-bash/webhook-fifo-<botname>
|
||||
4. Start script for Bashbot webhook polling mode:\
|
||||
`bin/process-batch.sh --startbot --watch data-bot-bash/webhook-fifo-<botname>`
|
||||
|
||||
The script read updates from given file line by line and forward updates to Bashbot update processing. `--startbot` will run the startup actions
|
||||
(_e.g. load addons, start TIMER, trigger first run_) and `--watch` will wait for new updates instead of exit on end of file.
|
||||
Short form: 'bin/process-batch.sh -s -w'
|
||||
|
||||
If script works as expected, you may run Bashbot webook polling in background by using `./bachbot.rc starthook/stophook`.
|
||||
|
||||
To switch back to default processing delete fifo `data-bot-bash/webhook-fifo-<botname>` and stop `bin/process-batch.sh`.
|
||||
|
||||
#### Enable webhook on Telegram side
|
||||
|
||||
To get updates via webhook your server must be reachable from the internet and you must
|
||||
instruct Telegram where to deliver updates, this is done by calling bashbot function `set_webhook`.
|
||||
|
||||
*Example:*
|
||||
|
||||
```bash
|
||||
bin/any_command.sh set_webhook "https://myserver.com/telegram"
|
||||
```
|
||||
|
||||
instruct Telegram to use the URL `https://myserver.com/telegram/<your_bot_token>/` to deliver updates.
|
||||
After you enable webhook to deliver Telegram updates it's no more possible to poll updates with `bashbot.sh start`.
|
||||
|
||||
To stop delivering of Telegram updates via webhook run `bin/any_command.sh delete_webhook`.
|
||||
|
||||
**Important**: Telegram will refuse to deliver updates if your webhook has no valid SSL certificate chain.
|
||||
|
||||
|
||||
#### Bash webhook
|
||||
|
||||
A pure bash webhook implementation is not possible without extra software because Telegram delivers
|
||||
webhook updates only over secure TLS connections with a valid SSL certificate chain.
|
||||
|
||||
`socat` looks like a tool to listen for Telegram updates from bash scripts, let's see ...
|
||||
|
||||
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
112
examples/webhook/index.php
Normal file
112
examples/webhook/index.php
Normal file
|
@ -0,0 +1,112 @@
|
|||
<?php
|
||||
/************************************************************
|
||||
* @file examples/webhook/index.php
|
||||
* @description example webhook implementation for apache
|
||||
* write to fifo/file if writeable, else pipe to command
|
||||
*
|
||||
* first line of BASHBOT_HOME is used as bot home (optional)
|
||||
* must start with /, not contain /. and min 20 characters long
|
||||
*
|
||||
* @author KayM (gnadelwartz), kay@rrr.de
|
||||
* @license http://www.wtfpl.net/txt/copying/ WTFPLv2
|
||||
* @since 30.01.2021 20:24
|
||||
*
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
***********************************************************/
|
||||
|
||||
// bashbot home dir
|
||||
$CONFIG_HOME='BASHBOT_HOME';
|
||||
$BASHBOT_HOME='/usr/local/telegram-bot-bash';
|
||||
// read from config file
|
||||
if (file_exists($CONFIG_HOME)) {
|
||||
$tmp = trim(fgets(fopen($CONFIG_HOME, 'r')));
|
||||
// start with '/', not '/.', min 20 chars
|
||||
if (substr($tmp,0,1) == '/' && strlen($tmp) >= 20 && strpos($tmp, '/.') === false) {
|
||||
$BASHBOT_HOME=$tmp;
|
||||
}
|
||||
}
|
||||
|
||||
// bashbot config file
|
||||
$CONFIG=$BASHBOT_HOME.'/botconfig.jssh';
|
||||
// set botname here or read botname from config file if unknown
|
||||
$botname="unknown";
|
||||
if ($botname == "unknown" && file_exists($CONFIG)) {
|
||||
$prefix='["botname"] "';
|
||||
$len=strlen($prefix);
|
||||
$arr = file($CONFIG, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
foreach ($arr as $line) {
|
||||
if(substr($line, 0, $len) == $prefix) {
|
||||
$botname=substr($line, $len, strlen($line)-$len-1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// script endpoint
|
||||
$cmd=$BASHBOT_HOME.'/bin/process_update.sh';
|
||||
// default fifo endpoint
|
||||
$fifo=$BASHBOT_HOME.'/data-bot-bash/webhook-fifo-'.$botname;
|
||||
|
||||
// prepeare read, e.g. run from CLI
|
||||
$data='';
|
||||
$input="php://input";
|
||||
$json_file="json.txt";
|
||||
if (php_sapi_name() == "cli") {
|
||||
if(is_readable($json_file)) {
|
||||
$input=$json_file;
|
||||
} else {
|
||||
$input="php://stdin";
|
||||
}
|
||||
}
|
||||
// read request data
|
||||
if($json = file_get_contents($input)) {
|
||||
$data = $json;
|
||||
} else {
|
||||
$data = implode(" ",$_POST);
|
||||
if ($data == '') { $data = implode(" ",$_GET); }
|
||||
}
|
||||
// uncomment to save last received JSON
|
||||
// file_put_contents($json_file, str_replace(array("\n", "\r"), '',$data). PHP_EOL));
|
||||
|
||||
// prepare for writing
|
||||
if ($data == '') {
|
||||
error_response(400, "No data received");
|
||||
}
|
||||
if (! chdir($BASHBOT_HOME)) {
|
||||
error_response(403, "No route to bot home");
|
||||
}
|
||||
|
||||
// fifo or command?
|
||||
if (! is_writeable($fifo)) {
|
||||
// pipe to command
|
||||
if (! file_exists($cmd)) {
|
||||
error_response(502, "Webhook endpoint not found");
|
||||
}
|
||||
if (! $handle = popen( $cmd.' debug', 'w' )) {
|
||||
error_response(503, "Can't open webhook command endpoint");
|
||||
}
|
||||
} else {
|
||||
// write to fifo
|
||||
if (! $handle = fopen( $fifo, 'a' )) {
|
||||
error_response(503, "Can't open webhook file endpoint");
|
||||
}
|
||||
flock($handle, LOCK_EX);
|
||||
}
|
||||
if (fwrite( $handle, str_replace(array("\n", "\r"), '',$data). PHP_EOL) === false) {
|
||||
error_response(504, "Write to webhook failed");
|
||||
}
|
||||
flock($handle, LOCK_UN);
|
||||
pclose($handle);
|
||||
/**/
|
||||
|
||||
function error_response($code, $msg) {
|
||||
$api = substr(php_sapi_name(), 0, 3);
|
||||
if ($api == 'cgi' || $api == 'fpm') {
|
||||
header('Status: '.$code.' '.$msg);
|
||||
} else {
|
||||
$protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0';
|
||||
header($protocol.' '.$code.' '.$msg);
|
||||
}
|
||||
exit('Error '.$code.': '.$msg. PHP_EOL);
|
||||
}
|
||||
?>
|
1
examples/webhook/json.txt
Normal file
1
examples/webhook/json.txt
Normal file
|
@ -0,0 +1 @@
|
|||
{"update_id":665220889,"message":{"message_id":760,"from":{"id":BOTADMIN,"is_bot":false,"first_name":"Kay","last_name":"M","username":"KayM","language_code":"de"},"chat":{"id":BOTADMIN,"first_name":"Kay","last_name":"M","username":"KayM","type":"private"},"date":1612029749,"text":"/info","entities":[{"offset":0,"length":5,"type":"bot_command"}]}}
|
|
@ -1,13 +1,16 @@
|
|||
#!/bin/bash
|
||||
# file: modules/alaises.sh
|
||||
# file: modules/aliases.sh
|
||||
# do not edit, this file will be overwritten on update
|
||||
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#
|
||||
# source from commands.sh to use the aliases
|
||||
# will be automatically sourced from bashbot
|
||||
|
||||
# source once magic, function named like file
|
||||
eval "$(basename "${BASH_SOURCE[0]}")(){ :; }"
|
||||
|
||||
# easy handling of users:
|
||||
_is_botadmin() {
|
||||
|
@ -20,36 +23,36 @@ _is_creator() {
|
|||
user_is_creator "${CHAT[ID]}" "${USER[ID]}"
|
||||
}
|
||||
_is_allowed() {
|
||||
user_is_allowed "${USER[ID]}" "${1}" "${CHAT[ID]}"
|
||||
user_is_allowed "${USER[ID]}" "$1" "${CHAT[ID]}"
|
||||
}
|
||||
_leave() {
|
||||
leave_chat "${CHAT[ID]}"
|
||||
}
|
||||
_kick_user() {
|
||||
kick_chat_member "${CHAT[ID]}" "${1}"
|
||||
kick_chat_member "${CHAT[ID]}" "$1"
|
||||
}
|
||||
_unban_user() {
|
||||
unban_chat_member "${CHAT[ID]}" "${1}"
|
||||
unban_chat_member "${CHAT[ID]}" "$1"
|
||||
}
|
||||
# easy sending of messages of messages
|
||||
_message() {
|
||||
send_normal_message "${CHAT[ID]}" "${1}"
|
||||
send_normal_message "${CHAT[ID]}" "$1"
|
||||
}
|
||||
_normal_message() {
|
||||
send_normal_message "${CHAT[ID]}" "${1}"
|
||||
send_normal_message "${CHAT[ID]}" "$1"
|
||||
}
|
||||
_html_message() {
|
||||
send_html_message "${CHAT[ID]}" "${1}"
|
||||
send_html_message "${CHAT[ID]}" "$1"
|
||||
}
|
||||
_markdown_message() {
|
||||
send_markdown_message "${CHAT[ID]}" "${1}"
|
||||
send_markdown_message "${CHAT[ID]}" "$1"
|
||||
}
|
||||
# easy handling of keyboards
|
||||
_inline_button() {
|
||||
send_inline_button "${CHAT[ID]}" "" "${1}" "${2}"
|
||||
send_inline_button "${CHAT[ID]}" "" "$1" "$2"
|
||||
}
|
||||
_inline_keyboard() {
|
||||
send_inline_keyboard "${CHAT[ID]}" "" "${1}"
|
||||
send_inline_keyboard "${CHAT[ID]}" "" "$1"
|
||||
}
|
||||
_keyboard_numpad() {
|
||||
send_keyboard "${CHAT[ID]}" "" '["1","2","3"],["4","5","6"],["7","8","9"],["-","0","."]' "yes"
|
||||
|
|
104
modules/answerInline.sh
Normal file
104
modules/answerInline.sh
Normal file
|
@ -0,0 +1,104 @@
|
|||
#!/bin/bash
|
||||
# file: modules/inline.sh
|
||||
# do not edit, this file will be overwritten on update
|
||||
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
# will be automatically sourced from bashbot
|
||||
|
||||
# source once magic, function named like file
|
||||
eval "$(basename "${BASH_SOURCE[0]}")(){ :; }"
|
||||
|
||||
|
||||
answer_inline_query() {
|
||||
answer_inline_multi "$1" "$(shift; inline_query_compose "${RANDOM}" "$@")"
|
||||
}
|
||||
answer_inline_multi() {
|
||||
sendJson "" '"inline_query_id": '"$1"', "results": ['"$2"']' "${URL}/answerInlineQuery"
|
||||
}
|
||||
|
||||
# $1 unique ID for answer
|
||||
# $2 type of answer
|
||||
# remaining arguments are the "must have" arguments in the order as in telegram doc
|
||||
# followed by the optional arguments: https://core.telegram.org/bots/api#inlinequeryresult
|
||||
inline_query_compose(){
|
||||
local JSON="{}"
|
||||
local ID="$1"
|
||||
local fours last
|
||||
# title2Json title caption description markup inlinekeyboard
|
||||
case "$2" in
|
||||
# user provided media
|
||||
"article"|"message") # article ID title message (markup description)
|
||||
JSON='{"type":"article","id":"'${ID}'","input_message_content": {"message_text":"'$4'"} '$(title2Json "$3" "" "$5" "$6" "$7")'}'
|
||||
;;
|
||||
"photo") # photo ID photoURL (thumbURL title description caption)
|
||||
[ -z "$4" ] && tumb="$3"
|
||||
JSON='{"type":"photo","id":"'${ID}'","photo_url":"'$3'","thumb_url":"'$4${tumb}'"'$(title2Json "$5" "$7" "$6" "$7" "$8")'}'
|
||||
;;
|
||||
"gif") # gif ID photoURL (thumbURL title caption)
|
||||
[ -z "$4" ] && tumb="$3"
|
||||
JSON='{"type":"gif","id":"'${ID}'","gif_url":"'$3'", "thumb_url":"'$4${tumb}'"'$(title2Json "$5" "$6" "$7" "$8" "$9")'}'
|
||||
;;
|
||||
"mpeg4_gif") # mpeg4_gif ID mpegURL (thumbURL title caption)
|
||||
[ -n "$4" ] && tumb='","thumb_url":"'$4'"'
|
||||
JSON='{"type":"mpeg4_gif","id":"'${ID}'","mpeg4_url":"'$3'"'${tumb}$(title2Json "$5" "$6" "" "$7" "$8")'}'
|
||||
;;
|
||||
"video") # video ID videoURL mime thumbURL title (caption)
|
||||
JSON='{"type":"video","id":"'${ID}'","video_url":"'$3'","mime_type":"'$4'","thumb_url":"'$5'"'$(title2Json "$6" "$7" "$8" "$9" "${10}")'}'
|
||||
;;
|
||||
"audio") # audio ID audioURL title (caption)
|
||||
JSON='{"type":"audio","id":"'${ID}'","audio_url":"'$3'"'$(title2Json "$4" "$5" "" "" "$6")'}'
|
||||
;;
|
||||
"voice") # voice ID voiceURL title (caption)
|
||||
JSON='{"type":"voice","id":"'${ID}'","voice_url":"'$3'"'$(title2Json "$4" "$5" "" "" "$6")'}'
|
||||
;;
|
||||
"document") # document ID title documentURL mimetype (caption description)
|
||||
JSON='{"type":"document","id":"'${ID}'","document_url":"'$4'","mime_type":"'$5'"'$(title2Json "$3" "$6" "$7" "$8" "$9")'}'
|
||||
;;
|
||||
"location") # location ID lat long title
|
||||
JSON='{"type":"location","id":"'${ID}'","latitude":"'$3'","longitude":"'$4'","title":"'$5'"}'
|
||||
;;
|
||||
"venue") # venue ID lat long title (address forsquare)
|
||||
[ -z "$6" ] && addr="$5"
|
||||
[ -n "$7" ] && fours=',"foursquare_id":"'$7'"'
|
||||
JSON='{"type":"venue","id":"'${ID}'","latitude":"'$3'","longitude":"'$4'","title":"'$5'","address":"'$6${addr}'"'${fours}'}'
|
||||
;;
|
||||
"contact") # contact ID phone first (last thumb)
|
||||
[ -n "$5" ] && last=',"last_name":"'$5'"'
|
||||
[ -n "$6" ] && tumb='","thumb_url":"'$6'"'
|
||||
JSON='{"type":"contact","id":"'${ID}'","phone_number":"'$3'","first_name":"'$4'"'${last}'"}'
|
||||
;;
|
||||
# title2Json title caption description markup inlinekeyboard
|
||||
# Cached media stored in Telegram server
|
||||
"cached_photo") # photo ID file (title description caption)
|
||||
JSON='{"type":"photo","id":"'${ID}'","photo_file_id":"'$3'"'$(title2Json "$4" "$6" "$5" "$7" "$8")'}'
|
||||
;;
|
||||
"cached_gif") # gif ID file (title caption)
|
||||
JSON='{"type":"gif","id":"'${ID}'","gif_file_id":"'$3'"'$(title2Json "$4" "$5" "$6" "$7" "$8" )'}'
|
||||
;;
|
||||
"cached_mpeg4_gif") # mpeg ID file (title caption)
|
||||
JSON='{"type":"mpeg4_gif","id":"'${ID}'","mpeg4_file_id":"'$3'"'$(title2Json "$4" "$5" "" "$6" "$7")'}'
|
||||
;;
|
||||
"cached_sticker") # sticker ID file
|
||||
JSON='{"type":"sticker","id":"'${ID}'","sticker_file_id":"'$3'"}'
|
||||
;;
|
||||
"cached_document") # document ID title file (description caption)
|
||||
JSON='{"type":"document","id":"'${ID}'","document_file_id":"'$4'"'$(title2Json "$3" "$6" "$5" "$6" "$7")'}'
|
||||
;;
|
||||
"cached_video") # video ID file title (description caption)
|
||||
JSON='{"type":"video","id":"'${ID}'","video_file_id":"'$3'"'$(title2Json "$4" "$6" "$5" "$7" "$8")'}'
|
||||
;;
|
||||
"cached_voice") # voice ID file title (caption)
|
||||
JSON='{"type":"voice","id":"'${ID}'","voice_file_id":"'$3'"'$(title2Json "$4" "$5" "" "" "$6")'}'
|
||||
;;
|
||||
"cached_audio") # audio ID file title (caption)
|
||||
JSON='{"type":"audio","id":"'${ID}'","audio_file_id":"'$3'"'$(title2Json "$4" "$5" "" "" "$6")'}'
|
||||
;;
|
||||
esac
|
||||
|
||||
printf '%s\n' "${JSON}"
|
||||
}
|
||||
|
|
@ -5,114 +5,170 @@
|
|||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
# shellcheck disable=SC1117,SC2059
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
# source from commands.sh if you want ro use interactive or background jobs
|
||||
# will be automatically sourced from bashbot
|
||||
|
||||
## to statisfy shellcheck
|
||||
export res
|
||||
|
||||
####
|
||||
# I placed send_message here because main use case is interactive chats and background jobs
|
||||
send_message() {
|
||||
[ "$2" = "" ] && return
|
||||
local text keyboard btext burl no_keyboard file lat long title address sent
|
||||
text="$(sed <<< "${2}" 's/ mykeyboardend.*//;s/ *my[kfltab][a-z]\{2,13\}startshere.*//')$(sed <<< "${2}" -n '/mytextstartshere/ s/.*mytextstartshere//p')"
|
||||
text="$(sed <<< "${text}" 's/ *mynewlinestartshere */\r\n/g')"
|
||||
[ "$3" != "safe" ] && {
|
||||
no_keyboard="$(sed <<< "${2}" '/mykeyboardendshere/!d;s/.*mykeyboardendshere.*/mykeyboardendshere/')"
|
||||
keyboard="$(sed <<< "${2}" '/mykeyboardstartshere /!d;s/.*mykeyboardstartshere *//;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')"
|
||||
btext="$(sed <<< "${2}" '/mybtextstartshere /!d;s/.*mybtextstartshere //;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')"
|
||||
burl="$(sed <<< "${2}" '/myburlstartshere /!d;s/.*myburlstartshere //;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//g;s/ *mykeyboardendshere.*//g')"
|
||||
file="$(sed <<< "${2}" '/myfilelocationstartshere /!d;s/.*myfilelocationstartshere //;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')"
|
||||
lat="$(sed <<< "${2}" '/mylatstartshere /!d;s/.*mylatstartshere //;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')"
|
||||
long="$(sed <<< "${2}" '/mylongstartshere /!d;s/.*mylongstartshere //;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')"
|
||||
title="$(sed <<< "${2}" '/mytitlestartshere /!d;s/.*mytitlestartshere //;s/ *my[kfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')"
|
||||
address="$(sed <<< "${2}" '/myaddressstartshere /!d;s/.*myaddressstartshere //;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')"
|
||||
}
|
||||
if [ "$no_keyboard" != "" ]; then
|
||||
remove_keyboard "$1" "$text"
|
||||
sent=y
|
||||
fi
|
||||
if [ "$keyboard" != "" ]; then
|
||||
if [[ "$keyboard" != *"["* ]]; then # pre 0.60 style
|
||||
keyboard="[ ${keyboard//\" \"/\" \] , \[ \"} ]"
|
||||
fi
|
||||
send_keyboard "$1" "$text" "$keyboard"
|
||||
sent=y
|
||||
fi
|
||||
if [ "$btext" != "" ] && [ "$burl" != "" ]; then
|
||||
send_button "$1" "$text" "$btext" "$burl"
|
||||
sent=y
|
||||
fi
|
||||
if [ "$file" != "" ]; then
|
||||
send_file "$1" "$file" "$text"
|
||||
sent=y
|
||||
fi
|
||||
if [ "$lat" != "" ] && [ "$long" != "" ]; then
|
||||
if [ "$address" != "" ] && [ "$title" != "" ]; then
|
||||
send_venue "$1" "$lat" "$long" "$title" "$address"
|
||||
else
|
||||
send_location "$1" "$lat" "$long"
|
||||
fi
|
||||
sent=y
|
||||
fi
|
||||
if [ "$sent" != "y" ];then
|
||||
send_text "$1" "$text"
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
send_text() {
|
||||
case "$2" in
|
||||
html_parse_mode*)
|
||||
send_html_message "$1" "${2//html_parse_mode}"
|
||||
;;
|
||||
markdown_parse_mode*)
|
||||
send_markdown_message "$1" "${2//markdown_parse_mode}"
|
||||
;;
|
||||
*)
|
||||
send_normal_message "$1" "$2"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
# source once magic, function named like file
|
||||
eval "$(basename "${BASH_SOURCE[0]}")(){ :; }"
|
||||
|
||||
######
|
||||
# interactive and background functions
|
||||
|
||||
# old syntax as aliases
|
||||
background() {
|
||||
echo "${CHAT[ID]}:$2:$1" >"${TMPDIR:-.}/${copname:--}$2-back.cmd"
|
||||
startproc "$1" "back-$2-"
|
||||
start_back "${CHAT[ID]}" "$1" "$2"
|
||||
}
|
||||
|
||||
startproc() {
|
||||
killproc "$2"
|
||||
local fifo="$2${copname}"
|
||||
mkfifo "${TMPDIR:-.}/${fifo}"
|
||||
tmux new-session -d -s "${fifo}" "$1 &>${TMPDIR:-.}/${fifo}; echo imprettydarnsuredatdisisdaendofdacmd>${TMPDIR:-.}/${fifo}"
|
||||
tmux new-session -d -s "sendprocess_${fifo}" "bash $SCRIPT outproc ${CHAT[ID]} ${fifo}"
|
||||
start_proc "${CHAT[ID]}" "$1" "$2"
|
||||
}
|
||||
|
||||
|
||||
checkback() {
|
||||
checkproc "back-$1-"
|
||||
check_back "${CHAT[ID]}" "$1"
|
||||
}
|
||||
|
||||
checkproc() {
|
||||
tmux ls | grep -q "$1${copname}"; res=$?; return $?
|
||||
check_proc "${CHAT[ID]}" "$1"
|
||||
}
|
||||
|
||||
killback() {
|
||||
killproc "back-$1-"
|
||||
rm -f "${TMPDIR:-.}/${copname}$1-back.cmd"
|
||||
kill_back "${CHAT[ID]}" "$1"
|
||||
}
|
||||
|
||||
killproc() {
|
||||
local fifo="$1${copname}"
|
||||
(tmux kill-session -t "${fifo}"; echo imprettydarnsuredatdisisdaendofdacmd>"${TMPDIR:-.}/${fifo}"; tmux kill-session -t "sendprocess_${fifo}"; rm -f -r "${TMPDIR:-.}/${fifo}")2>/dev/null
|
||||
kill_proc "${CHAT[ID]}" "$1"
|
||||
}
|
||||
|
||||
inproc() {
|
||||
tmux send-keys -t "$copname" "${MESSAGE[0]} ${URLS[*]}
|
||||
"
|
||||
# inline and background functions
|
||||
# $1 chatid
|
||||
# $2 program
|
||||
# $3 jobname
|
||||
# $4 $5 parameters
|
||||
start_back() {
|
||||
local cmdfile; cmdfile="${DATADIR:-.}/$(procname "$1")$3-back.cmd"
|
||||
printf '%s\n' "$1:$3:$2" >"${cmdfile}"
|
||||
restart_back "$@"
|
||||
}
|
||||
# $1 chatid
|
||||
# $2 program
|
||||
# $3 jobname
|
||||
# $4 $5 parameters
|
||||
restart_back() {
|
||||
local fifo; fifo="${DATADIR:-.}/$(procname "$1" "back-$3-")"
|
||||
log_update "Start background job CHAT=$1 JOB=${fifo##*/} CMD=${2##*/} $4 $5"
|
||||
check_back "$1" "$3" && kill_proc "$1" "back-$3-"
|
||||
nohup bash -c "{ $2 \"$4\" \"$5\" \"${fifo}\" | \"${SCRIPT}\" outproc \"$1\" \"${fifo}\"; }" &>>"${fifo}.log" &
|
||||
sleep 0.5 # give bg job some time to init
|
||||
}
|
||||
|
||||
|
||||
# $1 chatid
|
||||
# $2 program
|
||||
# $3 $4 parameters
|
||||
start_proc() {
|
||||
[ -z "$2" ] && return
|
||||
[ -x "${2%% *}" ] || return 1
|
||||
local fifo; fifo="${DATADIR:-.}/$(procname "$1")"
|
||||
check_proc "$1" && kill_proc "$1"
|
||||
mkfifo "${fifo}"
|
||||
log_update "Start interactive script CHAT=$1 JOB=${fifo##*/} CMD=$2 $3 $4"
|
||||
nohup bash -c "{ $2 \"$4\" \"$5\" \"${fifo}\" | \"${SCRIPT}\" outproc \"$1\" \"${fifo}\"
|
||||
rm \"${fifo}\"; [ -s \"${fifo}.log\" ] || rm -f \"${fifo}.log\"; }" &>>"${fifo}.log" &
|
||||
}
|
||||
|
||||
|
||||
# $1 chatid
|
||||
# $2 jobname
|
||||
check_back() {
|
||||
check_proc "$1" "back-$2-"
|
||||
}
|
||||
|
||||
# $1 chatid
|
||||
# $2 prefix
|
||||
check_proc() {
|
||||
[ -n "$(proclist "$(procname "$1" "$2")")" ]
|
||||
# shellcheck disable=SC2034
|
||||
res=$?; return $?
|
||||
}
|
||||
|
||||
# $1 chatid
|
||||
# $2 jobname
|
||||
kill_back() {
|
||||
kill_proc "$1" "back-$2-"
|
||||
rm -f "${DATADIR:-.}/$(procname "$1")$2-back.cmd"
|
||||
}
|
||||
|
||||
|
||||
# $1 chatid
|
||||
# $2 prefix
|
||||
kill_proc() {
|
||||
local fifo prid
|
||||
fifo="$(procname "$1" "$2")"
|
||||
prid="$(proclist "${fifo}")"
|
||||
fifo="${DATADIR:-.}/${fifo}"
|
||||
# shellcheck disable=SC2086
|
||||
if [ -n "${prid}" ]; then
|
||||
log_update "Stop interactive / background CHAT=$1 JOB=${fifo##*/}"
|
||||
kill ${prid}
|
||||
fi
|
||||
[ -s "${fifo}.log" ] || rm -f "${fifo}.log"
|
||||
[ -p "${fifo}" ] && rm -f "${fifo}";
|
||||
}
|
||||
|
||||
# $1 chatid
|
||||
# $2 message
|
||||
send_interactive() {
|
||||
local fifo; fifo="${DATADIR:-.}/$(procname "$1")"
|
||||
[ -p "${fifo}" ] && printf '%s\n' "$2" >"${fifo}" & # not blocking!
|
||||
}
|
||||
|
||||
# old style but may not work because of local checks
|
||||
inproc() {
|
||||
send_interactive "${CHAT[ID]}" "${MESSAGE[0]}"
|
||||
}
|
||||
|
||||
# start stop all jobs
|
||||
# $1 command # kill suspend resume restart
|
||||
job_control() {
|
||||
local BOT ADM content proc CHAT job fifo killall=""
|
||||
BOT="$(getConfigKey "botname")"
|
||||
ADM="${BOTADMIN}"
|
||||
debug_checks "Enter job_control" "$1"
|
||||
# cleanup on start
|
||||
[[ "$1" == "re"* ]] && bot_cleanup "startback"
|
||||
for FILE in "${DATADIR:-.}/"*-back.cmd; do
|
||||
[ "${FILE}" = "${DATADIR:-.}/*-back.cmd" ] && printf "${RED}No background processes.${NN}" && break
|
||||
content="$(< "${FILE}")"
|
||||
CHAT="${content%%:*}"
|
||||
job="${content#*:}"
|
||||
proc="${job#*:}"
|
||||
job="${job%:*}"
|
||||
fifo="$(procname "${CHAT}" "${job}")"
|
||||
debug_checks "Execute job_control" "$1" "${FILE##*/}"
|
||||
case "$1" in
|
||||
"resume"*|"restart"*)
|
||||
printf "Restart Job: %s %s\n" "${proc}" " ${fifo##*/}"
|
||||
restart_back "${CHAT}" "${proc}" "${job}"
|
||||
# inform botadmin about stop
|
||||
[ -n "${ADM}" ] && send_normal_message "${ADM}" "Bot ${BOT} restart background jobs ..." &
|
||||
;;
|
||||
"suspend"*)
|
||||
printf "Suspend Job: %s %s\n" "${proc}" " ${fifo##*/}"
|
||||
kill_proc "${CHAT}" "${job}"
|
||||
# inform botadmin about stop
|
||||
[ -n "${ADM}" ] && send_normal_message "${ADM}" "Bot ${BOT} suspend background jobs ..." &
|
||||
killall="y"
|
||||
;;
|
||||
"kill"*)
|
||||
printf "Kill Job: %s %s\n" "${proc}" " ${fifo##*/}"
|
||||
kill_proc "${CHAT}" "${job}"
|
||||
rm -f "${FILE}" # remove job
|
||||
# inform botadmin about stop
|
||||
[ -n "${ADM}" ] && send_normal_message "${ADM}" "Bot ${BOT} kill background jobs ..." &
|
||||
killall="y"
|
||||
;;
|
||||
esac
|
||||
# send message only onnfirst job
|
||||
ADM=""
|
||||
done
|
||||
debug_checks "end job_control" "$1"
|
||||
# kill all requestet. kill ALL background jobs, even not listed in data-bot-bash
|
||||
[ "${killall}" = "y" ] && killallproc "back-"
|
||||
}
|
||||
|
|
173
modules/chatMember.sh
Normal file
173
modules/chatMember.sh
Normal file
|
@ -0,0 +1,173 @@
|
|||
#!/bin/bash
|
||||
# file: modules/chatMember.sh
|
||||
# do not edit, this file will be overwritten on update
|
||||
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
# will be automatically sourced from bashbot
|
||||
|
||||
# source once magic, function named like file
|
||||
eval "$(basename "${BASH_SOURCE[0]}")(){ :; }"
|
||||
|
||||
|
||||
# manage chat functions -------
|
||||
# $1 chat
|
||||
new_chat_invite() {
|
||||
sendJson "$1" "" "${URL}/exportChatInviteLink"
|
||||
[ "${BOTSENT[OK]}" = "true" ] && printf "%s\n" "${BOTSENT[RESULT]}"
|
||||
}
|
||||
|
||||
# $1 chat, $2 user_id, $3 title
|
||||
set_chatadmin_title() {
|
||||
sendJson "$1" '"user_id":'"$2"',"custom_title": "'"$3"'"' "${URL}/setChatAdministratorCustomTitle"
|
||||
}
|
||||
# $1 chat, $2 title
|
||||
set_chat_title() {
|
||||
sendJson "$1" '"title": "'"$2"'"' "${URL}/setChatTitle"
|
||||
}
|
||||
|
||||
# $1 chat, $2 title
|
||||
set_chat_description() {
|
||||
sendJson "$1" '"description": "'"$2"'"' "${URL}/setChatDescription"
|
||||
}
|
||||
|
||||
# $1 chat $2 file
|
||||
set_chat_photo() {
|
||||
local file; file="$(checkUploadFile "$1" "$2" "set_chat_photo")"
|
||||
[ -z "${file}" ] && return 1
|
||||
sendUpload "$1" "photo" "${file}" "${URL}/setChatPhoto"
|
||||
}
|
||||
# $1 chat
|
||||
delete_chat_photo() {
|
||||
sendJson "$1" "" "${URL}/deleteChatPhoto"
|
||||
}
|
||||
|
||||
# $1 chat, $2 message_id
|
||||
pin_chat_message() {
|
||||
sendJson "$1" '"message_id": "'"$2"'"' "${URL}/pinChatMessage"
|
||||
}
|
||||
|
||||
# $1 chat, $2 message_id
|
||||
unpin_chat_message() {
|
||||
sendJson "$1" '"message_id": "'"$2"'"' "${URL}/unpinChatMessage"
|
||||
}
|
||||
|
||||
# $1 chat
|
||||
unpinall_chat_message() {
|
||||
sendJson "$1" "" "${URL}/unpinAllChatMessages"
|
||||
}
|
||||
|
||||
# $1 chat
|
||||
delete_chat_stickers() {
|
||||
sendJson "$1" "" "${URL}/deleteChatStickerSet"
|
||||
}
|
||||
|
||||
# manage chat member functions -------
|
||||
# $1 chat
|
||||
chat_member_count() {
|
||||
sendJson "$1" "" "${URL}/getChatMembersCount"
|
||||
[ "${BOTSENT[OK]}" = "true" ] && printf "%s\n" "${BOTSENT[RESULT]}"
|
||||
}
|
||||
|
||||
kick_chat_member() {
|
||||
sendJson "$1" '"user_id": '"$2"'' "${URL}/kickChatMember"
|
||||
}
|
||||
|
||||
unban_chat_member() {
|
||||
sendJson "$1" '"user_id": '"$2"'' "${URL}/unbanChatMember"
|
||||
}
|
||||
|
||||
leave_chat() {
|
||||
sendJson "$1" "" "${URL}/leaveChat"
|
||||
}
|
||||
|
||||
# $1 chat, $2 userid, $3 ... "right[:true]" default false
|
||||
# right: is_anonymous change_info post_messages edit_messages delete_messages invite_users restrict_members pin_messages promote_member
|
||||
promote_chat_member() {
|
||||
local arg bool json chat="$1" user="$2; shift 2"
|
||||
for arg in "$@"
|
||||
do
|
||||
# default false
|
||||
bool=false; [ "${arg##*:}" = "true" ] && bool="true"
|
||||
# expand args
|
||||
case "${arg}" in
|
||||
*"anon"*) arg="is_anonymous";;
|
||||
*"change"*) arg="can_change_info";;
|
||||
*"post"*) arg="can_post_messages";;
|
||||
*"edit"*) arg="can_edit_messages";;
|
||||
*"delete"*) arg="can_delete_messages";;
|
||||
*"pin"*) arg="can_pin_messages";;
|
||||
*"invite"*) arg="can_invite_users";;
|
||||
*"restrict"*) arg="can_restrict_members";;
|
||||
*"promote"*) arg="can_promote_members";;
|
||||
*) [ -n "${BASHBOTDEBUG}" ] && log_debug "promote_chat_member: unknown promotion CHAT=${chat} USER=${user} PROM=${arg}"
|
||||
continue;;
|
||||
esac
|
||||
# compose json
|
||||
[ -n "${json}" ] && json+=","
|
||||
json+='"'"${arg}"'": "'"${bool}"'"'
|
||||
done
|
||||
sendJson "${chat}" '"user_id":'"${user}"','"${json}"'' "${URL}/promoteChatMember"
|
||||
}
|
||||
|
||||
# bashbot specific functions ---------
|
||||
|
||||
# usage: status="$(get_chat_member_status "chat" "user")"
|
||||
# $1 chat # $2 user
|
||||
get_chat_member_status() {
|
||||
sendJson "$1" '"user_id":'"$2"'' "${URL}/getChatMember"
|
||||
# shellcheck disable=SC2154
|
||||
printf "%s\n" "${UPD["result,status"]}"
|
||||
}
|
||||
|
||||
user_is_creator() {
|
||||
# empty is false ...
|
||||
[[ "${1:--}" == "${2:-+}" || "$(get_chat_member_status "$1" "$2")" == "creator" ]] && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
# $1 chat
|
||||
bot_is_admin() {
|
||||
user_is_admin "$1" "$(getConfigKey "botid")"
|
||||
}
|
||||
|
||||
# $1 chat # $2 user
|
||||
user_is_admin() {
|
||||
[[ -z "$1" || -z "$2" ]] && return 1
|
||||
[ "${1:--}" == "${2:-+}" ] && return 0
|
||||
user_is_botadmin "$2" && return 0
|
||||
local me; me="$(get_chat_member_status "$1" "$2")"
|
||||
[[ "${me}" =~ ^creator$|^administrator$ ]] && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
# $1 user
|
||||
user_is_botadmin() {
|
||||
[ -z "$1" ] && return 1
|
||||
[ -z "${BOTADMIN}" ] && return 1
|
||||
[[ "${BOTADMIN}" == "$1" || "${BOTADMIN}" == "$2" ]] && return 0
|
||||
if [ "${BOTADMIN}" = "?" ]; then setConfigKey "botadmin" "${1:-?}"; BOTADMIN="${1:-?}"; return 0; fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# $1 user # $2 key # $3 chat
|
||||
user_is_allowed() {
|
||||
[ -z "$1" ] && return 1
|
||||
user_is_admin "$1" && return 0
|
||||
# user can do everything
|
||||
grep -F -xq "$1:*:*" "${BOTACL}" && return 0
|
||||
[ -z "$2" ] && return 1
|
||||
# user is allowed todo one action in every chat
|
||||
grep -F -xq "$1:$2:*" "${BOTACL}" && return 0
|
||||
# all users are allowed to do one action in every chat
|
||||
grep -F -xq "ALL:$2:*" "${BOTACL}" && return 0
|
||||
[ -z "$3" ] && return 1
|
||||
# user is allowed to do one action in one chat
|
||||
grep -F -xq "$1:$2:$3" "${BOTACL}" && return 0
|
||||
# all users are allowed to do one action in one chat
|
||||
grep -F -xq "ALL:$2:$3" "${BOTACL}" && return 0
|
||||
return 1
|
||||
}
|
|
@ -1,114 +0,0 @@
|
|||
#!/bin/bash
|
||||
# file: modules/inline.sh
|
||||
# do not edit, this file will be overwritten on update
|
||||
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
|
||||
# source from commands.sh to use the inline functions
|
||||
|
||||
INLINE_QUERY=$URL'/answerInlineQuery'
|
||||
declare -A iQUERY
|
||||
export iQUERY
|
||||
|
||||
process_inline() {
|
||||
local num="${1}"
|
||||
iQUERY[0]="$(JsonDecode "$(JsonGetString <<<"${UPDATE}" '"result",0,"inline_query","query"')")"
|
||||
iQUERY[USER_ID]="$(JsonGetValue <<<"${UPDATE}" '"result",'"${num}"',"inline_query","from","id"')"
|
||||
iQUERY[FIRST_NAME]="$(JsonDecode "$(JsonGetString <<<"${UPDATE}" '"result",'"${num}"',"inline_query","from","first_name"')")"
|
||||
iQUERY[LAST_NAME]="$(JsonDecode "$(JsonGetString <<<"${UPDATE}" '"result",'"${num}"',"inline_query","from","last_name"')")"
|
||||
iQUERY[USERNAME]="$(JsonDecode "$(JsonGetString <<<"${UPDATE}" '"result",'"${num}"',"inline_query","from","username"')")"
|
||||
}
|
||||
|
||||
|
||||
answer_inline_query() {
|
||||
answer_inline_multi "${1}" "$(shift; inline_query_compose "$RANDOM" "$@")"
|
||||
}
|
||||
answer_inline_multi() {
|
||||
sendJson "" '"inline_query_id": '"${1}"', "results": ['"${2}"']' "${INLINE_QUERY}"
|
||||
}
|
||||
|
||||
# $1 unique ID for answer
|
||||
# $2 type of answer
|
||||
# remaining arguments are the "must have" arguments in the order as in telegram doc
|
||||
# followed by the optional arguments: https://core.telegram.org/bots/api#inlinequeryresult
|
||||
inline_query_compose(){
|
||||
local JSON="{}"
|
||||
local ID="${1}"
|
||||
local fours last
|
||||
# title2Json title caption description markup inlinekeyboard
|
||||
case "${2}" in
|
||||
# user provided media
|
||||
"article"|"message") # article ID title message (markup decription)
|
||||
JSON='{"type":"article","id":"'$ID'","input_message_content": {"message_text":"'$4'"} '$(title2Json "$3" "" "$5" "$6")'}'
|
||||
;;
|
||||
"photo") # photo ID photoURL (thumbURL title description caption)
|
||||
[ "$4" = "" ] && tumb="$3"
|
||||
JSON='{"type":"photo","id":"'$ID'","photo_url":"'$3'","thumb_url":"'$4${tumb}'"'$(title2Json "$5" "$7" "$6")'}'
|
||||
;;
|
||||
"gif") # gif ID photoURL (thumbURL title caption)
|
||||
[ "$4" = "" ] && tumb="$3"
|
||||
JSON='{"type":"gif","id":"'$ID'","gif_url":"'$3'", "thumb_url":"'$4${tumb}'"'$(title2Json "$5" "$6")'}'
|
||||
;;
|
||||
"mpeg4_gif") # mpeg4_gif ID mpegURL (thumbURL title caption)
|
||||
[ "$4" != "" ] && tumb='","thumb_url":"'$4'"'
|
||||
JSON='{"type":"mpeg4_gif","id":"'$ID'","mpeg4_url":"'$3'"'${tumb}$(title2Json "$5" "$6")'}'
|
||||
;;
|
||||
"video") # video ID videoURL mime thumbURL title (caption)
|
||||
JSON='{"type":"video","id":"'$ID'","video_url":"'$3'","mime_type":"'$4'","thumb_url":"'$5'"'$(title2Json "$6" "$7")'}'
|
||||
;;
|
||||
"audio") # audio ID audioURL title (caption)
|
||||
JSON='{"type":"audio","id":"'$ID'","audio_url":"'$3'"'$(title2Json "$4" "$5")'}'
|
||||
;;
|
||||
"voice") # voice ID voiceURL title (caption)
|
||||
JSON='{"type":"voice","id":"'$ID'","voice_url":"'$3'"'$(title2Json "$4" "$5")'}'
|
||||
;;
|
||||
"document") # document ID title documentURL mimetype (caption description)
|
||||
JSON='{"type":"document","id":"'$ID'","document_url":"'$4'","mime_type":"'$5'"'$(title2Json "$3" "$6" "$7")'}'
|
||||
;;
|
||||
"location") # location ID lat long title
|
||||
JSON='{"type":"location","id":"'$ID'","latitude":"'$3'","longitude":"'$4'","title":"'$5'"}'
|
||||
;;
|
||||
"venue") # venue ID lat long title (adress forsquare)
|
||||
[ "$6" = "" ] && addr="$5"
|
||||
[ "$7" != "" ] && fours=',"foursquare_id":"'$7'"'
|
||||
JSON='{"type":"venue","id":"'$ID'","latitude":"'$3'","longitude":"'$4'","title":"'$5'","address":"'$6${addr}'"'${fours}'}'
|
||||
;;
|
||||
"contact") # contact ID phone first (last thumb)
|
||||
[ "$5" != "" ] && last=',"last_name":"'$5'"'
|
||||
[ "$6" != "" ] && tumb='","thumb_url":"'$6'"'
|
||||
JSON='{"type":"contact","id":"'$ID'","phone_number":"'$3'","first_name":"'$4'"'${last}'"}'
|
||||
;;
|
||||
# title2Json title caption description markup inlinekeyboard
|
||||
# Cached media stored in Telegram server
|
||||
"cached_photo") # photo ID file (title description caption)
|
||||
JSON='{"type":"photo","id":"'$ID'","photo_file_id":"'$3'"'$(title2Json "$4" "$6" "$5")'}'
|
||||
;;
|
||||
"cached_gif") # gif ID file (title caption)
|
||||
JSON='{"type":"gif","id":"'$ID'","gif_file_id":"'$3'"'$(title2Json "$4" "$5")'}'
|
||||
;;
|
||||
"cached_mpeg4_gif") # mpeg ID file (title caption)
|
||||
JSON='{"type":"mpeg4_gif","id":"'$ID'","mpeg4_file_id":"'$3'"'$(title2Json "$4" "$5")'}'
|
||||
;;
|
||||
"cached_sticker") # sticker ID file
|
||||
JSON='{"type":"sticker","id":"'$ID'","sticker_file_id":"'$3'"}'
|
||||
;;
|
||||
"cached_document") # document ID title file (description caption)
|
||||
JSON='{"type":"document","id":"'$ID'","document_file_id":"'$4'"'$(title2Json "$3" "$6" "$5")'}'
|
||||
;;
|
||||
"cached_video") # video ID file title (description caption)
|
||||
JSON='{"type":"video","id":"'$ID'","video_file_id":"'$3'"'$(title2Json "$4" "$6" "$5")'}'
|
||||
;;
|
||||
"cached_voice") # voice ID file title (caption)
|
||||
JSON='{"type":"voice","id":"'$ID'","voice_file_id":"'$3'"'$(title2Json "$4" "$5")'}'
|
||||
;;
|
||||
"cached_audio") # audio ID file title (caption)
|
||||
JSON='{"type":"audio","id":"'$ID'","audio_file_id":"'$3'"'$(title2Json "$4" "$5")'}'
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "${JSON}"
|
||||
}
|
||||
|
377
modules/jsonDB.sh
Normal file
377
modules/jsonDB.sh
Normal file
|
@ -0,0 +1,377 @@
|
|||
#!/bin/bash
|
||||
# file: modules/jsshDB.sh
|
||||
# do not edit, this file will be overwritten on update
|
||||
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#
|
||||
# source from commands.sh to use jsonDB functions
|
||||
#
|
||||
# jsonDB provides simple functions to read and store bash Arrays
|
||||
# from to file in JSON.sh output format, its a simple key/value storage.
|
||||
|
||||
# will be automatically sourced from bashbot
|
||||
# but can be used independent from bashbot also
|
||||
# e.g. to create scrupts to manage jssh files
|
||||
|
||||
# source once magic, function named like file
|
||||
eval "$(basename "${BASH_SOURCE[0]}")(){ :; }"
|
||||
|
||||
# new feature: serialize / atomic operations:
|
||||
# updates will be done atomic with flock
|
||||
# flock should flock should be available on all system as its part of busybox
|
||||
# tinybox
|
||||
|
||||
# lockfile filename.flock is persistent and will be testet with flock for active lock (file open)
|
||||
export JSSHDB_LOCKNAME=".flock"
|
||||
# an array value containing this string will not saveed to DB (unset)
|
||||
export JSSHDB_UNSET="99999999999999999999_JSSHDB_UNSET_99999999999999999999"
|
||||
|
||||
# in UTF-8 äöü etc. are part of [:alnum:] and ranges (e.g. a-z), but we want ASCII a-z ranges!
|
||||
# for more information see doc/4_expert.md#Character_classes
|
||||
azazaz='abcdefghijklmnopqrstuvwxyz' # a-z :lower:
|
||||
AZAZAZ='ABCDEFGHIJKLMNOPQRSTUVWXYZ' # A-Z :upper:
|
||||
o9o9o9='0123456789' # 0-9 :digit:
|
||||
azAZaz="${azazaz}${AZAZAZ}" # a-zA-Z :alpha:
|
||||
azAZo9="${azAZaz}${o9o9o9}" # a-zA-z0-9 :alnum:
|
||||
|
||||
# characters allowed for key in key/value pairs
|
||||
JSSH_KEYOK="[-${azAZo9},._]"
|
||||
|
||||
# read string from stdin and and strip invalid characters
|
||||
# $1 - invalid charcaters are replaced with first character
|
||||
# or deleted if $1 is empty
|
||||
jssh_stripKey() { # tr: we must escape first - in [-a-z...]
|
||||
if [[ "$1" =~ ^${JSSH_KEYOK} ]]; then # tr needs [\-...
|
||||
tr -c "${JSSH_KEYOK/\[-/[\\-}\r\n" "${1:0:1}"
|
||||
else
|
||||
tr -dc "${JSSH_KEYOK/\[-/[\\-}\r\n"
|
||||
fi
|
||||
}
|
||||
|
||||
# use flock if command exist
|
||||
if [ "$(LC_ALL=C type -t "flock")" = "file" ]; then
|
||||
|
||||
###############
|
||||
# we have flock
|
||||
# use flock for atomic operations
|
||||
|
||||
# read content of a file in JSON.sh format into given ARRAY
|
||||
# $1 ARRAY name, must be declared with "declare -A ARRAY" upfront
|
||||
# $2 filename, must be relative to BASHBOT_ETC, and not contain '..'
|
||||
jssh_readDB() {
|
||||
local DB; DB="$(jssh_checkDB "$2")"
|
||||
[ -z "${DB}" ] && return 1
|
||||
[ ! -f "${DB}" ] && return 2
|
||||
# shared lock, many processes can read, max wait 1s
|
||||
{ flock -s -w 1 200; Json2Array "$1" <"${DB}"; } 200>"${DB}${JSSHDB_LOCKNAME}"
|
||||
}
|
||||
|
||||
# write ARRAY content to a file in JSON.sh format
|
||||
# Warning: old content is overwritten
|
||||
# $1 ARRAY name, must be declared with "declare -A ARRAY" upfront
|
||||
# $2 filename (must exist!), must be relative to BASHBOT_ETC, and not contain '..'
|
||||
jssh_writeDB() {
|
||||
local DB; DB="$(jssh_checkDB "$2")"
|
||||
[ -z "${DB}" ] && return 1
|
||||
[ ! -f "${DB}" ] && return 2
|
||||
# exclusive lock, no other process can read or write, maximum wait to get lock is 10s
|
||||
{ flock -e -w 10 200; Array2Json "$1" >"${DB}"; } 200>"${DB}${JSSHDB_LOCKNAME}"
|
||||
}
|
||||
|
||||
# update/write ARRAY content in file without deleting keys not in ARRAY
|
||||
# $1 ARRAY name, must be declared with "declare -A ARRAY" upfront
|
||||
# $2 filename (must exist!), must be relative to BASHBOT_ETC, and not contain '..'
|
||||
# complex slow, warpper async
|
||||
jssh_updateDB() {
|
||||
# for atomic update we can't use read/writeDB
|
||||
[ -z "$2" ] && return 1
|
||||
local DB="$2.jssh" # check in async
|
||||
[ ! -f "${DB}" ] && return 2
|
||||
{ flock -e -w 10 200; jssh_updateDB_async "$@"; } 200>"${DB}${JSSHDB_LOCKNAME}"
|
||||
}
|
||||
|
||||
# insert, update, apped key/value to jsshDB
|
||||
# $1 key name, can only contain -a-zA-Z0-9,._
|
||||
# $2 key value
|
||||
# $3 filename (must exist!), must be relative to BASHBOT_ETC, and not contain '..'
|
||||
alias jssh_insertDB=jssh_insertKeyDB # backward compatibility
|
||||
# renamed to be more consistent
|
||||
jssh_insertKeyDB() {
|
||||
[[ "$1" =~ ^${JSSH_KEYOK}+$ ]] || return 3
|
||||
local DB; DB="$(jssh_checkDB "$3")"
|
||||
[ -z "${DB}" ] && return 1
|
||||
[ ! -f "${DB}" ] && return 2
|
||||
# start atomic update here, exclusive max wait 2, it's append, not overwrite
|
||||
{ flock -e -w 2 200
|
||||
# it's append, but last one counts, its a simple DB ...
|
||||
printf '["%s"]\t"%s"\n' "${1//,/\",\"}" "${2//\"/\\\"}" >>"${DB}"
|
||||
} 200>"${DB}${JSSHDB_LOCKNAME}"
|
||||
|
||||
}
|
||||
|
||||
# delete key/value from jsshDB
|
||||
# $1 key name, can only contain -a-zA-Z0-9,._
|
||||
# $2 filename (must exist!), must be relative to BASHBOT_ETC, and not contain '..'
|
||||
# medium complex slow, wrapper async
|
||||
jssh_deleteKeyDB() {
|
||||
[ -z "$2" ] && return 1
|
||||
[[ "$1" =~ ^${JSSH_KEYOK}+$ ]] || return 3
|
||||
local DB="$2.jssh"
|
||||
# start atomic delete here, exclusive max wait 10s
|
||||
{ flock -e -w 10 200; jssh_deleteKeyDB_async "$@"; } 200>"${DB}${JSSHDB_LOCKNAME}"
|
||||
}
|
||||
|
||||
# get key/value from jsshDB
|
||||
# $1 key name, can only contain -a-zA-Z0-9,._
|
||||
# $2 filename (must exist!), must be relative to BASHBOT_ETC, and not contain '..'
|
||||
alias jssh_getDB=jssh_getKeyDB
|
||||
jssh_getKeyDB() {
|
||||
[[ "$1" =~ ^${JSSH_KEYOK}+$ ]] || return 3
|
||||
local DB; DB="$(jssh_checkDB "$2")"
|
||||
[ -z "${DB}" ] && return 1
|
||||
# start atomic delete here, exclusive max wait 1s
|
||||
{ flock -s -w 1 200
|
||||
[ -r "${DB}" ] && sed -n 's/\["'"$1"'"\]\t*"\(.*\)"/\1/p' "${DB}" | tail -n 1
|
||||
} 200>"${DB}${JSSHDB_LOCKNAME}"
|
||||
}
|
||||
|
||||
|
||||
# add a value to key, used for conters
|
||||
# $1 key name, can only contain -a-zA-Z0-9,._
|
||||
# $2 filename (must exist!), must be relative to BASHBOT_ETC, and not contain '..'
|
||||
# $3 optional count, value added to counter, add 1 if empty
|
||||
# side effect: if $3 is not given, we add to end of file to be as fast as possible
|
||||
# complex, wrapper to async
|
||||
jssh_countKeyDB() {
|
||||
[ -z "$2" ] && return 1
|
||||
[[ "$1" =~ ^${JSSH_KEYOK}+$ ]] || return 3
|
||||
local DB="$2.jssh"
|
||||
# start atomic delete here, exclusive max wait 5
|
||||
{ flock -e -w 5 200; jssh_countKeyDB_async "$@"; } 200>"${DB}${JSSHDB_LOCKNAME}"
|
||||
}
|
||||
|
||||
# update key/value in place to jsshDB
|
||||
# $1 key name, can only contain -a-zA-Z0-9,._
|
||||
# $2 key value
|
||||
# $3 filename (must exist!), must be relative to BASHBOT_ETC, and not contain '..'
|
||||
#no own locking, so async is the same as updatekeyDB
|
||||
jssh_updateKeyDB() {
|
||||
[[ "$1" =~ ^${JSSH_KEYOK}+$ ]] || return 3
|
||||
[ -z "$3" ] && return 1
|
||||
declare -A updARR
|
||||
# shellcheck disable=SC2034
|
||||
updARR["$1"]="$2"
|
||||
jssh_updateDB "updARR" "$3" || return 3
|
||||
}
|
||||
|
||||
# $1 filename (must exist!), must be relative to BASHBOT_ETC, and not contain '..'
|
||||
jssh_clearDB() {
|
||||
local DB; DB="$(jssh_checkDB "$1")"
|
||||
[ -z "${DB}" ] && return 1
|
||||
{ flock -e -w 10 200; printf '' >"${DB}"; } 200>"${DB}${JSSHDB_LOCKNAME}"
|
||||
}
|
||||
|
||||
# updates Array if DB file has changed since last call
|
||||
# $1 name of array to update
|
||||
# $2 database
|
||||
# $3 id used to identify caller
|
||||
# medium complex, wrapper async
|
||||
jssh_updateArray() {
|
||||
[ -z "$2" ] && return 1
|
||||
local DB="$2.jssh" # name check in async
|
||||
[ ! -f "${DB}" ] && return 2
|
||||
declare -n ARRAY="$1"
|
||||
[[ -z "${ARRAY[*]}" || "${DB}" -nt "${DB}.last$3" ]] && touch "${DB}.last$3" && jssh_readDB "$1" "$2"
|
||||
}
|
||||
|
||||
else
|
||||
#########
|
||||
# we have no flock, use non atomic functions
|
||||
alias jssh_readDB=ssh_readDB_async
|
||||
alias jssh_writeDB=jssh_writeDB_async
|
||||
alias jssh_updateDB=jssh_updateDB_async
|
||||
alias jssh_insertDB=jssh_insertDB_async
|
||||
alias ssh_deleteKeyDB=jssh_deleteKeyDB_async
|
||||
alias jssh_getDB=jssh_getKeyDB_async
|
||||
alias jssh_getKeyDB=jssh_getKeyDB_async
|
||||
alias jssh_countKeyDB=jssh_countKeyDB_async
|
||||
alias jssh_updateKeyDB=jssh_updateKeyDB_async
|
||||
alias jssh_clearDB=jssh_clearDB_async
|
||||
alias jssh_updateArray=updateArray_async
|
||||
fi
|
||||
|
||||
##############
|
||||
# no need for atomic
|
||||
|
||||
# print ARRAY content to stdout instead of file
|
||||
# $1 ARRAY name, must be declared with "declare -A ARRAY" upfront
|
||||
jssh_printDB_async() { jssh_printDB "$@"; }
|
||||
jssh_printDB() {
|
||||
Array2Json "$1"
|
||||
}
|
||||
|
||||
# $1 filename (must exist!), must be relative to BASHBOT_ETC, and not contain '..'
|
||||
jssh_newDB_async() { jssh_newDB "$@"; }
|
||||
jssh_newDB() {
|
||||
local DB; DB="$(jssh_checkDB "$1")"
|
||||
[ -z "${DB}" ] && return 1
|
||||
[ -f "${DB}" ] && return 2 # already exist
|
||||
touch "${DB}"
|
||||
}
|
||||
|
||||
# $1 filename, check filename, it must be relative to BASHBOT_VAR, and not contain '..'
|
||||
# returns real path to DB file if everything is ok
|
||||
jssh_checkDB_async() { jssh_checkDB "$@"; }
|
||||
jssh_checkDB(){
|
||||
local DB
|
||||
[ -z "$1" ] && return 1
|
||||
[[ "$1" = *'../.'* ]] && return 2
|
||||
if [[ "$1" == "${BASHBOT_VAR:-.}"* ]] || [[ "$1" == "${BASHBOT_DATA:-.}"* ]]; then
|
||||
DB="$1.jssh"
|
||||
else
|
||||
DB="${BASHBOT_VAR:-.}/$1.jssh"
|
||||
fi
|
||||
[ "${DB}" != ".jssh" ] && printf '%s' "${DB}"
|
||||
}
|
||||
|
||||
|
||||
######################
|
||||
# implementations as non atomic functions
|
||||
# can be used explictitly or as fallback if flock is not available
|
||||
jssh_readDB_async() {
|
||||
local DB; DB="$(jssh_checkDB "$2")"
|
||||
[ -z "${DB}" ] && return 1
|
||||
[ ! -f "${DB}" ] && return 2
|
||||
Json2Array "$1" <"${DB}"
|
||||
}
|
||||
|
||||
jssh_writeDB_async() {
|
||||
local DB; DB="$(jssh_checkDB "$2")"
|
||||
[ -z "${DB}" ] && return 1
|
||||
[ ! -f "${DB}" ] && return 2
|
||||
Array2Json "$1" >"${DB}"
|
||||
}
|
||||
|
||||
jssh_updateDB_async() {
|
||||
[ -z "$2" ] && return 1
|
||||
declare -n ARRAY="$1"
|
||||
[ -z "${ARRAY[*]}" ] && return 1
|
||||
declare -A oldARR
|
||||
jssh_readDB_async "oldARR" "$2" || return "$?"
|
||||
if [ -z "${oldARR[*]}" ]; then
|
||||
# no old content
|
||||
jssh_writeDB_async "$1" "$2"
|
||||
else
|
||||
# merge arrays
|
||||
local key
|
||||
for key in "${!ARRAY[@]}"
|
||||
do
|
||||
oldARR["${key}"]="${ARRAY["${key}"]}"
|
||||
done
|
||||
Array2Json "oldARR" >"${DB}"
|
||||
fi
|
||||
}
|
||||
|
||||
jssh_insertDB_async() { jssh_insertKeyDB "$@"; }
|
||||
jssh_insertKeyDB_async() {
|
||||
[[ "$1" =~ ^${JSSH_KEYOK}+$ ]] || return 3
|
||||
local DB; DB="$(jssh_checkDB "$3")"
|
||||
[ -z "${DB}" ] && return 1
|
||||
[ ! -f "${DB}" ] && return 2
|
||||
# its append, but last one counts, its a simple DB ...
|
||||
printf '["%s"]\t"%s"\n' "${1//,/\",\"}" "${2//\"/\\\"}" >>"${DB}"
|
||||
|
||||
}
|
||||
|
||||
jssh_deleteKeyDB_async() {
|
||||
[[ "$1" =~ ^${JSSH_KEYOK}+$ ]] || return 3
|
||||
local DB; DB="$(jssh_checkDB "$2")"
|
||||
[ -z "${DB}" ] && return 1
|
||||
declare -A oldARR
|
||||
Json2Array "oldARR" <"${DB}"
|
||||
unset oldARR["$1"]
|
||||
Array2Json "oldARR" >"${DB}"
|
||||
}
|
||||
|
||||
jssh_getKeyDB_async() {
|
||||
[[ "$1" =~ ^${JSSH_KEYOK}+$ ]] || return 3
|
||||
local DB; DB="$(jssh_checkDB "$2")"
|
||||
[ -z "${DB}" ] && return 1
|
||||
[ -r "${DB}" ] && sed -n 's/\["'"$1"'"\]\t*"\(.*\)"/\1/p' "${DB}" | tail -n 1
|
||||
}
|
||||
|
||||
jssh_countKeyDB_async() {
|
||||
[[ "$1" =~ ^${JSSH_KEYOK}+$ ]] || return 3
|
||||
local VAL DB; DB="$(jssh_checkDB "$2")"
|
||||
[ -z "${DB}" ] && return 1
|
||||
# start atomic delete here, exclusive max wait 5
|
||||
if [ -n "$3" ]; then
|
||||
declare -A oldARR
|
||||
Json2Array "oldARR" <"${DB}"
|
||||
(( oldARR["$1"]+="$3" ));
|
||||
Array2Json "oldARR" >"${DB}"
|
||||
elif [ -r "${DB}" ]; then
|
||||
# it's append, but last one counts, its a simple DB ...
|
||||
VAL="$(sed -n 's/\["'"$1"'"\]\t*"\(.*\)"/\1/p' "${DB}" | tail -n 1)"
|
||||
printf '["%s"]\t"%s"\n' "${1//,/\",\"}" "$((++VAL))" >>"${DB}"
|
||||
fi
|
||||
}
|
||||
|
||||
# update key/value in place to jsshDB
|
||||
# $1 key name, can only contain -a-zA-Z0-9,._
|
||||
# $2 key value
|
||||
# $3 filename (must exist!), must be relative to BASHBOT_ETC, and not contain '..'
|
||||
#no own locking, so async is the same as updatekeyDB
|
||||
jssh_updateKeyDB_async() {
|
||||
[[ "$1" =~ ^${JSSH_KEYOK}+$ ]] || return 3
|
||||
[ -z "$3" ] && return 1
|
||||
declare -A updARR
|
||||
# shellcheck disable=SC2034
|
||||
updARR["$1"]="$2"
|
||||
jssh_updateDB_async "updARR" "$3" || return 3
|
||||
}
|
||||
|
||||
jssh_clearDB_async() {
|
||||
local DB; DB="$(jssh_checkDB "$1")"
|
||||
[ -z "${DB}" ] && return 1
|
||||
printf '' >"${DB}"
|
||||
}
|
||||
|
||||
function jssh_updateArray_async() {
|
||||
local DB; DB="$(jssh_checkDB "$2")"
|
||||
[ -z "${DB}" ] && return 1
|
||||
[ ! -f "${DB}" ] && return 2
|
||||
declare -n ARRAY="$1"
|
||||
[[ -z "${ARRAY[*]}" || "${DB}" -nt "${DB}.last$3" ]] && touch "${DB}.last$3" && jssh_readDB_async "$1" "$2"
|
||||
}
|
||||
|
||||
##############
|
||||
# these 2 functions does all key/value store "magic"
|
||||
# and convert from/to bash array
|
||||
|
||||
# read JSON.sh style data and asssign to an ARRAY
|
||||
# $1 ARRAY name, must be declared with "declare -A ARRAY" before calling
|
||||
Json2Array() {
|
||||
# shellcheck disable=SC1091,SC1090
|
||||
# step 1: output only basic pattern
|
||||
[ -z "$1" ] || source <( printf "$1"'=( %s )'\
|
||||
"$(sed -E -n -e 's/[`´]//g' -e 's/\t(true|false)/\t"\1"/' -e 's/([^\]|^)\$/\1\\$/g' -e '/\["[-0-9a-zA-Z_,."]+"\]\+*\t/ s/\t/=/p')" )
|
||||
}
|
||||
# get Config Key from jssh file without jsshDB
|
||||
# output ARRAY as JSON.sh style data
|
||||
# $1 ARRAY name, must be declared with "declare -A ARRAY" before calling
|
||||
Array2Json() {
|
||||
[ -z "$1" ] && return 1
|
||||
local key
|
||||
declare -n ARRAY="$1"
|
||||
for key in "${!ARRAY[@]}"
|
||||
do
|
||||
[[ ! "${key}" =~ ^${JSSH_KEYOK}+$ || "${ARRAY[${key}]}" == "${JSSHDB_UNSET}" ]] && continue
|
||||
# in case value contains newline convert to \n
|
||||
: "${ARRAY[${key}]//$'\n'/\\n}"
|
||||
printf '["%s"]\t"%s"\n' "${key//,/\",\"}" "${_//\"/\\\"}"
|
||||
done
|
||||
}
|
507
modules/processUpdates.sh
Normal file
507
modules/processUpdates.sh
Normal file
|
@ -0,0 +1,507 @@
|
|||
#!/bin/bash
|
||||
##################################################################
|
||||
#
|
||||
# File: processUpdates.sh
|
||||
# Note: DO NOT EDIT! this file will be overwritten on update
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
##################################################################
|
||||
|
||||
##############
|
||||
# manage webhooks
|
||||
|
||||
# $1 URL to sed updates to: https://host.dom[:port][/path], port and path are optional
|
||||
# port must be 443, 80, 88 8443, TOKEN will be added to URL for security
|
||||
# e.g. https://myhost.com -> https://myhost.com/12345678:azndfhbgdfbbbdsfg
|
||||
# $2 max connections 1-100 default 1 (because of bash ;-)
|
||||
set_webhook() {
|
||||
local url='"url": "'"$1/${BOTTOKEN}/"'"'
|
||||
local max=',"max_connections": 1'
|
||||
[[ "$2" =~ ^[0-9]+$ ]] && max=',"max_connections": '"$2"''
|
||||
# shellcheck disable=SC2153
|
||||
sendJson "" "${url}${max}" "${URL}/setWebhook"
|
||||
unset "BOTSENT[ID]" "BOTSENT[CHAT]"
|
||||
|
||||
}
|
||||
|
||||
get_webhook_info() {
|
||||
sendJson "" "" "${URL}/getWebhookInfo"
|
||||
if [ "${BOTSENT[OK]}" = "true" ]; then
|
||||
BOTSENT[URL]="${UPD[result,url]}"
|
||||
BOTSENT[COUNT]="${UPD[result,pending_update_count]}"
|
||||
BOTSENT[CERT]="${UPD[result,has_custom_certificate]}"
|
||||
BOTSENT[LASTERR]="${UPD[result,last_error_message]}"
|
||||
unset "BOTSENT[ID]" "BOTSENT[CHAT]"
|
||||
fi
|
||||
}
|
||||
|
||||
# $1 drop pending updates true/false, default false
|
||||
delete_webhook() {
|
||||
local drop; [ "$1" = "true" ] && drop='"drop_pending_updates": true'
|
||||
sendJson "" "${drop}" "${URL}/deleteWebhook"
|
||||
unset "BOTSENT[ID]" "BOTSENT[CHAT]"
|
||||
}
|
||||
|
||||
################
|
||||
# processing of array of updates starts here
|
||||
process_multi_updates() {
|
||||
local max num debug="$1"
|
||||
# get num array elements
|
||||
max="$(grep -F ',"update_id"]' <<< "${UPDATE}" | tail -1 | cut -d , -f 2 )"
|
||||
# escape bash $ expansion bug
|
||||
UPDATE="${UPDATE//$/\\$}"
|
||||
# convert updates to bash array
|
||||
Json2Array 'UPD' <<<"${UPDATE}"
|
||||
# iterate over array
|
||||
for ((num=0; num<=max; num++)); do
|
||||
process_update "${num}" "${debug}"
|
||||
done
|
||||
}
|
||||
|
||||
################
|
||||
# processing of a single array item of update
|
||||
# $1 array index
|
||||
process_update() {
|
||||
local chatuser="Chat" num="$1" debug="$2"
|
||||
pre_process_message "${num}"
|
||||
# log message on debug
|
||||
[[ -n "${debug}" ]] && log_message "New Message ==========\n$(grep -F '["result",'"${num}" <<<"${UPDATE}")"
|
||||
|
||||
# check for users / groups to ignore, inform them ...
|
||||
jssh_updateArray_async "BASHBOTBLOCKED" "${BLOCKEDFILE}"
|
||||
if [ -n "${USER[ID]}" ] && [[ -n "${BASHBOTBLOCKED[${USER[ID]}]}" || -n "${BASHBOTBLOCKED[${CHAT[ID]}]}" ]];then
|
||||
[ -n "${BASHBOTBLOCKED[${USER[ID]}]}" ] && chatuser="User"
|
||||
[ "${NOTIFY_BLOCKED_USERS}" == "yes" ] &&\
|
||||
send_normal_message "${CHAT[ID]}" "${chatuser} blocked because: ${BASHBOTBLOCKED[${USER[ID]}]} ${BASHBOTBLOCKED[${CHAT[ID]}]}" &
|
||||
return
|
||||
fi
|
||||
|
||||
# process per message type
|
||||
if [ -n "${iQUERY[ID]}" ]; then
|
||||
process_inline_query "${num}" "${debug}"
|
||||
printf "%(%c)T: Inline Query update received FROM=%s iQUERY=%s\n" -1\
|
||||
"${iQUERY[USERNAME]:0:20} (${iQUERY[USER_ID]})" "${iQUERY[0]}" >>"${UPDATELOG}"
|
||||
elif [ -n "${iBUTTON[ID]}" ]; then
|
||||
process_inline_button "${num}" "${debug}"
|
||||
printf "%(%c)T: Inline Button update received FROM=%s CHAT=%s CALLBACK=%s DATA:%s \n" -1\
|
||||
"${iBUTTON[USERNAME]:0:20} (${iBUTTON[USER_ID]})" "${iBUTTON[CHAT_ID]}" "${iBUTTON[ID]}" "${iBUTTON[DATA]}" >>"${UPDATELOG}"
|
||||
else
|
||||
if grep -qs -e '\["result",'"${num}"',"edited_message"' <<<"${UPDATE}"; then
|
||||
# edited message
|
||||
UPDATE="${UPDATE//,${num},\"edited_message\",/,${num},\"message\",}"
|
||||
Json2Array 'UPD' <<<"${UPDATE}"
|
||||
MESSAGE[0]="/_edited_message "
|
||||
fi
|
||||
process_message "${num}" "${debug}"
|
||||
printf "%(%c)T: update received FROM=%s CHAT=%s CMD=%s\n" -1 "${USER[USERNAME]:0:20} (${USER[ID]})"\
|
||||
"${CHAT[USERNAME]:0:20}${CHAT[TITLE]:0:30} (${CHAT[ID]})"\
|
||||
"${MESSAGE:0:30}${CAPTION:0:30}${URLS[*]}" >>"${UPDATELOG}"
|
||||
if [[ -z "${USER[ID]}" || -z "${CHAT[ID]}" ]]; then
|
||||
printf "%(%c)T: IGNORE unknown update type: %s\n" -1 "$(grep '\["result",'"${num}"'.*,"id"\]' <<<"${UPDATE}")" >>"${UPDATELOG}"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
#####
|
||||
# process inline and message events
|
||||
# first classic command dispatcher
|
||||
# shellcheck disable=SC2153,SC1090
|
||||
{ source "${COMMANDS}" "${debug}"; } &
|
||||
|
||||
# then all registered addons
|
||||
if [ -z "${iQUERY[ID]}" ]; then
|
||||
event_message "${debug}"
|
||||
else
|
||||
event_inline "${debug}"
|
||||
fi
|
||||
|
||||
# last count users
|
||||
jssh_countKeyDB_async "${CHAT[ID]}" "${COUNTFILE}"
|
||||
}
|
||||
|
||||
pre_process_message(){
|
||||
local num="$1"
|
||||
# unset everything to not have old values
|
||||
CMD=( ); iQUERY=( ); iBUTTON=(); MESSAGE=(); CHAT=(); USER=(); CONTACT=(); LOCATION=(); unset CAPTION
|
||||
REPLYTO=( ); FORWARD=( ); URLS=(); VENUE=( ); SERVICE=( ); NEWMEMBER=( ); LEFTMEMBER=( ); PINNED=( ); MIGRATE=( )
|
||||
iQUERY[ID]="${UPD["result,${num},inline_query,id"]}"
|
||||
iBUTTON[ID]="${UPD["result,${num},callback_query,id"]}"
|
||||
CHAT[ID]="${UPD["result,${num},message,chat,id"]}"
|
||||
USER[ID]="${UPD["result,${num},message,from,id"]}"
|
||||
[ -z "${CHAT[ID]}" ] && CHAT[ID]="${UPD["result,${num},edited_message,chat,id"]}"
|
||||
[ -z "${USER[ID]}" ] && USER[ID]="${UPD["result,${num},edited_message,from,id"]}"
|
||||
# always true
|
||||
return 0
|
||||
}
|
||||
|
||||
process_inline_query() {
|
||||
local num="$1"
|
||||
iQUERY[0]="$(JsonDecode "${UPD["result,${num},inline_query,query"]}")"
|
||||
iQUERY[USER_ID]="${UPD["result,${num},inline_query,from,id"]}"
|
||||
iQUERY[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},inline_query,from,first_name"]}")"
|
||||
iQUERY[LAST_NAME]="$(JsonDecode "${UPD["result,${num},inline_query,from,last_name"]}")"
|
||||
iQUERY[USERNAME]="$(JsonDecode "${UPD["result,${num},inline_query,from,username"]}")"
|
||||
# always true
|
||||
return 0
|
||||
}
|
||||
|
||||
process_inline_button() {
|
||||
local num="$1"
|
||||
iBUTTON[DATA]="${UPD["result,${num},callback_query,data"]}"
|
||||
iBUTTON[CHAT_ID]="${UPD["result,${num},callback_query,message,chat,id"]}"
|
||||
iBUTTON[MESSAGE_ID]="${UPD["result,${num},callback_query,message,message_id"]}"
|
||||
iBUTTON[MESSAGE]="$(JsonDecode "${UPD["result,${num},callback_query,message,text"]}")"
|
||||
# XXX should we give back pressed button, all buttons or nothing?
|
||||
iBUTTON[USER_ID]="${UPD["result,${num},callback_query,from,id"]}"
|
||||
iBUTTON[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},callback_query,from,first_name"]}")"
|
||||
iBUTTON[LAST_NAME]="$(JsonDecode "${UPD["result,${num},callback_query,from,last_name"]}")"
|
||||
iBUTTON[USERNAME]="$(JsonDecode "${UPD["result,${num},callback_query,from,username"]}")"
|
||||
# always true
|
||||
return 0
|
||||
}
|
||||
|
||||
process_message() {
|
||||
local num="$1"
|
||||
# Message
|
||||
MESSAGE[0]+="$(JsonDecode "${UPD["result,${num},message,text"]}" | sed 's|\\/|/|g')"
|
||||
MESSAGE[ID]="${UPD["result,${num},message,message_id"]}"
|
||||
MESSAGE[CAPTION]="$(JsonDecode "${UPD["result,${num},message,caption"]}")"
|
||||
CAPTION="${MESSAGE[CAPTION]}" # backward compatibility
|
||||
# dice received
|
||||
MESSAGE[DICE]="${UPD["result,${num},message,dice,emoji"]}"
|
||||
if [ -n "${MESSAGE[DICE]}" ]; then
|
||||
MESSAGE[RESULT]="${UPD["result,${num},message,dice,value"]}"
|
||||
MESSAGE[0]="/_dice_received ${MESSAGE[DICE]} ${MESSAGE[RESULT]}"
|
||||
fi
|
||||
# Chat ID is now parsed when update is received
|
||||
CHAT[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,chat,last_name"]}")"
|
||||
CHAT[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,chat,first_name"]}")"
|
||||
CHAT[USERNAME]="$(JsonDecode "${UPD["result,${num},message,chat,username"]}")"
|
||||
# set real name as username if empty
|
||||
[ -z "${CHAT[USERNAME]}" ] && CHAT[USERNAME]="${CHAT[FIRST_NAME]} ${CHAT[LAST_NAME]}"
|
||||
CHAT[TITLE]="$(JsonDecode "${UPD["result,${num},message,chat,title"]}")"
|
||||
CHAT[TYPE]="$(JsonDecode "${UPD["result,${num},message,chat,type"]}")"
|
||||
CHAT[ALL_ADMIN]="${UPD["result,${num},message,chat,all_members_are_administrators"]}"
|
||||
|
||||
# user ID is now parsed when update is received
|
||||
USER[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,from,first_name"]}")"
|
||||
USER[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,from,last_name"]}")"
|
||||
USER[USERNAME]="$(JsonDecode "${UPD["result,${num},message,from,username"]}")"
|
||||
# set real name as username if empty
|
||||
[ -z "${USER[USERNAME]}" ] && USER[USERNAME]="${USER[FIRST_NAME]} ${USER[LAST_NAME]}"
|
||||
|
||||
# in reply to message from
|
||||
if [ -n "${UPD["result,${num},message,reply_to_message,from,id"]}" ]; then
|
||||
REPLYTO[UID]="${UPD["result,${num},message,reply_to_message,from,id"]}"
|
||||
REPLYTO[0]="$(JsonDecode "${UPD["result,${num},message,reply_to_message,text"]}")"
|
||||
REPLYTO[ID]="${UPD["result,${num},message,reply_to_message,message_id"]}"
|
||||
REPLYTO[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,reply_to_message,from,first_name"]}")"
|
||||
REPLYTO[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,reply_to_message,from,last_name"]}")"
|
||||
REPLYTO[USERNAME]="$(JsonDecode "${UPD["result,${num},message,reply_to_message,from,username"]}")"
|
||||
fi
|
||||
|
||||
# forwarded message from
|
||||
if [ -n "${UPD["result,${num},message,forward_from,id"]}" ]; then
|
||||
FORWARD[UID]="${UPD["result,${num},message,forward_from,id"]}"
|
||||
FORWARD[ID]="${MESSAGE[ID]}" # same as message ID
|
||||
FORWARD[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,forward_from,first_name"]}")"
|
||||
FORWARD[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,forward_from,last_name"]}")"
|
||||
FORWARD[USERNAME]="$(JsonDecode "${UPD["result,${num},message,forward_from,username"]}")"
|
||||
fi
|
||||
|
||||
# get file URL from telegram, check for any of them!
|
||||
if grep -qs -e '\["result",'"${num}"',"message","[avpsd].*,"file_id"\]' <<<"${UPDATE}"; then
|
||||
URLS[AUDIO]="$(get_file "${UPD["result,${num},message,audio,file_id"]}")"
|
||||
URLS[DOCUMENT]="$(get_file "${UPD["result,${num},message,document,file_id"]}")"
|
||||
URLS[PHOTO]="$(get_file "${UPD["result,${num},message,photo,0,file_id"]}")"
|
||||
URLS[STICKER]="$(get_file "${UPD["result,${num},message,sticker,file_id"]}")"
|
||||
URLS[VIDEO]="$(get_file "${UPD["result,${num},message,video,file_id"]}")"
|
||||
URLS[VOICE]="$(get_file "${UPD["result,${num},message,voice,file_id"]}")"
|
||||
fi
|
||||
# Contact, must have phone_number
|
||||
if [ -n "${UPD["result,${num},message,contact,phone_number"]}" ]; then
|
||||
CONTACT[USER_ID]="$(JsonDecode "${UPD["result,${num},message,contact,user_id"]}")"
|
||||
CONTACT[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,contact,first_name"]}")"
|
||||
CONTACT[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,contact,last_name"]}")"
|
||||
CONTACT[NUMBER]="${UPD["result,${num},message,contact,phone_number"]}"
|
||||
CONTACT[VCARD]="${UPD["result,${num},message,contact,vcard"]}"
|
||||
fi
|
||||
|
||||
# venue, must have a position
|
||||
if [ -n "${UPD["result,${num},message,venue,location,longitude"]}" ]; then
|
||||
VENUE[TITLE]="$(JsonDecode "${UPD["result,${num},message,venue,title"]}")"
|
||||
VENUE[ADDRESS]="$(JsonDecode "${UPD["result,${num},message,venue,address"]}")"
|
||||
VENUE[LONGITUDE]="${UPD["result,${num},message,venue,location,longitude"]}"
|
||||
VENUE[LATITUDE]="${UPD["result,${num},message,venue,location,latitude"]}"
|
||||
VENUE[FOURSQUARE]="${UPD["result,${num},message,venue,foursquare_id"]}"
|
||||
fi
|
||||
|
||||
# Location
|
||||
LOCATION[LONGITUDE]="${UPD["result,${num},message,location,longitude"]}"
|
||||
LOCATION[LATITUDE]="${UPD["result,${num},message,location,latitude"]}"
|
||||
|
||||
# service messages, group or channel only!
|
||||
if [[ "${CHAT[ID]}" == "-"* ]] ; then
|
||||
# new chat member
|
||||
if [ -n "${UPD["result,${num},message,new_chat_member,id"]}" ]; then
|
||||
SERVICE[NEWMEMBER]="${UPD["result,${num},message,new_chat_member,id"]}"
|
||||
NEWMEMBER[ID]="${SERVICE[NEWMEMBER]}"
|
||||
NEWMEMBER[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,new_chat_member,first_name"]}")"
|
||||
NEWMEMBER[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,new_chat_member,last_name"]}")"
|
||||
NEWMEMBER[USERNAME]="$(JsonDecode "${UPD["result,${num},message,new_chat_member,username"]}")"
|
||||
NEWMEMBER[ISBOT]="${UPD["result,${num},message,new_chat_member,is_bot"]}"
|
||||
MESSAGE[0]="/_new_chat_member ${NEWMEMBER[ID]} ${NEWMEMBER[USERNAME]:=${NEWMEMBER[FIRST_NAME]} ${NEWMEMBER[LAST_NAME]}}"
|
||||
fi
|
||||
# left chat member
|
||||
if [ -n "${UPD["result,${num},message,left_chat_member,id"]}" ]; then
|
||||
SERVICE[LEFTMEMBER]="${UPD["result,${num},message,left_chat_member,id"]}"
|
||||
LEFTMEMBER[ID]="${SERVICE[LEFTMEBER]}"
|
||||
LEFTMEMBER[FIRST_NAME]="$(JsonDecode "${UPD["result,${num},message,left_chat_member,first_name"]}")"
|
||||
LEFTMEMBER[LAST_NAME]="$(JsonDecode "${UPD["result,${num},message,left_chat_member,last_name"]}")"
|
||||
LEFTMEBER[USERNAME]="$(JsonDecode "${UPD["result,${num},message,left_chat_member,username"]}")"
|
||||
LEFTMEMBER[ISBOT]="${UPD["result,${num},message,left_chat_member,is_bot"]}"
|
||||
MESSAGE[0]="/_left_chat_member ${LEFTMEMBER[ID]} ${LEFTMEMBER[USERNAME]:=${LEFTMEMBER[FIRST_NAME]} ${LEFTMEMBER[LAST_NAME]}}"
|
||||
fi
|
||||
# chat title / photo, check for any of them!
|
||||
if grep -qs -e '\["result",'"${num}"',"message","new_chat_[tp]' <<<"${UPDATE}"; then
|
||||
SERVICE[NEWTITLE]="$(JsonDecode "${UPD["result,${num},message,new_chat_title"]}")"
|
||||
[ -n "${SERVICE[NEWTITLE]}" ] &&\
|
||||
MESSAGE[0]="/_new_chat_title ${USER[ID]} ${SERVICE[NEWTITLE]}"
|
||||
SERVICE[NEWPHOTO]="$(get_file "${UPD["result,${num},message,new_chat_photo,0,file_id"]}")"
|
||||
[ -n "${SERVICE[NEWPHOTO]}" ] &&\
|
||||
MESSAGE[0]="/_new_chat_photo ${USER[ID]} ${SERVICE[NEWPHOTO]}"
|
||||
fi
|
||||
# pinned message
|
||||
if [ -n "${UPD["result,${num},message,pinned_message,message_id"]}" ]; then
|
||||
SERVICE[PINNED]="${UPD["result,${num},message,pinned_message,message_id"]}"
|
||||
PINNED[ID]="${SERVICE[PINNED]}"
|
||||
PINNED[MESSAGE]="$(JsonDecode "${UPD["result,${num},message,pinned_message,text"]}")"
|
||||
MESSAGE[0]="/_new_pinned_message ${USER[ID]} ${PINNED[ID]} ${PINNED[MESSAGE]}"
|
||||
fi
|
||||
# migrate to super group
|
||||
if [ -n "${UPD["result,${num},message,migrate_to_chat_id"]}" ]; then
|
||||
MIGRATE[TO]="${UPD["result,${num},message,migrate_to_chat_id"]}"
|
||||
MIGRATE[FROM]="${UPD["result,${num},message,migrate_from_chat_id"]}"
|
||||
# CHAT is already migrated, so set new chat id
|
||||
[ "${CHAT[ID]}" = "${MIGRATE[FROM]}" ] && CHAT[ID]="${MIGRATE[FROM]}"
|
||||
SERVICE[MIGRATE]="${MIGRATE[FROM]} ${MIGRATE[TO]}"
|
||||
MESSAGE[0]="/_migrate_group ${SERVICE[MIGRATE]}"
|
||||
fi
|
||||
# set SERVICE to yes if a service message was received
|
||||
[[ "${SERVICE[*]}" =~ ^[[:blank:]]*$ ]] || SERVICE[0]="yes"
|
||||
fi
|
||||
|
||||
# split message in command and args
|
||||
[[ "${MESSAGE[0]}" == "/"* ]] && read -ra CMD <<<"${MESSAGE[0]}" && CMD[0]="${CMD[0]%%@*}"
|
||||
# everything went well
|
||||
return 0
|
||||
}
|
||||
|
||||
#########################
|
||||
# bot startup actions, call before start polling or webhook loop
|
||||
declare -A BASHBOTBLOCKED
|
||||
start_bot() {
|
||||
local DEBUGMSG
|
||||
# startup message
|
||||
DEBUGMSG="BASHBOT startup actions, mode set to \"${1:-normal}\" =========="
|
||||
log_update "${DEBUGMSG}"
|
||||
# redirect to Debug.log
|
||||
if [[ "$1" == *"debug" ]]; then
|
||||
# shellcheck disable=SC2153
|
||||
exec &>>"${DEBUGLOG}"
|
||||
log_debug "${DEBUGMSG}";
|
||||
fi
|
||||
DEBUGMSG="$1"
|
||||
[[ "${DEBUGMSG}" == "xdebug"* ]] && set -x
|
||||
# cleaup old pipes and empty logfiles
|
||||
find "${DATADIR}" -type p -not -name "webhook-fifo-*" -delete
|
||||
find "${DATADIR}" -size 0 -name "*.log" -delete
|
||||
# load addons on startup
|
||||
for addons in "${ADDONDIR:-.}"/*.sh ; do
|
||||
# shellcheck disable=SC1090
|
||||
[ -r "${addons}" ] && source "${addons}" "startbot" "${DEBUGMSG}"
|
||||
done
|
||||
# shellcheck disable=SC1090
|
||||
source "${COMMANDS}" "startbot"
|
||||
# start timer events
|
||||
if [ -n "${BASHBOT_START_TIMER}" ] ; then
|
||||
# shellcheck disable=SC2064
|
||||
trap "event_timer ${DEBUGMSG}" ALRM
|
||||
start_timer &
|
||||
# shellcheck disable=SC2064
|
||||
trap "kill -9 $!; exit" EXIT INT HUP TERM QUIT
|
||||
fi
|
||||
# cleanup on start
|
||||
bot_cleanup "startup"
|
||||
# read blocked users
|
||||
jssh_readDB_async "BASHBOTBLOCKED" "${BLOCKEDFILE}"
|
||||
# inform botadmin about start
|
||||
send_normal_message "$(getConfigKey "botadmin")" "Bot ${ME} $2 started ..." &
|
||||
}
|
||||
|
||||
# main polling updates loop, should never terminate
|
||||
get_updates(){
|
||||
local errsleep="200" DEBUG="$1" OFFSET=0
|
||||
# adaptive sleep defaults
|
||||
local nextsleep="100"
|
||||
local stepsleep="${BASHBOT_SLEEP_STEP:-100}"
|
||||
local maxsleep="${BASHBOT_SLEEP:-5000}"
|
||||
printf "%(%c)T: %b\n" -1 "Bot startup actions done, start polling updates ..."
|
||||
while true; do
|
||||
# adaptive sleep in ms rounded to next 0.1 s
|
||||
sleep "$(_round_float "${nextsleep}e-3" "1")"
|
||||
# get next update
|
||||
# shellcheck disable=SC2153
|
||||
UPDATE="$(getJson "${URL}/getUpdates?offset=${OFFSET}" 2>/dev/null | "${JSONSHFILE}" -b -n 2>/dev/null | iconv -f utf-8 -t utf-8 -c)"
|
||||
# did we get an response?
|
||||
if [ -n "${UPDATE}" ]; then
|
||||
# we got something, do processing
|
||||
[ "${OFFSET}" = "-999" ] && [ "${nextsleep}" -gt "$((maxsleep*2))" ] &&\
|
||||
log_error "Recovered from timeout/broken/no connection, continue with telegram updates"
|
||||
# calculate next sleep interval
|
||||
((nextsleep+= stepsleep , nextsleep= nextsleep>maxsleep ?maxsleep:nextsleep))
|
||||
# warn if webhook is set
|
||||
if grep -q '^\["error_code"\] 409' <<<"${UPDATE}"; then
|
||||
[ "${OFFSET}" != "-999" ] && nextsleep="${stepsleep}"
|
||||
OFFSET="-999"; errsleep="$(_round_float "$(( errsleep= 300*nextsleep ))e-3")"
|
||||
log_error "Warning conflicting webhook set, can't get updates until your run delete_webhook! Sleep $((errsleep/60)) min ..."
|
||||
sleep "${errsleep}"
|
||||
continue
|
||||
fi
|
||||
# Offset
|
||||
OFFSET="$(grep <<<"${UPDATE}" '\["result",[0-9]*,"update_id"\]' | tail -1 | cut -f 2)"
|
||||
((OFFSET++))
|
||||
|
||||
if [ "${OFFSET}" != "1" ]; then
|
||||
nextsleep="100"
|
||||
process_multi_updates "${DEBUG}"
|
||||
fi
|
||||
else
|
||||
# oops, something bad happened, wait maxsleep*10
|
||||
(( nextsleep=nextsleep*2 , nextsleep= nextsleep>maxsleep*10 ?maxsleep*10:nextsleep ))
|
||||
# second time, report problem
|
||||
if [ "${OFFSET}" = "-999" ]; then
|
||||
log_error "Repeated timeout/broken/no connection on telegram update, sleep $(_round_float "${nextsleep}e-3")s"
|
||||
# try to recover
|
||||
if _is_function bashbotBlockRecover && [ -z "$(getJson "${ME_URL}")" ]; then
|
||||
log_error "Try to recover, calling bashbotBlockRecover ..."
|
||||
bashbotBlockRecover >>"${ERRORLOG}"
|
||||
fi
|
||||
fi
|
||||
OFFSET="-999"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
|
||||
declare -Ax BASHBOT_EVENT_INLINE BASHBOT_EVENT_MESSAGE BASHBOT_EVENT_CMD BASHBOT_EVENT_REPLYTO BASHBOT_EVENT_FORWARD BASHBOT_EVENT_SEND
|
||||
declare -Ax BASHBOT_EVENT_CONTACT BASHBOT_EVENT_LOCATION BASHBOT_EVENT_FILE BASHBOT_EVENT_TEXT BASHBOT_EVENT_TIMER BASHBOT_BLOCKED
|
||||
|
||||
start_timer(){
|
||||
# send alarm every ~60 s
|
||||
while :; do
|
||||
sleep 59.5
|
||||
kill -ALRM $$
|
||||
done;
|
||||
}
|
||||
|
||||
EVENT_TIMER="0"
|
||||
event_timer() {
|
||||
local key timer debug="$1"
|
||||
(( EVENT_TIMER++ ))
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_TIMER[@]}"
|
||||
do
|
||||
timer="${key##*,}"
|
||||
[[ ! "${timer}" =~ ^-*[1-9][0-9]*$ ]] && continue
|
||||
if [ "$(( EVENT_TIMER % timer ))" = "0" ]; then
|
||||
_exec_if_function "${BASHBOT_EVENT_TIMER[${key}]}" "timer" "${key}" "${debug}"
|
||||
[ "$(( EVENT_TIMER % timer ))" -lt "0" ] && \
|
||||
unset BASHBOT_EVENT_TIMER["${key}"]
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
event_inline() {
|
||||
local key debug="$1"
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_INLINE[@]}"
|
||||
do
|
||||
_exec_if_function "${BASHBOT_EVENT_INLINE[${key}]}" "inline" "${key}" "${debug}"
|
||||
done
|
||||
}
|
||||
event_message() {
|
||||
local key debug="$1"
|
||||
# ${MESSAEG[*]} event_message
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_MESSAGE[@]}"
|
||||
do
|
||||
_exec_if_function "${BASHBOT_EVENT_MESSAGE[${key}]}" "message" "${key}" "${debug}"
|
||||
done
|
||||
|
||||
# ${TEXT[*]} event_text
|
||||
if [ -n "${MESSAGE[0]}" ]; then
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_TEXT[@]}"
|
||||
do
|
||||
_exec_if_function "${BASHBOT_EVENT_TEXT[${key}]}" "text" "${key}" "${debug}"
|
||||
done
|
||||
|
||||
# ${CMD[*]} event_cmd
|
||||
if [ -n "${CMD[0]}" ]; then
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_CMD[@]}"
|
||||
do
|
||||
_exec_if_function "${BASHBOT_EVENT_CMD[${key}]}" "command" "${key}" "${debug}"
|
||||
done
|
||||
fi
|
||||
fi
|
||||
# ${REPLYTO[*]} event_replyto
|
||||
if [ -n "${REPLYTO[UID]}" ]; then
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_REPLYTO[@]}"
|
||||
do
|
||||
_exec_if_function "${BASHBOT_EVENT_REPLYTO[${key}]}" "replyto" "${key}" "${debug}"
|
||||
done
|
||||
fi
|
||||
|
||||
# ${FORWARD[*]} event_forward
|
||||
if [ -n "${FORWARD[UID]}" ]; then
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_FORWARD[@]}"
|
||||
do
|
||||
_exec_if_function && "${BASHBOT_EVENT_FORWARD[${key}]}" "forward" "${key}" "${debug}"
|
||||
done
|
||||
fi
|
||||
|
||||
# ${CONTACT[*]} event_contact
|
||||
if [ -n "${CONTACT[FIRST_NAME]}" ]; then
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_CONTACT[@]}"
|
||||
do
|
||||
_exec_if_function "${BASHBOT_EVENT_CONTACT[${key}]}" "contact" "${key}" "${debug}"
|
||||
done
|
||||
fi
|
||||
|
||||
# ${VENUE[*]} event_location
|
||||
# ${LOCATION[*]} event_location
|
||||
if [ -n "${LOCATION[LONGITUDE]}" ] || [ -n "${VENUE[TITLE]}" ]; then
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_LOCATION[@]}"
|
||||
do
|
||||
_exec_if_function "${BASHBOT_EVENT_LOCATION[${key}]}" "location" "${key}" "${debug}"
|
||||
done
|
||||
fi
|
||||
|
||||
# ${URLS[*]} event_file
|
||||
# NOTE: compare again #URLS -1 blanks!
|
||||
if [[ "${URLS[*]}" != " " ]]; then
|
||||
# shellcheck disable=SC2153
|
||||
for key in "${!BASHBOT_EVENT_FILE[@]}"
|
||||
do
|
||||
_exec_if_function "${BASHBOT_EVENT_FILE[${key}]}" "file" "${key}" "${debug}"
|
||||
done
|
||||
fi
|
||||
|
||||
}
|
||||
|
472
modules/sendMessage.sh
Normal file
472
modules/sendMessage.sh
Normal file
|
@ -0,0 +1,472 @@
|
|||
#!/bin/bash
|
||||
# file: modules/message.sh
|
||||
# do not edit, this file will be overwritten on update
|
||||
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
# shellcheck disable=SC1117
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
# will be automatically sourced from bashbot
|
||||
|
||||
# source once magic, function named like file
|
||||
eval "$(basename "${BASH_SOURCE[0]}")(){ :; }"
|
||||
|
||||
# source from commands.sh to use the sendMessage functions
|
||||
|
||||
MSG_URL=${URL}'/sendMessage'
|
||||
EDIT_URL=${URL}'/editMessageText'
|
||||
|
||||
#
|
||||
# send/edit message variants ------------------
|
||||
#
|
||||
|
||||
# $1 CHAT $2 message
|
||||
send_normal_message() {
|
||||
local len text; text="$(JsonEscape "$2")"
|
||||
until [ -z "${text}" ]; do
|
||||
if [ "${#text}" -le 4096 ]; then
|
||||
sendJson "$1" '"text":"'"${text}"'"' "${MSG_URL}"
|
||||
break
|
||||
else
|
||||
len=4095
|
||||
[ "${text:4095:2}" != "\n" ] &&\
|
||||
len="${text:0:4096}" && len="${len%\\n*}" && len="${#len}"
|
||||
sendJson "$1" '"text":"'"${text:0:${len}}"'"' "${MSG_URL}"
|
||||
text="${text:$((len+2))}"
|
||||
fi
|
||||
done
|
||||
# func="$1" err="$2" chat="$3" user="$4" emsg="$5" remaining args
|
||||
[ -n "${BOTSENT[ERROR]}" ] && processError "${FUNCNAME[0]}" "${BOTSENT[ERROR]}" "$1" "" "${BOTSENT[DESCRIPTION]}" "$2"
|
||||
}
|
||||
|
||||
# $1 CHAT $2 message
|
||||
send_markdown_message() {
|
||||
_format_message_url "$1" "$2" ',"parse_mode":"markdown"' "${MSG_URL}"
|
||||
# func="$1" err="$2" chat="$3" user="$4" emsg="$5" remaining args
|
||||
[ -n "${BOTSENT[ERROR]}" ] && processError "${FUNCNAME[0]}" "${BOTSENT[ERROR]}" "$1" "" "${BOTSENT[DESCRIPTION]}" "$2"
|
||||
}
|
||||
|
||||
# $1 CHAT $2 message
|
||||
send_markdownv2_message() {
|
||||
_markdownv2_message_url "$1" "$2" ',"parse_mode":"markdownv2"' "${MSG_URL}"
|
||||
# func="$1" err="$2" chat="$3" user="$4" emsg="$5" remaining args
|
||||
[ -n "${BOTSENT[ERROR]}" ] && processError "${FUNCNAME[0]}" "${BOTSENT[ERROR]}" "$1" "" "${BOTSENT[DESCRIPTION]}" "$2"
|
||||
}
|
||||
|
||||
# $1 CHAT $2 message
|
||||
send_html_message() {
|
||||
_format_message_url "$1" "$2" ',"parse_mode":"html"' "${MSG_URL}"
|
||||
# func="$1" err="$2" chat="$3" user="$4" emsg="$5" remaining args
|
||||
[ -n "${BOTSENT[ERROR]}" ] && processError "${FUNCNAME[0]}" "${BOTSENT[ERROR]}" "$1" "" "${BOTSENT[DESCRIPTION]}" "$2"
|
||||
}
|
||||
|
||||
# $1 CHAT $2 msg-id $3 message
|
||||
edit_normal_message() {
|
||||
_format_message_url "$1" "$3" ',"message_id":'"$2"'' "${EDIT_URL}"
|
||||
# func="$1" err="$2" chat="$3" user="$4" emsg="$5" remaining args
|
||||
[ -n "${BOTSENT[ERROR]}" ] && processError "${FUNCNAME[0]}" "${BOTSENT[ERROR]}" "$1" "" "${BOTSENT[DESCRIPTION]}" "$2" "$3"
|
||||
}
|
||||
|
||||
# $1 CHAT $2 msg-id $3 message
|
||||
edit_markdown_message() {
|
||||
_format_message_url "$1" "$3" ',"message_id":'"$2"',"parse_mode":"markdown"' "${EDIT_URL}"
|
||||
# func="$1" err="$2" chat="$3" user="$4" emsg="$5" remaining args
|
||||
[ -n "${BOTSENT[ERROR]}" ] && processError "${FUNCNAME[0]}" "${BOTSENT[ERROR]}" "$1" "" "${BOTSENT[DESCRIPTION]}" "$2" "$3"
|
||||
}
|
||||
|
||||
# $1 CHAT $2 msg-id $3 message
|
||||
edit_markdownv2_message() {
|
||||
_markdownv2_message_url "$1" "$3" ',"message_id":'"$2"',"parse_mode":"markdownv2"' "${EDIT_URL}"
|
||||
# func="$1" err="$2" chat="$3" user="$4" emsg="$5" remaining args
|
||||
[ -n "${BOTSENT[ERROR]}" ] && processError "${FUNCNAME[0]}" "${BOTSENT[ERROR]}" "$1" "" "${BOTSENT[DESCRIPTION]}" "$2" "$3"
|
||||
}
|
||||
|
||||
# $1 CHAT $2 msg-id $3 message
|
||||
edit_html_message() {
|
||||
_format_message_url "$1" "$3" ',"message_id":'"$2"',"parse_mode":"html"' "${EDIT_URL}"
|
||||
# func="$1" err="$2" chat="$3" user="$4" emsg="$5" remaining args
|
||||
[ -n "${BOTSENT[ERROR]}" ] && processError "${FUNCNAME[0]}" "${BOTSENT[ERROR]}" "$1" "" "${BOTSENT[DESCRIPTION]}" "$2" "$3"
|
||||
}
|
||||
|
||||
# $1 chat $2 mesage_id, $3 caption
|
||||
edit_message_caption() {
|
||||
sendJson "$1" '"message_id":'"$2"',"caption":"'"$3"'"' "${URL}/editMessageCaption"
|
||||
# func="$1" err="$2" chat="$3" user="$4" emsg="$5" remaining args
|
||||
[ -n "${BOTSENT[ERROR]}" ] && processError "${FUNCNAME[0]}" "${BOTSENT[ERROR]}" "$1" "" "${BOTSENT[DESCRIPTION]}" "$2" "$3"
|
||||
}
|
||||
|
||||
|
||||
# $ chat $2 msg_id $3 nolog
|
||||
delete_message() {
|
||||
[ -z "$3" ] && log_update "Delete Message CHAT=$1 MSG_ID=$2"
|
||||
sendJson "$1" '"message_id": '"$2"'' "${URL}/deleteMessage"
|
||||
[ "${BOTSENT[OK]}" = "true" ] && BOTSENT[CHAT]="$1"
|
||||
# func="$1" err="$2" chat="$3" user="$4" emsg="$5" remaining args
|
||||
[ -n "${BOTSENT[ERROR]}" ] && processError "${FUNCNAME[0]}" "${BOTSENT[ERROR]}" "$1" "" "${BOTSENT[DESCRIPTION]}" "$2" "$3"
|
||||
}
|
||||
|
||||
|
||||
# internal function, send/edit formatted message with parse_mode and URL
|
||||
# $1 CHAT $2 message $3 action $4 URL
|
||||
_format_message_url(){
|
||||
local text; text="$(JsonEscape "$2")"
|
||||
[ "${#text}" -ge 4096 ] && log_error "Warning: html/markdown message longer than 4096 characters, message is rejected if formatting crosses 4096 border."
|
||||
until [ -z "${text}" ]; do
|
||||
sendJson "$1" '"text":"'"${text:0:4096}"'"'"$3"'' "$4"
|
||||
text="${text:4096}"
|
||||
done
|
||||
}
|
||||
|
||||
# internal function, send/edit markdownv2 message with URL
|
||||
# $1 CHAT $2 message $3 action $4 URL
|
||||
_markdownv2_message_url() {
|
||||
local text; text="$(JsonEscape "$2")"
|
||||
[ "${#text}" -ge 4096 ] && log_error "Warning: markdownv2 message longer than 4096 characters, message is rejected if formatting crosses 4096 border."
|
||||
# markdown v2 needs additional double escaping!
|
||||
text="$(sed -E -e 's|([_|~`>+=#{}()!.-])|\\\1|g' <<< "${text}")"
|
||||
until [ -z "${text}" ]; do
|
||||
sendJson "$1" '"text":"'"${text:0:4096}"'"'"$3"'' "$4"
|
||||
text="${text:4096}"
|
||||
done
|
||||
}
|
||||
|
||||
#
|
||||
# send keyboard, buttons, files ---------------
|
||||
#
|
||||
|
||||
# $1 CHAT $2 message $3 keyboard
|
||||
send_keyboard() {
|
||||
if [[ "$3" != *'['* ]]; then old_send_keyboard "${@}"; return; fi
|
||||
local text='"text":"'"Keyboard:"'"'
|
||||
if [ -n "$2" ]; then
|
||||
text="$(JsonEscape "$2")"
|
||||
text='"text":"'"${text//$'\n'/\\n}"'"'
|
||||
fi
|
||||
# text longer than 4096, send text and keyboard separate
|
||||
if [ "${#2}" -gt 4096 ]; then
|
||||
send_normal_message "$1" "$2"
|
||||
send_keyboard "$1" "..." "$3"
|
||||
return
|
||||
fi
|
||||
local one_time=', "one_time_keyboard":true' && [ -n "$4" ] && one_time=""
|
||||
# '"text":"$2", "reply_markup": {"keyboard": [ $3 ], "one_time_keyboard": true}'
|
||||
sendJson "$1" "${text}"', "reply_markup": {"keyboard": [ '"$3"' ] '"${one_time}"'}' "${MSG_URL}"
|
||||
# func="$1" err="$2" chat="$3" user="$4" emsg="$5" remaining args
|
||||
[ -n "${BOTSENT[ERROR]}" ] && processError "${FUNCNAME[0]}" "${BOTSENT[ERROR]}" "$1" "" "${BOTSENT[DESCRIPTION]}" "$2"
|
||||
}
|
||||
|
||||
# $1 CHAT $2 message $3 remove
|
||||
remove_keyboard() {
|
||||
local text='"text":"'"remove custom keyboard ..."'"'
|
||||
if [ -n "$2" ]; then
|
||||
text="$(JsonEscape "$2")"
|
||||
text='"text":"'"${text//$'\n'/\\n}"'"'
|
||||
fi
|
||||
sendJson "$1" "${text}"', "reply_markup": {"remove_keyboard":true}' "${MSG_URL}"
|
||||
# delete message if no message or $3 not empty
|
||||
#JSON='"text":"$2", "reply_markup": {"remove_keyboard":true}'
|
||||
[[ -z "$2" || -n "$3" ]] && delete_message "$1" "${BOTSENT[ID]}" "nolog"
|
||||
# func="$1" err="$2" chat="$3" user="$4" emsg="$5" remaining args
|
||||
[ -n "${BOTSENT[ERROR]}" ] && processError "${FUNCNAME[0]}" "${BOTSENT[ERROR]}" "$1" "" "${BOTSENT[DESCRIPTION]}" "$2"
|
||||
}
|
||||
|
||||
# buttons will specified as "texts
|
||||
#|url" ... "text|url" empty arg starts new row
|
||||
# url not starting with http:// or https:// will be send as callback_data
|
||||
send_inline_buttons(){
|
||||
send_inline_keyboard "$1" "$2" "$(_button_row "${@:3}")"
|
||||
}
|
||||
|
||||
# $1 CHAT $2 message-id $3 buttons
|
||||
# buttons will specified as "text|url" ... "text|url" empty arg starts new row
|
||||
# url not starting with http:// or https:// will be send as callback_data
|
||||
edit_inline_buttons(){
|
||||
edit_inline_keyboard "$1" "$2" "$(_button_row "${@:3}")"
|
||||
}
|
||||
|
||||
|
||||
# $1 CHAT $2 message $3 button text $4 button url
|
||||
send_button() {
|
||||
send_inline_keyboard "$1" "$2" '[{"text":"'"$(JsonEscape "$3")"'", "url":"'"$4"'"}]'
|
||||
}
|
||||
|
||||
# helper function to create json for a button row
|
||||
# buttons will specified as "text|url" ... "text|url" empty arg starts new row
|
||||
# url not starting with http:// or https:// will be send as callback_data
|
||||
_button_row() {
|
||||
[ -z "$1" ] && return 1
|
||||
local arg type json sep
|
||||
for arg in "$@"
|
||||
do
|
||||
[ -z "${arg}" ] && sep="],[" && continue
|
||||
type="callback_data"
|
||||
[[ "${arg##*|}" =~ ^(https*://|tg://) ]] && type="url"
|
||||
json+="${sep}"'{"text":"'"$(JsonEscape "${arg%|*}")"'", "'"${type}"'":"'"${arg##*|}"'"}'
|
||||
sep=","
|
||||
done
|
||||
printf "[%s]" "${json}"
|
||||
}
|
||||
|
||||
# raw inline functions, for special use
|
||||
# $1 CHAT $2 message-id $3 keyboard
|
||||
edit_inline_keyboard() {
|
||||
# JSON='"message_id":"$2", "reply_markup": {"inline_keyboard": [ $3->[{"text":"text", "url":"url"}]<- ]}'
|
||||
sendJson "$1" '"message_id":'"$2"', "reply_markup": {"inline_keyboard": [ '"$3"' ]}' "${URL}/editMessageReplyMarkup"
|
||||
# func="$1" err="$2" chat="$3" user="$4" emsg="$5" remaining args
|
||||
[ -n "${BOTSENT[ERROR]}" ] && processError "${FUNCNAME[0]}" "${BOTSENT[ERROR]}" "$1" "" "${BOTSENT[DESCRIPTION]}" "$2"
|
||||
}
|
||||
|
||||
|
||||
# $1 CHAT $2 message $3 keyboard
|
||||
send_inline_keyboard() {
|
||||
local text; text='"text":"'$(JsonEscape "$2")'"'; [ -z "$2" ] && text='"text":"..."'
|
||||
sendJson "$1" "${text}"', "reply_markup": {"inline_keyboard": [ '"$3"' ]}' "${MSG_URL}"
|
||||
# func="$1" err="$2" chat="$3" user="$4" emsg="$5" remaining args
|
||||
[ -n "${BOTSENT[ERROR]}" ] && processError "${FUNCNAME[0]}" "${BOTSENT[ERROR]}" "$1" "" "${BOTSENT[DESCRIPTION]}" "$2" "$3"
|
||||
}
|
||||
|
||||
# $1 callback id, $2 text to show, alert if not empty
|
||||
answer_callback_query() {
|
||||
local alert
|
||||
[ -n "$3" ] && alert='","show_alert": true'
|
||||
sendJson "" '"callback_query_id": "'"$1"'","text":"'"$2${alert}"'"' "${URL}/answerCallbackQuery"
|
||||
}
|
||||
|
||||
# $1 chat, $2 file_id on telegram server
|
||||
send_sticker() {
|
||||
sendJson "$1" '"sticker": "'"$2"'"' "${URL}/sendSticker"
|
||||
# func="$1" err="$2" chat="$3" user="$4" emsg="$5" remaining args
|
||||
[ -n "${BOTSENT[ERROR]}" ] && processError "${FUNCNAME[0]}" "${BOTSENT[ERROR]}" "$1" "" "${BOTSENT[DESCRIPTION]}" "$2"
|
||||
}
|
||||
|
||||
|
||||
# only curl can send files ...
|
||||
if detect_curl ; then
|
||||
# there are no checks if URL or ID exists
|
||||
# $1 chat $3 ... $n URL or ID
|
||||
send_album(){
|
||||
[ -z "$1" ] && return 1
|
||||
[ -z "$3" ] && return 2 # minimum 2 files
|
||||
local CHAT JSON IMAGE; CHAT="$1"; shift
|
||||
for IMAGE in "$@"
|
||||
do
|
||||
[ -n "${JSON}" ] && JSON+=","
|
||||
JSON+='{"type":"photo","media":"'${IMAGE}'"}'
|
||||
done
|
||||
# shellcheck disable=SC2086
|
||||
res="$("${BASHBOT_CURL}" -s -k ${BASHBOT_CURL_ARGS} "${URL}/sendMediaGroup" -F "chat_id=${CHAT}"\
|
||||
-F "media=[${JSON}]" | "${JSONSHFILE}" -s -b -n 2>/dev/null )"
|
||||
sendJsonResult "${res}" "send_album (curl)" "${CHAT}" "$@"
|
||||
[[ -z "${SOURCE}" && -n "${BASHBOT_EVENT_SEND[*]}" ]] && event_send "album" "$@" &
|
||||
}
|
||||
else
|
||||
send_album(){
|
||||
log_error "Sorry, wget Album upload not implemented"
|
||||
BOTSENT[OK]="false"
|
||||
[[ -z "${SOURCE}" && -n "${BASHBOT_EVENT_SEND[*]}" ]] && event_send "album" "$@" &
|
||||
}
|
||||
fi
|
||||
|
||||
# supports local file, URL and file_id
|
||||
# $1 chat, $2 file https::// file_id:// , $3 caption, $4 extension (optional)
|
||||
send_file(){
|
||||
local url what num stat media capt="$3" file="$2" ext="$4"
|
||||
if [[ "${file}" =~ ^https*:// ]]; then
|
||||
media="URL"
|
||||
elif [[ "${file}" == file_id://* ]]; then
|
||||
media="ID"
|
||||
file="${file#file_id://}"
|
||||
else
|
||||
# we have a file, check file location ...
|
||||
media="FILE"
|
||||
file="$(checkUploadFile "$1" "$2" "send_file")"
|
||||
[ -z "${file}" ] && return 1
|
||||
# file OK, let's continue
|
||||
fi
|
||||
|
||||
# no type given, use file ext, if no ext type photo
|
||||
if [ -z "${ext}" ]; then
|
||||
ext="${file##*.}"
|
||||
[ "${ext}" = "${file}" ] && ext="photo"
|
||||
fi
|
||||
# select upload URL
|
||||
case "${ext}" in
|
||||
photo|png|jpg|jpeg|gif|pic)
|
||||
url="${URL}/sendPhoto"; what="photo"; num=",0"; stat="upload_photo"
|
||||
;;
|
||||
audio|mp3|flac)
|
||||
url="${URL}/sendAudio"; what="audio"; stat="upload_audio"
|
||||
;;
|
||||
sticker|webp)
|
||||
url="${URL}/sendSticker"; what="sticker"; stat="upload_photo"
|
||||
;;
|
||||
video|mp4)
|
||||
url="${URL}/sendVideo"; what="video"; stat="upload_video"
|
||||
;;
|
||||
voice|ogg)
|
||||
url="${URL}/sendVoice"; what="voice"; stat="record_audio"
|
||||
;;
|
||||
*) url="${URL}/sendDocument"; what="document"; stat="upload_document"
|
||||
;;
|
||||
esac
|
||||
|
||||
# show file upload to user
|
||||
send_action "$1" "${stat}"
|
||||
# select method to send
|
||||
case "${media}" in
|
||||
FILE) # send local file ...
|
||||
sendUpload "$1" "${what}" "${file}" "${url}" "${capt//\\n/$'\n'}";;
|
||||
|
||||
URL|ID) # send URL, file_id ...
|
||||
sendJson "$1" '"'"${what}"'":"'"${file}"'","caption":"'"${capt//\\n/$'\n'}"'"' "${url}"
|
||||
esac
|
||||
# get file_id and file_type
|
||||
if [ "${BOTSENT[OK]}" = "true" ]; then
|
||||
BOTSENT[FILE_ID]="${UPD["result,${what}${num},file_id"]}"
|
||||
BOTSENT[FILE_TYPE]="${what}"
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# $1 chat $2 typing upload_photo record_video upload_video record_audio upload_audio upload_document find_location
|
||||
send_action() {
|
||||
[ -z "$2" ] && return
|
||||
sendJson "$1" '"action": "'"$2"'"' "${URL}/sendChatAction" &
|
||||
# func="$1" err="$2" chat="$3" user="$4" emsg="$5" remaining args
|
||||
[ -n "${BOTSENT[ERROR]}" ] && processError "${FUNCNAME[0]}" "${BOTSENT[ERROR]}" "$1" "" "${BOTSENT[DESCRIPTION]}" "$2"
|
||||
}
|
||||
|
||||
# $1 chat $2 emoji “🎲”, “🎯”, “🏀”, “⚽”, “🎰" "🎳"
|
||||
# code: "\ud83c\udfb2" "\ud83c\udfaf" "\ud83c\udfc0" "\u26bd" "\ud83c\udfb0"
|
||||
# text: ":game_die:" ":dart:" ":basketball:" ":soccer:" :slot_machine:"
|
||||
# $3 reply_to_id
|
||||
send_dice() {
|
||||
local reply emoji='\ud83c\udfb2' # default "🎲"
|
||||
[[ "$3" =~ ^[${o9o9o9}-]+$ ]] && reply=',"reply_to_message_id":'"$3"',"allow_sending_without_reply": true'
|
||||
case "$2" in # convert input to single character emoji
|
||||
*🎲*|*game*|*dice*|*'dfb2'*|*'DFB2'*) : ;;
|
||||
*🎯*|*dart* |*'dfaf'*|*'DFAF'*) emoji='\ud83c\udfaf' ;;
|
||||
*🏀*|*basket*|*'dfc0'*|*'DFC0'*) emoji='\ud83c\udfc0' ;;
|
||||
*⚽*|*soccer*|*'26bd'*|*'26BD'*) emoji='\u26bd' ;;
|
||||
*🎰*|*slot* |*'dfb0'*|*'DFB0'*) emoji='\ud83c\udfb0' ;;
|
||||
*🎳*|*bowl* |*'dfb3'*|*'DFB3'*) emoji='\ud83c\udfb3' ;;
|
||||
esac
|
||||
sendJson "$1" '"emoji": "'"${emoji}"'"'"${reply}" "${URL}/sendDice"
|
||||
if [ "${BOTSENT[OK]}" = "true" ]; then
|
||||
BOTSENT[DICE]="${UPD["result,dice,emoji"]}"
|
||||
BOTSENT[RESULT]="${UPD["result,dice,value"]}"
|
||||
else
|
||||
# func="$1" err="$2" chat="$3" user="$4" emsg="$5" remaining args
|
||||
processError "${FUNCNAME[0]}" "${BOTSENT[ERROR]}" "$1" "" "${BOTSENT[DESCRIPTION]}" "$2"
|
||||
fi
|
||||
}
|
||||
|
||||
# $1 CHAT $2 lat $3 long
|
||||
send_location() {
|
||||
[ -z "$3" ] && return
|
||||
sendJson "$1" '"latitude": '"$2"', "longitude": '"$3"'' "${URL}/sendLocation"
|
||||
# func="$1" err="$2" chat="$3" user="$4" emsg="$5" remaining args
|
||||
[ -n "${BOTSENT[ERROR]}" ] && processError "${FUNCNAME[0]}" "${BOTSENT[ERROR]}" "$1" "" "${BOTSENT[DESCRIPTION]}" "$2" "$3"
|
||||
}
|
||||
|
||||
# $1 CHAT $2 lat $3 long $4 title $5 address $6 foursquare id
|
||||
send_venue() {
|
||||
local add=""
|
||||
[ -z "$5" ] && return
|
||||
[ -n "$6" ] && add=', "foursquare_id": '"$6"''
|
||||
sendJson "$1" '"latitude": '"$2"', "longitude": '"$3"', "address": "'"$5"'", "title": "'"$4"'"'"${add}" "${URL}/sendVenue"
|
||||
# func="$1" err="$2" chat="$3" user="$4" emsg="$5" remaining args
|
||||
[ -n "${BOTSENT[ERROR]}" ] && processError "${FUNCNAME[0]}" "${BOTSENT[ERROR]}" "$1" "" "${BOTSENT[DESCRIPTION]}" "$2" "$3" "$4" "$5" "$6"
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# other send message variants ---------------------------------
|
||||
#
|
||||
|
||||
# $1 CHAT $2 from chat $3 from msg id
|
||||
forward_message() {
|
||||
[ -z "$3" ] && return
|
||||
sendJson "$1" '"from_chat_id": '"$2"', "message_id": '"$3"'' "${URL}/forwardMessage"
|
||||
# func="$1" err="$2" chat="$3" user="$4" emsg="$5" remaining args
|
||||
[ -n "${BOTSENT[ERROR]}" ] && processError "${FUNCNAME[0]}" "${BOTSENT[ERROR]}" "$1" "" "${BOTSENT[DESCRIPTION]}" "$2" "$3"
|
||||
}
|
||||
|
||||
# $1 CHAT $2 from chat $3 from msg id
|
||||
copy_message() {
|
||||
[ -z "$3" ] && return
|
||||
sendJson "$1" '"from_chat_id": '"$2"', "message_id": '"$3"'' "${URL}/copyMessage"
|
||||
# func="$1" err="$2" chat="$3" user="$4" emsg="$5" remaining args
|
||||
[ -n "${BOTSENT[ERROR]}" ] && processError "${FUNCNAME[0]}" "${BOTSENT[ERROR]}" "$1" "" "${BOTSENT[DESCRIPTION]}" "$2" "$3"
|
||||
}
|
||||
|
||||
# $1 CHAT $2 bashbot formatted message, see manual advanced usage
|
||||
send_message() {
|
||||
[ -z "$2" ] && return
|
||||
local text keyboard btext burl no_keyboard file lat long title address sent
|
||||
text="$(sed <<< "$2" 's/ mykeyboardend.*//;s/ *my[kfltab][a-z]\{2,13\}startshere.*//')$(sed <<< "$2" -n '/mytextstartshere/ s/.*mytextstartshere//p')"
|
||||
#shellcheck disable=SC2001
|
||||
text="$(sed <<< "${text}" 's/ *mynewlinestartshere */\n/g')"
|
||||
text="${text//$'\n'/\\n}"
|
||||
[ "$3" != "safe" ] && {
|
||||
no_keyboard="$(sed <<< "$2" '/mykeyboardendshere/!d;s/.*mykeyboardendshere.*/mykeyboardendshere/')"
|
||||
keyboard="$(sed <<< "$2" '/mykeyboardstartshere /!d;s/.*mykeyboardstartshere *//;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')"
|
||||
btext="$(sed <<< "$2" '/mybtextstartshere /!d;s/.*mybtextstartshere //;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')"
|
||||
burl="$(sed <<< "$2" '/myburlstartshere /!d;s/.*myburlstartshere //;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//g;s/ *mykeyboardendshere.*//g')"
|
||||
file="$(sed <<< "$2" '/myfile[^s]*startshere /!d;s/.*myfile[^s]*startshere //;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')"
|
||||
lat="$(sed <<< "$2" '/mylatstartshere /!d;s/.*mylatstartshere //;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')"
|
||||
long="$(sed <<< "$2" '/mylongstartshere /!d;s/.*mylongstartshere //;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')"
|
||||
title="$(sed <<< "$2" '/mytitlestartshere /!d;s/.*mytitlestartshere //;s/ *my[kfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')"
|
||||
address="$(sed <<< "$2" '/myaddressstartshere /!d;s/.*myaddressstartshere //;s/ *my[nkfltab][a-z]\{2,13\}startshere.*//;s/ *mykeyboardendshere.*//')"
|
||||
}
|
||||
if [ -n "${no_keyboard}" ]; then
|
||||
remove_keyboard "$1" "${text}"
|
||||
sent=y
|
||||
fi
|
||||
if [ -n "${keyboard}" ]; then
|
||||
if [[ "${keyboard}" != *"["* ]]; then # pre 0.60 style
|
||||
keyboard="[ ${keyboard//\" \"/\" \] , \[ \"} ]"
|
||||
fi
|
||||
send_keyboard "$1" "${text}" "${keyboard}"
|
||||
sent=y
|
||||
fi
|
||||
if [ -n "${btext}" ] && [ -n "${burl}" ]; then
|
||||
send_button "$1" "${text}" "${btext}" "${burl}"
|
||||
sent=y
|
||||
fi
|
||||
if [ -n "${file}" ]; then
|
||||
send_file "$1" "${file}" "${text}"
|
||||
sent=y
|
||||
fi
|
||||
if [ -n "${lat}" ] && [ -n "${long}" ]; then
|
||||
if [ -n "${address}" ] && [ -n "${title}" ]; then
|
||||
send_venue "$1" "${lat}" "${long}" "${title}" "${address}"
|
||||
else
|
||||
send_location "$1" "${lat}" "${long}"
|
||||
fi
|
||||
sent=y
|
||||
fi
|
||||
if [ "${sent}" != "y" ];then
|
||||
send_text_mode "$1" "${text}"
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
# $1 CHAT $2 message starting possibly with html_parse_mode or markdown_parse_mode
|
||||
# not working, fix or remove after 1.0!!
|
||||
send_text_mode() {
|
||||
case "$2" in
|
||||
'html_parse_mode'*)
|
||||
send_html_message "$1" "${2//html_parse_mode}"
|
||||
;;
|
||||
'markdown_parse_mode'*)
|
||||
send_markdown_message "$1" "${2//markdown_parse_mode}"
|
||||
;;
|
||||
*)
|
||||
send_normal_message "$1" "$2"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
112
mycommands.conf
Normal file
112
mycommands.conf
Normal file
|
@ -0,0 +1,112 @@
|
|||
#!/bin/bash
|
||||
# shellcheck disable=SC2034
|
||||
#######################################################
|
||||
#
|
||||
# File: mycommands.conf
|
||||
#
|
||||
# Description: place your config and messages here
|
||||
#
|
||||
# Usage: will be sourced from mycommands.sh
|
||||
#
|
||||
# License: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# Author: KayM (gnadelwartz), kay@rrr.de
|
||||
# Created: 09.01.2021 07:27
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#######################################################
|
||||
|
||||
##########
|
||||
# adjust your language setting here, default is C.UTF-8
|
||||
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
|
||||
export 'LC_ALL=C.UTF-8'
|
||||
export 'LANG=C.UTF-8'
|
||||
export 'LANGUAGE=C.UTF-8'
|
||||
|
||||
##########
|
||||
# in UTF-8 äöü etc. are part of [:alnum:] and ranges (e.g. a-z)
|
||||
# for more information see doc/4_expert.md#Character_classes
|
||||
# uncomment next line if you want classic ASCII ranges for [a-z] etc.
|
||||
#export LC_COLLATE=C
|
||||
|
||||
|
||||
##########
|
||||
# edit the following lines to fit your bot usage
|
||||
# use ${ME} for current bot name in messages
|
||||
# Note: you must escape '_' in botname with two \ in markdown messages!
|
||||
|
||||
# output of /info command
|
||||
export bashbot_info='This is @'"${ME//_/\\\\_}"', the Telegram example bot written entirely in bash.
|
||||
Edit commands and messages in mycommands.sh!
|
||||
'
|
||||
|
||||
# output of /help command (uncomment the next 2 lines
|
||||
# export bashbot_help='*Available commands*:
|
||||
# '
|
||||
|
||||
# Set INLINE to 1 in order to receive inline queries.
|
||||
# To enable this option in your bot, send the /setinline command to @BotFather.
|
||||
export INLINE="0"
|
||||
|
||||
# Set CALLBACK to 1 in order to receive callback queries.
|
||||
# callbacks are sent from inline_keyboards (buttons) attached tp bot messages
|
||||
export CALLBACK="0"
|
||||
|
||||
# if your bot is group admin it get commands sent to other bots
|
||||
# Set MEONLY to 1 to ignore commands sent to other bots
|
||||
export MEONLY="0"
|
||||
|
||||
# Set to .* to allow sending files from all locations
|
||||
# NOTE: this is a regex, not shell globbing! you must use a valid egex,
|
||||
# '.' matches any character and '.*' matches all remaining charatcers!
|
||||
# additionally you must escape special characters with '\', e.g. '\. \? \[ \*" to match them literally
|
||||
export FILE_REGEX="${BASHBOT_ETC}/.*"
|
||||
|
||||
# set BASHBOT_RETRY to enable retry in case of recoverable errors, e.g. throtteling
|
||||
# problems with send_xxx message etc are looged to logs/ERROR.log
|
||||
unset BASHBOT_RETRY
|
||||
#export BASHBOT_RETRY="yes"
|
||||
|
||||
# set value for adaptive sleeping while waiting for uodates in millisconds
|
||||
# max slepp between polling updates 10s (default 5s)
|
||||
# export BASHBOT_SLEEP="10000"
|
||||
|
||||
# max slepp between polling updates 2s (default 5s)
|
||||
# export BASHBOT_SLEEP="2000"
|
||||
|
||||
# add 0.2s if no update available, up to BASHBOT_SLEEP (default 0.1s)
|
||||
export BASHBOT_SLEEP_STEP="200"
|
||||
|
||||
# if you want to use timer functions, set BASHBOT_START_TIMER to a not empty value
|
||||
# default is to not start timer
|
||||
unset BASHBOT_START_TIMER
|
||||
#export BASHBOT_START_TIMER="yes"
|
||||
|
||||
# set to "yes" and give your bot admin privilegs to remove service messages from groups
|
||||
export SILENCER="no"
|
||||
|
||||
# uncomment to remove keyboards sent from your bot
|
||||
# export REMOVEKEYBOARD="yes"
|
||||
# export REMOVEKEYBOARD_PRIVATE="yes"
|
||||
|
||||
# uncomment to say welcome to new chat members
|
||||
# export WELCOME_NEWMEMBER="yes"
|
||||
WELCOME_MSG="Welcome"
|
||||
|
||||
# uncomment to be informed about new/left chat members
|
||||
# export REPORT_NEWMEMBER="yes"
|
||||
# export REPORT_LEFTMEMBER="yes"
|
||||
|
||||
# uncomment to send user blocked by bot a warning if they send commands
|
||||
# export NOTIFY_BLOCKED_USERS="yes"
|
||||
|
||||
# messages for admin only commands
|
||||
NOTADMIN="Sorry, this command is allowed for admin or owner only"
|
||||
NOTBOTADMIN="Sorry, this command is allowed for bot owner only"
|
||||
|
||||
########
|
||||
# special network setup may require additional ARGS to curl
|
||||
#
|
||||
# example: run bashbot over TOR or SOCKS proxy
|
||||
# export BASHBOT_CURL_ARGS="--socks5-hostname 127.0.0.1:9050" # TOR
|
||||
# export BASHBOT_CURL_ARGS="--socks5-hostname 127.0.0.1" # regular SOCKS
|
||||
|
328
mycommands.sh
328
mycommands.sh
|
@ -1,69 +1,252 @@
|
|||
#!/bin/bash
|
||||
# files: mycommands.sh.dist
|
||||
# copy to mycommands.sh and add all your commands and functions here ...
|
||||
#######################################################
|
||||
#
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
# File: mycommands.sh.dist
|
||||
#
|
||||
# shellcheck disable=SC2154
|
||||
# shellcheck disable=SC2034
|
||||
# this is an out of the box test and example file to show what's possible in mycommands.sh
|
||||
#
|
||||
# #### if you start to develop your own bot, use the clean version of this file:
|
||||
# #### mycommands.clean
|
||||
#
|
||||
# Usage: will be executed when a bot command is received
|
||||
#
|
||||
# License: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# Author: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#######################################################
|
||||
# shellcheck disable=SC1117
|
||||
|
||||
####################
|
||||
# Config has moved to bashbot.conf
|
||||
# shellcheck source=./commands.sh
|
||||
[ -r "${BASHBOT_ETC:-.}/mycommands.conf" ] && source "${BASHBOT_ETC:-.}/mycommands.conf" "$1"
|
||||
|
||||
|
||||
# uncomment the following lines to overwrite info and help messages
|
||||
# bashbot_info='This is bashbot, the Telegram bot written entirely in bash.
|
||||
#'
|
||||
# bashbot_help='*Available commands*:
|
||||
#'
|
||||
|
||||
if [ "$1" = "source" ];then
|
||||
# Set INLINE to 1 in order to receive inline queries.
|
||||
# To enable this option in your bot, send the /setinline command to @BotFather.
|
||||
INLINE="0"
|
||||
# Set to .* to allow sending files from all locations
|
||||
FILE_REGEX='/home/user/allowed/.*'
|
||||
##################
|
||||
# let's go ...
|
||||
if [ "$1" = "startbot" ];then
|
||||
###################
|
||||
# this section is processed on startup
|
||||
|
||||
# mark startup, triggers action on first message
|
||||
setConfigKey "startupaction" "await"
|
||||
else
|
||||
# your additional bahsbot commands
|
||||
# NOTE: command can have @botname attached, you must add * in case tests...
|
||||
mycommands() {
|
||||
|
||||
case "$MESSAGE" in
|
||||
#############################
|
||||
# your own bashbot commands
|
||||
# NOTE: command can have @botname attached, you must add * to case tests...
|
||||
mycommands() {
|
||||
|
||||
#############
|
||||
# action triggered on first message after startup
|
||||
if [[ "$(getConfigKey "startupaction")" != "done"* ]]; then
|
||||
# send message to first user on startup
|
||||
send_normal_message "${CHAT[ID]}" "Hi, you are the first user after startup!"
|
||||
# mark as done and when
|
||||
setConfigKey "startupaction" "done $(date)"
|
||||
fi
|
||||
|
||||
##############
|
||||
# a service Message was received
|
||||
# add your own stuff here
|
||||
if [ -n "${SERVICE}" ]; then
|
||||
|
||||
# example: delete every service message
|
||||
if [ "${SILENCER}" = "yes" ]; then
|
||||
delete_message "${CHAT[ID]}" "${MESSAGE[ID]}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# remove keyboard if you use keyboards
|
||||
[ -n "${REMOVEKEYBOARD}" ] && remove_keyboard "${CHAT[ID]}" &
|
||||
[[ -n "${REMOVEKEYBOARD_PRIVATE}" && "${CHAT[ID]}" == "${USER[ID]}" ]] && remove_keyboard "${CHAT[ID]}" &
|
||||
|
||||
# example for actions based on chat or sender
|
||||
case "${USER[ID]}+${CHAT[ID]}" in
|
||||
'USERID1+'*) # do something for all messages from USER
|
||||
printf "%s: U=%s C=%s M=%s\n" "$(date)" "${USER[ID]}" "${CHAT[ID]}" "${MESSAGE}" >>"${DATADIR}/${USER[ID]}.log"
|
||||
;;&
|
||||
*'+CHATID1') # do something for all messages from CHAT
|
||||
printf "%s: U=%s C=%s M=%s\n" "$(date)" "${USER[ID]}" "${CHAT[ID]}" "${MESSAGE}" >>"${DATADIR}/${CHAT[ID]}.log"
|
||||
;;&
|
||||
'USERID2+CHATID2') # do something only for messages form USER in CHAT
|
||||
printf "%s: U=%s C=%s M=%s\n" "$(date)" "${USER[ID]}" "${CHAT[ID]}" "${MESSAGE}" >>"${DATADIR}/${CHAT[ID]}+${USER[ID]}.log"
|
||||
;;&
|
||||
esac
|
||||
|
||||
# fix first letter upper case because of smartphone auto correction
|
||||
[[ "${MESSAGE}" =~ ^/[[:upper:]] ]] && MESSAGE="${MESSAGE:0:1}$(tr '[:upper:]' '[:lower:]' <<<"${MESSAGE:1:1}")${MESSAGE:2}"
|
||||
# pre-check admin only commands
|
||||
case "${MESSAGE}" in
|
||||
# must be private, group admin, or botadmin
|
||||
'/run_'*|'stop_'*)
|
||||
send_action "${CHAT[ID]}" "typing"
|
||||
if ! user_is_admin "${CHAT[ID]}" "${USER[ID]}" ; then
|
||||
send_normal_message "${CHAT[ID]}" "${NOTADMIN}"; return 1
|
||||
fi
|
||||
# ok, now lets process the real command
|
||||
;;
|
||||
# must be botadmin
|
||||
'/echo'*)
|
||||
send_action "${CHAT[ID]}" "typing"
|
||||
if ! user_is_botadmin "${USER[ID]}" ; then
|
||||
send_markdownv2_message "${CHAT[ID]}" "*${NOTBOTADMIN}*"; return 1
|
||||
fi
|
||||
;;
|
||||
# will we process edited messages also?
|
||||
'/_edited_message'*)
|
||||
return 1 # no
|
||||
# but if we do, remove /edited_message
|
||||
MESSAGE="${MESSAGE#/* }"
|
||||
;;
|
||||
'/_new_chat_member'*)
|
||||
if [[ -n "${WELCOME_NEWMEMBER}" && "${NEWMEMBER[ISBOT]}" != "true" ]] && bot_is_admin "${CHAT[ID]}"; then
|
||||
send_normal_message "${CHAT[ID]}"\
|
||||
"${WELCOME_MSG} ${NEWMEMBER[FIRST_NAME]} ${NEWMEMBER[LAST_NAME]} (@${NEWMEMBER[USERNAME]})"
|
||||
MYSENTID="${BOTSENT[ID]}"
|
||||
{ sleep 5; delete_message "${CHAT[ID]}" "${MYSENTID}"; } &
|
||||
[ -n "${REPORT_NEWMEMBER}" ] && send_normal_message "${BOTADMIN}"\
|
||||
"New member: ${CHAT[TITLE]} (${CHAT[ID]}): ${NEWMEMBER[FIRST_NAME]} ${NEWMEMBER[LAST_NAME]} (@${NEWMEMBER[USERNAME]})"
|
||||
fi
|
||||
;;
|
||||
'/_left_chat_member'*)
|
||||
[ -n "${REPORT_LEFTMEMBER}" ] && send_normal_message "${BOTADMIN}"\
|
||||
"Left member: ${CHAT[TITLE]} (${CHAT[ID]}): ${LEFTMEMBER[FIRST_NAME]} ${LEFTMEMBER[LAST_NAME]} (@${LEFTMEMBER[USERNAME]})"
|
||||
;;
|
||||
'/_migrate_group'*)
|
||||
# call group migration function if provided
|
||||
_exec_if_function my_migrate_group "${MIGRATE[FROM]}" "${MIGRATE[TO]}"
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
case "${MESSAGE}" in
|
||||
##################
|
||||
# example commands, replace them by your own
|
||||
'/_dice_re'*) # dice from user received
|
||||
sleep 5
|
||||
local gameresult="*Congratulation ${USER[FIRST_NAME]} ${USER[LAST_NAME]}* you got *${MESSAGE[RESULT]} Points*."
|
||||
[ -z "${FORWARD[UID]}" ] && send_markdownv2_message "${CHAT[ID]}" "${gameresult}"
|
||||
;;
|
||||
'/game'*) # send random dice, edit list to fit your needs
|
||||
send_dice "${CHAT[ID]}" ":$(printf "slot_machine\ngame_die\ndart\nbasketball\nsoccer\nslot_machine"|sort -R|shuf -n 1shuf -n 1):"
|
||||
if [ "${BOTSENT[OK]}" = "true" ]; then
|
||||
local gameresult="*Congratulation ${USER[FIRST_NAME]}* ${USER[LAST_NAME]} you got *${BOTSENT[RESULT]} Points*."
|
||||
sleep 5
|
||||
case "${BOTSENT[RESULT]}" in
|
||||
1) gameresult="*Sorry* only *one Point* ...";;
|
||||
2) gameresult="*Hey*, 2 Points are *more then one!*";;
|
||||
5|6) [[ "${BOTSENT[EMOJI]}" =~ fb0$ ]] || gameresult="*Super! ${BOTSENT[RESULT]} Points!*";;
|
||||
6*) gameresult="*JACKPOT! ${BOTSENT[RESULT]} Points!*";;
|
||||
esac
|
||||
send_markdownv2_message "${CHAT[ID]}" "${gameresult}"
|
||||
fi
|
||||
;;
|
||||
'/unpin'*) # unpin all messages if (bot)admin or allowed for user
|
||||
user_is_allowed "${USER[ID]}" "unpin" "${CHAT[ID]}" &&\
|
||||
unpinall_chat_messages "${CHAT[ID]}"
|
||||
;;
|
||||
'/echo'*) # example echo command
|
||||
send_normal_message "${CHAT[ID]}" "$MESSAGE"
|
||||
send_normal_message "${CHAT[ID]}" "${MESSAGE}"
|
||||
;;
|
||||
'/button'*)# inline button, set CALLBACK=1 for processing callbacks
|
||||
send_inline_buttons "${CHAT[ID]}" "Press Button ..." " Button |RANDOM-BUTTON"
|
||||
;;
|
||||
'/question'*) # start interactive questions
|
||||
checkproc
|
||||
if [ "$res" -gt 0 ] ; then
|
||||
startproc "example/question"
|
||||
if [ "${res}" -gt 0 ] ; then
|
||||
startproc "examples/question.sh" || send_normal_message "${CHAT[ID]}" "Can't start question."
|
||||
else
|
||||
send_normal_message "${CHAT[ID]}" "$MESSAGE already running ..."
|
||||
send_normal_message "${CHAT[ID]}" "${MESSAGE} already running ..."
|
||||
fi
|
||||
;;
|
||||
|
||||
'/run_notify'*) # start notify background job
|
||||
myback="notify"; checkback "$myback"
|
||||
if [ "$res" -gt 0 ] ; then
|
||||
background "example/notify 60" "$myback" # notify every 60 seconds
|
||||
'/cancel'*) # cancel interactive command
|
||||
checkproc
|
||||
if [ "${res}" -gt 0 ] ;then
|
||||
killproc && send_normal_message "${CHAT[ID]}" "Command canceled."
|
||||
else
|
||||
send_normal_message "${CHAT[ID]}" "Background command $myback already running ..."
|
||||
send_normal_message "${CHAT[ID]}" "No command is currently running."
|
||||
fi
|
||||
;;
|
||||
'/run_notify'*) # start notify background job
|
||||
myback="notify"; checkback "${myback}"
|
||||
if [ "${res}" -gt 0 ] ; then
|
||||
background "examples/notify.sh 60" "${myback}" || send_normal_message "${CHAT[ID]}" "Can't start notify."
|
||||
else
|
||||
send_normal_message "${CHAT[ID]}" "Background command ${myback} already running ..."
|
||||
fi
|
||||
;;
|
||||
'/stop_notify'*) # kill notify background job
|
||||
myback="notify"; checkback "$myback"
|
||||
if [ "$res" -eq 0 ] ; then
|
||||
killback "$myback"
|
||||
send_normal_message "${CHAT[ID]}" "Background command $myback canceled."
|
||||
myback="notify"; checkback "${myback}"
|
||||
if [ "${res}" -eq 0 ] ; then
|
||||
killback "${myback}"
|
||||
send_normal_message "${CHAT[ID]}" "Background command ${myback} canceled."
|
||||
else
|
||||
send_normal_message "${CHAT[ID]}" "No background command $myback is currently running.."
|
||||
send_normal_message "${CHAT[ID]}" "No background command ${myback} is currently running.."
|
||||
fi
|
||||
;;
|
||||
|
||||
##########
|
||||
# command overwrite examples
|
||||
'/info'*) # output date in front of regular info
|
||||
send_normal_message "${CHAT[ID]}" "$(date)"
|
||||
return 0
|
||||
;;
|
||||
'/kickme'*) # this will replace the /kickme command
|
||||
send_markdownv2_mesage "${CHAT[ID]}" "This bot will *not* kick you!"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
mycallbacks() {
|
||||
#######################
|
||||
# callbacks from buttons attached to messages will be processed here
|
||||
# no standard use case for processing callbacks, let's log them for some users and chats
|
||||
case "${iBUTTON[USER_ID]}+${iBUTTON[CHAT_ID]}" in
|
||||
'USERID1+'*) # do something for all callbacks from USER
|
||||
printf "%s: U=%s C=%s D=%s\n" "$(date)" "${iBUTTON[USER_ID]}" "${iBUTTON[CHAT_ID]}" "${iBUTTON[DATA]}"\
|
||||
>>"${DATADIR}/${iBUTTON[USER_ID]}.log"
|
||||
answer_callback_query "${iBUTTON[ID]}" "Request has been logged in your user log..."
|
||||
return
|
||||
;;
|
||||
*'+CHATID1') # do something for all callbacks from CHAT
|
||||
printf "%s: U=%s C=%s D=%s\n" "$(date)" "${iBUTTON[USER_ID]}" "${iBUTTON[CHAT_ID]}" "${iBUTTON[DATA]}"\
|
||||
>>"${DATADIR}/${iBUTTON[CHAT_ID]}.log"
|
||||
answer_callback_query "${iBUTTON[ID]}" "Request has been logged in chat log..."
|
||||
return
|
||||
;;
|
||||
'USERID2+CHATID2') # do something only for callbacks form USER in CHAT
|
||||
printf "%s: U=%s C=%s D=%s\n" "$(date)" "${iBUTTON[USER_ID]}" "${iBUTTON[CHAT_ID]}" "${iBUTTON[DATA]}"\
|
||||
>>"${DATADIR}/${iBUTTON[USER_ID]}-${iBUTTON[CHAT_ID]}.log"
|
||||
answer_callback_query "${iBUTTON[ID]}" "Request has been logged in user-chat log..."
|
||||
return
|
||||
;;
|
||||
*) # all other callbacks are processed here
|
||||
local callback_answer
|
||||
# your processing here ...
|
||||
# message available?
|
||||
if [[ -n "${iBUTTON[CHAT_ID]}" && -n "${iBUTTON[MESSAGE_ID]}" ]]; then
|
||||
if [ "${iBUTTON[DATA]}" = "RANDOM-BUTTON" ]; then
|
||||
callback_answer="Button pressed"
|
||||
edit_inline_buttons "${iBUTTON[CHAT_ID]}" "${iBUTTON[MESSAGE_ID]}" "Button ${RANDOM}|RANDOM-BUTTON"
|
||||
fi
|
||||
else
|
||||
callback_answer="Button to old, sorry."
|
||||
fi
|
||||
# Telegram needs an ack each callback query, default empty
|
||||
answer_callback_query "${iBUTTON[ID]}" "${callback_answer}"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
myinlines() {
|
||||
#######################
|
||||
# Inline query examples, do not use them in production (exept image search ;-)
|
||||
# Inline query examples, do not use them in production (except image search ;-)
|
||||
# shellcheck disable=SC2128
|
||||
iQUERY="${iQUERY,,}" # all lowercase
|
||||
case "${iQUERY}" in
|
||||
"image "*) # search images with yahoo
|
||||
local search="${iQUERY#* }"
|
||||
|
@ -78,50 +261,99 @@ else
|
|||
;;
|
||||
"2"*) # two photos
|
||||
answer_inline_multi "${iQUERY[ID]}" "
|
||||
$(inline_query_compose "$RANDOM" "photo" "https://avatars.githubusercontent.com/u/13046303"),
|
||||
$(inline_query_compose "$RANDOM" "photo" "https://avatars.githubusercontent.com/u/4593242")
|
||||
$(inline_query_compose "${RANDOM}" "photo" "https://avatars.githubusercontent.com/u/13046303"),
|
||||
$(inline_query_compose "${RANDOM}" "photo" "https://avatars.githubusercontent.com/u/4593242")
|
||||
"
|
||||
;;
|
||||
"3"*) # three photos
|
||||
answer_inline_multi "${iQUERY[ID]}" "
|
||||
$(inline_query_compose "$RANDOM" "photo" "https://avatars.githubusercontent.com/u/13046303"),
|
||||
$(inline_query_compose "$RANDOM" "photo" "https://avatars.githubusercontent.com/u/4593242")
|
||||
$(inline_query_compose "$RANDOM" "photo" "https://avatars.githubusercontent.com/u/102707")
|
||||
$(inline_query_compose "${RANDOM}" "photo" "https://avatars.githubusercontent.com/u/13046303"),
|
||||
$(inline_query_compose "${RANDOM}" "photo" "https://avatars.githubusercontent.com/u/4593242")
|
||||
$(inline_query_compose "${RANDOM}" "photo" "https://avatars.githubusercontent.com/u/102707")
|
||||
"
|
||||
;;
|
||||
|
||||
"4") # four photo from array
|
||||
"4") # four photos from array
|
||||
local sep=""
|
||||
local avatar=("https://avatars.githubusercontent.com/u/13046303" "https://avatars.githubusercontent.com/u/4593242" "https://avatars.githubusercontent.com/u/102707" "https://avatars.githubusercontent.com/u/6460407")
|
||||
answer_inline_multi "${iQUERY[ID]}" "
|
||||
$(for photo in ${avatar[*]} ; do
|
||||
echo "${sep}"; inline_query_compose "$RANDOM" "photo" "${photo}" "${photo}"; sep=","
|
||||
printf "%s\n" "${sep}"; inline_query_compose "${RANDOM}" "photo" "${photo}" "${photo}"; sep=","
|
||||
done)
|
||||
"
|
||||
;;
|
||||
|
||||
"sticker") # example chaecd telegram sticker
|
||||
"sticker") # example cached telegram sticker
|
||||
answer_inline_query "${iQUERY[ID]}" "cached_sticker" "BQADBAAD_QEAAiSFLwABWSYyiuj-g4AC"
|
||||
;;
|
||||
"gif") # exmaple chaehed gif
|
||||
"gif") # example cached gif
|
||||
answer_inline_query "${iQUERY[ID]}" "cached_gif" "BQADBAADIwYAAmwsDAABlIia56QGP0YC"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# place your processing functions here
|
||||
# debug function called on start, stop of bot, interactive and background processes
|
||||
# if your bot was started with debug as second argument
|
||||
# $1 current date, $2 from where the function was called, $3 ... $n optional information
|
||||
my_debug_checks() {
|
||||
# example check because my bot created a wrong file
|
||||
[ -f ".jssh" ] && printf "%s: %s\n" "$1" "Ups, found file \"${PWD:-.}/.jssh\"! =========="
|
||||
}
|
||||
|
||||
###########################
|
||||
# example recover from telegram block function
|
||||
# called when bashbot send_xxx command failed because we can not connect to telegram
|
||||
# return 0 to retry, return non 0 to give up
|
||||
bashbotBlockRecover() {
|
||||
# place your commands to unblock here, e.g. change IP or simply wait
|
||||
sleep 60 # may be temporary
|
||||
# check connection working
|
||||
[ -n "$(getJson "${ME_URL}")" ] && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
###########################
|
||||
# example error processing
|
||||
# called when delete Message failed
|
||||
# func="$1" err="$2" chat="$3" user="$4" emsg="$5" remaining args
|
||||
bashbotError_delete_message() {
|
||||
log_debug "custom errorProcessing delete_message: ERR=$2 CHAT=$3 MSGID=$6 ERTXT=$5"
|
||||
}
|
||||
|
||||
# called when error 403 is returned (and no func processing)
|
||||
# func="$1" err="$2" chat="$3" user="$4" emsg="$5" remaining args
|
||||
bashbotError_403() {
|
||||
log_debug "custom errorProcessing error 403: FUNC=$1 CHAT=$3 USER=${4:-no-user} MSGID=$6 ERTXT=$5"
|
||||
local user="$4"; [[ -z "$4" && -n "$3" ]] && user="$3"
|
||||
if [ -n "${user}" ]; then
|
||||
# block chat/user
|
||||
case "$5" in
|
||||
*"blocked"*)
|
||||
jssh_insertKeyDB "${user}" "User blocked bot on $(LANG=C date)" "${BLOCKEDFILE}";;
|
||||
*"kicked"*)
|
||||
jssh_insertKeyDB "${user}" "Bot kicked from chat on $(LANG=C date)" "${BLOCKEDFILE}";;
|
||||
*)
|
||||
jssh_insertKeyDB "${user}" "Reason: $6 on $(LANG=C date)" "${BLOCKEDFILE}";;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
###########################
|
||||
# place your processing functions here --------------
|
||||
|
||||
# $1 search parameter
|
||||
my_image_search(){
|
||||
local image result sep="" count="1"
|
||||
result="$(wget --user-agent 'Mozilla/5.0' -qO - "https://images.search.yahoo.com/search/images?p=$1" | sed 's/</\n</g' | grep "<img src=")"
|
||||
while read -r image; do
|
||||
[ "$count" -gt "9" ] && break
|
||||
[ "${count}" -gt "20" ] && break
|
||||
image="${image#* src=\'}"; image="${image%%&pid=*}"
|
||||
[[ "${image}" = *"src="* ]] && continue
|
||||
echo "${sep}"; inline_query_compose "$RANDOM" "photo" "${image}"; sep=","
|
||||
printf "%s\n" "${sep}"; inline_query_compose "${RANDOM}" "photo" "${image}"; sep=","
|
||||
count=$(( count + 1 ))
|
||||
done <<<"${result}"
|
||||
}
|
||||
|
||||
fi
|
||||
|
||||
|
|
142
mycommands.sh.clean
Normal file
142
mycommands.sh.clean
Normal file
|
@ -0,0 +1,142 @@
|
|||
#!/bin/bash
|
||||
#######################################################
|
||||
#
|
||||
# File: mycommands.sh.clean
|
||||
#
|
||||
# copy to mycommands.sh and add all your commands and functions here ...
|
||||
#
|
||||
# Usage: will be executed when a bot command is received
|
||||
#
|
||||
# License: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# Author: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#######################################################
|
||||
# shellcheck disable=SC1117
|
||||
|
||||
####################
|
||||
# Config has moved to bashbot.conf
|
||||
# shellcheck source=./commands.sh
|
||||
[ -r "${BASHBOT_ETC:-.}/mycommands.conf" ] && source "${BASHBOT_ETC:-.}/mycommands.conf" "$1"
|
||||
|
||||
|
||||
##################
|
||||
# lets's go
|
||||
if [ "$1" = "startbot" ];then
|
||||
###################
|
||||
# this section is processed on startup
|
||||
|
||||
# run once after startup when the first message is received
|
||||
my_startup(){
|
||||
:
|
||||
}
|
||||
touch .mystartup
|
||||
else
|
||||
# call my_startup on first message after startup
|
||||
# things to do only once
|
||||
[ -f .mystartup ] && rm -f .mystartup && _exec_if_function my_startup
|
||||
|
||||
#############################
|
||||
# your own bashbot commands
|
||||
# NOTE: command can have @botname attached, you must add * to case tests...
|
||||
mycommands() {
|
||||
|
||||
##############
|
||||
# a service Message was received
|
||||
# add your own stuff here
|
||||
if [ -n "${SERVICE}" ]; then
|
||||
# example: delete every service message
|
||||
if [ "${SILENCER}" = "yes" ]; then
|
||||
delete_message "${CHAT[ID]}" "${MESSAGE[ID]}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# remove keyboard if you use keyboards
|
||||
[ -n "${REMOVEKEYBOARD}" ] && remove_keyboard "${CHAT[ID]}" &
|
||||
[[ -n "${REMOVEKEYBOARD_PRIVATE}" && "${CHAT[ID]}" == "${USER[ID]}" ]] && remove_keyboard "${CHAT[ID]}" &
|
||||
|
||||
# uncommet to fix first letter upper case because of smartphone auto correction
|
||||
#[[ "${MESSAGE}" =~ ^/[[:upper:]] ]] && MESSAGE="${MESSAGE:0:1}$(tr '[:upper:]' '[:lower:]' <<<"${MESSAGE:1:1}")${MESSAGE:2}"
|
||||
case "${MESSAGE}" in
|
||||
##################
|
||||
# example command, replace them by your own
|
||||
'/echo'*) # example echo command
|
||||
send_normal_message "${CHAT[ID]}" "${MESSAGE}"
|
||||
;;
|
||||
|
||||
##########
|
||||
# command overwrite examples
|
||||
# return 0 -> run default command afterwards
|
||||
# return 1 -> skip possible default commands
|
||||
'/info'*) # output date in front of regular info
|
||||
send_normal_message "${CHAT[ID]}" "$(date)"
|
||||
return 0
|
||||
;;
|
||||
'/kickme'*) # this will replace the /kickme command
|
||||
send_markdownv2_mesage "${CHAT[ID]}" "This bot will *not* kick you!"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
mycallbacks() {
|
||||
#######################
|
||||
# callbacks from buttons attached to messages will be processed here
|
||||
case "${iBUTTON[USER_ID]}+${iBUTTON[CHAT_ID]}" in
|
||||
*) # all other callbacks are processed here
|
||||
local callback_answer
|
||||
: # your processing here ...
|
||||
:
|
||||
# Telegram needs an ack each callback query, default empty
|
||||
answer_callback_query "${iBUTTON[ID]}" "${callback_answer}"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
myinlines() {
|
||||
#######################
|
||||
# this fuinction is called only if you has set INLINE=1 !!
|
||||
# shellcheck disable=SC2128
|
||||
iQUERY="${iQUERY,,}"
|
||||
|
||||
|
||||
case "${iQUERY}" in
|
||||
##################
|
||||
# example inline command, replace it by your own
|
||||
"image "*) # search images with yahoo
|
||||
local search="${iQUERY#* }"
|
||||
answer_inline_multi "${iQUERY[ID]}" "$(my_image_search "${search}")"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
#####################
|
||||
# place your processing functions here
|
||||
|
||||
# example inline processing function, not really useful
|
||||
# $1 search parameter
|
||||
my_image_search(){
|
||||
local image result sep="" count="1"
|
||||
result="$(wget --user-agent 'Mozilla/5.0' -qO - "https://images.search.yahoo.com/search/images?p=$1" | sed 's/</\n</g' | grep "<img src=")"
|
||||
while read -r image; do
|
||||
[ "${count}" -gt "20" ] && break
|
||||
image="${image#* src=\'}"; image="${image%%&pid=*}"
|
||||
[[ "${image}" = *"src="* ]] && continue
|
||||
printf "%s\n" "${sep}"; inline_query_compose "${RANDOM}" "photo" "${image}"; sep=","
|
||||
count=$(( count + 1 ))
|
||||
done <<<"${result}"
|
||||
}
|
||||
|
||||
###########################
|
||||
# example error processing
|
||||
# called when delete Message failed
|
||||
# func="$1" err="$2" chat="$3" user="$4" emsg="$5" remaining args
|
||||
bashbotError_delete_message() {
|
||||
log_debug "custom errorProcessing delete_message: ERR=$2 CHAT=$3 MSGID=$6 ERTXT=$5"
|
||||
}
|
||||
|
||||
# called when error 403 is returned (and no func processing)
|
||||
# func="$1" err="$2" chat="$3" user="$4" emsg="$5" remaining args
|
||||
bashbotError_403() {
|
||||
log_debug "custom errorProcessing error 403: FUNC=$1 CHAT=$3 USER=${4:-no-user} MSGID=$6 ERTXT=$5"
|
||||
}
|
||||
fi
|
49
scripts/interactive.sh.clean
Executable file
49
scripts/interactive.sh.clean
Executable file
|
@ -0,0 +1,49 @@
|
|||
#!/bin/bash
|
||||
########################################################################
|
||||
#
|
||||
# File: interactive.sh
|
||||
#
|
||||
# Description: template for an interactive chat
|
||||
#
|
||||
# Usgage: start_proc "${CHAT[ID]}" ./scripts/interactive.sh.clean
|
||||
#
|
||||
# Test in CLI: ./scripts/interactive.sh.clean
|
||||
#
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
########################################################################
|
||||
|
||||
######
|
||||
# parameters
|
||||
# $1 $2 args as given to start_proc chat script arg1 arg2
|
||||
# $3 path to named pipe
|
||||
|
||||
# adjust your language setting here
|
||||
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
|
||||
export 'LC_ALL=C.UTF-8'
|
||||
export 'LANG=C.UTF-8'
|
||||
export 'LANGUAGE=C.UTF-8'
|
||||
|
||||
unset IFS
|
||||
# set -f # if you are paranoid use set -f to disable globbing
|
||||
|
||||
#######################
|
||||
# place your commands here
|
||||
#
|
||||
# IMPORTTANT: to read user input from $INPUT
|
||||
INPUT="${3:-/dev/stdin}"
|
||||
#
|
||||
# read -r variable <"${INPUT}"
|
||||
|
||||
# example wait form user input and echo it
|
||||
printf "Enter a message:\n"
|
||||
|
||||
read -r test <"${INPUT}"
|
||||
printf "%s\n" "Your Message: ${test}\nbye!"
|
||||
|
||||
|
||||
# your commands ends here
|
||||
######################
|
||||
|
|
@ -1,58 +1,79 @@
|
|||
#!/usr/bin/env bash
|
||||
#===============================================================================
|
||||
#
|
||||
# ADD a new test skeleton to test dir, but does not activate test
|
||||
# FILE: ADD-test-new.sh
|
||||
#
|
||||
# USAGE: ADD-test-new.sh
|
||||
#
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
# DESCRIPTION: creates interactive a new test skeleton, but does not activate test
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
# magic to ensure that we're always inside the root of our application,
|
||||
# no matter from which directory we'll run script
|
||||
GIT_DIR=$(git rev-parse --git-dir)
|
||||
cd "${GIT_DIR}/.." || exit 1
|
||||
|
||||
echo -ne "\\nDo your really want to create an new test for bashbot test suite? (y/N) N\\b"
|
||||
printf "\nDo your really want to create an new test for bashbot test suite? (y/N) N\b"
|
||||
read -r REALLY
|
||||
|
||||
[ "${REALLY}" != "y" ] && echo "Aborting ..." && exit 1
|
||||
[ "${REALLY}" != "y" ] && printf "Stop ...\n\n" && exit 1
|
||||
|
||||
# enter name
|
||||
echo -ne "\\nEnter Name for the the new test, 6+ chars, no :space: (empty to abort) abort\\b\\b\\b\\b\\b"
|
||||
printf "\nEnter Name for the the new test, 6+ chars, no :space: (empty to stop) stop\b\b\b\b"
|
||||
read -r NAME
|
||||
|
||||
if [ "${NAME}" = "" ] || [ "${NAME}" = "" ]; then echo "Aborting ..."; exit 1; fi
|
||||
if [ "${NAME}" = "" ] || [ "${NAME}" = "" ]; then printf "Stop ...\n\n"; exit 1; fi
|
||||
|
||||
# enter pass a-z
|
||||
echo -ne "\\nEnter PASS \"a\" to \"z\" to execute the new test, d\\b"
|
||||
printf "\nEnter PASS \"a\" to \"z\" to execute the new test, d\b"
|
||||
read -r PASS
|
||||
|
||||
# pass to lower, default pass d
|
||||
PASS="${PASS,,}"
|
||||
[ "${PASS}" = "" ] && PASS="d"
|
||||
[ "${#PASS}" != '1' ] && echo "Sorry, PASS must exactly one charater from a to z, aborting ..." && exit 1
|
||||
[ "${#PASS}" != '1' ] && printf "SORRY: PASS must exactly one character from a to z! Stop ...\n\n" && exit 1
|
||||
|
||||
TEST="${PASS}-${NAME}-test"
|
||||
|
||||
echo -e " OK! You entered name \"${NAME}\" and pass \"${PASS}\".\\n"
|
||||
printf "%s\n\n" " OK! Let's create test name \"${NAME}\" for pass \"${PASS}\"."
|
||||
|
||||
# check if already exist
|
||||
if [ -f "test/${TEST}.sh" ] || [ -d "test/${TEST}" ]; then
|
||||
echo "TEST EXIST ALREADY! Aborting ..."
|
||||
printf "%s\n\n" "SORRY: Test test/${TEST}.sh already exists! Stop ..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "The following files will be created for test \"${TEST}.sh\":"
|
||||
echo -e " test/${TEST}.sh\\n test/${TEST}/${TEST}.input\\n test/${TEST}/${TEST}.result"
|
||||
printf "The following files will be created:\n"
|
||||
printf "%s\n%s\n%s\n" " test/${TEST}.sh" " test/${TEST}/${TEST}.input" " test/${TEST}/${TEST}.result"
|
||||
|
||||
echo -ne "\\nCreate the new test for bashbot test suite? (y/N) N\\b"
|
||||
printf "\nCreate the new test for bashbot test suite? (y/N) N\b"
|
||||
read -r REALLY
|
||||
|
||||
[ "${REALLY}" != "y" ] && echo "Aborting ..." && exit 1
|
||||
[ "${REALLY}" != "y" ] && printf "Stop ...\n\n" && exit 1
|
||||
|
||||
echo -e " OK!\\n"
|
||||
printf " OK!\n\n"
|
||||
|
||||
# create files
|
||||
cat >"test/${TEST}.sh" <<EOF
|
||||
#!/usr/bin/env bash
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: test/${TEST}.sh
|
||||
#
|
||||
# USAGE: must run only from dev/all-tests.sh
|
||||
#
|
||||
# DESCRIPTION: test ,,,
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: yourname, your@e-mail.com
|
||||
#
|
||||
#### \$\$VERSION\$\$
|
||||
#===============================================================================
|
||||
|
||||
# include common functions and definitions
|
||||
# shellcheck source=test/ALL-tests.inc.sh
|
||||
|
@ -64,7 +85,8 @@ cd "\${TESTDIR}" || exit 1
|
|||
|
||||
# source bashbot.sh function, uncomment if you want to test functions
|
||||
# shellcheck source=./bashbot.sh
|
||||
# source "\\${TESTDIR}/bashbot.sh" source
|
||||
# source "\${TESTDIR}/bashbot.sh" source
|
||||
# source "\${TESTDIR}/commands.sh" source
|
||||
|
||||
# start writing your tests here ...
|
||||
|
||||
|
@ -76,4 +98,4 @@ touch "test/${TEST}/${TEST}.input" "test/${TEST}/${TEST}.result"
|
|||
set +f
|
||||
ls -l test/"${PASS}"-"${NAME}"-*
|
||||
|
||||
echo "Done."
|
||||
printf "\nDone.\n"
|
||||
|
|
|
@ -1,5 +1,18 @@
|
|||
#!/usr/bin/env bash
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: ALL-tests.inc.sh
|
||||
#
|
||||
# USAGE: source ALL-tests.inc.sh
|
||||
#
|
||||
# DESCRIPTION: must be included from all tests,
|
||||
# setup bashbot test environment and common test functions
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
# common variables
|
||||
export TESTME DIRME TESTDIR LOGFILE REFDIR TESTNAME
|
||||
|
@ -11,12 +24,14 @@ export TESTME DIRME TESTDIR LOGFILE REFDIR TESTNAME
|
|||
TESTNAME="${REFDIR//-/ }"
|
||||
|
||||
# common filenames
|
||||
export TOKENFILE ACLFILE COUNTFILE ADMINFILE DATADIR
|
||||
TOKENFILE="token"
|
||||
export TOKENFILE ACLFILE COUNTFILE BLOCKEDFILE ADMINFILE DATADIR JSONSHFILE
|
||||
TOKENFILE="botconfig.jssh"
|
||||
ACLFILE="botacl"
|
||||
COUNTFILE="count"
|
||||
ADMINFILE="botadmin"
|
||||
COUNTFILE="count.jssh"
|
||||
BLOCKEDFILE="blocked.jssh"
|
||||
ADMINFILE="botconfig.jssh"
|
||||
DATADIR="data-bot-bash"
|
||||
JSONSHFILE="JSON.sh/JSON.sh"
|
||||
|
||||
# SUCCESS NOSUCCES
|
||||
export SUCCESS NOSUCCESS
|
||||
|
@ -24,31 +39,53 @@ export SUCCESS NOSUCCESS
|
|||
NOSUCCESS=" FAILED!"
|
||||
|
||||
# default input, reference and output files
|
||||
export INPUTFILE REFFILE OUTPUTFILE
|
||||
export INPUTFILE REFFILE OUTPUTFILE INPUTFILELIST
|
||||
# shellcheck disable=SC2125
|
||||
INPUTFILELIST="${DIRME}/${REFDIR}/${REFDIR}-"*".input"
|
||||
OUTPUTFILE="${TESTDIR}/${REFDIR}.out"
|
||||
INPUTFILE="${DIRME}/${REFDIR}/${REFDIR}.input"
|
||||
REFFILE="${DIRME}/${REFDIR}/${REFDIR}.result"
|
||||
OUTPUTFILE="${TESTDIR}/${REFDIR}.out"
|
||||
|
||||
# reset ENVIRONMENT
|
||||
export BASHBOT_URL TESTTOKEN BOTTOKEN BASHBOT_HOME BASHBOT_VAR BASHBOT_ETC
|
||||
BOTTOKEN=""
|
||||
BASHBOT_HOME=""
|
||||
BASHBOT_VAR=""
|
||||
BASHBOT_ETC=""
|
||||
# do not query telegram when testing
|
||||
BASHBOT_URL="https://my-json-server.typicode.com/topkecleon/telegram-bot-bash/getMe?"
|
||||
TESTTOKEN="123456789:BASHBOTTESTSCRIPTbashbottestscript_"
|
||||
|
||||
# print arrays in reproducible order
|
||||
print_array() {
|
||||
local idx t
|
||||
local arrays=( "${@}" )
|
||||
for idx in "${arrays[@]}"; do
|
||||
declare -n temp="$idx"
|
||||
declare -n temp="${idx}"
|
||||
for t in "${!temp[@]}"; do
|
||||
printf '%s:\t%s\t%s\n' "$idx" "$t" "${temp[$t]}"
|
||||
printf '%s:\t%s\t%s\n' "${idx}" "${t}" "${temp[${t}]}"
|
||||
done | sort
|
||||
done | grep -v '^USER: 0'
|
||||
}
|
||||
|
||||
|
||||
compare_sorted() {
|
||||
local ret=0
|
||||
sort -d -o "$1.sort" "$1"
|
||||
sort -d -o "$2.sort" "$2"
|
||||
diff -c "$1.sort" "$2.sort" || ret=1
|
||||
[[ "$1" != "${TESTDIR}"* ]] && rm -f "$1.sort"
|
||||
[[ "$2" != "${TESTDIR}"* ]] && rm -f "$2.sort"
|
||||
return "${ret}"
|
||||
}
|
||||
|
||||
######
|
||||
# lets go ...
|
||||
echo "Running ${TESTNAME#? } ..."
|
||||
echo "............................"
|
||||
[ "${TESTDIR}" = "" ] && echo "${NOSUCCESS} not called from testsuite, exit" && exit 1
|
||||
printf "Running %s ...\n" "${TESTNAME#? }"
|
||||
printf "............................\n"
|
||||
[ "${TESTDIR}" = "" ] && printf "%s not called from testsuite, exit" "${NOSUCCESS}" && exit 1
|
||||
|
||||
# reset env for test
|
||||
unset IFS; set -f
|
||||
unset IFS;
|
||||
export TERM=""
|
||||
|
||||
|
|
|
@ -1,5 +1,17 @@
|
|||
#!/usr/bin/env bash
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: b-example-test.sh
|
||||
#
|
||||
# USAGE: must run only from dev/all-tests.sh
|
||||
#
|
||||
# DESCRIPTION: run pre-commit tests first
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
../dev/hooks/pre-commit.sh
|
||||
|
||||
|
|
|
@ -1,16 +1,35 @@
|
|||
#!/usr/bin/env bash
|
||||
# file: b-example-test.sh
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: b-example-test.sh
|
||||
#
|
||||
# USAGE: must run only from dev/all-tests.sh
|
||||
#
|
||||
# DESCRIPTION: minimal test file as template
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
# include common functions and definitions
|
||||
# shellcheck source=test/ALL-tests.inc.sh
|
||||
source "./ALL-tests.inc.sh"
|
||||
|
||||
###
|
||||
# place your tests here ....
|
||||
|
||||
# example: test if TESTDIR contains file bashbot.sh
|
||||
printf "Check if bashbot.sh exists in %s ...\n" " ${TESTDIR}"
|
||||
if [ -f "${TESTDIR}/bashbot.sh" ]; then
|
||||
echo "${SUCCESS} bashbot.sh exist!"
|
||||
exit 0
|
||||
printf " ... bashbot.sh found!\n"
|
||||
else
|
||||
echo "${NOSUCCESS} ${TESTDIR}/bashbot.sh missing!"
|
||||
# stop test script if test failed
|
||||
printf "%s\n" "${NOSUCCESS} ${TESTDIR}/bashbot.sh missing!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# only if all tests was successful
|
||||
printf "%s\n" "${SUCCESS}"
|
||||
|
||||
|
|
|
@ -1,46 +1,62 @@
|
|||
#!/usr/bin/env bash
|
||||
#### $$VERSION$$ v0.72-1-g67c47ac
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: c-init-test.sh
|
||||
#
|
||||
# USAGE: must run only from dev/all-tests.sh
|
||||
#
|
||||
# DESCRIPTION: test "bashbot.sh init" and sourcing bashbot.sh
|
||||
#
|
||||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
# include common functions and definitions
|
||||
# shellcheck source=test/ALL-tests.inc.sh
|
||||
source "./ALL-tests.inc.sh"
|
||||
|
||||
TESTTOKEN="bashbottestscript"
|
||||
TESTFILES="${TOKENFILE} ${ACLFILE} ${COUNTFILE} ${ADMINFILE}"
|
||||
TESTFILES="${TOKENFILE} ${ACLFILE} ${COUNTFILE} ${BLOCKEDFILE} ${ADMINFILE}"
|
||||
|
||||
set -e
|
||||
#set -e
|
||||
|
||||
# run bashbot first time with init
|
||||
printf "Run bashbot init ...\n"
|
||||
"${TESTDIR}/bashbot.sh" init >"${LOGFILE}" <<EOF
|
||||
$TESTTOKEN
|
||||
${TESTTOKEN}
|
||||
nobody
|
||||
botadmin
|
||||
EOF
|
||||
echo "${SUCCESS}"
|
||||
|
||||
# compare files with refrence files
|
||||
echo "Check new files after init ..."
|
||||
EOF
|
||||
printf "%s\n" "${SUCCESS}"
|
||||
|
||||
# compare files with reference files
|
||||
printf "Check new files after init ...\n"
|
||||
export FAIL="0"
|
||||
for file in ${TESTFILES}
|
||||
do
|
||||
ls -d "${TESTDIR}/${file}" >>"${LOGFILE}"
|
||||
if ! diff -q "${TESTDIR}/${file}" "${REFDIR}/${file}" >>"${LOGFILE}"; then echo "${NOSUCCESS} Fail diff ${file}!"; FAIL="1"; fi
|
||||
|
||||
diff -q "${TESTDIR}/${file}" "${REFDIR}/${file}" >>"${LOGFILE}" || { printf "%s\n" "${NOSUCCESS} Fail diff ${file}!"; FAIL="1"; }
|
||||
done
|
||||
[ "${FAIL}" != "0" ] && exit "${FAIL}"
|
||||
echo "${SUCCESS}"
|
||||
printf "%s\n" "${SUCCESS}"
|
||||
|
||||
echo "Test Sourcing of bashbot.sh ..."
|
||||
trap exit 1 EXIT
|
||||
cd "${TESTDIR}" || exit
|
||||
|
||||
printf "%s\n" "Test if ${JSONSHFILE} exists ..."
|
||||
[ ! -x "${JSONSHFILE}" ] && { printf "%s\n" "${NOSUCCESS} json.sh not found"; exit 1; }
|
||||
|
||||
printf "Test Sourcing of bashbot.sh ...\n"
|
||||
# shellcheck source=./bashbot.sh
|
||||
source "${TESTDIR}/bashbot.sh" source
|
||||
|
||||
printf "Test Sourcing of commands.sh ...\n"
|
||||
source "${TESTDIR}/commands.sh" source
|
||||
|
||||
trap '' EXIT
|
||||
cd "${DIRME}" || exit 1
|
||||
echo "${SUCCESS}"
|
||||
|
||||
echo "Test bashbot.sh count"
|
||||
cp "${REFDIR}/count.test" "${TESTDIR}/count"
|
||||
"${TESTDIR}/bashbot.sh" count
|
||||
printf "%s\n" "${SUCCESS}"
|
||||
|
||||
|
|
1
test/c-init-test/blocked.jssh
Normal file
1
test/c-init-test/blocked.jssh
Normal file
|
@ -0,0 +1 @@
|
|||
["blocked_user_or_chat_id"] "name and reason"
|
|
@ -1 +0,0 @@
|
|||
?
|
3
test/c-init-test/botconfig.jssh
Normal file
3
test/c-init-test/botconfig.jssh
Normal file
|
@ -0,0 +1,3 @@
|
|||
["bot_config_key"] "config_key_value"
|
||||
["bottoken"] "123456789:BASHBOTTESTSCRIPTbashbottestscript_"
|
||||
["botadmin"] "?"
|
|
@ -1 +0,0 @@
|
|||
|
1
test/c-init-test/count.jssh
Normal file
1
test/c-init-test/count.jssh
Normal file
|
@ -0,0 +1 @@
|
|||
["counted_user_chat_id"] "num_messages_seen"
|
|
@ -1,80 +1,27 @@
|
|||
COUNT-3474588
|
||||
COUNT2224533
|
||||
COUNT-10011894466
|
||||
COUNT7053247
|
||||
COUNT6391479
|
||||
COUNT6341244
|
||||
COUNT4919830
|
||||
COUNT2640175
|
||||
COUNT7349731
|
||||
COUNT7244826
|
||||
COUNT2741728
|
||||
COUNT6376258
|
||||
COUNT-10012414459
|
||||
COUNT5869285
|
||||
COUNT-10011297801
|
||||
COUNT190323
|
||||
COUNT7784183
|
||||
COUNT-2766119
|
||||
COUNT-3859393
|
||||
COUNT-10013599717
|
||||
COUNT-10012886611
|
||||
COUNT2442778
|
||||
COUNT5759451
|
||||
COUNT5254245
|
||||
COUNT3781067
|
||||
COUNT7916264
|
||||
COUNT7235018
|
||||
COUNT3349831
|
||||
COUNT2933766
|
||||
COUNT5924516
|
||||
COUNT6374645
|
||||
COUNT6407149
|
||||
COUNT2383316
|
||||
COUNT5447722
|
||||
COUNT231261
|
||||
COUNT7853337
|
||||
COUNT7768269
|
||||
COUNT7546987
|
||||
COUNT7882954
|
||||
COUNT6081264
|
||||
COUNT4473899
|
||||
COUNT6000622
|
||||
COUNT7489339
|
||||
COUNT7925467
|
||||
COUNT146383
|
||||
COUNT1850458
|
||||
COUNT5232050
|
||||
COUNT7827320
|
||||
COUNT3230155
|
||||
COUNT5110579
|
||||
COUNT2968981
|
||||
COUNT6709735
|
||||
COUNT3042403
|
||||
COUNT6973351
|
||||
COUNT3739552
|
||||
COUNT6073516
|
||||
COUNT7773218
|
||||
COUNT7570810
|
||||
COUNT7165830
|
||||
COUNT7836756
|
||||
COUNT2603688
|
||||
COUNT2792256
|
||||
COUNT1199924
|
||||
COUNT7044680
|
||||
COUNT5011616
|
||||
COUNT5944645
|
||||
COUNT6040303
|
||||
COUNT7787713
|
||||
COUNT7670967
|
||||
COUNT4902763
|
||||
COUNT8168450
|
||||
COUNT5233276
|
||||
COUNT-10012311537
|
||||
COUNT7648681
|
||||
COUNT4170584
|
||||
COUNT3045040
|
||||
COUNT5919227
|
||||
COUNT3364980
|
||||
COUNT-3450384
|
||||
COUNT7287381
|
||||
["counted_user_id"] "num_messages_seen"
|
||||
["712677"] "2"
|
||||
["-1001189446"] "29"
|
||||
["-1001288661"] "6"
|
||||
["-1001433755"] "4"
|
||||
["-408138"] "2"
|
||||
["1246831"] "7"
|
||||
["-1001186489"] "4"
|
||||
["-1001259400"] "8"
|
||||
["791626"] "18"
|
||||
["-1001293952"] "4"
|
||||
["-1001435141"] "7"
|
||||
["733039"] "2"
|
||||
["-1001319011"] "6"
|
||||
["-1001220313"] "15"
|
||||
["26122"] "3"
|
||||
["988411"] "8"
|
||||
["908527"] "6"
|
||||
["-1001450413"] "58"
|
||||
["748933"] "2"
|
||||
["-1001425571"] "5"
|
||||
["788295"] "3"
|
||||
["586928"] "45"
|
||||
["-1001359971"] "7"
|
||||
["1069707"] "19"
|
||||
["-1001189446"] "30"
|
||||
["-1001189446"] "31"
|
||||
|
|
1
test/c-init-test/stats.out
Normal file
1
test/c-init-test/stats.out
Normal file
|
@ -0,0 +1 @@
|
|||
A total of 272 messages from 24 users are processed.
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user