Compare commits
360 Commits
Author | SHA1 | Date |
---|---|---|
Kay Marquardt | 8f23bca8a1 | |
Kay Marquardt | 420029c7f6 | |
Kay Marquardt | 02c73d432e | |
Kay Marquardt | 1c2c07397a | |
Kay Marquardt | 8f742ff1fb | |
Kay Marquardt | d0c3156e7d | |
Kay Marquardt | d157f61cf2 | |
Kay Marquardt | af7596f69a | |
Kay Marquardt | 0c25a11c5c | |
Kay Marquardt | 5653582d68 | |
Kay Marquardt | b6dc3a0d93 | |
Kay Marquardt | 4b2331b623 | |
Kay Marquardt | 38f2cc475b | |
Kay Marquardt | 74294f3fb4 | |
Kay Marquardt | 4591b357d1 | |
Kay Marquardt (Gnadelwartz) | bc71f37a2e | |
Kay Marquardt (Gnadelwartz) | 0dae2db8ac | |
Kay Marquardt (Gnadelwartz) | 1a83202a07 | |
Kay Marquardt (Gnadelwartz) | 58e6d0aaf6 | |
Kay Marquardt (Gnadelwartz) | 479f41c80e | |
Kay Marquardt (Gnadelwartz) | 67d75feace | |
Kay Marquardt (Gnadelwartz) | 1ffa890428 | |
Kay Marquardt | 6490f6756f | |
z4zz | 90d3d7551d | |
Kay Marquardt (Gnadelwartz) | d06c162f16 | |
Kay Marquardt | 89ac61afe7 | |
konqi | 369d7f8d4d | |
konqi | 93dc4a09d6 | |
konqi | 738c5e5f6d | |
Kay Marquardt (Gnadelwartz) | aad42a52fb | |
Kay Marquardt (Gnadelwartz) | a2a3927117 | |
Kay Marquardt (Gnadelwartz) | 5205fe3990 | |
Kay Marquardt (Gnadelwartz) | 783bf30190 | |
Kay Marquardt | a23370645f | |
Kay Marquardt (Gnadelwartz) | 36d8604cde | |
Kay Marquardt (Gnadelwartz) | 6e66a2877c | |
Kay Marquardt (Gnadelwartz) | 52fbb14770 | |
Kay Marquardt (Gnadelwartz) | c63f098fb0 | |
Kay Marquardt (Gnadelwartz) | 69b1871eea | |
Kay Marquardt (Gnadelwartz) | 45efa80699 | |
Kay Marquardt (Gnadelwartz) | b097f088c8 | |
Kay Marquardt (Gnadelwartz) | e4c13ddabe | |
Kay Marquardt (Gnadelwartz) | f7f55ea45f | |
Kay Marquardt (Gnadelwartz) | 9b6aba0586 | |
Kay Marquardt (Gnadelwartz) | ecaecfee6f | |
Kay Marquardt (Gnadelwartz) | 4c4ba0ba5e | |
Kay Marquardt (Gnadelwartz) | f790d73e66 | |
Kay Marquardt (Gnadelwartz) | 79fc511bdb | |
Kay Marquardt (Gnadelwartz) | 3501318d84 | |
Kay Marquardt | 443958aa5f | |
Kay Marquardt (Gnadelwartz) | 12157b380d | |
Kay Marquardt (Gnadelwartz) | cbd74a7f72 | |
Kay Marquardt (Gnadelwartz) | dedcc00b8c | |
Kay Marquardt (Gnadelwartz) | 721e433b47 | |
Kay Marquardt (Gnadelwartz) | cbde841bae | |
Kay Marquardt (Gnadelwartz) | f1ea49426b | |
Kay Marquardt (Gnadelwartz) | e60ada0bfe | |
Kay Marquardt (Gnadelwartz) | 85f7c074f4 | |
Kay Marquardt (Gnadelwartz) | 43cab461f8 | |
Kay Marquardt (Gnadelwartz) | 99950e6518 | |
Kay Marquardt | 94aefbe4d5 | |
Kay Marquardt (Gnadelwartz) | 369124bada | |
Kay Marquardt (Gnadelwartz) | 8adca9beea | |
Kay Marquardt (Gnadelwartz) | 41e6883817 | |
Kay Marquardt (Gnadelwartz) | ae525c47e0 | |
Kay Marquardt (Gnadelwartz) | 47a032d582 | |
Kay Marquardt (Gnadelwartz) | 761aa46b66 | |
Kay Marquardt (Gnadelwartz) | a5b230646b | |
Kay Marquardt (Gnadelwartz) | 24638662d3 | |
Kay Marquardt (Gnadelwartz) | b1af0f07e7 | |
Kay Marquardt (Gnadelwartz) | c4e2981116 | |
Kay Marquardt (Gnadelwartz) | 235f26a0e9 | |
Kay Marquardt (Gnadelwartz) | 50777ceff7 | |
Kay Marquardt (Gnadelwartz) | fdb2b3ac7b | |
Kay Marquardt (Gnadelwartz) | 0a296eaaa1 | |
Kay Marquardt (Gnadelwartz) | eb0c227615 | |
Kay Marquardt (Gnadelwartz) | 7500ca0d12 | |
Kay Marquardt (Gnadelwartz) | ac16103361 | |
Kay Marquardt (Gnadelwartz) | b78431eacd | |
Kay Marquardt (Gnadelwartz) | b454827109 | |
Kay Marquardt (Gnadelwartz) | e6838d1436 | |
Kay Marquardt (Gnadelwartz) | 53e936ee65 | |
Kay Marquardt (Gnadelwartz) | ec90ce820d | |
Kay Marquardt (Gnadelwartz) | 859ce92379 | |
Kay Marquardt (Gnadelwartz) | fff79d6daf | |
Kay Marquardt (Gnadelwartz) | e098aee321 | |
Kay Marquardt (Gnadelwartz) | 4854d0d051 | |
Kay Marquardt (Gnadelwartz) | 7b8e391479 | |
Kay Marquardt (Gnadelwartz) | 24158142f9 | |
Kay Marquardt (Gnadelwartz) | a9ac7eaeda | |
Kay Marquardt (Gnadelwartz) | a473e25dfd | |
Kay Marquardt (Gnadelwartz) | b6e90af4fa | |
Kay Marquardt (Gnadelwartz) | 0859354be8 | |
Kay Marquardt (Gnadelwartz) | 5dd24c3958 | |
Kay Marquardt (Gnadelwartz) | dda86e3496 | |
Kay Marquardt (Gnadelwartz) | 941598d01f | |
Kay Marquardt (Gnadelwartz) | 84ff8cec15 | |
Kay Marquardt (Gnadelwartz) | f7842f4f60 | |
Kay Marquardt (Gnadelwartz) | 34923ddabe | |
Kay Marquardt (Gnadelwartz) | 2131911625 | |
Kay Marquardt (Gnadelwartz) | f4d45d814f | |
Kay Marquardt (Gnadelwartz) | f4323e48b5 | |
Kay Marquardt (Gnadelwartz) | c57e9273fb | |
Kay Marquardt (Gnadelwartz) | 6b8ad9783a | |
Kay Marquardt (Gnadelwartz) | 17efeeb903 | |
Kay Marquardt (Gnadelwartz) | ac71000519 | |
Kay Marquardt (Gnadelwartz) | 1a0642bcce | |
Kay Marquardt (Gnadelwartz) | 192fae8a37 | |
Kay Marquardt (Gnadelwartz) | 70724427d9 | |
Kay Marquardt (Gnadelwartz) | 8b18f25c88 | |
Kay Marquardt (Gnadelwartz) | 882efa8f1a | |
Kay Marquardt (Gnadelwartz) | fdbfcebc7c | |
Kay Marquardt (Gnadelwartz) | f7897fd41b | |
Kay Marquardt (Gnadelwartz) | 473d802aab | |
Kay Marquardt | b1e6e0fc50 | |
Kay Marquardt | aee7bae141 | |
Kay Marquardt (Gnadelwartz) | 622a394494 | |
Kay Marquardt (Gnadelwartz) | 3f848ac17d | |
Kay Marquardt (Gnadelwartz) | 8efbfcaab9 | |
Kay Marquardt (Gnadelwartz) | d6f37afa3a | |
Kay Marquardt (Gnadelwartz) | 9958b5b5e1 | |
Kay Marquardt (Gnadelwartz) | 77ffbabf22 | |
Kay Marquardt (Gnadelwartz) | 82a57a77ed | |
Kay Marquardt (Gnadelwartz) | b1f6a0b230 | |
Kay Marquardt (Gnadelwartz) | 785e769460 | |
Kay Marquardt (Gnadelwartz) | 805a74eb6d | |
Kay Marquardt (Gnadelwartz) | 6b07242179 | |
Kay Marquardt (Gnadelwartz) | e67e43dd2e | |
Kay Marquardt (Gnadelwartz) | 2f4ef69971 | |
Kay Marquardt (Gnadelwartz) | 429f271939 | |
Kay Marquardt (Gnadelwartz) | 193ca1e5b9 | |
Kay Marquardt (Gnadelwartz) | a7d85e352c | |
Kay Marquardt (Gnadelwartz) | c58fa22b7a | |
Kay Marquardt (Gnadelwartz) | d3a1cecf1f | |
Kay Marquardt (Gnadelwartz) | f842730645 | |
Kay Marquardt (Gnadelwartz) | 117255a958 | |
Kay Marquardt (Gnadelwartz) | 066274c943 | |
Kay Marquardt (Gnadelwartz) | 897458a37f | |
Kay Marquardt (Gnadelwartz) | b2fc4052fc | |
Kay Marquardt (Gnadelwartz) | 62b6b618d5 | |
Kay Marquardt (Gnadelwartz) | 069570e4ed | |
Kay Marquardt (Gnadelwartz) | a9ed559383 | |
Kay Marquardt (Gnadelwartz) | 2f6f3bd4d8 | |
Kay Marquardt (Gnadelwartz) | eee5458232 | |
Kay Marquardt (Gnadelwartz) | 52d1ac5618 | |
Kay Marquardt (Gnadelwartz) | 429c230627 | |
Kay Marquardt (Gnadelwartz) | a6ff405cc5 | |
Kay Marquardt (Gnadelwartz) | 34455c2c4c | |
Kay Marquardt (Gnadelwartz) | 9d36f23b14 | |
Kay Marquardt (Gnadelwartz) | ad1b91f3bc | |
Kay Marquardt (Gnadelwartz) | ccac62dd72 | |
Kay Marquardt (Gnadelwartz) | 5294d00ae3 | |
Kay Marquardt (Gnadelwartz) | b91e96dce1 | |
Kay Marquardt (Gnadelwartz) | 5212df422e | |
Kay Marquardt (Gnadelwartz) | 0702d58ab0 | |
Kay Marquardt (Gnadelwartz) | 54673ac396 | |
Kay Marquardt (Gnadelwartz) | baa4e14ebc | |
Kay Marquardt (Gnadelwartz) | bc40a3fcbb | |
Kay Marquardt (Gnadelwartz) | 5a689d22de | |
Kay Marquardt (Gnadelwartz) | 58fb001d1e | |
Kay Marquardt | d15b4f5070 | |
Kay Marquardt (Gnadelwartz) | 6fe19556b7 | |
Kay Marquardt (Gnadelwartz) | f9dab50f84 | |
Kay Marquardt (Gnadelwartz) | 1440d56f48 | |
Kay Marquardt (Gnadelwartz) | 969c7a9fbb | |
Kay Marquardt (Gnadelwartz) | d876f758ee | |
Kay Marquardt (Gnadelwartz) | 9ce139a689 | |
Kay Marquardt (Gnadelwartz) | 3a29a9dc4a | |
Kay Marquardt (Gnadelwartz) | 737be16b3f | |
Kay Marquardt (Gnadelwartz) | 91a143ab15 | |
Kay Marquardt (Gnadelwartz) | c4d100e0ad | |
Kay Marquardt (Gnadelwartz) | e86c8dc116 | |
Kay Marquardt (Gnadelwartz) | c1aec9285e | |
Kay Marquardt (Gnadelwartz) | e4a983b16f | |
Kay Marquardt (Gnadelwartz) | 4e7b3052de | |
Kay Marquardt (Gnadelwartz) | 6754273c6e | |
Kay Marquardt (Gnadelwartz) | 5b0b121ba5 | |
Kay Marquardt (Gnadelwartz) | a7c98d750c | |
Kay Marquardt (Gnadelwartz) | 0dd5f83d5a | |
Kay Marquardt (Gnadelwartz) | 342a5da97a | |
Kay Marquardt (Gnadelwartz) | 8034a5f055 | |
Kay Marquardt (Gnadelwartz) | f377e17e44 | |
Kay Marquardt (Gnadelwartz) | bc3a3b3def | |
Kay Marquardt (Gnadelwartz) | 4833712246 | |
Kay Marquardt (Gnadelwartz) | 2a3663a463 | |
Kay Marquardt (Gnadelwartz) | a289cb8e5b | |
Kay Marquardt (Gnadelwartz) | 9316caa260 | |
Kay Marquardt (Gnadelwartz) | c0f1af529e | |
Kay Marquardt (Gnadelwartz) | 1e49f6c2b1 | |
Kay Marquardt (Gnadelwartz) | 9cfeab9cdc | |
Kay Marquardt (Gnadelwartz) | 10d275c557 | |
Kay Marquardt (Gnadelwartz) | 08b7b85d03 | |
Kay Marquardt (Gnadelwartz) | c9daa822bb | |
Kay Marquardt (Gnadelwartz) | c693ab5bb9 | |
Kay Marquardt (Gnadelwartz) | 7c748247d8 | |
Kay Marquardt (Gnadelwartz) | cfc4d2eed1 | |
Kay Marquardt (Gnadelwartz) | 41e2d09067 | |
Kay Marquardt (Gnadelwartz) | 279a9e7ca3 | |
Kay Marquardt (Gnadelwartz) | a3eec98491 | |
Kay Marquardt (Gnadelwartz) | e83f4d443f | |
Kay Marquardt (Gnadelwartz) | 0c0dc01f26 | |
Kay Marquardt (Gnadelwartz) | 3f331dc8e8 | |
Kay Marquardt (Gnadelwartz) | ca9ea1bf31 | |
Kay Marquardt (Gnadelwartz) | b45efa3726 | |
Kay Marquardt (Gnadelwartz) | 079eb1c289 | |
Kay Marquardt (Gnadelwartz) | 5a0a5712dd | |
Kay Marquardt (Gnadelwartz) | 5192212782 | |
Kay Marquardt (Gnadelwartz) | 8c85c81f94 | |
Kay Marquardt (Gnadelwartz) | cbf3945e4f | |
Kay Marquardt (Gnadelwartz) | fa0cb75c60 | |
Kay Marquardt (Gnadelwartz) | 75e775606a | |
Kay Marquardt (Gnadelwartz) | e4ee88003e | |
Kay Marquardt (Gnadelwartz) | b096338c33 | |
Kay Marquardt (Gnadelwartz) | 2222875e2b | |
Kay Marquardt (Gnadelwartz) | b441384d4a | |
Kay Marquardt (Gnadelwartz) | 08a05242f9 | |
Kay Marquardt (Gnadelwartz) | bc414eef5a | |
Kay Marquardt (Gnadelwartz) | 47cab8021d | |
Kay Marquardt (Gnadelwartz) | 6b102a728a | |
Kay Marquardt (Gnadelwartz) | 70a3c194a0 | |
Kay Marquardt (Gnadelwartz) | 5ceddde4e8 | |
Kay Marquardt (Gnadelwartz) | cc4ac1a816 | |
Kay Marquardt (Gnadelwartz) | 9584068ea3 | |
Kay Marquardt (Gnadelwartz) | c90b5658b3 | |
Kay Marquardt (Gnadelwartz) | cc7afdb149 | |
Kay Marquardt (Gnadelwartz) | aa2c20b37e | |
Kay Marquardt (Gnadelwartz) | 461e748c92 | |
Kay Marquardt (Gnadelwartz) | 1fe22a0345 | |
Kay Marquardt (Gnadelwartz) | 9023b21791 | |
Kay Marquardt (Gnadelwartz) | d9b3342c3c | |
Kay Marquardt (Gnadelwartz) | f995eeea13 | |
Kay Marquardt (Gnadelwartz) | 78e4551107 | |
Kay Marquardt (Gnadelwartz) | 41e956d517 | |
Kay Marquardt (Gnadelwartz) | 121f131bb4 | |
Kay Marquardt (Gnadelwartz) | 13052f01da | |
Kay Marquardt (Gnadelwartz) | 2960e58941 | |
Kay Marquardt (Gnadelwartz) | 8bb4b7e5ac | |
Kay Marquardt (Gnadelwartz) | 28328013c7 | |
Kay Marquardt (Gnadelwartz) | 3378c1a5d1 | |
Kay Marquardt (Gnadelwartz) | 407194b23f | |
Kay Marquardt (Gnadelwartz) | 4371050206 | |
Kay Marquardt (Gnadelwartz) | db8f32b732 | |
Kay Marquardt (Gnadelwartz) | 662c6f48cb | |
Kay Marquardt (Gnadelwartz) | e9543991ee | |
Kay Marquardt (Gnadelwartz) | 07f026c6a7 | |
Kay Marquardt (Gnadelwartz) | 749eee74a4 | |
Kay Marquardt (Gnadelwartz) | 127cc85a2a | |
Kay Marquardt (Gnadelwartz) | 85a178d68a | |
Kay Marquardt (Gnadelwartz) | f6e319c6eb | |
Kay Marquardt (Gnadelwartz) | f95b6c2e7d | |
Kay Marquardt (Gnadelwartz) | 6c91a327a6 | |
Kay Marquardt (Gnadelwartz) | 8854e03ece | |
Kay Marquardt (Gnadelwartz) | e923e2e8fc | |
Kay Marquardt (Gnadelwartz) | f2dd64c900 | |
Kay Marquardt (Gnadelwartz) | f66e5702b0 | |
Kay Marquardt (Gnadelwartz) | 0ee6973143 | |
Kay Marquardt (Gnadelwartz) | b0f653b705 | |
Kay Marquardt (Gnadelwartz) | 427f670a02 | |
Kay Marquardt (Gnadelwartz) | 62378f7cf6 | |
Kay Marquardt (Gnadelwartz) | fe1fb75748 | |
Kay Marquardt | ad532cce54 | |
Kay Marquardt (Gnadelwartz) | 5f21fcb0dc | |
Kay Marquardt (Gnadelwartz) | 3266427bcc | |
Kay Marquardt (Gnadelwartz) | d8453aad36 | |
Kay Marquardt (Gnadelwartz) | 172a9e5461 | |
Kay Marquardt (Gnadelwartz) | 161e883a9a | |
Kay Marquardt (Gnadelwartz) | 6bfab17170 | |
Kay Marquardt (Gnadelwartz) | a545bf1d8e | |
Kay Marquardt (Gnadelwartz) | d269f9816d | |
Kay Marquardt (Gnadelwartz) | 6857a5558f | |
Kay Marquardt (Gnadelwartz) | d12ab8600d | |
Kay Marquardt (Gnadelwartz) | ef972c5714 | |
Kay Marquardt (Gnadelwartz) | 277178389a | |
Kay Marquardt (Gnadelwartz) | 0f27e71b0f | |
Kay Marquardt (Gnadelwartz) | 0596983056 | |
Kay Marquardt (Gnadelwartz) | 550a0defb3 | |
Kay Marquardt (Gnadelwartz) | 541a279f29 | |
Kay Marquardt (Gnadelwartz) | 0794506753 | |
Kay Marquardt (Gnadelwartz) | abe058a53a | |
Kay Marquardt (Gnadelwartz) | eab840868e | |
Kay Marquardt (Gnadelwartz) | 28ab301ce4 | |
Kay Marquardt (Gnadelwartz) | 83990961a3 | |
Kay Marquardt (Gnadelwartz) | 8ae30faffc | |
Kay Marquardt (Gnadelwartz) | 29fa5cfcca | |
Kay Marquardt (Gnadelwartz) | 0739a51130 | |
Kay Marquardt (Gnadelwartz) | ab71f3765b | |
Kay Marquardt (Gnadelwartz) | e13b9eb940 | |
Kay Marquardt (Gnadelwartz) | 5f602a9a14 | |
Kay Marquardt (Gnadelwartz) | afade2e2f0 | |
Kay Marquardt (Gnadelwartz) | 71daed3487 | |
Kay Marquardt (Gnadelwartz) | 87f618fadb | |
Kay Marquardt (Gnadelwartz) | daeffb30e8 | |
Kay Marquardt (Gnadelwartz) | f573d63c55 | |
Kay Marquardt (Gnadelwartz) | f8d8edef0b | |
Kay Marquardt (Gnadelwartz) | cc299a5819 | |
Kay Marquardt (Gnadelwartz) | e1f209783f | |
Kay Marquardt (Gnadelwartz) | d521d35815 | |
Kay Marquardt (Gnadelwartz) | c6c30a4b9d | |
Kay Marquardt (Gnadelwartz) | bd664dacfe | |
Kay Marquardt (Gnadelwartz) | fb8b022e24 | |
Kay Marquardt (Gnadelwartz) | b9c323573c | |
Kay Marquardt (Gnadelwartz) | b2eecc56e2 | |
Kay Marquardt (Gnadelwartz) | 427e4df6ca | |
Kay Marquardt (Gnadelwartz) | 41ce9cc486 | |
Kay Marquardt (Gnadelwartz) | 171b196bbf | |
Kay Marquardt (Gnadelwartz) | 88a24cb2a3 | |
Kay Marquardt (Gnadelwartz) | 8253a53994 | |
Kay Marquardt (Gnadelwartz) | 2a3ab2a145 | |
Kay Marquardt (Gnadelwartz) | 168584d693 | |
Kay Marquardt (Gnadelwartz) | eac21375e8 | |
Kay Marquardt (Gnadelwartz) | de24dede53 | |
Kay Marquardt (Gnadelwartz) | 37e4539ef8 | |
Kay Marquardt (Gnadelwartz) | 4a9d1f0a29 | |
Kay Marquardt (Gnadelwartz) | bd2d2e1e58 | |
Kay Marquardt (Gnadelwartz) | 1eafc91452 | |
Kay Marquardt (Gnadelwartz) | f0a2843f2a | |
Kay Marquardt (Gnadelwartz) | 58e789a079 | |
Kay Marquardt (Gnadelwartz) | fa8e8a267c | |
Kay Marquardt (Gnadelwartz) | da214ab819 | |
Kay Marquardt (Gnadelwartz) | 04e3c18cc4 | |
Kay Marquardt (Gnadelwartz) | d3253fdf76 | |
Kay Marquardt (Gnadelwartz) | 6f8515d701 | |
Kay Marquardt (Gnadelwartz) | efca2e013b | |
Kay Marquardt (Gnadelwartz) | ac2e1a96f7 | |
Kay Marquardt (Gnadelwartz) | 1525ac8231 | |
Kay Marquardt (Gnadelwartz) | f08df73ddd | |
Kay Marquardt (Gnadelwartz) | c205ae528c | |
Kay Marquardt (Gnadelwartz) | cb81f7c8e0 | |
Kay Marquardt (Gnadelwartz) | bbc679463a | |
Kay Marquardt | 8be95a3abf | |
Kay Marquardt (Gnadelwartz) | ac02f5a3d3 | |
Kay Marquardt (Gnadelwartz) | 3d9f7848cf | |
Kay Marquardt (Gnadelwartz) | 126f61f00c | |
Kay Marquardt (Gnadelwartz) | dd19f0f34e | |
David Coomber | 0d3a53a7d2 | |
David Coomber | 6408befddd | |
David Coomber | 7cf624ff2e | |
Kay Marquardt (Gnadelwartz) | 4582efd556 | |
Kay Marquardt (Gnadelwartz) | 2fe6d4b0cc | |
Kay Marquardt (Gnadelwartz) | 1631b0263b | |
Kay Marquardt (Gnadelwartz) | b3c22bcf74 | |
Kay Marquardt (Gnadelwartz) | fc5d50e3d5 | |
Kay Marquardt (Gnadelwartz) | 5f50011891 | |
Kay Marquardt (Gnadelwartz) | 14fa2c7635 | |
Kay Marquardt (Gnadelwartz) | 248a065be4 | |
Kay Marquardt (Gnadelwartz) | 9ef8778f85 | |
Kay Marquardt (Gnadelwartz) | 641727dc99 | |
Kay Marquardt (Gnadelwartz) | a5aa756596 | |
Kay Marquardt (Gnadelwartz) | 63379de77b | |
Kay Marquardt (Gnadelwartz) | 53c107d4ee | |
Kay Marquardt (Gnadelwartz) | 0d678f4234 | |
Kay Marquardt (Gnadelwartz) | 8162695451 | |
Kay Marquardt (Gnadelwartz) | d310805a98 | |
Kay Marquardt (Gnadelwartz) | 0798f1ae00 | |
Kay Marquardt (Gnadelwartz) | 5f6476d691 | |
Kay Marquardt (Gnadelwartz) | 8a095bc79f | |
Kay Marquardt (Gnadelwartz) | 966ee5d5a7 | |
Kay Marquardt (Gnadelwartz) | e072afac41 | |
Kay Marquardt (Gnadelwartz) | 5ad7be59ba | |
Kay Marquardt (Gnadelwartz) | 83fc57e46c |
241
README.html
241
README.html
|
@ -6,136 +6,6 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
<title>Bashbot README</title>
|
||||
<style>
|
||||
html {
|
||||
line-height: 1.5;
|
||||
font-family: Georgia, serif;
|
||||
font-size: 20px;
|
||||
color: #1a1a1a;
|
||||
background-color: #fdfdfd;
|
||||
}
|
||||
body {
|
||||
margin: 0 auto;
|
||||
max-width: 36em;
|
||||
padding-left: 50px;
|
||||
padding-right: 50px;
|
||||
padding-top: 50px;
|
||||
padding-bottom: 50px;
|
||||
hyphens: auto;
|
||||
word-wrap: break-word;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-kerning: normal;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
font-size: 0.9em;
|
||||
padding: 1em;
|
||||
}
|
||||
}
|
||||
@media print {
|
||||
body {
|
||||
background-color: transparent;
|
||||
color: black;
|
||||
font-size: 12pt;
|
||||
}
|
||||
p, h2, h3 {
|
||||
orphans: 3;
|
||||
widows: 3;
|
||||
}
|
||||
h2, h3, h4 {
|
||||
page-break-after: avoid;
|
||||
}
|
||||
}
|
||||
p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
a {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
a:visited {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 1.4em;
|
||||
}
|
||||
h5, h6 {
|
||||
font-size: 1em;
|
||||
font-style: italic;
|
||||
}
|
||||
h6 {
|
||||
font-weight: normal;
|
||||
}
|
||||
ol, ul {
|
||||
padding-left: 1.7em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
li > ol, li > ul {
|
||||
margin-top: 0;
|
||||
}
|
||||
blockquote {
|
||||
margin: 1em 0 1em 1.7em;
|
||||
padding-left: 1em;
|
||||
border-left: 2px solid #e6e6e6;
|
||||
color: #606060;
|
||||
}
|
||||
code {
|
||||
font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
|
||||
font-size: 85%;
|
||||
margin: 0;
|
||||
}
|
||||
pre {
|
||||
margin: 1em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
pre code {
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
}
|
||||
.sourceCode {
|
||||
background-color: transparent;
|
||||
overflow: visible;
|
||||
}
|
||||
hr {
|
||||
background-color: #1a1a1a;
|
||||
border: none;
|
||||
height: 1px;
|
||||
margin: 1em 0;
|
||||
}
|
||||
table {
|
||||
margin: 1em 0;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
display: block;
|
||||
font-variant-numeric: lining-nums tabular-nums;
|
||||
}
|
||||
table caption {
|
||||
margin-bottom: 0.75em;
|
||||
}
|
||||
tbody {
|
||||
margin-top: 0.5em;
|
||||
border-top: 1px solid #1a1a1a;
|
||||
border-bottom: 1px solid #1a1a1a;
|
||||
}
|
||||
th {
|
||||
border-top: 1px solid #1a1a1a;
|
||||
padding: 0.25em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
td {
|
||||
padding: 0.125em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
header {
|
||||
margin-bottom: 4em;
|
||||
text-align: center;
|
||||
}
|
||||
#TOC li {
|
||||
list-style: none;
|
||||
}
|
||||
#TOC a:not(:hover) {
|
||||
text-decoration: none;
|
||||
}
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
span.underline{text-decoration: underline;}
|
||||
|
@ -204,7 +74,6 @@
|
|||
code span.va { color: #19177c; } /* Variable */
|
||||
code span.vs { color: #4070a0; } /* VerbatimString */
|
||||
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
|
||||
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
|
||||
</style>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
|
||||
|
@ -223,8 +92,8 @@ Written by Drew (@topkecleon) and Kay M (@gnadelwartz).
|
|||
<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>
|
||||
<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> 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 concrete information on the common 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>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>
|
||||
|
@ -284,63 +153,66 @@ Written by Drew (@topkecleon) and Kay M (@gnadelwartz).
|
|||
<li>Setup your environment</li>
|
||||
<li>Bashbot test suite</li>
|
||||
</ul></li>
|
||||
<li><a href="examples/README.md">Examples Directory</a></li>
|
||||
<li><a href="examples">Examples Directory</a></li>
|
||||
<li><a href="examples/webhook">Webhook Example</a></li>
|
||||
</ul>
|
||||
<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" aria-hidden="true" tabindex="-1"></a><span class="co"># create bot dir</span></span>
|
||||
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="fu">mkdir</span> mybot</span>
|
||||
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="bu">cd</span> mybot</span>
|
||||
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></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" aria-hidden="true" tabindex="-1"></a><span class="fu">wget</span> <span class="st">"https://github.com/</span><span class="va">$(</span><span class="fu">wget</span> <span class="at">-q</span> <span class="st">"https://github.com/topkecleon/telegram-bot-bash/releases/latest"</span> <span class="at">-O</span> <span class="at">-</span> <span class="kw">|</span> <span class="fu">egrep</span> <span class="st">'/.*/download/.*/.*tar.gz'</span> <span class="at">-o</span><span class="va">)</span><span class="st">"</span></span>
|
||||
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="co"># Extract the tar archive and go into bot dir</span></span>
|
||||
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="fu">tar</span> <span class="at">-xzf</span> <span class="pp">*</span>.tar.gz</span>
|
||||
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="bu">cd</span> telegram-bot-bash</span>
|
||||
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="co"># initialize your bot</span></span>
|
||||
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></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" aria-hidden="true" tabindex="-1"></a><span class="ex">./bashbot.sh</span> init</span>
|
||||
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a><span class="co"># Now start your bot</span></span>
|
||||
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a><span class="ex">./bashbot.sh</span> start</span>
|
||||
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a><span class="ex">Bottoken</span> is valid ...</span>
|
||||
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a><span class="ex">Bot</span> Name: yourbotname_bot</span>
|
||||
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a><span class="ex">Session</span> Name: yourbotname_bot-startbot</span>
|
||||
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a><span class="ex">Bot</span> started successfully.</span></code></pre></div>
|
||||
<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_....
|
||||
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>
|
||||
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>
|
||||
<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> 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>${}</code> and<code>$()</code> can lead to remote code execution (RCE) or remote information disclosure (RID) bugs if unescaped <code>$</code> is included in untrusted input (e.g. <code>$$</code> or <code>$(rm -rf /*)</code>).</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>
|
||||
|
@ -349,8 +221,9 @@ It features background tasks and interactive chats, and can serve as an interfac
|
|||
<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> and <code>data-bot-bash</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>
|
||||
<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>
|
||||
<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>
|
||||
|
@ -364,32 +237,32 @@ It features background tasks and interactive chats, and can serve as an interfac
|
|||
<li>no database, not event driven, not object oriented ...</li>
|
||||
</ul>
|
||||
<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>
|
||||
<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" aria-hidden="true" tabindex="-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" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="ex">bin/send_message.sh</span> <span class="at">--help</span></span></code></pre></div>
|
||||
<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" aria-hidden="true" tabindex="-1"></a><span class="ex">curl</span> <span class="at">-m</span> 10 https://api.telegram.org/bot</span>
|
||||
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="co">#curl: (28) Connection timed out after 10001 milliseconds</span></span>
|
||||
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="fu">wget</span> <span class="at">-t</span> 1 <span class="at">-T</span> 10 https://api.telegram.org/bot</span>
|
||||
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></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" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a><span class="ex">nc</span> <span class="at">-w</span> 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" aria-hidden="true" tabindex="-1"></a><span class="co">#your IP seems blocked by telegram</span></span></code></pre></div>
|
||||
<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.21-0-gc85af77</h4>
|
||||
<h4>$$VERSION$$ v1.52-0-g1a83202</h4>
|
||||
</body>
|
||||
</html>
|
||||
|
|
52
README.md
52
README.md
|
@ -10,11 +10,19 @@ Elsewhere, consider it released under the [WTFPLv2](http://www.wtfpl.net/txt/cop
|
|||
|
||||
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
|
||||
Uses [JSON.sh](http://github.com/dominictarr/JSON.sh) and the magic of sed.
|
||||
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 concrete information on the common 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).
|
||||
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).
|
||||
|
||||
|
@ -63,7 +71,8 @@ Bashbot [Documentation](https://github.com/topkecleon/telegram-bot-bash) and [Do
|
|||
* Modules, addons, events
|
||||
* Setup your environment
|
||||
* Bashbot test suite
|
||||
* [Examples Directory](examples/README.md)
|
||||
* [Examples Directory](examples)
|
||||
* [Webhook Example](examples/webhook)
|
||||
|
||||
### Your very first bashbot in a nutshell
|
||||
|
||||
|
@ -104,10 +113,10 @@ Now open the Telegram App on your mobile phone and start a chat with your bot (_
|
|||
/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_....
|
||||
Available commands:
|
||||
/start: _Start bot and get this message_.
|
||||
/help: _Get this message_.
|
||||
/info: _Get shorter info message about this bot_....
|
||||
|
||||
/info
|
||||
|
||||
|
@ -124,12 +133,12 @@ Start bashbot in debug mode to see all messages sent to / received from Telegram
|
|||
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)
|
||||
|__ 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)
|
||||
```
|
||||
|
||||
----
|
||||
|
@ -145,8 +154,9 @@ Whenever you are processing input from untrusted sources (messages, files, netwo
|
|||
(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 `$` in input from user, files or network (_as bashbot does_).
|
||||
One of the powerful features of Unix shells is variable and command substitution using `${}` and`$()` can lead to remote code execution (RCE) or remote information disclosure (RID) bugs if unescaped `$` is included in untrusted input (e.g. `$$` or `$(rm -rf /*)`).
|
||||
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
|
||||
|
@ -168,9 +178,11 @@ For the same reason every file your Bot can read is in danger of being disclosed
|
|||
### Secure your Bot installation
|
||||
**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` and `data-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
|
||||
|
||||
|
@ -188,9 +200,9 @@ Well, that's a damn good question... maybe because I'm a Unix admin from the sto
|
|||
- 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.
|
||||
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
|
||||
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?
|
||||
|
@ -238,4 +250,4 @@ See `mycommnds.sh.dist` for an example.
|
|||
|
||||
If you feel that there's something missing or if you found a bug, feel free to submit a pull request!
|
||||
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
|
543
README.txt
543
README.txt
|
@ -1,324 +1,323 @@
|
|||
<h2><img align="middle"
|
||||
src="https://raw.githubusercontent.com/odb/official-bash-logo/master/assets/Logo
|
||||
s/Icons/PNG/64x64.png" >
|
||||
Bashbot - A Telegram bot written in bash.
|
||||
</h2>
|
||||
|
||||
..
|
||||
****
|
||||
****oooooo*****
|
||||
*****ooooooooooooo*****
|
||||
*****oooooooooooooooooooooo****
|
||||
****oooooooooooooooooooooooooooooooo**
|
||||
*.*oooooooooooooooooooooooooooooooooooo**
|
||||
*.ooooooooooooooooooooooooooooooooo**....
|
||||
*.oooooooooooooooooooooooooooo**.........
|
||||
*.oooooooooooooooooooooooo**.............
|
||||
*.ooooooooooooooooooo**.................. ____ _ _ _
|
||||
*.ooooooooooooooooo*.......,............. | _ \ | | | | | |
|
||||
*.ooooooooooooooooo*.....,***,........... | |_) | __ _ ___ | |__ | |__ ___ | |_
|
||||
*.ooooooooooooooooo*....o*............... | _ < / _` |/ __|| '_ \ | '_ \ / _ \ | __|
|
||||
*.ooooooooooooooooo*....*o***,........... | |_) || (_| |\__ \| | | || |_) || (_) || |_
|
||||
*.*oooooooooooooooo*........o*.....oo.... |____/ \__,_||___/|_| |_||_.__/ \___/ \__|
|
||||
****ooooooooooooo*....`***....oo.....*
|
||||
*****oooooooo*......*..oo.....**
|
||||
******ooo*.............*
|
||||
***o*........**
|
||||
**...**
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Bashbot README
|
||||
|
||||
|
||||
Bashbot - A Telegram bot written in bash.
|
||||
|
||||
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
|
||||
|
||||
Contributions by Daniil Gentili (@danog), JuanPotato, BigNerd95, TiagoDanin,
|
||||
iicc1 and dcoomber.
|
||||
Prerequisites
|
||||
|
||||
Released to the public domain wherever applicable.
|
||||
Elsewhere, consider it released under the
|
||||
[WTFPLv2](http://www.wtfpl.net/txt/copying/).
|
||||
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].
|
||||
|
||||
Linted by [#ShellCheck](https://github.com/koalaman/shellcheck)
|
||||
Documentation
|
||||
|
||||
## Prerequisites
|
||||
Uses [JSON.sh](http://github.com/dominictarr/JSON.sh) and the magic of sed.
|
||||
|
||||
Bashbot is written in bash. It depends on commands typically available in a
|
||||
Linux/Unix Environment.
|
||||
For more concrete information on the common 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).
|
||||
* Introduction to Telegram Bots [https://core.telegram.org/bots]
|
||||
* Install Bashbot [doc/0_install.md]
|
||||
|
||||
**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).
|
||||
o Install release
|
||||
o Install from github
|
||||
o Update Bashbot
|
||||
o Notes on Updates
|
||||
|
||||
**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).
|
||||
* Get Bottoken from Botfather [doc/1_firstbot.md]
|
||||
* Getting Started [doc/2_usage.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).
|
||||
o Managing your Bot
|
||||
o Receive data
|
||||
o Send messages
|
||||
o Send files, locations, keyboards
|
||||
|
||||
## Documentation
|
||||
* [Introduction to Telegram Bots](https://core.telegram.org/bots)
|
||||
* [Install Bashbot](doc/0_install.md)
|
||||
* Install release
|
||||
* Install from github
|
||||
* Update Bashbot
|
||||
* Notes on Updates
|
||||
* [Get Bottoken from Botfather](doc/1_firstbot.md)
|
||||
* [Getting Started](doc/2_usage.md)
|
||||
* Managing your Bot
|
||||
* Receive data
|
||||
* Send messages
|
||||
* Send files, locations, keyboards
|
||||
* [Advanced Features](doc/3_advanced.md)
|
||||
* Access Control
|
||||
* 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
|
||||
* Schedule bashbot from Cron
|
||||
* Use from CLI and Scripts
|
||||
* Customize Bashbot Environment
|
||||
* [Best Practices](doc/5_practice.md)
|
||||
* 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
|
||||
* [Developer Notes](doc/7_develop.md)
|
||||
* Debug bashbot
|
||||
* Modules, addons, events
|
||||
* Setup your environment
|
||||
* Bashbot test suite
|
||||
* [Examples Directory](examples/README.md)
|
||||
* Advanced Features [doc/3_advanced.md]
|
||||
|
||||
### Your very first bashbot in a nutshell
|
||||
o Access Control
|
||||
o Interactive Chats
|
||||
o Background Jobs
|
||||
o Inline queries
|
||||
o Send message errors
|
||||
|
||||
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/).
|
||||
* Expert Use [doc/4_expert.md]
|
||||
|
||||
First you need to [create a new Telegram Bot token](doc/1_firstbot.md) for your
|
||||
bot and write it down.
|
||||
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
|
||||
|
||||
Now open a Linux/Unix terminal with bash, create a new directory, change to it
|
||||
and install telegram-bot-bash:
|
||||
* Best Practices [doc/5_practice.md]
|
||||
|
||||
```bash
|
||||
# create bot dir
|
||||
mkdir mybot
|
||||
cd mybot
|
||||
o Customize mycommands.sh
|
||||
o Overwrite/disable commands
|
||||
o Separate logic from commands
|
||||
o Test your Bot with shellcheck
|
||||
|
||||
# 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)"
|
||||
* Function Reference [doc/6_reference.md]
|
||||
|
||||
# Extract the tar archive and go into bot dir
|
||||
tar -xzf *.tar.gz
|
||||
cd telegram-bot-bash
|
||||
o Sending Messages, Files, Keyboards
|
||||
o User Access Control
|
||||
o Inline Queries
|
||||
o jsshDB Bashbot key-value storage
|
||||
o Background and Interactive Jobs
|
||||
|
||||
# initialize your bot
|
||||
# Enter your bot token when asked, all other questions can be answered by
|
||||
hitting the \<Return\> key.
|
||||
./bashbot.sh init
|
||||
* Developer Notes [doc/7_develop.md]
|
||||
|
||||
# Now start your bot
|
||||
./bashbot.sh start
|
||||
o Debug bashbot
|
||||
o Modules, addons, events
|
||||
o Setup your environment
|
||||
o Bashbot test suite
|
||||
|
||||
Bottoken is valid ...
|
||||
Bot Name: yourbotname_bot
|
||||
Session Name: yourbotname_bot-startbot
|
||||
Bot started successfully.
|
||||
```
|
||||
* Examples Directory [examples]
|
||||
* Webhook Example [examples/webhook]
|
||||
|
||||
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
|
||||
Your very first bashbot in a nutshell
|
||||
|
||||
You are Botadmin
|
||||
*Available commands*:
|
||||
*• /start*: _Start bot and get this message_.
|
||||
*• /help*: _Get this message_.
|
||||
*• /info*: _Get shorter info message about this bot_....
|
||||
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:
|
||||
|
||||
/info
|
||||
# create bot dir
|
||||
mkdir mybot
|
||||
cd mybot
|
||||
|
||||
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).
|
||||
# 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)"
|
||||
|
||||
### Log files
|
||||
# Extract the tar archive and go into bot dir
|
||||
tar -xzf *.tar.gz
|
||||
cd telegram-bot-bash
|
||||
|
||||
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
|
||||
# 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
|
||||
|
||||
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)
|
||||
|
||||
```
|
||||
├── 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
|
||||
|
||||
## 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-o
|
||||
f-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 `$` in input from user, files or network
|
||||
(_as bashbot does_).
|
||||
One of the powerful features of Unix shells is variable and command
|
||||
substitution using `${}` and`$()` can lead to remote code execution (RCE) or
|
||||
remote information disclosure (RID) bugs if unescaped `$` 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
|
||||
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.
|
||||
|
||||
### Use printf whenever possible
|
||||
Use printf whenever possible
|
||||
|
||||
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).
|
||||
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.
|
||||
Run your Bot as a restricted user
|
||||
|
||||
**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.
|
||||
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 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!
|
||||
Secure your Bot installation
|
||||
|
||||
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` and `data-bot-bash`
|
||||
only, all other files must be write protected.
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
## FAQ
|
||||
|
||||
### 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`.
|
||||
|
||||
```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).
|
||||
FAQ
|
||||
|
||||
|
||||
### 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.
|
||||
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:
|
||||
```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.
|
||||
curl -m 10 https://api.telegram.org/bot
|
||||
#curl: (28) Connection timed out after 10001 milliseconds
|
||||
|
||||
nc -w 2 api.telegram.org 443 || echo "your IP seems blocked by telegram"
|
||||
#your IP seems blocked by telegram
|
||||
```
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
---
|
||||
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 all guys!
|
||||
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$$ v1.21-0-gc85af77
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# this addon counts how many files, e.g. stickers, are sent to
|
||||
# a chat and takes actions if threshold is reached
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
# used events:
|
||||
#
|
||||
|
@ -37,7 +37,7 @@ ANTIFL_BAN="5" # 5 minutes
|
|||
|
||||
# initialize after installation or update
|
||||
if [[ "$1" = "init"* ]]; then
|
||||
jssh_newDB "addons/$ANTIFL_ME"
|
||||
jssh_newDB "addons/${ANTIFL_ME}"
|
||||
fi
|
||||
|
||||
|
||||
|
@ -46,7 +46,7 @@ fi
|
|||
if [[ "$1" = "start"* ]]; then
|
||||
ANTIFL_ADMIN="$(getConfigKey "botadmin")"
|
||||
#load existing chat settings on start
|
||||
jssh_readDB "ANTIFL_CHATS" "addons/$ANTIFL_ME"
|
||||
jssh_readDB "ANTIFL_CHATS" "addons/${ANTIFL_ME}"
|
||||
|
||||
# register to CMD
|
||||
BASHBOT_EVENT_CMD["${ANTIFL_ME}"]="${ANTIFL_ME}_cmd"
|
||||
|
@ -71,14 +71,14 @@ if [[ "$1" = "start"* ]]; then
|
|||
"/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" &
|
||||
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" &
|
||||
jssh_writeDB "ANTIFL_CHATS" "addons/${ANTIFL_ME}" &
|
||||
send_normal_message "${USER[ID]}" "Antiflood stopped for chat ${chat}" &
|
||||
;;
|
||||
esac
|
||||
|
@ -90,7 +90,7 @@ if [[ "$1" = "start"* ]]; then
|
|||
# save settings and reset flood level every BAN Min
|
||||
antiFlood_timer(){
|
||||
ANTIFL_ACTUALS=( )
|
||||
jssh_writeDB "ANTIFL_CHATS" "addons/$ANTIFL_ME" &
|
||||
jssh_writeDB "ANTIFL_CHATS" "addons/${ANTIFL_ME}" &
|
||||
}
|
||||
|
||||
# register to inline and command
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# Addons can register to bashbot events at startup
|
||||
# by providing their name and a callback per event
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#
|
||||
# If an event occurs each registered event function is called.
|
||||
#
|
||||
|
|
110
bashbot.rc
110
bashbot.rc
|
@ -1,13 +1,14 @@
|
|||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
# description: Start or stop telegram-bash-bot
|
||||
#
|
||||
# example service script to run bashbot in background as specified user
|
||||
#
|
||||
# tested on: ubuntu, opensuse, debian
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
# shellcheck disable=SC2009
|
||||
# shellcheck disable=SC2181
|
||||
# shellcheck disable=SC2250
|
||||
|
||||
#
|
||||
### BEGIN INIT INFO
|
||||
|
@ -30,57 +31,124 @@ runcmd="echo Dry run:" # not activated until you edit lines below
|
|||
runas="nobody"
|
||||
|
||||
# uncomment one of the example 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*
|
||||
# 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="cd /usr/local/telegram-bot-bash; /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
|
||||
#######################
|
||||
|
||||
[ "$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=$?
|
||||
;;
|
||||
'stop')
|
||||
$runcmd "$start stop"
|
||||
[[ "${stat}" != *"poll"* ]] && printf "Warning, bot is not in poll mode: %s\n" "${stat}"
|
||||
$runcmd "$bashbot stop $mode"
|
||||
RETVAL=$?
|
||||
;;
|
||||
'status')
|
||||
ps -f -u "$runas" | grep "$name" | grep -qF "bashbot.sh startbot"
|
||||
if [ "$?" = "0" ]; then
|
||||
printf "bashbot (%s) is runningi\n" "$name"
|
||||
RETVAL=0
|
||||
else
|
||||
printf "bashbot (%s) is stopped\n" "$name"
|
||||
RETVAL=1
|
||||
'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')
|
||||
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
|
||||
kill -9 $(ps -u "${runas}" | grep inotifywait | sed 's/ .*//') >/dev/null 2>&1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
printf "%s\n" "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}"
|
||||
|
|
985
bashbot.sh
985
bashbot.sh
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -13,16 +13,16 @@
|
|||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 18.12.2020 12:27
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
############
|
||||
# set where your bashbot lives
|
||||
export BASHBOT_HOME BASHBOT_ETC BASHBOT_VAR FILE_REGEX
|
||||
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="../"
|
||||
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"
|
||||
|
@ -32,20 +32,21 @@ BASHBOT_ETC="${BASHBOT_HOME}"
|
|||
#####
|
||||
# if files are not readable, eviroment is wrong or bashbot is not initialized
|
||||
|
||||
# source bashbot
|
||||
# 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."
|
||||
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. Did you run bashbot init?"
|
||||
printf "%s\n" "Bashbot count file in \"${BASHBOT_VAR}\" does not exist or is not readable. ${dev}"
|
||||
exit 3
|
||||
fi
|
||||
|
||||
|
@ -58,8 +59,33 @@ UPLOADDIR="${BASHBOT_VAR%/bin*}"
|
|||
FILE_REGEX="${UPLOADDIR}/.*"
|
||||
|
||||
# get and check ADMIN and NAME
|
||||
BOT_ADMIN="$(getConfigKey "botadmin")"
|
||||
BOT_NAME="$(getConfigKey "botname")"
|
||||
[[ -z "${BOT_ADMIN}" || "${BOT_ADMIN}" == "?" ]] && printf "%s\n" "${ORANGE}Warning: Botadmin not set, did you forget to sent command${NC} /start"
|
||||
[[ -z "${BOT_NAME}" ]] && printf "%s\n" "${ORANGE}Warning: Botname not set, did you ever run bashbot?"
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -1,9 +1,10 @@
|
|||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/bashbot_stats.sh
|
||||
#
|
||||
# USAGE: bashbot_stats.sh [-h|--help] [debug]
|
||||
USAGE='bashbot_stats.sh [-h|--help] [debug]'
|
||||
#
|
||||
# DESCRIPTION: output bashbot user stats
|
||||
#
|
||||
|
@ -16,30 +17,17 @@
|
|||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 23.12.2020 20:34
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
case "$1" in
|
||||
"-h"*)
|
||||
echo "usage: send_message [-h|--help] [debug]"
|
||||
exit 1
|
||||
;;
|
||||
'--h'*)
|
||||
sed -n '3,/###/p' <"$0"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# set bashbot environment
|
||||
# shellcheck disable=SC1090
|
||||
source "${0%/*}/bashbot_env.inc.sh" "$1"
|
||||
[ -n "$1" ] && print_help "$1"
|
||||
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
|
||||
echo -e "${GREEN}Hi I'm ${BOT_NAME}.${NC}"
|
||||
echo -e "${GREEN}Hi I'm ${BOTNAME}.${NC}"
|
||||
declare -A STATS
|
||||
jssh_readDB_async "STATS" "${COUNTFILE}"
|
||||
for MSG in ${!STATS[*]}
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -1,13 +1,14 @@
|
|||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/send_message.sh
|
||||
# FILE: bin/edit_message.sh
|
||||
#
|
||||
# USAGE: send_edit_message.sh [-h|--help] [format] "CHAT[ID]" "MESSAGE[ID]" "message ...." [debug]
|
||||
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 (optional)
|
||||
# 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
|
||||
|
@ -22,14 +23,14 @@
|
|||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 23.12.2020 16:52
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
SEND="edit_normal_message"
|
||||
case "$1" in
|
||||
"nor*"|"tex*")
|
||||
"nor"*|"tex"*)
|
||||
SEND="edit_normal_message"
|
||||
shift
|
||||
;;
|
||||
|
@ -37,33 +38,24 @@ case "$1" in
|
|||
SEND="edit_markdownv2_message"
|
||||
shift
|
||||
;;
|
||||
"html")
|
||||
"htm"*)
|
||||
SEND="edit_html_message"
|
||||
shift
|
||||
;;
|
||||
'')
|
||||
printf "missing arguments\n"
|
||||
;&
|
||||
"-h"*)
|
||||
printf 'usage: send_edit_message [-h|--help] [format] "CHAT[ID]" "MESSAGE[ID]" "message ..." [debug]\n'
|
||||
exit 1
|
||||
;;
|
||||
'--h'*)
|
||||
sed -n '3,/###/p' <"$0"
|
||||
exit 1
|
||||
"cap"*)
|
||||
SEND="edit_message_caption"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
# set bashbot environment
|
||||
# shellcheck disable=SC1090
|
||||
source "${0%/*}/bashbot_env.inc.sh" "$4" # $4 debug
|
||||
source "${0%/*}/bashbot_env.inc.sh" "${4:-debug}" # $4 debug
|
||||
print_help "$1"
|
||||
|
||||
####
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
if [ "$1" == "BOTADMIN" ]; then
|
||||
CHAT="${BOT_ADMIN}"
|
||||
CHAT="${BOTADMIN}"
|
||||
else
|
||||
CHAT="$1"
|
||||
fi
|
||||
|
@ -72,5 +64,4 @@ fi
|
|||
"${SEND}" "${CHAT}" "$2" "$3"
|
||||
|
||||
# output send message result
|
||||
jssh_printDB "BOTSENT" | sort -r
|
||||
|
||||
print_result
|
|
@ -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
|
|
@ -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
|
|
@ -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"
|
||||
|
|
@ -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
|
|
@ -1,15 +1,19 @@
|
|||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034
|
||||
#===============================================================================
|
||||
# shellcheck disable=SC2059
|
||||
#
|
||||
# FILE: bin/broadcast_message.sh
|
||||
#
|
||||
# USAGE: broadcast_message.sh [-h|--help] [--doit] [--groups|--both] [format] "message ...." [debug]
|
||||
USAGE='broadcast_message.sh [-h|--help] [--doit] [--groups|--both|--db=file] [format] "message ...." [debug]'
|
||||
#
|
||||
# DESCRIPTION: send a message to all users the bot have seen (listet in count.jssh)
|
||||
# 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
|
||||
# --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
|
||||
|
@ -24,13 +28,13 @@
|
|||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 16.12.2020 16:14
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
# shellcheck disable=SC2059
|
||||
|
||||
####
|
||||
# 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 ...
|
||||
|
@ -49,13 +53,18 @@ 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*")
|
||||
"nor"*|"tex"*)
|
||||
SEND="send_normal_message"
|
||||
shift
|
||||
;;
|
||||
|
@ -67,33 +76,22 @@ case "$1" in
|
|||
SEND="send_html_message"
|
||||
shift
|
||||
;;
|
||||
'')
|
||||
printf "missing missing arguments\n"
|
||||
;&
|
||||
"-h"*)
|
||||
printf 'usage: send_message [-h|--help] [--groups|--both] [format] "message ...." [debug]\n'
|
||||
exit 1
|
||||
;;
|
||||
'--h'*)
|
||||
sed -n '3,/###/p' <"$0"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# set bashbot environment
|
||||
# shellcheck disable=SC1090
|
||||
source "${0%/*}/bashbot_env.inc.sh" "$2" # $3 debug
|
||||
print_help "$1"
|
||||
|
||||
|
||||
# read in users
|
||||
# read in users from given DB or count.jssh
|
||||
database="${USERDB:-${COUNTFILE}}"
|
||||
declare -A SENDALL
|
||||
jssh_readDB_async "SENDALL" "${COUNTFILE}"
|
||||
jssh_readDB_async "SENDALL" "${database}"
|
||||
if [ -z "${SENDALL[*]}" ]; then
|
||||
printf "${ORANGE}Countfile not found or empty,${NC}\n"
|
||||
printf "${ORANGE}User database not found or empty: ${NC}${database}\n"
|
||||
fi
|
||||
|
||||
# loop over users
|
||||
printf "${GREEN}Sending broadcast message to all users of ${BOT_NAME}${NC}${GREY}"
|
||||
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"
|
||||
|
@ -106,7 +104,7 @@ fi
|
|||
# ignore everything not a user or group
|
||||
[[ ! "${USER}" =~ ^[0-9-]*$ ]] && continue
|
||||
# ignore chats with no count or lower MINCOUNT
|
||||
[[ ! "${SENDALL[${USER}]}" =~ ^[0-9]*$ || "${SENDALL[${USER}]}" -lt "${MINCOUNT}" ]] && continue
|
||||
[[ -n "${MINCOUNT}" && ( ! "${SENDALL[${USER}]}" =~ ^[0-9]*$ || "${SENDALL[${USER}]}" -lt "${MINCOUNT}" ) ]] && continue
|
||||
(( COUNT++ ))
|
||||
if [ -z "${DOIT}" ]; then
|
||||
printf "${SEND} ${USER} $1 $2\n"
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -1,16 +1,20 @@
|
|||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/send_file.sh
|
||||
#
|
||||
# USAGE: send_file.sh [-h|--help] "CHAT[ID]" "file" "caption ...." [debug]
|
||||
#
|
||||
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 - file to send, must be an absolute path or relative to pwd
|
||||
# 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
|
||||
|
@ -21,44 +25,31 @@
|
|||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 25.12.2020 20:24
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
SEND="upload_file"
|
||||
case "$1" in
|
||||
'')
|
||||
printf "missing arguments\n"
|
||||
;&
|
||||
"-h"*)
|
||||
printf 'usage: send_file [-h|--help] "CHAT[ID]" "file" "caption ...." [debug]\n'
|
||||
exit 1
|
||||
;;
|
||||
'--h'*)
|
||||
sed -n '3,/###/p' <"$0"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
SEND="send_file"
|
||||
|
||||
# set bashbot environment
|
||||
# shellcheck disable=SC1090
|
||||
source "${0%/*}/bashbot_env.inc.sh" "$4" # $4 debug
|
||||
source "${0%/*}/bashbot_env.inc.sh" "${5:-debug}" # $5 debug
|
||||
print_help "$1"
|
||||
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
if [ "$1" == "BOTADMIN" ]; then
|
||||
CHAT="${BOT_ADMIN}"
|
||||
CHAT="${BOTADMIN}"
|
||||
else
|
||||
CHAT="$1"
|
||||
fi
|
||||
|
||||
FILE="$2"
|
||||
[[ "$2" != "/"* ]] && FILE="${PWD}/$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"
|
||||
"${SEND}" "${CHAT}" "${FILE}" "$3" "$4"
|
||||
|
||||
# output send message result
|
||||
jssh_printDB "BOTSENT" | sort -r
|
||||
|
||||
print_result
|
||||
|
|
|
@ -1,17 +1,22 @@
|
|||
#!/bin/bash
|
||||
# shellcheck disable=SC1090,SC2034
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: bin/send_message.sh
|
||||
#
|
||||
# USAGE: send_message.sh [-h|--help] [format] "CHAT[ID]" "message ...." [debug]
|
||||
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 (optional)
|
||||
# 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
|
||||
#
|
||||
|
@ -21,14 +26,14 @@
|
|||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
# CREATED: 16.12.2020 11:34
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
####
|
||||
# parse args
|
||||
SEND="send_message"
|
||||
case "$1" in
|
||||
"nor*"|"tex*")
|
||||
"nor"*|"tex"*)
|
||||
SEND="send_normal_message"
|
||||
shift
|
||||
;;
|
||||
|
@ -40,34 +45,29 @@ case "$1" in
|
|||
SEND="send_html_message"
|
||||
shift
|
||||
;;
|
||||
'')
|
||||
printf "missing arguments\n"
|
||||
;&
|
||||
"-h"*)
|
||||
printf 'usage: send_message [-h|--help] [format] "CHAT[ID]" "message ...." [debug]\n'
|
||||
exit 1
|
||||
;;
|
||||
'--h'*)
|
||||
sed -n '3,/###/p' <"$0"
|
||||
exit 1
|
||||
"stdin"|"-")
|
||||
FILE="stdin"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
|
||||
# set bashbot environment
|
||||
# shellcheck disable=SC1090
|
||||
source "${0%/*}/bashbot_env.inc.sh" "$3" # $3 debug
|
||||
source "${0%/*}/bashbot_env.inc.sh" "${3:-debug}" # $3 debug
|
||||
print_help "$1"
|
||||
|
||||
####
|
||||
# ready, do stuff here -----
|
||||
if [ "$1" == "BOTADMIN" ]; then
|
||||
CHAT="${BOT_ADMIN}"
|
||||
CHAT="${BOTADMIN}"
|
||||
else
|
||||
CHAT="$1"
|
||||
fi
|
||||
|
||||
# send message in selected format
|
||||
"${SEND}" "${CHAT}" "$2"
|
||||
|
||||
if [ "${FILE}" = "stdin" ]; then
|
||||
"${SEND}" "${CHAT}" "$(cat)"
|
||||
else
|
||||
"${SEND}" "${CHAT}" "$2"
|
||||
fi
|
||||
# output send message result
|
||||
jssh_printDB "BOTSENT" | sort -r
|
||||
|
||||
print_result
|
||||
|
|
55
commands.sh
55
commands.sh
|
@ -8,18 +8,17 @@
|
|||
# | |__/ / |_| | | | | | |_| | |__ | |____( (_| | | |__ _
|
||||
# |_____/ \___/ |_| |_|\___/ \___) |_______)____|_|\___)_|
|
||||
#
|
||||
# this file *MUST* not be edited! place your config and commands in
|
||||
# the file "mycommands.sh". a clean version is provided as "mycommands.sh.clean"
|
||||
# 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$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#
|
||||
|
||||
# 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'
|
||||
|
@ -43,21 +42,25 @@ bashbot_help='
|
|||
*• /start*: _Start bot and get this message_.
|
||||
*• /help*: _Get this message_.
|
||||
*• /info*: _Get shorter info message about this bot_.
|
||||
*• /question*: _Start interactive chat (mycommands.dist)_.
|
||||
*• /cancel*: _Cancel any currently running interactive chat_.
|
||||
*• /kickme*: _You will be autokicked from the group_.
|
||||
*• /leavechat*: _The bot will leave the group with this command _.
|
||||
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 in my [GitHub](http://github.com/topkecleon/telegram-bot-bash)
|
||||
Get the code on [GitHub](http://github.com/topkecleon/telegram-bot-bash)
|
||||
'
|
||||
|
||||
# load modules on startup and always on on debug
|
||||
if [ -n "${1}" ]; then
|
||||
if [ -n "$1" ]; then
|
||||
# load all readable modules
|
||||
for modules in "${MODULEDIR:-.}"/*.sh ; do
|
||||
if [[ "${1}" == *"debug"* ]] || ! _is_function "$(basename "${modules}")"; then
|
||||
if [[ "$1" == *"debug"* ]] || ! _is_function "$(basename "${modules}")"; then
|
||||
# shellcheck source=./modules/aliases.sh
|
||||
[ -r "${modules}" ] && source "${modules}" "${1}"
|
||||
[ -r "${modules}" ] && source "${modules}" "$1"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
@ -67,33 +70,37 @@ fi
|
|||
# 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 [ -z "${1}" ] || [[ "${1}" == *"debug"* ]];then
|
||||
# detect inline commands....
|
||||
# no default commands, all processing is done in myinlines()
|
||||
if [ "$INLINE" != "0" ] && [ -n "${iQUERY[ID]}" ]; then
|
||||
# forward iinline query to optional dispatcher
|
||||
_exec_if_function myinlines
|
||||
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
|
||||
|
||||
# regular (global) commands ...
|
||||
# your commands are in mycommands()
|
||||
elif [ -n "${iBUTTON[ID]}" ]; then
|
||||
# forward inline query to optional dispatcher
|
||||
[ "${CALLBACK:-0}" != "0" ] && _exec_if_function mycallbacks
|
||||
|
||||
#################
|
||||
# regular command
|
||||
else
|
||||
|
||||
###################
|
||||
# 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}" == "/"* && "${MESSAGE%% *}" == *"@"* ]]; then
|
||||
if [[ "${MEONLY}" != "0" && "${MESSAGE}" == "/"*"@"* ]]; then
|
||||
# here we have a command with @xyz_bot added, check if it's our bot
|
||||
MYCHECK="${MESSAGE%% *}"
|
||||
[ "${MYCHECK}" != "${MYCHECK%%@${ME}}" ] && return
|
||||
[ "${MESSAGE%%@*}" != "${MESSAGE%%@${ME}}" ] && return
|
||||
fi
|
||||
|
||||
###################
|
||||
|
@ -128,7 +135,7 @@ if [ -z "${1}" ] || [[ "${1}" == *"debug"* ]];then
|
|||
'/help'*)
|
||||
send_markdown_message "${CHAT[ID]}" "${bashbot_help}"
|
||||
;;
|
||||
'/leavechat'*) # bot leave chat if user is admin in chat
|
||||
'/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]}"
|
||||
|
|
|
@ -5,17 +5,11 @@
|
|||
#
|
||||
# Description: run all tests, exit after failed test
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$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 2>/dev/null)
|
||||
if [ "$GIT_DIR" != "" ] ; then
|
||||
cd "$GIT_DIR/.." || exit 1
|
||||
else
|
||||
printf "Sorry, no git repository %s\n" "$(pwd)" && exit 1
|
||||
fi
|
||||
#shellcheck disable=SC1090
|
||||
source "${0%/*}/dev.inc.sh"
|
||||
|
||||
##########################
|
||||
# create test environment
|
||||
|
@ -52,7 +46,7 @@ do
|
|||
"${test}" "${TESTENV}"
|
||||
ret=$?
|
||||
set +e
|
||||
if [ "$ret" -eq 0 ] ; then
|
||||
if [ "${ret}" -eq 0 ] ; then
|
||||
printf "OK: ---- %s\n" "${test}"
|
||||
passed=$((passed+1))
|
||||
else
|
||||
|
@ -64,7 +58,7 @@ done
|
|||
|
||||
###########################
|
||||
# cleanup depending on test state
|
||||
if [ "$fail" -eq 0 ]; then
|
||||
if [ "${fail}" -eq 0 ]; then
|
||||
printf 'SUCCESS '
|
||||
exitcode=0
|
||||
rm -rf "${TESTENV}"
|
||||
|
@ -82,4 +76,4 @@ printf "%s\n\n" "${passed} / ${tests}"
|
|||
|
||||
ls -ld /tmp/bashbot.test* 2>/dev/null && printf "Do not forget to delete bashbot test files in /tmp!!\n"
|
||||
|
||||
exit ${exitcode}
|
||||
exit "${exitcode}"
|
||||
|
|
|
@ -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,21 +3,21 @@
|
|||
#
|
||||
# works together with git pre-push.sh and ADD all changed files since last push
|
||||
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$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 2>/dev/null)
|
||||
if [ "$GIT_DIR" != "" ] ; then
|
||||
cd "$GIT_DIR/.." || exit 1
|
||||
else
|
||||
printf "Sorry, no git repository %s\n" "$(pwd)" && exit 1
|
||||
#shellcheck disable=SC1090
|
||||
source "${0%/*}/dev.inc.sh"
|
||||
|
||||
# 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
|
||||
|
||||
[ ! -f .git/.lastcommit ] && printf "No previous commit or hooks not installed, use \"git add\" instead ... Abort\n" && exit
|
||||
|
||||
set +f
|
||||
FILES="$(find ./* -newer .git/.lastcommit| grep -v -e 'DIST\/' -e 'STANDALONE\/' -e 'JSON.sh')"
|
||||
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
|
||||
|
@ -31,7 +31,9 @@ for file in ${FILES}
|
|||
do
|
||||
[ -d "${file}" ] && continue
|
||||
printf "%s" "${file} "
|
||||
git add "$file"
|
||||
done
|
||||
printf " - Done.\n"
|
||||
|
||||
# stay with "." for (re)moved files!
|
||||
git add .
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env bash
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$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/.lastcommit'
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env bash
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$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'
|
||||
|
@ -32,25 +32,26 @@ set +f
|
|||
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
|
||||
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//' -e 's/,/./')"
|
||||
|
||||
[ -z "${REMOTEVER}" ] && REMOTEVER="${VERSION}"
|
||||
|
||||
# LOCAL version must greater than latest REMOTE release version
|
||||
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
|
||||
printf " "
|
||||
# shellcheck disable=SC2086
|
||||
|
@ -64,7 +65,7 @@ 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" -L "ba"
|
||||
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"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env bash
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$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'
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#
|
||||
# Usage: source inject-json.sh
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
##############################################################
|
||||
|
||||
# download JSON.sh
|
||||
|
|
|
@ -1,25 +1,17 @@
|
|||
#!/usr/bin/env bash
|
||||
# this has to run once atfer git clone
|
||||
# and every time we create new hooks
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$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 2>/dev/null)
|
||||
if [ "$GIT_DIR" != "" ] ; then
|
||||
cd "$GIT_DIR/.." || exit 1
|
||||
else
|
||||
printf "Sorry, no git repository %s\n" "$(pwd)" && exit 1
|
||||
fi
|
||||
|
||||
HOOKDIR="dev/hooks"
|
||||
#shellcheck disable=SC1090
|
||||
source "${0%/*}/dev.inc.sh"
|
||||
|
||||
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
|
||||
printf "%s"" $hook"
|
||||
printf "%s"" ${hook}"
|
||||
ln -s "../../${HOOKDIR}/${hook}.sh" "${GIT_DIR}/hooks/${hook}"
|
||||
fi
|
||||
done
|
||||
|
|
|
@ -7,25 +7,21 @@
|
|||
#
|
||||
# Options: --notest - skip tests
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$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 2>/dev/null)
|
||||
if [ "$GIT_DIR" != "" ] ; then
|
||||
[[ "$GIT_DIR" != "/"* ]] && GIT_DIR="${PWD}/${GIT_DIR}"
|
||||
cd "$GIT_DIR/.." || exit 1
|
||||
else
|
||||
printf "Sorry, no git repository %s\n" "$(pwd)" && exit 1
|
||||
fi
|
||||
#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}"
|
||||
DISTFILES="bashbot.rc bashbot.sh commands.sh mycommands.sh mycommands.sh.clean bin doc examples scripts modules addons LICENSE README.md README.txt README.html"
|
||||
DISTMKDIR="data-bot-bash logs bin bin/logs"
|
||||
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
|
||||
|
@ -44,9 +40,13 @@ 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}"
|
||||
|
@ -54,15 +54,15 @@ done
|
|||
|
||||
# do not overwrite on update
|
||||
printf "Create .dist files\n"
|
||||
for file in mycommands.sh bashbot.rc addons/*.sh
|
||||
for file in ${DISTFILESDIST}
|
||||
do
|
||||
[ "${file}" = "addons/*.sh" ] && continue
|
||||
mv "${file}" "${file}.dist"
|
||||
cp "${BASE_DIR}/${file}" "${file}.dist"
|
||||
done
|
||||
|
||||
# inject JSON.sh into distribution
|
||||
# shellcheck disable=SC1090
|
||||
source "$GIT_DIR/../dev/inject-json.sh"
|
||||
source "${BASE_DIR}/dev/inject-json.sh"
|
||||
|
||||
# make html doc
|
||||
printf "Create html doc\n"
|
||||
|
@ -73,13 +73,13 @@ source "../../dev/make-html.sh"
|
|||
cd .. || exit 1
|
||||
printf "Create dist archives\n"
|
||||
# shellcheck disable=SC2046
|
||||
zip -rq - "${DISTNAME}" --exclude $(cat "$GIT_DIR/../dev/${0##*/}.exclude") >"${DISTNAME}-${VERSION}.zip"
|
||||
tar --exclude-ignore="$GIT_DIR/../dev/${0##*/}.exclude" -czf "${DISTNAME}-${VERSION}.tar.gz" "${DISTNAME}"
|
||||
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}.*
|
||||
ls -ld "${DISTNAME}-${VERSION}".*
|
||||
|
||||
# an empty DEBUG.log is created ... :-(
|
||||
rm -f "$GIT_DIR/../test/"*.log
|
||||
rm -f "${BASE_DIR}/test/"*.log
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
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
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#
|
||||
# Usage: source make-hmtl
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
##############################################################
|
||||
|
||||
# check for correct dir
|
||||
|
@ -28,16 +28,17 @@ else
|
|||
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)"' {} \;
|
||||
'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"' {} \;
|
||||
'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}' {} \;
|
||||
'sed -i -E "s/href=\"(\.\.\/)*doc\//href=\"\1html\//g;s/href=\"(.*).md(#.*)*\"/href=\"\1.html\"/g" $0' {} \;
|
||||
printf " Done!\n"
|
||||
fi
|
||||
fi
|
||||
|
|
|
@ -6,38 +6,67 @@
|
|||
# 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.21-0-gc85af77
|
||||
#### $$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 2>/dev/null)
|
||||
if [ "$GIT_DIR" != "" ] ; then
|
||||
[[ "$GIT_DIR" != "/"* ]] && GIT_DIR="${PWD}/${GIT_DIR}"
|
||||
cd "$GIT_DIR/.." || exit 1
|
||||
else
|
||||
[ ! -f "bashbot.sh" ] && printf "bashbot.sh not found in %s\n" " $(pwd)" && exit 1
|
||||
# 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
|
||||
|
||||
#DISTNAME="telegram-bot-bash"
|
||||
DISTDIR="./STANDALONE/${DISTNAME}"
|
||||
DISTFILES="bashbot.sh bashbot.rc commands.sh mycommands.sh dev/obfuscate.sh modules scripts logs LICENSE README.* doc botacl botconfig.jssh"
|
||||
# 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 on files
|
||||
dev/hooks/pre-commit.sh
|
||||
# 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
|
||||
mkdir -p "${DISTDIR}" 2>/dev/null
|
||||
printf "Create directories and copy files\n"
|
||||
mkdir -p "${DISTDIR}/bin" 2>/dev/null
|
||||
# shellcheck disable=SC2086
|
||||
cp -r ${DISTFILES} "${DISTDIR}" 2>/dev/null
|
||||
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 "$GIT_DIR/../dev/inject-json.sh"
|
||||
source "${BASE_DIR}/dev/inject-json.sh"
|
||||
|
||||
#######################
|
||||
# here the magic starts
|
||||
|
@ -62,19 +91,20 @@ printf "OK, now lets do the magic ...\n\t... create unified commands.sh\n"
|
|||
mv $$commands.sh commands.sh
|
||||
rm -f mycommands.sh
|
||||
|
||||
printf "\n... create unified bashbot.sh\n"
|
||||
printf "\t... create unified bashbot.sh\n"
|
||||
|
||||
{
|
||||
# first head of bashbot.sh
|
||||
sed -n '0,/for modules in/ p' bashbot.sh | head -n -3
|
||||
sed -n '0,/for module in/ p' bashbot.sh | head -n -3
|
||||
|
||||
# then mycommands from first non comment line on
|
||||
# then modules without shebang
|
||||
printf '\n##############################\n# bashbot modules starts here ...\n'
|
||||
cat modules/*.sh | sed -e 's/^#\!\/bin\/bash.*//'
|
||||
# shellcheck disable=SC2016
|
||||
cat modules/*.sh | sed -e 's/^#\!\/bin\/bash.*//' -e '/^#.*\$\$VERSION\$\$/d'
|
||||
|
||||
# last tail of commands.sh
|
||||
printf '\n##############################\n# bashbot internal functions starts here ...\n\n'
|
||||
sed -n '/BASHBOT INTERNAL functions/,$ p' bashbot.sh
|
||||
# last remaining commands.sh
|
||||
printf '\n##############################\n'
|
||||
sed -n '/^# read commands file/,$ p' bashbot.sh
|
||||
|
||||
} >>$$bashbot.sh
|
||||
|
||||
|
@ -85,17 +115,17 @@ 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 's/^[[:space:]]*//' -e '/^$/d' -e 'N;s/\\\n/ /;P;D' bashbot.sh |\
|
||||
sed 'N;s/\\\n/ /;P;D' > bashbot.sh.min
|
||||
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 's/^[[:space:]]*//' -e 's/\)[[:space:]]+#.*/)/' -e '/^$/d' commands.sh |\
|
||||
sed 'N;s/\\\n/ /;P;D' > commands.sh.min
|
||||
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 "$GIT_DIR/../dev/make-html.sh"
|
||||
source "${BASE_DIR}/dev/make-html.sh"
|
||||
|
||||
printf "%s Done!\n" "$0"
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
bashbot.rc
|
||||
botacl
|
||||
botconfig.jssh
|
||||
mycommands.conf
|
||||
dev/obfuscate.sh
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# joke hack to obfuscate bashbot.min.sh
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
# shellcheck disable=SC2028,SC2016,SC1117
|
||||
|
||||
infile="bashbot.sh"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# list of additional files to check from shellcheck
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
bashbot.rc
|
||||
mycommands.conf
|
||||
mycommands.sh.clean
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
# shellcheck disable=SC2016
|
||||
#
|
||||
# Easy Versioning in git:
|
||||
|
@ -34,14 +34,8 @@
|
|||
# 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 2>/dev/null)
|
||||
if [ "$GIT_DIR" != "" ] ; then
|
||||
cd "$GIT_DIR/.." || exit 1
|
||||
else
|
||||
printf "Sorry, no git repository %s\n" "$(pwd)" && exit 1
|
||||
fi
|
||||
#shellcheck disable=SC1090
|
||||
source "${0%/*}/dev.inc.sh"
|
||||
|
||||
unset IFS
|
||||
# set -f # if you are paranoid use set -f to disable globbing
|
||||
|
@ -49,19 +43,39 @@ unset IFS
|
|||
VERSION="$(git describe --tags --long)"
|
||||
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
|
||||
# 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
|
||||
printf " README.txt" >&2
|
||||
type -f pandoc >/dev/null && pandoc -s -f commonmark -M "title=Bashbot README" README.md >README.html
|
||||
fold -s README.md >README.txt
|
||||
|
||||
printf " done.\n"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
## 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.
|
||||
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 ...
|
||||
|
@ -15,7 +15,7 @@ if which bash; then echo "bash seems available..."; else echo "NO bash"; fi
|
|||
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 [ "$(echo -e "\u1111")" != "\u1111" ]; then echo "Bash version ok ..."; else echo "Bash version may to old ..."; fi'
|
||||
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"
|
||||
|
@ -23,58 +23,60 @@ 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 / tar archive from github](https://github.com/topkecleon/telegram-bot-bash/releases/latest) and extract all files.
|
||||
3. Change into the directory `telegram-bot-bash`
|
||||
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.
|
||||
Installing bashbot is very simple: Download and extract the installation archive.
|
||||
|
||||
Edit `mycommands.sh` to fit your needs.
|
||||
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)*
|
||||
|
||||
\* _Run with sudo if you want to run bashbot from different user, e.g. from `bashbot.rc`._
|
||||
|
||||
### Update bashbot
|
||||
|
||||
**Important: all files including `mycommands.sh` may overwritten, make a backup!**
|
||||
Update bashbot is almost identical to installing bashbot: Download and extract the installation archive.
|
||||
|
||||
1. Go to the directory where you have installed bashbot, e.g.
|
||||
* your $HOME directory
|
||||
* /usr/local
|
||||
2. [Download latest release zip / tar archive from github](https://github.com/topkecleon/telegram-bot-bash/releases/latest)
|
||||
**Important: All files may overwritten, make a backup!**
|
||||
|
||||
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. Extract all files to your existing bashbot dir
|
||||
5. Run `sudo ./bashbot.sh init` to setup your environment after the update
|
||||
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`
|
||||
|
||||
If you modified `commands.sh` move your changes to `mycommands.sh`, this avoids overwriting your commands on every update.
|
||||
|
||||
Now you can restart your bashbot instances.
|
||||
`mycommands.conf` and `mycommands.sh` will not overwritten, this avoids losing your bot config and commands on updates.
|
||||
|
||||
*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!
|
||||
|
||||
### Use JSON.awk (beta)
|
||||
### Use JSON.awk
|
||||
|
||||
[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.
|
||||
Most systems with awk can use `JSON.awk` as drop in replacement
|
||||
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) ).
|
||||
|
||||
After you have checked that `JSON.awk.dist` is working on your system copy it to `JSON.awk` and (re)start bashbot.
|
||||
|
||||
BSD and MacOS users must install `gnu awk` and adjust the shebang, see below
|
||||
|
||||
After you have checked that 'JSON.awk.dist' is working correct on your system copy it to `JSON.awk` and (re)start bashbot.
|
||||
|
||||
Note: If you are not using the zip / tar archive, you must install `JSON.awk` manually into the same directory as 'JSON.sh`:
|
||||
*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
|
||||
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 ...
|
||||
|
@ -82,7 +84,8 @@ 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 archives and set up bashbot to run in `DIST/telegram.bot-bash`.
|
||||
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`.
|
||||
|
||||
|
@ -92,10 +95,10 @@ To install or update bashbot from git repo execute `dev/make-distribution.sh`, t
|
|||
4. Run ` dev/make-distribution.sh` (_add --notest to skip tests_)
|
||||
5. Change to dir `DIST/`
|
||||
|
||||
Use the archives created in `DIST/` to install or update bashbot as described above.
|
||||
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, e.g. after git pull, local changes or switch master/develop, run `dev/make-distrubition.sh` again.
|
||||
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
|
||||
|
@ -104,32 +107,30 @@ To update the test installation, e.g. after git pull, local changes or switch ma
|
|||
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 ...
|
||||
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.
|
||||
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 more secure than the portable /usr/bin/env variant, see
|
||||
[Security Considerations](../README.md#Security-Considerations)
|
||||
Bashbot will stay with `#!/bin/bash` shebang, as using a fixed path is IMHO more secure than the portable '!/usr/bin/env bash` variant.
|
||||
|
||||
I considered to make bashbot BSD sed compatible, but much of the bashbot "magic" relies on
|
||||
(gnu) sed features, e.g. alternation ```|```, non printables ```\n\t\<``` or repeat ```?+``` pattern, not supported by BSD sed.
|
||||
|
||||
BSD/MacOS sed compatibility will result in a rewrite of all grep/sed commands with an uncertain outcome,
|
||||
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 is no more supported!
|
||||
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$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
|
|
|
@ -65,5 +65,5 @@ group. This step is up to you actually.
|
|||
#### [Prev Installation](0_install.md)
|
||||
#### [Next Getting started](2_usage.md)
|
||||
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
|
|
133
doc/2_usage.md
133
doc/2_usage.md
|
@ -19,8 +19,10 @@ Have FUN!
|
|||
```
|
||||
.
|
||||
├── mycommands.sh # THIS is your bot, place logic and commands here!
|
||||
├── mycommands.conf # place your bot config and bot messages here!
|
||||
│
|
||||
├── mycommands.sh.clean # copy to "mycommands.sh" if you start developing your bot
|
||||
├── 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
|
||||
|
@ -28,16 +30,24 @@ Have FUN!
|
|||
│
|
||||
├── bashbot.sh # main bashbot script - DO NOT EDIT!
|
||||
├── commands.sh # command dispatcher - DO NOT EDIT!
|
||||
├── JSON.sh # bashbots JSON parser, see https://github.com/dominictarr/JSON.sh
|
||||
├── 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_broadcast.sh # send message to all known chats
|
||||
│ ├── send_file.sh # send file to given chat
|
||||
│ ├── bashbot_stats.sh # does what it says ...
|
||||
│ ├── 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 # bashbot location included from scripts, adapt if needed
|
||||
│ ├── 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
|
||||
|
@ -47,15 +57,15 @@ Have FUN!
|
|||
├── modules # optional functions, sourced by commands.sh
|
||||
│ ├── aliases.sh # to disable modules rename them xxx.sh.off
|
||||
│ ├── answerInline.sh
|
||||
│ ├── jsshDB.sh # read and store JSON.sh style JSON, mandatory
|
||||
│ ├── background.sh # interactive and background functions
|
||||
│ ├── chatMember.sh
|
||||
│ └── sendMessage.sh # main send message functions, mandatory
|
||||
│ ├── 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
|
||||
│ └── xxxxxage.sh
|
||||
│ └── 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
|
||||
│
|
||||
|
@ -88,6 +98,7 @@ Start or Stop your Bot use the following commands:
|
|||
```
|
||||
|
||||
### 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:
|
||||
|
||||
|
@ -118,7 +129,7 @@ bin/send_message.sh "CHAT[ID]" "Hey, I just wanted to let you know that the bot'
|
|||
To replace a message already sent to one user or chat run the following command:
|
||||
|
||||
```bash
|
||||
bin/send_edit_message.sh "CHAT[ID]" "12345" "Done!"
|
||||
bin/edit_message.sh "CHAT[ID]" "12345" "Done!"
|
||||
|
||||
["OK"] "true"
|
||||
["ID"] "12345"
|
||||
|
@ -138,11 +149,17 @@ Note: to get help about a script in bin/ run `scriptname.sh --help`
|
|||
----
|
||||
|
||||
## Receive data
|
||||
Evertime a Message is received, you can read incoming data using the following variables:
|
||||
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.
|
||||
|
||||
### Regular Messages
|
||||
### Processing Messages
|
||||
|
||||
These Variables are always present in regular 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
|
||||
|
@ -162,6 +179,8 @@ These Variables are always present in regular messages:
|
|||
|
||||
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
|
||||
|
@ -175,14 +194,15 @@ The following variables are set if the message contains optional parts:
|
|||
* `${FORWARD[FIRST_NAME]}`: Original user's first name
|
||||
* `${FORWARD[LAST_NAME]}`: Original user's' last name
|
||||
* `${FORWARD[USERNAME]}`: Original user's username
|
||||
* `$CAPTION`: Picture, Audio, Video, File Captions
|
||||
* `$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
|
||||
* `$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
|
||||
|
@ -202,11 +222,10 @@ The following variables are set if the message contains optional parts:
|
|||
|
||||
### Service Messages
|
||||
|
||||
Service Messages are regular messages not itended for end users, instead they signal special events to the
|
||||
client, e.g. new users.
|
||||
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 sets MESSAGE to the service message type as a command,
|
||||
e.g. if a new user joins a chat MESSAGE is set to "/_new_chat_user".
|
||||
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
|
||||
|
@ -228,6 +247,8 @@ e.g. if a new user joins a chat MESSAGE is set to "/_new_chat_user".
|
|||
* `${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
|
||||
|
@ -240,11 +261,17 @@ e.g. if a new user joins a chat MESSAGE is set to "/_new_chat_user".
|
|||
|
||||
|
||||
### 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.
|
||||
|
||||
Inline query messages are small, non regular messages used for interaction with the user,
|
||||
they contain the following variables only:
|
||||
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.
|
||||
|
||||
* `${iQUERY}`: Current inline query
|
||||
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
|
||||
|
@ -252,20 +279,43 @@ they contain the following variables only:
|
|||
* `${iQUERY[LAST_NAME]}`: User's last name
|
||||
|
||||
|
||||
### Send Message Results
|
||||
|
||||
BOTSENT is set on every send_xxx action and only valid until next send action. For more on message results see.
|
||||
[Advanced Usage](3_advanced.md)
|
||||
### 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
|
||||
|
||||
|
||||
|
||||
## 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:
|
||||
|
@ -281,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"
|
||||
```
|
||||
|
@ -314,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 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"
|
||||
|
@ -341,5 +392,5 @@ send_action "${CHAT[ID]}" "action"
|
|||
#### [Prev Create Bot](1_firstbot.md)
|
||||
#### [Next Advanced Usage](3_advanced.md)
|
||||
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@ You must use the function `user_is_allowed` to check if a user has the capabilit
|
|||
# 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
|
||||
|
@ -72,18 +73,31 @@ You must use the function `user_is_allowed` to check if a user has the capabilit
|
|||
**See also [Bashbot User Access Control functions](6_reference.md#User-Access-Control)**
|
||||
|
||||
### Interactive Chats
|
||||
Interactive chats are short running scripts, reading user input and echo data to the user.
|
||||
Interactive chats are simple Bash scripts, reading user input as TEXT and output TEXT to the user.
|
||||
|
||||
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
|
||||
|
||||
**IMPORTANT:** Scripts must read user input from '$3' instead of stdin!
|
||||
|
||||
**Note:** Scripts must read user input from '$3' instead of stdin!
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
@ -143,7 +157,7 @@ echo "Text that will appear in one message \nwith this text on a new line"
|
|||
```
|
||||
|
||||
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:
|
||||
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."
|
||||
|
@ -171,7 +185,7 @@ All output of the script will be sent to the user, to stop a background job use:
|
|||
```bash
|
||||
kill_back "${CHAT[ID]}" "jobname"
|
||||
```
|
||||
You can also suspend and resume currently 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
|
||||
|
@ -189,7 +203,7 @@ Note: Background jobs run independent from main bot and continue running until y
|
|||
|
||||
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 messages or links through an *inline query*:
|
||||
```bash
|
||||
|
@ -257,7 +271,7 @@ By default you don't have to care about retry, as bashbot resend the message aft
|
|||
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.
|
||||
set `BASHBOT_RETRY` to any no zero value.
|
||||
|
||||
[Telegram Bot API error codes](https://github.com/TelegramBotAPI/errors)
|
||||
|
||||
|
@ -265,9 +279,9 @@ set `BASHBOT_RETRY`to any no zero value.
|
|||
#### 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`.
|
||||
bashbot set `BOTSENT[ERROR]` to `999`.
|
||||
|
||||
To get a notification on every connection problem create a function named `bashbotBlockRecover`and handle blocks there.
|
||||
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.
|
||||
|
||||
|
@ -301,5 +315,5 @@ Note: If you disable automatic retry, se above, you disable also connection prob
|
|||
#### [Prev Getting started](2_usage.md)
|
||||
#### [Next Expert Use](4_expert.md)
|
||||
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
|
|
|
@ -10,12 +10,12 @@ two bytes for encoding and covers almost all `Latin` alphabets, also `Greek`, `C
|
|||
|
||||
#### Setting up your Environment
|
||||
In general `bash` and `GNU` utitities are UTF-8 aware if you to setup your environment
|
||||
and your scripts accordingly:
|
||||
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.
|
||||
|
||||
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,11 +31,67 @@ 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 sure 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 available 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.
|
||||
|
@ -45,11 +101,11 @@ The Emoticons ` 😁 😘 ❤️ 😊 👍 ` are encoded as: ` \uD83D\uDE01 \uD8
|
|||
|
||||
**This "mixed" JSON encoding needs special handling and can not decoded from** `echo -e` or `printf '%s\\n'`
|
||||
|
||||
Bbashbot uses an internal, pure bash implementation which is well tested now, even there may 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 scheduled from cron. This is recommended if you want to bashbot run as a service.
|
||||
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
|
||||
|
@ -98,8 +154,9 @@ To use bashbot as a system service include a working `bashbot.rc` in your init s
|
|||
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 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`
|
||||
|
||||
**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
|
||||
|
@ -175,10 +232,10 @@ 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
|
||||
# fist Hello World
|
||||
# first Hello World
|
||||
send_normal_message "$(getConfigKey "botadmin")" "Hello World! This is my first message"
|
||||
|
||||
# now with some markdown and HTML
|
||||
# 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" ]'
|
||||
|
@ -202,10 +259,10 @@ This section describe how you can customize bashbot to your needs by setting env
|
|||
|
||||
|
||||
#### Change file locations
|
||||
In standard setup bashbot is self containing, this means you can place 'telegram-bot-bash' any location
|
||||
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.
|
||||
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
|
||||
|
@ -323,7 +380,7 @@ BASHBOT_TIMEOUT to a numeric value between 1 and 999. Any non numeric or negativ
|
|||
|
||||
##### 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 dealy. If no messages are available bashbot add 100ms delay
|
||||
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)
|
||||
|
@ -378,5 +435,5 @@ for every poll until the maximum of BASHBOT_SLEEP ms.
|
|||
#### [Prev Advanced Use](3_advanced.md)
|
||||
#### [Next Best Practice](5_practice.md)
|
||||
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ If you don't have a github account, it may time to [setup a free account now](ht
|
|||
### Add commands to mycommands.sh only
|
||||
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():
|
||||
the message strings and place commands in the` case ... esac` block of the function mycommands():
|
||||
```bash
|
||||
# file: mycommands.sh
|
||||
# your additional bashbot commands
|
||||
|
@ -160,5 +160,5 @@ The second warning is about an unused variable, this is true because in our exam
|
|||
#### [Prev Best Practice](5_practice.md)
|
||||
#### [Next Functions Reference](6_reference.md)
|
||||
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
101
doc/7_develop.md
101
doc/7_develop.md
|
@ -1,7 +1,7 @@
|
|||
#### [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, modules and addons, not on develop your individual bot. Nevertheless the information provided here should help your bot development also.
|
||||
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.
|
||||
|
||||
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).
|
||||
|
||||
|
@ -11,21 +11,20 @@ If you want to get error messages (and more) start bashbot `./bashbot.sh startb
|
|||
you can the change the level of verbosity of the debug argument:
|
||||
|
||||
```
|
||||
"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 in your code.
|
||||
"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`
|
||||
```
|
||||
|
||||
```
|
||||
sometimes its useful to watch the bot live in the terminal:
|
||||
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
|
||||
|
||||
"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
|
||||
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
|
||||
|
@ -36,7 +35,7 @@ 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 a not mandatory module is used in 'bashbot.sh' or 'commands.sh', the use of `_is_function` or
|
||||
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
|
||||
|
@ -63,18 +62,17 @@ Note: For the same reason event function MUST return immediately! Time consuming
|
|||
|
||||
##### SEND RECEIVE events
|
||||
|
||||
An RECEIVE event is executed when a Message is received, same iQuery / Message variables are available as in commands.sh
|
||||
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
|
||||
* `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"
|
||||
|
||||
|
@ -149,7 +147,7 @@ This means if you register an every 5 minutes callback first execution may < 5 M
|
|||
* 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 plus x" as time: `-(EVENT_TIMER + x)`
|
||||
Note: If you want exact "in x minutes" use "EVENT_TIMER" as reference: `(EVENT_TIMER +x)`
|
||||
|
||||
*Example:*
|
||||
```bash
|
||||
|
@ -168,8 +166,8 @@ 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
|
||||
BASHBOT_EVENT_TIMER["example_10min","$(( (EVENT_TIMER+10) * -1 ))"]="example_in10min"
|
||||
# once in exact 10 minutes, note the -
|
||||
BASHBOT_EVENT_TIMER["example_10min","-$(( EVENT_TIMER+10 ))"]="example_in10min"
|
||||
|
||||
```
|
||||
|
||||
|
@ -182,8 +180,8 @@ 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 not needed standard commands and messages from `commands.sh`
|
||||
- delete not needed commands and functions from `mycommands.sh`
|
||||
- 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.
|
||||
|
@ -198,8 +196,8 @@ Now have a look at the directory `standalone`, here you find the files `bashbot.
|
|||
5. give your (dev) fork a new version tag: `git tag v1.xx`
|
||||
6. setup github hooks by running `dev/install-hooks.sh`
|
||||
|
||||
Run `dev/make-distrubition.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-distrubition.sh` again.
|
||||
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
|
||||
|
@ -210,7 +208,7 @@ sudo apt-get -t buster-backports install git shellcheck pandoc codespell curl
|
|||
A typical bashbot develop loop looks as follow:
|
||||
|
||||
1. start developing - *change, copy, edit bashbot files ...*
|
||||
2. after changing a bash sript: `shellcheck -x script.sh`
|
||||
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`
|
||||
|
@ -254,6 +252,8 @@ 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""
|
||||
|
@ -261,10 +261,39 @@ 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.
|
||||
|
@ -291,15 +320,15 @@ To update version in all files run 'dev/version.sh' without parameter.
|
|||
|
||||
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 test suite
|
||||
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.
|
||||
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
|
||||
|
||||
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
|
||||
|
@ -328,7 +357,7 @@ The file `ALL-tests.inc.sh` must be included from all tests and provide the test
|
|||
ADMINFILE="botadmin"
|
||||
DATADIR="data-bot-bash"
|
||||
|
||||
# SUCCESS NOSUCCES -> echo "${SUCCESS}" or echo "${NOSUCCESS}"
|
||||
# SUCCESS NOSUCCESS -> echo "${SUCCESS}" or echo "${NOSUCCESS}"
|
||||
SUCCESS=" OK"
|
||||
NOSUCCESS=" FAILED!"
|
||||
|
||||
|
@ -358,5 +387,5 @@ fi
|
|||
|
||||
#### [Prev Function Reference](6_reference.md)
|
||||
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
|
|
|
@ -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*........**
|
||||
**...**
|
|
@ -56,6 +56,10 @@ convert existing bots.
|
|||
**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$$ v1.21-0-gc85af77
|
||||
### Webhook
|
||||
|
||||
**Webhook** contains instructions on how use webhook API to get updates from telegram instead polling Telegram server.
|
||||
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
|
||||
|
|
|
@ -6,12 +6,12 @@ export res
|
|||
# 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
|
||||
|
@ -56,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
|
||||
|
@ -94,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
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
######
|
||||
# parameters
|
||||
|
@ -28,8 +28,8 @@ cat >/dev/null &
|
|||
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
|
||||
|
@ -39,11 +39,11 @@ NEWLINE=$'\n'
|
|||
|
||||
# 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,7 @@
|
|||
# file: run_filename
|
||||
# background job to display content of all new files in WATCHDIR
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
######
|
||||
# parameters
|
||||
|
@ -40,4 +40,4 @@ loop_callback() {
|
|||
output_telegram "Contents of ${1}: ${NEWLINE} $(cat "${1}")"
|
||||
}
|
||||
|
||||
watch_dir_loop "$WATCHDIR"
|
||||
watch_dir_loop "${WATCHDIR}"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# file: run_filename
|
||||
# background job to display all new files in WATCHDIR
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
######
|
||||
# parameters
|
||||
|
@ -38,5 +38,5 @@ loop_callback() {
|
|||
echo "New file ${1} created in ${WATCHDIR}!"
|
||||
}
|
||||
|
||||
watch_dir_loop "$WATCHDIR"
|
||||
watch_dir_loop "${WATCHDIR}"
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#
|
||||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
######
|
||||
# parameters
|
||||
|
@ -25,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
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
# 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.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
# adjust your language setting here
|
||||
# https://github.com/topkecleon/telegram-bot-bash#setting-up-your-environment
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
# file. multibot.sh
|
||||
# description: run multiple telegram bots from one installation
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$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="$1"
|
||||
[ "${#BOT}" -lt 5 ] && echo "Botname must have a minimum length of 5 characters" && exit 1
|
||||
|
||||
# where should the bots live?
|
||||
|
|
|
@ -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$$ v1.21-0-gc85af77
|
||||
#### $$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 plus random sleep between 0-3h
|
||||
0 0 * * * nobody sleep "$((RANDOM \% 180 ))m" ; /usr/local/telegram-bot-bash/bashbot.sh start # (re)start bot
|
||||
0 0 * * * nobody sleep "$((RANDOM \% 180 ))m" ; /usr/local/telegram-bot-bash/bashbot.sh resumeback # (re)start background jobs
|
||||
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
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
########################################################################
|
||||
|
||||
######
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
# AUTHOR: KayM (), kay@rrr.de
|
||||
# DATE: 19.12.2020 19:03
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
# shellcheck disable=SC2154
|
||||
# shellcheck disable=SC2034
|
||||
|
@ -326,8 +326,8 @@ fi
|
|||
MYKEYF="$2"
|
||||
MINLEN="4"
|
||||
# check len of keys
|
||||
for MYKEY in ${MYFIND}; do [ "${#MYKEY}" -lt ${MINLEN} ] && break; done
|
||||
if [ "${#MYKEY}" -lt ${MINLEN} ]; then
|
||||
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}")"
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
########################################################################
|
||||
|
||||
######
|
||||
|
@ -47,6 +47,6 @@ printf "Output time every %s seconds ...\n" "${SLEEP}"
|
|||
while true
|
||||
do
|
||||
date "+* It's %k:%M:%S o'clock ..."
|
||||
sleep $SLEEP
|
||||
sleep "${SLEEP}"
|
||||
done
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
########################################################################
|
||||
|
||||
######
|
||||
|
@ -29,6 +29,10 @@ export 'LANGUAGE=C.UTF-8'
|
|||
unset IFS
|
||||
# set -f # if you are paranoid use set -f to disable globbing
|
||||
|
||||
# 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}"
|
||||
|
@ -39,7 +43,7 @@ else
|
|||
fi
|
||||
|
||||
# question with Keyboard, repeating until correct answer given
|
||||
until [ "$SUCCESS" = "y" ] ;do
|
||||
until [ "${SUCCESS}" = "y" ] ;do
|
||||
printf 'Do you like Music? mykeyboardstartshere "Yass!" , "No"\n'
|
||||
read -r answer <"${INPUT}"
|
||||
case ${answer,,} in
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# file: botacl
|
||||
# a user not listed here, will return false from 'user_is_allowed'
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
# Format:
|
||||
# user:resource:chat
|
||||
|
||||
|
|
|
@ -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$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#
|
||||
# shellcheck disable=SC2154
|
||||
# shellcheck disable=SC2034
|
||||
|
@ -38,7 +38,7 @@ mycommands() {
|
|||
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=/\//')";;
|
||||
|
@ -51,14 +51,14 @@ mycommands() {
|
|||
'/smart'*)
|
||||
[ "${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")"
|
||||
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!"
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
?>
|
|
@ -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,11 +1,11 @@
|
|||
#!/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$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#
|
||||
# will be automatically sourced from bashbot
|
||||
|
||||
|
@ -23,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"
|
||||
|
|
|
@ -5,20 +5,19 @@
|
|||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
# will be automatically sourced from bashbot
|
||||
|
||||
# source once magic, function named like file
|
||||
eval "$(basename "${BASH_SOURCE[0]}")(){ :; }"
|
||||
|
||||
INLINE_QUERY=$URL'/answerInlineQuery'
|
||||
|
||||
answer_inline_query() {
|
||||
answer_inline_multi "${1}" "$(shift; inline_query_compose "$RANDOM" "$@")"
|
||||
answer_inline_multi "$1" "$(shift; inline_query_compose "${RANDOM}" "$@")"
|
||||
}
|
||||
answer_inline_multi() {
|
||||
sendJson "" '"inline_query_id": '"${1}"', "results": ['"${2}"']' "${INLINE_QUERY}"
|
||||
sendJson "" '"inline_query_id": '"$1"', "results": ['"$2"']' "${URL}/answerInlineQuery"
|
||||
}
|
||||
|
||||
# $1 unique ID for answer
|
||||
|
@ -27,76 +26,76 @@ answer_inline_multi() {
|
|||
# followed by the optional arguments: https://core.telegram.org/bots/api#inlinequeryresult
|
||||
inline_query_compose(){
|
||||
local JSON="{}"
|
||||
local ID="${1}"
|
||||
local ID="$1"
|
||||
local fours last
|
||||
# title2Json title caption description markup inlinekeyboard
|
||||
case "${2}" in
|
||||
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")'}'
|
||||
"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)
|
||||
"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")'}'
|
||||
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)
|
||||
"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")'}'
|
||||
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)
|
||||
"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")'}'
|
||||
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}")'}'
|
||||
"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")'}'
|
||||
"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")'}'
|
||||
"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")'}'
|
||||
"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'"}'
|
||||
"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)
|
||||
"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}'}'
|
||||
JSON='{"type":"venue","id":"'${ID}'","latitude":"'$3'","longitude":"'$4'","title":"'$5'","address":"'$6${addr}'"'${fours}'}'
|
||||
;;
|
||||
"contact") # contact ID phone first (last thumb)
|
||||
"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}'"}'
|
||||
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_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_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_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_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_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_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_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")'}'
|
||||
"cached_audio") # audio ID file title (caption)
|
||||
JSON='{"type":"audio","id":"'${ID}'","audio_file_id":"'$3'"'$(title2Json "$4" "$5" "" "" "$6")'}'
|
||||
;;
|
||||
esac
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
# shellcheck disable=SC1117,SC2059
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
# will be automatically sourced from bashbot
|
||||
|
||||
|
@ -46,12 +46,16 @@ start_back() {
|
|||
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-")"
|
||||
printf "%s: Start background job CHAT=%s JOB=%s CMD=%s\n" "$(date)" "${1}" "${fifo##*/}" "${2##*/} ${4} ${5}" >>"${UPDATELOG}"
|
||||
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
|
||||
nohup bash -c "{ $2 \"$4\" \"$5\" \"${fifo}\" | \"${SCRIPT}\" outproc \"$1\" \"${fifo}\"; }" &>>"${fifo}.log" &
|
||||
sleep 0.5 # give bg job some time to init
|
||||
}
|
||||
|
||||
|
||||
|
@ -62,10 +66,10 @@ start_proc() {
|
|||
[ -z "$2" ] && return
|
||||
[ -x "${2%% *}" ] || return 1
|
||||
local fifo; fifo="${DATADIR:-.}/$(procname "$1")"
|
||||
printf "%s: Start interacitve script CHAT=%s JOB=%s CMD=%s\n" "$(date)" "${1}" "${fifo##*/}" "${2} ${3} ${4}" >>"${UPDATELOG}"
|
||||
check_proc "$1" && kill_proc "$1"
|
||||
mkfifo "${fifo}"
|
||||
nohup bash -c "{ $2 \"$4\" \"$5\" \"$fifo\" | \"${SCRIPT}\" outproc \"${1}\" \"${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" &
|
||||
}
|
||||
|
||||
|
@ -99,9 +103,11 @@ kill_proc() {
|
|||
fifo="$(procname "$1" "$2")"
|
||||
prid="$(proclist "${fifo}")"
|
||||
fifo="${DATADIR:-.}/${fifo}"
|
||||
printf "%s: Stop interacitve / background CHAT=%s JOB=%s\n" "$(date)" "${1}" "${fifo##*/}" >>"${UPDATELOG}"
|
||||
# shellcheck disable=SC2086
|
||||
[ -n "${prid}" ] && kill ${prid}
|
||||
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}";
|
||||
}
|
||||
|
@ -110,7 +116,7 @@ kill_proc() {
|
|||
# $2 message
|
||||
send_interactive() {
|
||||
local fifo; fifo="${DATADIR:-.}/$(procname "$1")"
|
||||
[ -p "${fifo}" ] && printf '%s\n' "$2" >"${fifo}" & # not blocking!
|
||||
[ -p "${fifo}" ] && printf '%s\n' "$2" >"${fifo}" & # not blocking!
|
||||
}
|
||||
|
||||
# old style but may not work because of local checks
|
||||
|
@ -118,16 +124,15 @@ inproc() {
|
|||
send_interactive "${CHAT[ID]}" "${MESSAGE[0]}"
|
||||
}
|
||||
|
||||
# start stop all jobs
|
||||
# $1 command
|
||||
# killb*
|
||||
# suspendb*
|
||||
# resumeb*
|
||||
# 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="$(getConfigKey "botadmin")"
|
||||
debug_checks "Enter job_control" "${1}"
|
||||
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}")"
|
||||
|
@ -136,25 +141,25 @@ job_control() {
|
|||
proc="${job#*:}"
|
||||
job="${job%:*}"
|
||||
fifo="$(procname "${CHAT}" "${job}")"
|
||||
debug_checks "Execute job_control" "${1}" "${FILE##*/}"
|
||||
debug_checks "Execute job_control" "$1" "${FILE##*/}"
|
||||
case "$1" in
|
||||
"resumeb"*|"backgr"*)
|
||||
"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 ..." &
|
||||
;;
|
||||
"suspendb"*)
|
||||
"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"
|
||||
;;
|
||||
"killb"*)
|
||||
"kill"*)
|
||||
printf "Kill Job: %s %s\n" "${proc}" " ${fifo##*/}"
|
||||
kill_proc "${CHAT}" "${job}"
|
||||
rm -f "${FILE}" # remove job
|
||||
rm -f "${FILE}" # remove job
|
||||
# inform botadmin about stop
|
||||
[ -n "${ADM}" ] && send_normal_message "${ADM}" "Bot ${BOT} kill background jobs ..." &
|
||||
killall="y"
|
||||
|
@ -163,7 +168,7 @@ job_control() {
|
|||
# send message only onnfirst job
|
||||
ADM=""
|
||||
done
|
||||
debug_checks "end job_control" "${1}"
|
||||
debug_checks "end job_control" "$1"
|
||||
# kill all requestet. kill ALL background jobs, even not listed in data-bot-bash
|
||||
[ "${killall}" = "y" ] && killallproc "back-"
|
||||
}
|
||||
|
|
|
@ -5,36 +5,122 @@
|
|||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
# will be automatically sourced from bashbot
|
||||
|
||||
# source once magic, function named like file
|
||||
eval "$(basename "${BASH_SOURCE[0]}")(){ :; }"
|
||||
|
||||
LEAVE_URL=$URL'/leaveChat'
|
||||
KICK_URL=$URL'/kickChatMember'
|
||||
UNBAN_URL=$URL'/unbanChatMember'
|
||||
GETMEMBER_URL=$URL'/getChatMember'
|
||||
|
||||
# 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"'' "$GETMEMBER_URL"
|
||||
sendJson "$1" '"user_id":'"$2"'' "${URL}/getChatMember"
|
||||
# shellcheck disable=SC2154
|
||||
JsonGetString '"result","status"' <<< "$res"
|
||||
}
|
||||
|
||||
kick_chat_member() {
|
||||
sendJson "$1" 'user_id: '"$2"'' "$KICK_URL"
|
||||
}
|
||||
|
||||
unban_chat_member() {
|
||||
sendJson "$1" 'user_id: '"$2"'' "$UNBAN_URL"
|
||||
}
|
||||
|
||||
leave_chat() {
|
||||
sendJson "$1" "" "$LEAVE_URL"
|
||||
printf "%s\n" "${UPD["result,status"]}"
|
||||
}
|
||||
|
||||
user_is_creator() {
|
||||
|
@ -61,27 +147,27 @@ user_is_admin() {
|
|||
# $1 user
|
||||
user_is_botadmin() {
|
||||
[ -z "$1" ] && return 1
|
||||
local admin; admin="$(getConfigKey "botadmin")"; [ -z "${admin}" ] && return 1
|
||||
[[ "${admin}" == "${1}" || "${admin}" == "${2}" ]] && return 0
|
||||
#[[ "${admin}" = "@*" ]] && [[ "${admin}" = "${2}" ]] && return 0
|
||||
if [ "${admin}" = "?" ]; then setConfigKey "botadmin" "${1:-?}"; return 0; fi
|
||||
[ -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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
grep -F -xq "ALL:$2:$3" "${BOTACL}" && return 0
|
||||
return 1
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
# This file is public domain in the USA and all free countries.
|
||||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#
|
||||
# source from commands.sh to use jsonDB functions
|
||||
#
|
||||
|
@ -25,7 +25,31 @@ eval "$(basename "${BASH_SOURCE[0]}")(){ :; }"
|
|||
# tinybox
|
||||
|
||||
# lockfile filename.flock is persistent and will be testet with flock for active lock (file open)
|
||||
export JSSH_LOCKNAME=".flock"
|
||||
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
|
||||
|
@ -42,7 +66,7 @@ if [ "$(LC_ALL=C type -t "flock")" = "file" ]; then
|
|||
[ -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}${JSSH_LOCKNAME}"
|
||||
{ flock -s -w 1 200; Json2Array "$1" <"${DB}"; } 200>"${DB}${JSSHDB_LOCKNAME}"
|
||||
}
|
||||
|
||||
# write ARRAY content to a file in JSON.sh format
|
||||
|
@ -54,7 +78,7 @@ if [ "$(LC_ALL=C type -t "flock")" = "file" ]; then
|
|||
[ -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}${JSSH_LOCKNAME}"
|
||||
{ flock -e -w 10 200; Array2Json "$1" >"${DB}"; } 200>"${DB}${JSSHDB_LOCKNAME}"
|
||||
}
|
||||
|
||||
# update/write ARRAY content in file without deleting keys not in ARRAY
|
||||
|
@ -63,20 +87,20 @@ if [ "$(LC_ALL=C type -t "flock")" = "file" ]; then
|
|||
# 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
|
||||
[ -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}${JSSH_LOCKNAME}"
|
||||
{ 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
|
||||
alias jssh_insertDB=jssh_insertKeyDB # backward compatibility
|
||||
# renamed to be more consistent
|
||||
jssh_insertKeyDB() {
|
||||
[[ "$1" =~ ^[-a-zA-Z0-9,._]+$ ]] || return 3
|
||||
[[ "$1" =~ ^${JSSH_KEYOK}+$ ]] || return 3
|
||||
local DB; DB="$(jssh_checkDB "$3")"
|
||||
[ -z "${DB}" ] && return 1
|
||||
[ ! -f "${DB}" ] && return 2
|
||||
|
@ -84,7 +108,7 @@ if [ "$(LC_ALL=C type -t "flock")" = "file" ]; then
|
|||
{ 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}${JSSH_LOCKNAME}"
|
||||
} 200>"${DB}${JSSHDB_LOCKNAME}"
|
||||
|
||||
}
|
||||
|
||||
|
@ -93,11 +117,11 @@ if [ "$(LC_ALL=C type -t "flock")" = "file" ]; then
|
|||
# $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" =~ ^[-a-zA-Z0-9,._]+$ ]] || return 3
|
||||
local DB="${2}.jssh"
|
||||
[ -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}${JSSH_LOCKNAME}"
|
||||
{ flock -e -w 10 200; jssh_deleteKeyDB_async "$@"; } 200>"${DB}${JSSHDB_LOCKNAME}"
|
||||
}
|
||||
|
||||
# get key/value from jsshDB
|
||||
|
@ -105,13 +129,13 @@ if [ "$(LC_ALL=C type -t "flock")" = "file" ]; then
|
|||
# $2 filename (must exist!), must be relative to BASHBOT_ETC, and not contain '..'
|
||||
alias jssh_getDB=jssh_getKeyDB
|
||||
jssh_getKeyDB() {
|
||||
[[ "$1" =~ ^[-a-zA-Z0-9,._]+$ ]] || return 3
|
||||
[[ "$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}${JSSH_LOCKNAME}"
|
||||
[ -r "${DB}" ] && sed -n 's/\["'"$1"'"\]\t*"\(.*\)"/\1/p' "${DB}" | tail -n 1
|
||||
} 200>"${DB}${JSSHDB_LOCKNAME}"
|
||||
}
|
||||
|
||||
|
||||
|
@ -122,11 +146,11 @@ if [ "$(LC_ALL=C type -t "flock")" = "file" ]; then
|
|||
# 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" =~ ^[-a-zA-Z0-9,._]+$ ]] || return 3
|
||||
local DB="${2}.jssh"
|
||||
[ -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}${JSSH_LOCKNAME}"
|
||||
{ flock -e -w 5 200; jssh_countKeyDB_async "$@"; } 200>"${DB}${JSSHDB_LOCKNAME}"
|
||||
}
|
||||
|
||||
# update key/value in place to jsshDB
|
||||
|
@ -135,19 +159,19 @@ if [ "$(LC_ALL=C type -t "flock")" = "file" ]; then
|
|||
# $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" =~ ^[-a-zA-Z0-9,._]+$ ]] || return 3
|
||||
[ -z "${3}" ] && return 1
|
||||
[[ "$1" =~ ^${JSSH_KEYOK}+$ ]] || return 3
|
||||
[ -z "$3" ] && return 1
|
||||
declare -A updARR
|
||||
# shellcheck disable=SC2034
|
||||
updARR["$1"]="$2"
|
||||
jssh_updateDB "updARR" "${3}" || return 3
|
||||
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}${JSSH_LOCKNAME}"
|
||||
{ flock -e -w 10 200; printf '' >"${DB}"; } 200>"${DB}${JSSHDB_LOCKNAME}"
|
||||
}
|
||||
|
||||
# updates Array if DB file has changed since last call
|
||||
|
@ -156,11 +180,11 @@ if [ "$(LC_ALL=C type -t "flock")" = "file" ]; then
|
|||
# $3 id used to identify caller
|
||||
# medium complex, wrapper async
|
||||
jssh_updateArray() {
|
||||
[ -z "${2}" ] && return 1
|
||||
local DB="${2}.jssh" # name check in async
|
||||
[ -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}"
|
||||
[[ -z "${ARRAY[*]}" || "${DB}" -nt "${DB}.last$3" ]] && touch "${DB}.last$3" && jssh_readDB "$1" "$2"
|
||||
}
|
||||
|
||||
else
|
||||
|
@ -194,7 +218,7 @@ jssh_newDB_async() { jssh_newDB "$@"; }
|
|||
jssh_newDB() {
|
||||
local DB; DB="$(jssh_checkDB "$1")"
|
||||
[ -z "${DB}" ] && return 1
|
||||
[ -f "${DB}" ] && return 2 # already exist
|
||||
[ -f "${DB}" ] && return 2 # already exist
|
||||
touch "${DB}"
|
||||
}
|
||||
|
||||
|
@ -206,9 +230,9 @@ jssh_checkDB(){
|
|||
[ -z "$1" ] && return 1
|
||||
[[ "$1" = *'../.'* ]] && return 2
|
||||
if [[ "$1" == "${BASHBOT_VAR:-.}"* ]] || [[ "$1" == "${BASHBOT_DATA:-.}"* ]]; then
|
||||
DB="${1}.jssh"
|
||||
DB="$1.jssh"
|
||||
else
|
||||
DB="${BASHBOT_VAR:-.}/${1}.jssh"
|
||||
DB="${BASHBOT_VAR:-.}/$1.jssh"
|
||||
fi
|
||||
[ "${DB}" != ".jssh" ] && printf '%s' "${DB}"
|
||||
}
|
||||
|
@ -232,7 +256,7 @@ jssh_writeDB_async() {
|
|||
}
|
||||
|
||||
jssh_updateDB_async() {
|
||||
[ -z "${2}" ] && return 1
|
||||
[ -z "$2" ] && return 1
|
||||
declare -n ARRAY="$1"
|
||||
[ -z "${ARRAY[*]}" ] && return 1
|
||||
declare -A oldARR
|
||||
|
@ -253,7 +277,7 @@ jssh_updateDB_async() {
|
|||
|
||||
jssh_insertDB_async() { jssh_insertKeyDB "$@"; }
|
||||
jssh_insertKeyDB_async() {
|
||||
[[ "$1" =~ ^[-a-zA-Z0-9,._]+$ ]] || return 3
|
||||
[[ "$1" =~ ^${JSSH_KEYOK}+$ ]] || return 3
|
||||
local DB; DB="$(jssh_checkDB "$3")"
|
||||
[ -z "${DB}" ] && return 1
|
||||
[ ! -f "${DB}" ] && return 2
|
||||
|
@ -263,7 +287,7 @@ jssh_insertKeyDB_async() {
|
|||
}
|
||||
|
||||
jssh_deleteKeyDB_async() {
|
||||
[[ "$1" =~ ^[-a-zA-Z0-9,._]+$ ]] || return 3
|
||||
[[ "$1" =~ ^${JSSH_KEYOK}+$ ]] || return 3
|
||||
local DB; DB="$(jssh_checkDB "$2")"
|
||||
[ -z "${DB}" ] && return 1
|
||||
declare -A oldARR
|
||||
|
@ -273,14 +297,14 @@ jssh_deleteKeyDB_async() {
|
|||
}
|
||||
|
||||
jssh_getKeyDB_async() {
|
||||
[[ "$1" =~ ^[-a-zA-Z0-9,._]+$ ]] || return 3
|
||||
[[ "$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
|
||||
[ -r "${DB}" ] && sed -n 's/\["'"$1"'"\]\t*"\(.*\)"/\1/p' "${DB}" | tail -n 1
|
||||
}
|
||||
|
||||
jssh_countKeyDB_async() {
|
||||
[[ "$1" =~ ^[-a-zA-Z0-9,._]+$ ]] || return 3
|
||||
[[ "$1" =~ ^${JSSH_KEYOK}+$ ]] || return 3
|
||||
local VAL DB; DB="$(jssh_checkDB "$2")"
|
||||
[ -z "${DB}" ] && return 1
|
||||
# start atomic delete here, exclusive max wait 5
|
||||
|
@ -291,7 +315,7 @@ jssh_countKeyDB_async() {
|
|||
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)"
|
||||
VAL="$(sed -n 's/\["'"$1"'"\]\t*"\(.*\)"/\1/p' "${DB}" | tail -n 1)"
|
||||
printf '["%s"]\t"%s"\n' "${1//,/\",\"}" "$((++VAL))" >>"${DB}"
|
||||
fi
|
||||
}
|
||||
|
@ -302,12 +326,12 @@ jssh_countKeyDB_async() {
|
|||
# $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" =~ ^[-a-zA-Z0-9,._]+$ ]] || return 3
|
||||
[ -z "${3}" ] && return 1
|
||||
[[ "$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_updateDB_async "updARR" "$3" || return 3
|
||||
}
|
||||
|
||||
jssh_clearDB_async() {
|
||||
|
@ -321,7 +345,7 @@ function jssh_updateArray_async() {
|
|||
[ -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}"
|
||||
[[ -z "${ARRAY[*]}" || "${DB}" -nt "${DB}.last$3" ]] && touch "${DB}.last$3" && jssh_readDB_async "$1" "$2"
|
||||
}
|
||||
|
||||
##############
|
||||
|
@ -331,22 +355,23 @@ function jssh_updateArray_async() {
|
|||
# read JSON.sh style data and asssign to an ARRAY
|
||||
# $1 ARRAY name, must be declared with "declare -A ARRAY" before calling
|
||||
Json2Array() {
|
||||
# match ["....."]\t and replace \t with = and print quote true false escape not escaped $
|
||||
# shellcheck disable=SC1091,SC1090
|
||||
[ -z "$1" ] || source <( printf "$1"'=( %s )' "$(sed -E -n -e '/\["[-0-9a-zA-Z_,."]+"\]\+*\t/ s/\t/=/p' -e 's/=(true|false)/="\1"/' -e 's/([^\]|^)\$/\1\\$/g')" )
|
||||
# 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 val
|
||||
local key
|
||||
declare -n ARRAY="$1"
|
||||
for key in "${!ARRAY[@]}"
|
||||
do
|
||||
# in case val contains newline convert to \n
|
||||
val="${ARRAY[${key}]//$'\n'/\\n}"
|
||||
printf '["%s"]\t"%s"\n' "${key//,/\",\"}" "${val//\"/\\\"}"
|
||||
[[ ! "${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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
# Elsewhere, consider it to be WTFPLv2. (wtfpl.net/txt/copying)
|
||||
#
|
||||
# shellcheck disable=SC1117
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
# will be automatically sourced from bashbot
|
||||
|
||||
|
@ -15,19 +15,8 @@ eval "$(basename "${BASH_SOURCE[0]}")(){ :; }"
|
|||
|
||||
# source from commands.sh to use the sendMessage functions
|
||||
|
||||
MSG_URL=$URL'/sendMessage'
|
||||
EDIT_URL=$URL'/editMessageText'
|
||||
PHO_URL=$URL'/sendPhoto'
|
||||
AUDIO_URL=$URL'/sendAudio'
|
||||
DOCUMENT_URL=$URL'/sendDocument'
|
||||
STICKER_URL=$URL'/sendSticker'
|
||||
VIDEO_URL=$URL'/sendVideo'
|
||||
VOICE_URL=$URL'/sendVoice'
|
||||
LOCATION_URL=$URL'/sendLocation'
|
||||
VENUE_URL=$URL'/sendVenue'
|
||||
ACTION_URL=$URL'/sendChatAction'
|
||||
FORWARD_URL=$URL'/forwardMessage'
|
||||
ALBUM_URL=$URL'/sendMediaGroup'
|
||||
MSG_URL=${URL}'/sendMessage'
|
||||
EDIT_URL=${URL}'/editMessageText'
|
||||
|
||||
#
|
||||
# send/edit message variants ------------------
|
||||
|
@ -35,66 +24,97 @@ ALBUM_URL=$URL'/sendMediaGroup'
|
|||
|
||||
# $1 CHAT $2 message
|
||||
send_normal_message() {
|
||||
local len text; text="$(JsonEscape "${2}")"
|
||||
text="${text//$'\n'/\\n}"
|
||||
local len text; text="$(JsonEscape "$2")"
|
||||
until [ -z "${text}" ]; do
|
||||
if [ "${#text}" -le 4096 ]; then
|
||||
sendJson "${1}" '"text":"'"${text}"'"' "${MSG_URL}"
|
||||
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}"
|
||||
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}"
|
||||
_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}"
|
||||
_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}"
|
||||
_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}"
|
||||
_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}"
|
||||
_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}"
|
||||
_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}"
|
||||
_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="${text//$'\n'/\\n}"
|
||||
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}"
|
||||
sendJson "$1" '"text":"'"${text:0:4096}"'"'"$3"'' "$4"
|
||||
text="${text:4096}"
|
||||
done
|
||||
}
|
||||
|
@ -102,13 +122,12 @@ _format_message_url(){
|
|||
# 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="${text//$'\n'/\\n}"
|
||||
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")"
|
||||
text="$(sed -E -e 's|([_|~`>+=#{}()!.-])|\\\1|g' <<< "${text}")"
|
||||
until [ -z "${text}" ]; do
|
||||
sendJson "${1}" '"text":"'"${text:0:4096}"'"'"${3}"'' "${4}"
|
||||
sendJson "$1" '"text":"'"${text:0:4096}"'"'"$3"'' "$4"
|
||||
text="${text:4096}"
|
||||
done
|
||||
}
|
||||
|
@ -121,158 +140,245 @@ _markdownv2_message_url() {
|
|||
send_keyboard() {
|
||||
if [[ "$3" != *'['* ]]; then old_send_keyboard "${@}"; return; fi
|
||||
local text='"text":"'"Keyboard:"'"'
|
||||
if [ -n "${2}" ]; then
|
||||
text="$(JsonEscape "${2}")"
|
||||
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=""
|
||||
sendJson "${1}" "${text}"', "reply_markup": {"keyboard": [ '"${3}"' ] '"${one_time}"'}' "$MSG_URL"
|
||||
# '"text":"$2", "reply_markup": {"keyboard": [ ${3} ], "one_time_keyboard": true}'
|
||||
# '"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}")"
|
||||
if [ -n "$2" ]; then
|
||||
text="$(JsonEscape "$2")"
|
||||
text='"text":"'"${text//$'\n'/\\n}"'"'
|
||||
fi
|
||||
sendJson "${1}" "${text}"', "reply_markup": {"remove_keyboard":true}' "$MSG_URL"
|
||||
sendJson "$1" "${text}"', "reply_markup": {"remove_keyboard":true}' "${MSG_URL}"
|
||||
# delete message if no message or $3 not empty
|
||||
[[ -z "${2}" || -n "${3}" ]] && delete_message "${1}" "${BOTSENT[ID]}" "nolog"
|
||||
#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":"'"Keyboard:"'"'
|
||||
sendJson "${1}" "${text}"', "reply_markup": {"inline_keyboard": [ '"${3}"' ]}' "$MSG_URL"
|
||||
# JSON='"text":"$2", "reply_markup": {"inline_keyboard": [ $3->[{"text":"text", "url":"url"}]<- ]}'
|
||||
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 CHAT $2 message $3 button text $4 URL
|
||||
send_button() {
|
||||
send_inline_keyboard "${1}" "${2}" '[ {"text":"'"$(JsonEscape "${3}")"'", "url":"'"${4}"'"}]'
|
||||
|
||||
# $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"
|
||||
}
|
||||
|
||||
|
||||
if [ -z "${BASHBOT_WGET}" ] && _exists curl ; then
|
||||
# there are no checks if URL or ID exists
|
||||
# $1 chat $3 ... $n URL or ID
|
||||
# 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
|
||||
[ -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} "${ALBUM_URL}" -F "chat_id=${CHAT}"\
|
||||
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 yet implemented"
|
||||
log_error "Sorry, wget Album upload not implemented"
|
||||
BOTSENT[OK]="false"
|
||||
[[ -z "${SOURCE}" && -n "${BASHBOT_EVENT_SEND[*]}" ]] && event_send "album" "$@" &
|
||||
}
|
||||
fi
|
||||
|
||||
UPLOADDIR="${BASHBOT_UPLOAD:-${DATADIR}/upload}"
|
||||
|
||||
# for now this can only send local files with curl!
|
||||
# extend to allow send files by URL or telegram ID
|
||||
send_file() {
|
||||
local err
|
||||
upload_file "${@}"; err="$?"
|
||||
# fake Telegram response to provide error
|
||||
if [ "${err}" != "0" ]; then
|
||||
BOTSENT=()
|
||||
BOTSENT[OK]="false"
|
||||
case "$err" in
|
||||
1) BOTSENT[ERROR]="Path to file $2 contains to much '../' or starts with '.'";;
|
||||
2) BOTSENT[ERROR]="Path to file $2 does not match regex: ${FILE_REGEX} ";;
|
||||
3) if [[ "$2" == "/"* ]];then
|
||||
BOTSENT[ERROR]="File not found: $2"
|
||||
else
|
||||
BOTSENT[ERROR]="File not found: ${UPLOADDIR}/$2"
|
||||
fi;;
|
||||
esac
|
||||
[ -n "${BASHBOTDEBUG}" ] && log_message "Error in upload_file: ${BOTSENT[ERROR]}"
|
||||
fi
|
||||
}
|
||||
|
||||
upload_file(){
|
||||
local CUR_URL WHAT STATUS text=$3 file="$2"
|
||||
# file access checks ...
|
||||
[[ "$file" = *'..'* ]] && return 1 # no directory traversal
|
||||
[[ "$file" = '.'* ]] && return 1 # no hidden or relative files
|
||||
if [[ "$file" = '/'* ]] ; then
|
||||
[[ ! "$file" =~ ${FILE_REGEX} ]] && return 2 # absolute must match REGEX
|
||||
# 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
|
||||
file="${UPLOADDIR:-NOUPLOADDIR}/${file}" # othiers must be in UPLOADDIR
|
||||
# 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
|
||||
[ ! -r "$file" ] && return 3 # and file must exits of course
|
||||
|
||||
local ext="${file##*.}"
|
||||
case $ext in
|
||||
mp3|flac)
|
||||
CUR_URL="$AUDIO_URL"
|
||||
WHAT="audio"
|
||||
STATUS="upload_audio"
|
||||
;;
|
||||
png|jpg|jpeg|gif|pic)
|
||||
CUR_URL="$PHO_URL"
|
||||
WHAT="photo"
|
||||
STATUS="upload_photo"
|
||||
;;
|
||||
webp)
|
||||
CUR_URL="$STICKER_URL"
|
||||
WHAT="sticker"
|
||||
STATUS="upload_photo"
|
||||
;;
|
||||
mp4)
|
||||
CUR_URL="$VIDEO_URL"
|
||||
WHAT="video"
|
||||
STATUS="upload_video"
|
||||
;;
|
||||
|
||||
ogg)
|
||||
CUR_URL="$VOICE_URL"
|
||||
WHAT="voice"
|
||||
STATUS="upload_audio"
|
||||
# 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"
|
||||
;;
|
||||
*)
|
||||
CUR_URL="$DOCUMENT_URL"
|
||||
WHAT="document"
|
||||
STATUS="upload_document"
|
||||
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
|
||||
send_action "${1}" "$STATUS"
|
||||
sendUpload "$1" "${WHAT}" "${file}" "${CUR_URL}" "${text//\\n/$'\n'}"
|
||||
|
||||
# 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
|
||||
}
|
||||
|
||||
# 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 location
|
||||
# $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}"'"' "$ACTION_URL" &
|
||||
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}"'' "$LOCATION_URL"
|
||||
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 foursquard id
|
||||
# $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}" "$VENUE_URL"
|
||||
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"
|
||||
}
|
||||
|
||||
|
||||
|
@ -283,60 +389,67 @@ send_venue() {
|
|||
# $1 CHAT $2 from chat $3 from msg id
|
||||
forward_message() {
|
||||
[ -z "$3" ] && return
|
||||
sendJson "${1}" '"from_chat_id": '"${2}"', "message_id": '"${3}"'' "$FORWARD_URL"
|
||||
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"
|
||||
}
|
||||
forward() { # backward compatibility
|
||||
forward_message "$@" || return
|
||||
|
||||
# $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')"
|
||||
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.*//')"
|
||||
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"
|
||||
if [ -n "${no_keyboard}" ]; then
|
||||
remove_keyboard "$1" "${text}"
|
||||
sent=y
|
||||
fi
|
||||
if [ -n "$keyboard" ]; then
|
||||
if [[ "$keyboard" != *"["* ]]; then # pre 0.60 style
|
||||
if [ -n "${keyboard}" ]; then
|
||||
if [[ "${keyboard}" != *"["* ]]; then # pre 0.60 style
|
||||
keyboard="[ ${keyboard//\" \"/\" \] , \[ \"} ]"
|
||||
fi
|
||||
send_keyboard "$1" "$text" "$keyboard"
|
||||
send_keyboard "$1" "${text}" "${keyboard}"
|
||||
sent=y
|
||||
fi
|
||||
if [ -n "$btext" ] && [ -n "$burl" ]; then
|
||||
send_button "$1" "$text" "$btext" "$burl"
|
||||
if [ -n "${btext}" ] && [ -n "${burl}" ]; then
|
||||
send_button "$1" "${text}" "${btext}" "${burl}"
|
||||
sent=y
|
||||
fi
|
||||
if [ -n "$file" ]; then
|
||||
send_file "$1" "$file" "$text"
|
||||
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"
|
||||
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"
|
||||
send_location "$1" "${lat}" "${long}"
|
||||
fi
|
||||
sent=y
|
||||
fi
|
||||
if [ "$sent" != "y" ];then
|
||||
send_text_mode "$1" "$text"
|
||||
if [ "${sent}" != "y" ];then
|
||||
send_text_mode "$1" "${text}"
|
||||
fi
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
233
mycommands.sh
233
mycommands.sh
|
@ -1,83 +1,30 @@
|
|||
#!/bin/bash
|
||||
#########
|
||||
#######################################################
|
||||
#
|
||||
# files: mycommands.sh.dist
|
||||
# File: mycommands.sh.dist
|
||||
#
|
||||
# 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
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#
|
||||
|
||||
# uncomment the following lines to overwrite info and help messages
|
||||
# use ${ME} for current bot name in messages
|
||||
# Note: you must escape '_' in botname with two \ in markdown messages!
|
||||
export bashbot_info='This is @'"${ME//_/\\\\_}"', the Telegram example bot written entirely in bash.
|
||||
Edit commands and messages in mycommands.sh!
|
||||
'
|
||||
# export bashbot_help='*Available commands*:
|
||||
#'
|
||||
export res=""
|
||||
####################
|
||||
# Config has moved to bashbot.conf
|
||||
# shellcheck source=./commands.sh
|
||||
[ -r "${BASHBOT_ETC:-.}/mycommands.conf" ] && source "${BASHBOT_ETC:-.}/mycommands.conf" "$1"
|
||||
|
||||
# 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"
|
||||
|
||||
# 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"
|
||||
# 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"
|
||||
|
||||
# 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
|
||||
|
||||
##################
|
||||
# let's go ...
|
||||
if [ "$1" = "startbot" ];then
|
||||
###################
|
||||
# this section is processed on startup
|
||||
|
@ -159,12 +106,12 @@ else
|
|||
"${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 "$(getConfigKey "botadmin")"\
|
||||
[ -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 "$(getConfigKey "botadmin")"\
|
||||
[ -n "${REPORT_LEFTMEMBER}" ] && send_normal_message "${BOTADMIN}"\
|
||||
"Left member: ${CHAT[TITLE]} (${CHAT[ID]}): ${LEFTMEMBER[FIRST_NAME]} ${LEFTMEMBER[LAST_NAME]} (@${LEFTMEMBER[USERNAME]})"
|
||||
;;
|
||||
'/_migrate_group'*)
|
||||
|
@ -176,42 +123,68 @@ else
|
|||
|
||||
case "${MESSAGE}" in
|
||||
##################
|
||||
# example commands, replace thm by your own
|
||||
# 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
|
||||
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
|
||||
;;
|
||||
|
||||
'/cancel'*) # cancel interactive command
|
||||
checkproc
|
||||
if [ "$res" -gt 0 ] ;then
|
||||
if [ "${res}" -gt 0 ] ;then
|
||||
killproc && send_normal_message "${CHAT[ID]}" "Command canceled."
|
||||
else
|
||||
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."
|
||||
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 ..."
|
||||
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
|
||||
;;
|
||||
|
||||
|
@ -228,6 +201,47 @@ else
|
|||
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 (except image search ;-)
|
||||
|
@ -247,15 +261,15 @@ 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")
|
||||
"
|
||||
;;
|
||||
|
||||
|
@ -264,7 +278,7 @@ else
|
|||
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
|
||||
printf "%s\n" "${sep}"; inline_query_compose "$RANDOM" "photo" "${photo}" "${photo}"; sep=","
|
||||
printf "%s\n" "${sep}"; inline_query_compose "${RANDOM}" "photo" "${photo}" "${photo}"; sep=","
|
||||
done)
|
||||
"
|
||||
;;
|
||||
|
@ -283,9 +297,11 @@ else
|
|||
# $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\"! =========="
|
||||
[ -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() {
|
||||
|
@ -296,19 +312,48 @@ else
|
|||
return 1
|
||||
}
|
||||
|
||||
# place your processing functions here
|
||||
###########################
|
||||
# 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 "20" ] && break
|
||||
[ "${count}" -gt "20" ] && break
|
||||
image="${image#* src=\'}"; image="${image%%&pid=*}"
|
||||
[[ "${image}" = *"src="* ]] && continue
|
||||
printf "%s\n" "${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
|
||||
|
||||
|
|
|
@ -1,66 +1,31 @@
|
|||
#!/bin/bash
|
||||
########
|
||||
#######################################################
|
||||
#
|
||||
# File: mycommands.sh.clean
|
||||
#
|
||||
# files: mycommands.sh.clean
|
||||
# copy to mycommands.sh and add all your commands and functions here ...
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
# Usage: will be executed when a bot command is received
|
||||
#
|
||||
|
||||
##########
|
||||
# edit the following lines to fit your bot usage
|
||||
|
||||
export bashbot_info='This is bashbot, the Telegram bot written entirely in bash.
|
||||
'
|
||||
|
||||
export bashbot_help='*Available commands*:
|
||||
'
|
||||
export res=""
|
||||
|
||||
# Set INLINE to 1 in order to receive inline queries.
|
||||
# To enable this option in your bot must also send the /setinline command to @BotFather.
|
||||
export 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="0"
|
||||
|
||||
# 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
|
||||
# do NOT set to .* as this allow sending files from all locations!
|
||||
export FILE_REGEX="${BASHBOT_ETC}/.*"
|
||||
|
||||
# set BASHBOT_RETRY to enable retry in case of recoverable errors, e.g. throtteling
|
||||
# problems with send_,´message etc are looged to logs/ERROR.log
|
||||
unset BASHBOT_RETRY
|
||||
#export BASHBOT_RETRY="yes"
|
||||
|
||||
# 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="200"
|
||||
|
||||
# if you want to use timer functions, set BASHBOT_START_TIMER to a not empty value
|
||||
# default is to nit start timer
|
||||
unset BASHBOT_START_TIMER
|
||||
#export BASHBOT_START_TIMER="yes"
|
||||
# set to "yes" and give your bot admin privilegs to remove service messaes from groups
|
||||
export SILENCER="no"
|
||||
|
||||
# uncomment to remove keyboards sent by your bot
|
||||
# export REMOVEKEYBOARD="yes"
|
||||
# export REMOVEKEYBOARD_PRIVATE="yes"
|
||||
|
||||
########
|
||||
# special network setup may require additional ARGS to curl
|
||||
# License: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# Author: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
# 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
|
||||
#### $$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(){
|
||||
:
|
||||
|
@ -90,11 +55,13 @@ else
|
|||
[ -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"
|
||||
send_normal_message "${CHAT[ID]}" "${MESSAGE}"
|
||||
;;
|
||||
|
||||
##########
|
||||
|
@ -112,6 +79,19 @@ else
|
|||
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 !!
|
||||
|
@ -138,12 +118,25 @@ else
|
|||
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
|
||||
[ "${count}" -gt "20" ] && break
|
||||
image="${image#* src=\'}"; image="${image%%&pid=*}"
|
||||
[[ "${image}" = *"src="* ]] && continue
|
||||
printf "%s\n" "${sep}"; inline_query_compose "$RANDOM" "photo" "${image}"; sep=","
|
||||
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
|
||||
|
|
|
@ -1,12 +1,19 @@
|
|||
#!/bin/bash
|
||||
# file: interactive.sh
|
||||
# template for an interactive chat
|
||||
# test: start_proc "${CHAT[ID]}" "./scripts/interactive.sh.clean"
|
||||
########################################################################
|
||||
#
|
||||
# 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.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
########################################################################
|
||||
|
||||
######
|
||||
# parameters
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
# magic to ensure that we're always inside the root of our application,
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
# common variables
|
||||
|
@ -39,12 +39,12 @@ export SUCCESS NOSUCCESS
|
|||
NOSUCCESS=" FAILED!"
|
||||
|
||||
# default input, reference and output files
|
||||
export INPUTFILE REFFILE INPUTFILE2 REFFILE2 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"
|
||||
INPUTFILE2="${DIRME}/${REFDIR}/${REFDIR}2.input"
|
||||
REFFILE2="${DIRME}/${REFDIR}/${REFDIR}2.result"
|
||||
|
||||
# reset ENVIRONMENT
|
||||
export BASHBOT_URL TESTTOKEN BOTTOKEN BASHBOT_HOME BASHBOT_VAR BASHBOT_ETC
|
||||
|
@ -61,9 +61,9 @@ 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'
|
||||
}
|
||||
|
@ -71,12 +71,12 @@ print_array() {
|
|||
|
||||
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"
|
||||
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}"
|
||||
}
|
||||
|
||||
######
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
../dev/hooks/pre-commit.sh
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
# include common functions and definitions
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
# include common functions and definitions
|
||||
|
@ -24,7 +24,7 @@ TESTFILES="${TOKENFILE} ${ACLFILE} ${COUNTFILE} ${BLOCKEDFILE} ${ADMINFILE}"
|
|||
# run bashbot first time with init
|
||||
printf "Run bashbot init ...\n"
|
||||
"${TESTDIR}/bashbot.sh" init >"${LOGFILE}" <<EOF
|
||||
$TESTTOKEN
|
||||
${TESTTOKEN}
|
||||
nobody
|
||||
botadmin
|
||||
|
||||
|
@ -46,7 +46,7 @@ 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; }
|
||||
[ ! -x "${JSONSHFILE}" ] && { printf "%s\n" "${NOSUCCESS} json.sh not found"; exit 1; }
|
||||
|
||||
printf "Test Sourcing of bashbot.sh ...\n"
|
||||
# shellcheck source=./bashbot.sh
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env bash
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
|
||||
# include common functions and definitions
|
||||
# shellcheck source=test/ALL-tests.inc.sh
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
# include common functions and definitions
|
||||
|
@ -41,7 +41,7 @@ source <( printf 'UPD=( %s )' "$(sed <<<"${UPDATE}" -E -e 's/\t/=/g' -e 's/=(tru
|
|||
printf "Check process_inline ...\n"
|
||||
printf " ... with JsonDecode Bash\n"
|
||||
set -x
|
||||
{ process_inline "0"; set +x; } >>"${LOGFILE}" 2>&1;
|
||||
{ process_inline_query "0"; set +x; } >>"${LOGFILE}" 2>&1;
|
||||
|
||||
# output processed input
|
||||
print_array "iQUERY" >"${OUTPUTFILE}"
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
# LICENSE: WTFPLv2 http://www.wtfpl.net/txt/copying/
|
||||
# AUTHOR: KayM (gnadelwartz), kay@rrr.de
|
||||
#
|
||||
#### $$VERSION$$ v1.21-0-gc85af77
|
||||
#### $$VERSION$$ v1.52-1-g0dae2db
|
||||
#===============================================================================
|
||||
|
||||
# include common functions and definitions
|
||||
|
@ -38,34 +38,24 @@ declare -Ax UPD
|
|||
# run process_message --------------
|
||||
ARRAYS="USER CHAT REPLYTO FORWARD URLS CONTACT CAPTION LOCATION MESSAGE VENUE SERVICE NEWMEMBER LEFTMEMBER PINNED"
|
||||
|
||||
printf "Check process_message regular message...\n"
|
||||
printf "Check process_message ...\n"
|
||||
|
||||
UPDATE="$(< "${INPUTFILE}")"
|
||||
Json2Array 'UPD' <"${INPUTFILE}"
|
||||
set -x
|
||||
{ pre_process_message "0"; process_message "0"; set +x; } >>"${LOGFILE}" 2>&1;
|
||||
USER[ID]="123456789"; CHAT[ID]="123456789"
|
||||
for testfile in ${INPUTFILELIST}
|
||||
do
|
||||
printf " ... %s\n" "${testfile##*/}"
|
||||
testref="${testfile%.input}.result"
|
||||
UPDATE="$(< "${testfile}")"
|
||||
Json2Array 'UPD' <"${testfile}"
|
||||
set -x
|
||||
{ pre_process_message "0"; process_message "0"; set +x; } >>"${LOGFILE}" 2>&1;
|
||||
USER[ID]="123456789"; CHAT[ID]="123456789"
|
||||
|
||||
# output processed input
|
||||
# shellcheck disable=SC2086
|
||||
print_array ${ARRAYS} >"${OUTPUTFILE}"
|
||||
compare_sorted "${REFFILE}" "${OUTPUTFILE}" || exit 1
|
||||
# output processed input
|
||||
# shellcheck disable=SC2086
|
||||
print_array ${ARRAYS} >"${OUTPUTFILE}"
|
||||
compare_sorted "${testref}" "${OUTPUTFILE}" || exit 1
|
||||
printf "%s\n" "${SUCCESS}"
|
||||
|
||||
# run process_message ------------
|
||||
printf "Check process_message service message...\n"
|
||||
|
||||
UPDATE="$(cat "${INPUTFILE2}")"
|
||||
Json2Array 'UPD' <"${INPUTFILE2}"
|
||||
set -x
|
||||
{ pre_process_message "0"; process_message "0"; set +x; } >>"${LOGFILE}" 2>&1;
|
||||
USER[ID]="123456789"; CHAT[ID]="123456789"
|
||||
|
||||
# output processed input
|
||||
# shellcheck disable=SC2086
|
||||
print_array ${ARRAYS} >"${OUTPUTFILE}"
|
||||
compare_sorted "${REFFILE2}" "${OUTPUTFILE}" || exit 1
|
||||
|
||||
|
||||
printf "%s\n" "${SUCCESS}"
|
||||
done
|
||||
|
||||
cd "${DIRME}" || exit 1
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
["ok"] true
|
||||
["result",0,"update_id"] 123456789
|
||||
["result",0,"message","message_id"] 123456789
|
||||
["result",0,"message","from","id"] 123456789
|
||||
["result",0,"message","from","is_bot"] false
|
||||
["result",0,"message","from","first_name"] "Kay"
|
||||
["result",0,"message","from","last_name"] "M"
|
||||
["result",0,"message","from","username"] "Gnadelwartz"
|
||||
["result",0,"message","from","language_code"] "de"
|
||||
["result",0,"message","chat","id"] -123456789
|
||||
["result",0,"message","chat","title"] "Testgruppe bot only test"
|
||||
["result",0,"message","chat","type"] "group"
|
||||
["result",0,"message","chat","all_members_are_administrators"] true
|
||||
["result",0,"message","date"] 1592372719
|
||||
|
||||
["result",0,"message","left_chat_participant","id"] 123456789
|
||||
["result",0,"message","left_chat_participant","is_bot"] false
|
||||
["result",0,"message","left_chat_participant","first_name"] "Kay"
|
||||
["result",0,"message","left_chat_participant","last_name"] "M"
|
||||
["result",0,"message","left_chat_participant","username"] "Gnadelwartz"
|
||||
["result",0,"message","left_chat_member","id"] 123456789
|
||||
["result",0,"message","left_chat_member","is_bot"] false
|
||||
["result",0,"message","left_chat_member","first_name"] "Kay"
|
||||
["result",0,"message","left_chat_member","last_name"] "M"
|
||||
["result",0,"message","left_chat_member","username"] "Gnadelwartz"
|
|
@ -0,0 +1,25 @@
|
|||
USER: FIRST_NAME Kay
|
||||
USER: ID 123456789
|
||||
USER: LAST_NAME M
|
||||
USER: USERNAME Gnadelwartz
|
||||
CHAT: ALL_ADMIN true
|
||||
CHAT: FIRST_NAME
|
||||
CHAT: ID 123456789
|
||||
CHAT: LAST_NAME
|
||||
CHAT: TITLE Testgruppe bot only test
|
||||
CHAT: TYPE group
|
||||
CHAT: USERNAME
|
||||
CAPTION: 0
|
||||
LOCATION: LATITUDE
|
||||
LOCATION: LONGITUDE
|
||||
MESSAGE: 0 /_left_chat_member Kay M
|
||||
MESSAGE: CAPTION
|
||||
MESSAGE: DICE
|
||||
MESSAGE: ID 123456789
|
||||
SERVICE: 0 yes
|
||||
SERVICE: LEFTMEMBER 123456789
|
||||
LEFTMEMBER: FIRST_NAME Kay
|
||||
LEFTMEMBER: ID
|
||||
LEFTMEMBER: ISBOT false
|
||||
LEFTMEMBER: LAST_NAME M
|
||||
LEFTMEMBER: USERNAME Kay M
|
|
@ -31,11 +31,13 @@ CONTACT: LAST_NAME Pannenhilfe
|
|||
CONTACT: NUMBER 222222
|
||||
CONTACT: USER_ID
|
||||
CONTACT: VCARD BEGIN:VCARD\nVERSION:2.1\nN:Pannenhilfe;ADAC;;;\nFN:ADAC Pannenhilfe\nTEL;CELL;PREF:+49179222222\nTEL;X-Mobil:222222\nEND:VCARD
|
||||
CAPTION: 0
|
||||
CAPTION: 0 Myproteine kein spell check
|
||||
LOCATION: LATITUDE 49.631824
|
||||
LOCATION: LONGITUDE 8.377072
|
||||
MESSAGE: 0 😂😝👌☺❤😕😈#⃣🌏🎉🙊🙉☕🚀✈🚂💯✔〽🔚
|
||||
MESSAGE: ID 6541
|
||||
MESSAGE: CAPTION Myproteine kein spell check
|
||||
MESSAGE: DICE
|
||||
VENUE: ADDRESS Am Rhein 1
|
||||
VENUE: FOURSQUARE 4c4321afce54e21eee980d1a
|
||||
VENUE: LATITUDE 49.631824
|
|
@ -89,3 +89,7 @@
|
|||
["result",0,"message","voice","duration"] 2
|
||||
["result",0,"message","voice","mime_type"] "audio/ogg"
|
||||
["result",0,"message","voice","file_size"] 4262
|
||||
["result",0,"message","caption"] "Myproteine kein spell check"
|
||||
["result","dice","emoji"] "\ud83c\udfb2"
|
||||
["result","dice","value"] 5
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
USER: FIRST_NAME Kay
|
||||
USER: ID 123456789
|
||||
USER: LAST_NAME M
|
||||
USER: USERNAME Gnadelwartz
|
||||
CHAT: ALL_ADMIN
|
||||
CHAT: FIRST_NAME Test
|
||||
CHAT: ID 123456789
|
||||
CHAT: LAST_NAME Bot
|
||||
CHAT: TITLE BotTestTitle
|
||||
CHAT: TYPE private
|
||||
CHAT: USERNAME BotTest
|
||||
REPLYTO: 0 Ich bin der Deal-O-Mat Bot. Für eine Liste der Befehle sende /help
|
||||
REPLYTO: FIRST_NAME dealzbot
|
||||
REPLYTO: ID 6542
|
||||
REPLYTO: LAST_NAME
|
||||
REPLYTO: UID 987654321
|
||||
REPLYTO: USERNAME Deal_O_Mat_bot
|
||||
FORWARD: FIRST_NAME Kay
|
||||
FORWARD: ID 6541
|
||||
FORWARD: LAST_NAME M
|
||||
FORWARD: UID 123456789
|
||||
FORWARD: USERNAME Gnadelwartz
|
||||
URLS: AUDIO audio-AgADAgADL6oxG-Gw4EndCWGl2WUfUo1pXw8ABOusSilDGzAYa
|
||||
URLS: DOCUMENT document-AgADAgADL6oxG-Gw4EndCWGl2WUfUo1pXw8ABOusSilDGzAYa
|
||||
URLS: PHOTO photo-AgADAgADL6oxG-Gw4EndCWGl2WUfUo1pXw8ABOusSilDGzAYa
|
||||
URLS: STICKER sticker-AgADAgADL6oxG-Gw4EndCWGl2WUfUo1pXw8ABOusSilDGzAYa
|
||||
URLS: VIDEO video-AgADAgADL6oxG-Gw4EndCWGl2WUfUo1pXw8ABOusSilDGzAYa
|
||||
URLS: VOICE voice-AgADAgADL6oxG-Gw4EndCWGl2WUfUo1pXw8ABOusSilDGzAYa
|
||||
CONTACT: FIRST_NAME ADAC
|
||||
CONTACT: LAST_NAME Pannenhilfe
|
||||
CONTACT: NUMBER 222222
|
||||
CONTACT: USER_ID
|
||||
CONTACT: VCARD BEGIN:VCARD\nVERSION:2.1\nN:Pannenhilfe;ADAC;;;\nFN:ADAC Pannenhilfe\nTEL;CELL;PREF:+49179222222\nTEL;X-Mobil:222222\nEND:VCARD
|
||||
CAPTION: 0 Myproteine kein spell check
|
||||
LOCATION: LATITUDE 49.631824
|
||||
LOCATION: LONGITUDE 8.377072
|
||||
MESSAGE: 0 😂😝👌☺❤😕😈#⃣🌏🎉🙊🙉☕🚀✈🚂💯✔〽🔚
|
||||
MESSAGE: CAPTION Myproteine kein spell check
|
||||
MESSAGE: DICE
|
||||
MESSAGE: ID 6541
|
||||
VENUE: ADDRESS Am Rhein 1
|
||||
VENUE: FOURSQUARE 4c4321afce54e21eee980d1a
|
||||
VENUE: LATITUDE 49.631824
|
||||
VENUE: LONGITUDE 8.377072
|
||||
VENUE: TITLE Kolb's Biergarten
|
|
@ -0,0 +1,25 @@
|
|||
["ok"] true
|
||||
["result",0,"update_id"] 123456789
|
||||
["result",0,"message","message_id"] 123456789
|
||||
["result",0,"message","from","id"] 123456789
|
||||
["result",0,"message","from","is_bot"] false
|
||||
["result",0,"message","from","first_name"] "Kay"
|
||||
["result",0,"message","from","last_name"] "M"
|
||||
["result",0,"message","from","username"] "Gnadelwartz"
|
||||
["result",0,"message","from","language_code"] "de"
|
||||
["result",0,"message","chat","id"] -123456789
|
||||
["result",0,"message","chat","title"] "Testgruppe bot only test"
|
||||
["result",0,"message","chat","type"] "group"
|
||||
["result",0,"message","chat","all_members_are_administrators"] true
|
||||
["result",0,"message","date"] 1592372719
|
||||
|
||||
["result",0,"message","new_chat_participant","id"] 123456789
|
||||
["result",0,"message","new_chat_participant","is_bot"] false
|
||||
["result",0,"message","new_chat_participant","first_name"] "Kay"
|
||||
["result",0,"message","new_chat_participant","last_name"] "M"
|
||||
["result",0,"message","new_chat_participant","username"] "Gnadelwartz"
|
||||
["result",0,"message","new_chat_member","id"] 123456789
|
||||
["result",0,"message","new_chat_member","is_bot"] false
|
||||
["result",0,"message","new_chat_member","first_name"] "Kay"
|
||||
["result",0,"message","new_chat_member","last_name"] "M"
|
||||
["result",0,"message","new_chat_member","username"] "Gnadelwartz"
|
|
@ -13,21 +13,15 @@ CAPTION: 0
|
|||
LOCATION: LATITUDE
|
||||
LOCATION: LONGITUDE
|
||||
MESSAGE: 0 /_new_chat_member 123456789 Gnadelwartz
|
||||
MESSAGE: CAPTION
|
||||
MESSAGE: DICE
|
||||
MESSAGE: ID 123456789
|
||||
SERVICE: 0 yes
|
||||
SERVICE: LEFTMEMBER 123456789
|
||||
SERVICE: NEWMEMBER 123456789
|
||||
SERVICE: NEWPHOTO AgACAgIAAxkBAAEBFute6a3vIpB99vim811hxeu2tyQWfwACrKwxG0TMUUtDBH10RqlzGCukupIuAAMBAAMCAANhAAM3SAMAARoE
|
||||
SERVICE: NEWTITLE new Testgruppe bot only
|
||||
SERVICE: PINNED 3022
|
||||
SERVICE: NEWPHOTO
|
||||
SERVICE: NEWTITLE
|
||||
NEWMEMBER: FIRST_NAME Kay
|
||||
NEWMEMBER: ID 123456789
|
||||
NEWMEMBER: ISBOT false
|
||||
NEWMEMBER: LAST_NAME M
|
||||
NEWMEMBER: USERNAME Gnadelwartz
|
||||
LEFTMEMBER: FIRST_NAME Kay
|
||||
LEFTMEMBER: ID
|
||||
LEFTMEMBER: ISBOT false
|
||||
LEFTMEMBER: LAST_NAME M
|
||||
PINNED: ID 3022
|
||||
PINNED: MESSAGE new pinned Message
|
|
@ -0,0 +1,30 @@
|
|||
["ok"] true
|
||||
["result",0,"update_id"] 123456789
|
||||
["result",0,"message","message_id"] 123456789
|
||||
["result",0,"message","from","id"] 123456789
|
||||
["result",0,"message","from","is_bot"] false
|
||||
["result",0,"message","from","first_name"] "Kay"
|
||||
["result",0,"message","from","last_name"] "M"
|
||||
["result",0,"message","from","username"] "Gnadelwartz"
|
||||
["result",0,"message","from","language_code"] "de"
|
||||
["result",0,"message","chat","id"] -123456789
|
||||
["result",0,"message","chat","title"] "Testgruppe bot only test"
|
||||
["result",0,"message","chat","type"] "group"
|
||||
["result",0,"message","chat","all_members_are_administrators"] true
|
||||
["result",0,"message","date"] 1592372719
|
||||
|
||||
["result",0,"message","new_chat_photo",0,"file_id"] "AgACAgIAAxkBAAEBFute6a3vIpB99vim811hxeu2tyQWfwACrKwxG0TMUUtDBH10RqlzGCukupIuAAMBAAMCAANhAAM3SAMAARoE"
|
||||
["result",0,"message","new_chat_photo",0,"file_unique_id"] "AQADK6S6ki4AAzdIAwAB"
|
||||
["result",0,"message","new_chat_photo",0,"file_size"] 5939
|
||||
["result",0,"message","new_chat_photo",0,"width"] 160
|
||||
["result",0,"message","new_chat_photo",0,"height"] 160
|
||||
["result",0,"message","new_chat_photo",1,"file_id"] "AgACAgIAAxkBAAEBFute6a3vIpB99vim811hxeu2tyQWfwACrKwxG0TMUUtDBH10RqlzGCukupIuAAMBAAMCAANiAAM4SAMAARoE"
|
||||
["result",0,"message","new_chat_photo",1,"file_unique_id"] "AQADK6S6ki4AAzhIAwAB"
|
||||
["result",0,"message","new_chat_photo",1,"file_size"] 14124
|
||||
["result",0,"message","new_chat_photo",1,"width"] 320
|
||||
["result",0,"message","new_chat_photo",1,"height"] 320
|
||||
["result",0,"message","new_chat_photo",2,"file_id"] "AgACAgIAAxkBAAEBFute6a3vIpB99vim811hxeu2tyQWfwACrKwxG0TMUUtDBH10RqlzGCukupIuAAMBAAMCAANjAAM5SAMAARoE"
|
||||
["result",0,"message","new_chat_photo",2,"file_unique_id"] "AQADK6S6ki4AAzlIAwAB"
|
||||
["result",0,"message","new_chat_photo",2,"file_size"] 34052
|
||||
["result",0,"message","new_chat_photo",2,"width"] 640
|
||||
["result",0,"message","new_chat_photo",2,"height"] 640
|
|
@ -0,0 +1,21 @@
|
|||
USER: FIRST_NAME Kay
|
||||
USER: ID 123456789
|
||||
USER: LAST_NAME M
|
||||
USER: USERNAME Gnadelwartz
|
||||
CHAT: ALL_ADMIN true
|
||||
CHAT: FIRST_NAME
|
||||
CHAT: ID 123456789
|
||||
CHAT: LAST_NAME
|
||||
CHAT: TITLE Testgruppe bot only test
|
||||
CHAT: TYPE group
|
||||
CHAT: USERNAME
|
||||
CAPTION: 0
|
||||
LOCATION: LATITUDE
|
||||
LOCATION: LONGITUDE
|
||||
MESSAGE: 0 /_new_chat_photo 123456789 AgACAgIAAxkBAAEBFute6a3vIpB99vim811hxeu2tyQWfwACrKwxG0TMUUtDBH10RqlzGCukupIuAAMBAAMCAANhAAM3SAMAARoE
|
||||
MESSAGE: CAPTION
|
||||
MESSAGE: DICE
|
||||
MESSAGE: ID 123456789
|
||||
SERVICE: 0 yes
|
||||
SERVICE: NEWPHOTO AgACAgIAAxkBAAEBFute6a3vIpB99vim811hxeu2tyQWfwACrKwxG0TMUUtDBH10RqlzGCukupIuAAMBAAMCAANhAAM3SAMAARoE
|
||||
SERVICE: NEWTITLE
|
|
@ -0,0 +1,16 @@
|
|||
["ok"] true
|
||||
["result",0,"update_id"] 123456789
|
||||
["result",0,"message","message_id"] 123456789
|
||||
["result",0,"message","from","id"] 123456789
|
||||
["result",0,"message","from","is_bot"] false
|
||||
["result",0,"message","from","first_name"] "Kay"
|
||||
["result",0,"message","from","last_name"] "M"
|
||||
["result",0,"message","from","username"] "Gnadelwartz"
|
||||
["result",0,"message","from","language_code"] "de"
|
||||
["result",0,"message","chat","id"] -123456789
|
||||
["result",0,"message","chat","title"] "Testgruppe bot only test"
|
||||
["result",0,"message","chat","type"] "group"
|
||||
["result",0,"message","chat","all_members_are_administrators"] true
|
||||
["result",0,"message","date"] 1592372719
|
||||
|
||||
["result",0,"message","new_chat_title"] "new Testgruppe bot only"
|
|
@ -0,0 +1,21 @@
|
|||
USER: FIRST_NAME Kay
|
||||
USER: ID 123456789
|
||||
USER: LAST_NAME M
|
||||
USER: USERNAME Gnadelwartz
|
||||
CHAT: ALL_ADMIN true
|
||||
CHAT: FIRST_NAME
|
||||
CHAT: ID 123456789
|
||||
CHAT: LAST_NAME
|
||||
CHAT: TITLE Testgruppe bot only test
|
||||
CHAT: TYPE group
|
||||
CHAT: USERNAME
|
||||
CAPTION: 0
|
||||
LOCATION: LATITUDE
|
||||
LOCATION: LONGITUDE
|
||||
MESSAGE: 0 /_new_chat_title 123456789 new Testgruppe bot only
|
||||
MESSAGE: CAPTION
|
||||
MESSAGE: DICE
|
||||
MESSAGE: ID 123456789
|
||||
SERVICE: 0 yes
|
||||
SERVICE: NEWPHOTO
|
||||
SERVICE: NEWTITLE new Testgruppe bot only
|
|
@ -0,0 +1,27 @@
|
|||
["ok"] true
|
||||
["result",0,"update_id"] 123456789
|
||||
["result",0,"message","message_id"] 123456789
|
||||
["result",0,"message","from","id"] 123456789
|
||||
["result",0,"message","from","is_bot"] false
|
||||
["result",0,"message","from","first_name"] "Kay"
|
||||
["result",0,"message","from","last_name"] "M"
|
||||
["result",0,"message","from","username"] "Gnadelwartz"
|
||||
["result",0,"message","from","language_code"] "de"
|
||||
["result",0,"message","chat","id"] -123456789
|
||||
["result",0,"message","chat","title"] "Testgruppe bot only test"
|
||||
["result",0,"message","chat","type"] "group"
|
||||
["result",0,"message","chat","all_members_are_administrators"] true
|
||||
["result",0,"message","date"] 1592372719
|
||||
|
||||
["result",0,"message","pinned_message","message_id"] 3022
|
||||
["result",0,"message","pinned_message","from","id"] 796814662
|
||||
["result",0,"message","pinned_message","from","is_bot"] true
|
||||
["result",0,"message","pinned_message","from","first_name"] "DealOMat"
|
||||
["result",0,"message","pinned_message","from","username"] "Deal_O_Mat_bot"
|
||||
["result",0,"message","pinned_message","chat","id"] -1001220313778
|
||||
["result",0,"message","pinned_message","chat","title"] "Testgruppe bot only test"
|
||||
["result",0,"message","pinned_message","chat","type"] "supergroup"
|
||||
["result",0,"message","pinned_message","date"] 1593121152
|
||||
["result",0,"message","pinned_message","text"] "new pinned Message"
|
||||
|
||||
["result",0,"message","new_chat_title"] "new Testgruppe bot only"
|
|
@ -0,0 +1,24 @@
|
|||
USER: FIRST_NAME Kay
|
||||
USER: ID 123456789
|
||||
USER: LAST_NAME M
|
||||
USER: USERNAME Gnadelwartz
|
||||
CHAT: ALL_ADMIN true
|
||||
CHAT: FIRST_NAME
|
||||
CHAT: ID 123456789
|
||||
CHAT: LAST_NAME
|
||||
CHAT: TITLE Testgruppe bot only test
|
||||
CHAT: TYPE group
|
||||
CHAT: USERNAME
|
||||
CAPTION: 0
|
||||
LOCATION: LATITUDE
|
||||
LOCATION: LONGITUDE
|
||||
MESSAGE: 0 /_new_pinned_message 123456789 3022 new pinned Message
|
||||
MESSAGE: CAPTION
|
||||
MESSAGE: DICE
|
||||
MESSAGE: ID 123456789
|
||||
SERVICE: 0 yes
|
||||
SERVICE: NEWPHOTO
|
||||
SERVICE: NEWTITLE new Testgruppe bot only
|
||||
SERVICE: PINNED 3022
|
||||
PINNED: ID 3022
|
||||
PINNED: MESSAGE new pinned Message
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue