mirror of
https://github.com/python-telegram-bot/python-telegram-bot.git
synced 2026-06-19 15:45:13 +00:00
Compare commits
713 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d028d4edd0 | |||
| 4d770843cc | |||
| 53de38f6c9 | |||
| be105a2d4a | |||
| ac55ba007e | |||
| 6bdca1e4f8 | |||
| fd7b571e92 | |||
| 9243cd3507 | |||
| 1b09738191 | |||
| 836c50965a | |||
| 1d9d0fc764 | |||
| e57e6dd645 | |||
| 49122d6a99 | |||
| d445d35ceb | |||
| 703b8d1301 | |||
| 46993d5f2d | |||
| 880746baed | |||
| 8ad1f330ea | |||
| 56b1d4f5ce | |||
| df16846d80 | |||
| 3ac9a1cd71 | |||
| 4d8174edc3 | |||
| 235bb72702 | |||
| 9a5ccb1c2d | |||
| a18640a8d3 | |||
| fdc3ac0cc5 | |||
| d881fa6a5f | |||
| c551d71735 | |||
| bee3d881d1 | |||
| 6ec81dd552 | |||
| 6e9f30ca6e | |||
| 252cafb04c | |||
| d4f7b7165c | |||
| 0ed5e8e1a3 | |||
| 335813a11a | |||
| 10a98211f8 | |||
| b5570ddfa5 | |||
| 99c9544a27 | |||
| 0e0611767a | |||
| 4ba5fbf4f5 | |||
| 4b0be65a76 | |||
| 5971cb35f8 | |||
| 6e5302c089 | |||
| 5aab4525c2 | |||
| 62c651d167 | |||
| 41e457f5ed | |||
| 4ce0ab53d0 | |||
| d940afa718 | |||
| a327e9d6ff | |||
| 5e5510d42b | |||
| 73c60ee817 | |||
| 474d5f0c9f | |||
| 74a2baf03d | |||
| 0612385233 | |||
| c0489db17c | |||
| 592352c849 | |||
| 9d367e9f2c | |||
| d86ca30601 | |||
| ec15e866be | |||
| 998040da92 | |||
| 0c74b3cfb9 | |||
| 0ca3ef7a38 | |||
| e160355190 | |||
| d80e0b4b8c | |||
| 96d98084c7 | |||
| 865bba3f3e | |||
| 2745023854 | |||
| fd15e51e28 | |||
| d093506ef2 | |||
| 7f463131aa | |||
| a79f636345 | |||
| 4a4dbcdbf8 | |||
| 7b13adb34b | |||
| e905f310c4 | |||
| 631c825c1d | |||
| ed7ecddb8d | |||
| a3dae1f112 | |||
| 1d33c39a1b | |||
| 14d3f62e44 | |||
| 931b22f49e | |||
| f0aafda1b9 | |||
| ecb6ddd83d | |||
| cb46b0373f | |||
| 35f6de326b | |||
| a686db2c6f | |||
| 1f29093027 | |||
| 0e34c0395f | |||
| 49385493f4 | |||
| f107070db2 | |||
| 3f28633e79 | |||
| 8ff8d57998 | |||
| e9a782a3c8 | |||
| 1f83e7ae4e | |||
| 856f4460fc | |||
| c5ad34b074 | |||
| 78d1faa21e | |||
| 4ac8f86156 | |||
| 8a087dce69 | |||
| 82282ae125 | |||
| 02243f6fda | |||
| 05a90dc3bc | |||
| 1425533871 | |||
| 186db99565 | |||
| 835c4d04c1 | |||
| 5b867b2290 | |||
| ff66a9fa21 | |||
| 3189d4d339 | |||
| d66493b038 | |||
| eca5f66cd6 | |||
| f7aec236e7 | |||
| fc7c161018 | |||
| c0d63deae3 | |||
| f152195a68 | |||
| b2fd2ba697 | |||
| d21ee819b7 | |||
| d3cec77e78 | |||
| 94e35d5b1c | |||
| 39ba575a4d | |||
| 87ac962805 | |||
| 01cca924ca | |||
| 14cb13acfd | |||
| 4ecb4911db | |||
| d47787876a | |||
| 4b173bfd52 | |||
| bfbad1625e | |||
| 564baea8c3 | |||
| adc3104214 | |||
| 2f7cccfc9f | |||
| 5a7a62c3d8 | |||
| ca1fff25f7 | |||
| 0d6b3a5411 | |||
| 6cacea96f7 | |||
| 4775107af0 | |||
| fe06708d34 | |||
| 6390b7fd9b | |||
| 2160ce70a6 | |||
| 5e5125444c | |||
| f86e6f97db | |||
| 325d8131ee | |||
| f68b8c3a4a | |||
| 7c8a0e00c0 | |||
| 4c0737d7c1 | |||
| 5dd95f1968 | |||
| b30417681b | |||
| 37e48b4707 | |||
| 9e306dce16 | |||
| 9b1a55f9e9 | |||
| 252abb138d | |||
| 203364d939 | |||
| 1450478d27 | |||
| 5b36a85e63 | |||
| 7daf26198e | |||
| 8c0de59d46 | |||
| d46d9a711d | |||
| b444cd7bce | |||
| 93e15fa9f8 | |||
| d383c10d4e | |||
| 012bbe1307 | |||
| 4faa4774bd | |||
| cb79317354 | |||
| cfdfdeb4fc | |||
| 67a2d31edf | |||
| 0669c72fe3 | |||
| 185c40da79 | |||
| 5315e072cb | |||
| a8255e4f51 | |||
| e56c6dfab6 | |||
| 263310be36 | |||
| 720c4d22d8 | |||
| 3be8b9ecb9 | |||
| bb36c725af | |||
| ba7e1cada7 | |||
| 9bf5da5ed3 | |||
| c0dd9c6ffc | |||
| 10a96481f5 | |||
| 9a96ad8efd | |||
| fc277d7393 | |||
| 48eb623f15 | |||
| 9a340d2ea9 | |||
| 693df6dc2c | |||
| a98919a86e | |||
| 9790d6d8dc | |||
| 7913d09295 | |||
| 1db337fe2b | |||
| b40a59f509 | |||
| 0d9d5032ef | |||
| de5619f3ca | |||
| b6fceefc80 | |||
| 687a3b0ba1 | |||
| bf5ba9a369 | |||
| d879a0d018 | |||
| ad211655ea | |||
| 3a0eb588cb | |||
| c9bfa71ff9 | |||
| 5f19452dd7 | |||
| 5cccf2603b | |||
| 185b080daa | |||
| cb99341848 | |||
| 1544f612ae | |||
| 53d1d5f589 | |||
| 6992a7a369 | |||
| a846c8fd86 | |||
| 0e5129e59f | |||
| 90576de9e2 | |||
| 79ca07f839 | |||
| 63c793aad4 | |||
| 5e80efaa54 | |||
| a114f70249 | |||
| 31fba47829 | |||
| 360c3077ea | |||
| f2a92ccf46 | |||
| dd8f94885a | |||
| 06ec465c5f | |||
| 79228b0655 | |||
| b2045717d6 | |||
| 15cc410c10 | |||
| f6524b0207 | |||
| ecc86d4bcd | |||
| 56b17f2a17 | |||
| 8bf4a6fdda | |||
| 109af62425 | |||
| ec27edef58 | |||
| 7231eaa349 | |||
| 1876867ec7 | |||
| 17509fc24f | |||
| 2d2b269932 | |||
| 802a74c606 | |||
| c4074f740e | |||
| 1e0ee0694f | |||
| 6a7c0bb584 | |||
| fb2fc3842b | |||
| c794c3520b | |||
| 0fd013feec | |||
| 1834d6c754 | |||
| f51564f7cd | |||
| 624160e1db | |||
| d2f2b74bdb | |||
| 85f1b1af0c | |||
| 6cb177d2a7 | |||
| b5cbf17ef5 | |||
| 0d0ad1334c | |||
| b9305ca7ac | |||
| 0e21609382 | |||
| 95fde0c6c4 | |||
| 884bb41d4a | |||
| a9b305edd0 | |||
| 1e19084a0d | |||
| e179b27f57 | |||
| 8b95f9cbeb | |||
| 390184f605 | |||
| 086fa1251c | |||
| 60f9aede07 | |||
| c411ef7822 | |||
| e1de7220df | |||
| 429ea92254 | |||
| 751402a0d3 | |||
| 2af15cadd6 | |||
| 93e19dc2ae | |||
| c2f5309cbf | |||
| 1657e43904 | |||
| 23eba8a24e | |||
| ed170e1595 | |||
| 46ca28f01c | |||
| b99518e8b8 | |||
| 62045316fe | |||
| 736d62e20d | |||
| 68dca31f15 | |||
| 9a523dbc40 | |||
| 0342a5b30b | |||
| b7f83cf375 | |||
| d9d48f5c91 | |||
| 01b90e7ede | |||
| ba0ea4f268 | |||
| a0788788da | |||
| a264530540 | |||
| 33f047a3dc | |||
| 88eb332c99 | |||
| eb6bafc003 | |||
| f4603831b8 | |||
| b41e1ab127 | |||
| 5c71ebce52 | |||
| 6db377d56d | |||
| da193711b1 | |||
| 4f26bdd18f | |||
| 808945b623 | |||
| 63a83d4cc2 | |||
| c43b348117 | |||
| 45a47d54bd | |||
| 5e7f2688be | |||
| 7199d2894f | |||
| d9a58fd904 | |||
| cf9897e74b | |||
| 30308bdcc6 | |||
| af62c5be8e | |||
| cd7bc8dfac | |||
| 150914cf25 | |||
| 19390b9659 | |||
| fac4eb6438 | |||
| 2939885c5b | |||
| f07f33e160 | |||
| 0ddcb16889 | |||
| 594b81e463 | |||
| 41d0d45e2f | |||
| 1e4ae6546f | |||
| fd170773e2 | |||
| d1516f66ac | |||
| 739e218eb7 | |||
| dcea2c8015 | |||
| 98112d3987 | |||
| 45a4689fd0 | |||
| 82030c4109 | |||
| 25595e6d9e | |||
| 9637a8748c | |||
| 00e2b4815a | |||
| fb34f81533 | |||
| 3d89f6b284 | |||
| 7a8e84b46f | |||
| 8ad34fc3c0 | |||
| 00f4328bab | |||
| 8b196ce71f | |||
| 196d1fcc3d | |||
| 7ff7397d0f | |||
| 0c676b1a75 | |||
| dc9b77e02c | |||
| e7b339d527 | |||
| 5958da0031 | |||
| 0600b2634e | |||
| f8f16f0fe9 | |||
| 433110abe9 | |||
| 793437fec7 | |||
| a0a040a9c2 | |||
| f0e7a3316c | |||
| 218e22631c | |||
| 75c6662f35 | |||
| cd42524fd4 | |||
| b5875a3abd | |||
| 139cbc657d | |||
| 4aca4d1d1f | |||
| 2e6db1330f | |||
| ccb24d1288 | |||
| 26f87c4873 | |||
| fc618274ae | |||
| d2623d2671 | |||
| ec8cd37345 | |||
| ee56ffc9a5 | |||
| ca8404adb7 | |||
| d5b35e7e1d | |||
| df8e388189 | |||
| a2632b777a | |||
| e0cf0abb1b | |||
| ec13a36bdd | |||
| d05fa1275a | |||
| e189e8ad05 | |||
| efd10507d0 | |||
| 2338377eda | |||
| ca526fba73 | |||
| e2cc8db992 | |||
| 04c86813b3 | |||
| 7d39e1bdef | |||
| d415a60ebf | |||
| fd7baa2236 | |||
| 4945d99de6 | |||
| c103c05679 | |||
| 8afea8cd69 | |||
| 9d77a3b503 | |||
| 3e978277b3 | |||
| d02e656700 | |||
| edf4e8abbe | |||
| c55c5408b1 | |||
| d1dc32d849 | |||
| fc73948c82 | |||
| 70dfb88eb5 | |||
| 2a01292a64 | |||
| 5b9ec7ff40 | |||
| bec81b5c3b | |||
| f5a1e00af9 | |||
| eac3d8842d | |||
| 17ac73c3c4 | |||
| 4a5001668d | |||
| 7ebbc60694 | |||
| 9c81b810f2 | |||
| e8363f2440 | |||
| e82ae432f7 | |||
| d4beb94059 | |||
| 029705e0af | |||
| 2859a8873f | |||
| e5df2072e4 | |||
| 034d0054ea | |||
| 0edb2e0a0f | |||
| 2436cab2e5 | |||
| 3e7dc705db | |||
| cabbef8780 | |||
| 08836c60ca | |||
| 6d2e159d75 | |||
| 8d94c14504 | |||
| 69183d85f7 | |||
| 142cc6e6ad | |||
| d4370e49e5 | |||
| df1d639144 | |||
| c13af4d61d | |||
| 516d41eac0 | |||
| 702544f709 | |||
| 713f0d1335 | |||
| a383cee558 | |||
| 44645d2cc6 | |||
| 77f00e386c | |||
| 1000a56e0d | |||
| c3bca9af48 | |||
| 9eec34edd1 | |||
| 383a2d3742 | |||
| d1e4eeaf30 | |||
| 80b53f1ab7 | |||
| 0faa38b8af | |||
| 5a2a541ae0 | |||
| 7508c2f8bf | |||
| bb2cce56a3 | |||
| 2c12bd6775 | |||
| 5b05bcc8f2 | |||
| adb446abf6 | |||
| 545767ea40 | |||
| 7931045bf3 | |||
| 17c2857622 | |||
| cbcbfab45f | |||
| 1dc9907a70 | |||
| b8c9992eff | |||
| fe26c94440 | |||
| a6650de93d | |||
| dc032b349c | |||
| 5c2458bfd8 | |||
| 6166e7f07a | |||
| 2a7b03e7c2 | |||
| da97c1741c | |||
| 70445dc054 | |||
| d3a02405b2 | |||
| dfc75cc64e | |||
| 332667c98b | |||
| f71c40e0b8 | |||
| 9f55c15cc7 | |||
| a32ae8b895 | |||
| a539a0c3a5 | |||
| b4abf75524 | |||
| 12d71d5a91 | |||
| 48bf6bfab0 | |||
| 7227ca3aab | |||
| 307d2621d7 | |||
| 831a0a31e5 | |||
| d10b657521 | |||
| ef1012b722 | |||
| 5fd7a4fe0d | |||
| 85d20ba549 | |||
| 48c1673d7c | |||
| af6eb457c1 | |||
| 6ece89bc56 | |||
| c69cdfd184 | |||
| 6dab7068c3 | |||
| fd90c16265 | |||
| 77ca036d02 | |||
| e2e98e86db | |||
| 71f82d57d9 | |||
| 6a3d514ed1 | |||
| 6aa2e510a3 | |||
| 099deabf4e | |||
| b78ceeed10 | |||
| a8240dca1f | |||
| 7e207433cc | |||
| fc6d0f4f07 | |||
| 4fef5bcceb | |||
| fc64cc0a4a | |||
| 14a9962296 | |||
| 4197400853 | |||
| aa8966832b | |||
| e27427676d | |||
| 8175fd7b53 | |||
| 2875bae881 | |||
| c756aa1c02 | |||
| 6d5c3187fc | |||
| c2f04331f3 | |||
| 5293ec49ff | |||
| 9319903343 | |||
| 95e2aad9bd | |||
| 73f4f26da5 | |||
| 24b2bf335c | |||
| fc3fa0f515 | |||
| 87657bcd70 | |||
| 81b58c7d00 | |||
| dd7d1255d1 | |||
| f813d4f5ec | |||
| 623863cee1 | |||
| aa125e59fb | |||
| 68c844df0c | |||
| 3779d454f3 | |||
| 5d168bd479 | |||
| 1c8bb21790 | |||
| 054c976ad6 | |||
| bc2679f2ae | |||
| 17dae68654 | |||
| 7734c1d6a6 | |||
| aeca3ca174 | |||
| 21fdaa4ff7 | |||
| 79f29c4b9e | |||
| a2d8ca3663 | |||
| 6f76bfc2de | |||
| 97ebebefc1 | |||
| 119743433d | |||
| b0ad07f30f | |||
| 114cb787ea | |||
| 5d1ef673a3 | |||
| 3e1cb08567 | |||
| 29a4062945 | |||
| 2ff6fe9901 | |||
| 34b91f5062 | |||
| cc6c4a6eb9 | |||
| fc9456e1a8 | |||
| 41ba57f064 | |||
| b205751aee | |||
| c4f13bd1bb | |||
| 7d7397317e | |||
| 631954e5d9 | |||
| 90ed128a61 | |||
| 2a2b679362 | |||
| f75e329225 | |||
| ea7c54ba07 | |||
| 3c7b037eaa | |||
| c15a1bc151 | |||
| 9e7314134e | |||
| 37271e4a02 | |||
| 0e78606d37 | |||
| cb0736fb3d | |||
| e0233a59a0 | |||
| 6e158042e1 | |||
| d791a6ee89 | |||
| 5a3e142358 | |||
| 37a58fe1ad | |||
| 80281cc66d | |||
| fffa9d8a7c | |||
| 806b71030f | |||
| 764c5dac53 | |||
| 007dc5807a | |||
| 16534872a7 | |||
| a13245dfbf | |||
| 6622ea3ec0 | |||
| bcadfc5398 | |||
| 89ecb04a85 | |||
| 56ab40d94f | |||
| f5ac1ae067 | |||
| 23507202e8 | |||
| 185bff7117 | |||
| 9f07900d99 | |||
| 809fe4b74f | |||
| 8a4d5c5de7 | |||
| 1976822dd0 | |||
| e60694a8cc | |||
| 14b4c1ac62 | |||
| d5890d403b | |||
| ef569b68c6 | |||
| 628a4c4eac | |||
| 83d2ca3aa7 | |||
| 29cdfe671e | |||
| f21b6046c5 | |||
| 8090658ab4 | |||
| f49f592f0d | |||
| c2853fa1ef | |||
| e1f3f346bc | |||
| 1005ad57ce | |||
| 0b72acc7c8 | |||
| 8d267ed896 | |||
| 83812f3af6 | |||
| 658b5ff1c0 | |||
| 593153128c | |||
| d91f210f7c | |||
| 65177e791f | |||
| 15501e185b | |||
| 1782d0d19b | |||
| 88fbf3b5cf | |||
| c7a1d8dca3 | |||
| 3e732a0736 | |||
| 628e1b743a | |||
| e4de3f00b8 | |||
| 32c021fdd5 | |||
| a6e5a71e05 | |||
| 4d87e236be | |||
| 29ab0556f0 | |||
| fca8aee177 | |||
| 6a80a33aef | |||
| 7c9928c58f | |||
| 0cd7aa92ae | |||
| 6626d4534e | |||
| 6b309397e8 | |||
| 618df51811 | |||
| d38add1a1c | |||
| 1c7e784662 | |||
| 0006294f29 | |||
| c1f194a310 | |||
| cccd6e5baf | |||
| a0baa68cf3 | |||
| 62b79df0a4 | |||
| 1246039872 | |||
| ed6dd76ae8 | |||
| 70de2bd3f1 | |||
| 8bde310ec7 | |||
| be368f7d74 | |||
| 9defc41774 | |||
| ee8b78aa0d | |||
| 0b8fd24771 | |||
| 396dc6cd3c | |||
| ba3d174fde | |||
| ab313488ad | |||
| d808462fb6 | |||
| 71e73c3999 | |||
| a55df8b5e1 | |||
| f59efe0f4b | |||
| 1b79a57673 | |||
| ae59a18e2d | |||
| 12201f392d | |||
| 8f3fe123e3 | |||
| 04050ca883 | |||
| c3b3d51286 | |||
| 10451509f1 | |||
| ff0d724f32 | |||
| c64e577049 | |||
| f08dca0af6 | |||
| 8c0bcbf5bb | |||
| 596fc2aeda | |||
| 968b19e8b7 | |||
| 7993328ff7 | |||
| 16349ac69a | |||
| 45712c52f1 | |||
| 235dcd2ad2 | |||
| ed92d1c254 | |||
| 0b4c23f50e | |||
| 63c895c0a0 | |||
| 3162bc60e9 | |||
| 206802cf4d | |||
| 5eb4f8e5cd | |||
| 0a27e3927b | |||
| 401add78d3 | |||
| af375eb402 | |||
| 2797111ced | |||
| d7d4889c50 | |||
| bf356e124f | |||
| d7fd43ca79 | |||
| 42e11d169e | |||
| c1fae0b5ee | |||
| ef99bab435 | |||
| 93afd3eabe | |||
| 61dac76bee | |||
| 245f5abc45 | |||
| 0f8f6584ce | |||
| dd498ded00 | |||
| 5d2999818b | |||
| eb1f197ff4 | |||
| 4bc03ed56a | |||
| 9191d333ca | |||
| c6533a2d69 | |||
| 6c13762c93 | |||
| 06c09b96cf | |||
| 8a5ec3b2a1 | |||
| 21c26aed2f | |||
| 5fe1481ae9 | |||
| 1879cff82d | |||
| cd5e805692 | |||
| 90a77ab7a1 | |||
| 3928e27cf4 | |||
| 45b1124553 | |||
| 252b43dcb7 | |||
| c19a84ac05 | |||
| 404fdc2dd7 | |||
| 2ec56abe7e | |||
| 63a8700258 | |||
| d363185031 | |||
| aabaaa9049 | |||
| eb2be61eac | |||
| 0688691974 | |||
| d3d5c1e907 | |||
| cbf66d411d | |||
| 0e5b48f3b4 | |||
| df7cfdc8d0 | |||
| 89015e5ecc | |||
| 025d4c9a75 | |||
| d3bea4c3b4 | |||
| a6c12adda2 | |||
| dcb9129809 | |||
| bd1f171f51 | |||
| 54efb034a4 | |||
| fe94f146bb | |||
| 22b492762b | |||
| fea0c5cc2b | |||
| 688d6af541 | |||
| bcbd32cdd3 | |||
| 3fa8b97ed2 | |||
| 7cd4e2e205 | |||
| f2b0cb46a2 | |||
| cf5d184766 | |||
| 5738dc553f | |||
| 386accab80 | |||
| e7686db759 | |||
| 6c9490f2c6 | |||
| 855ab19dea | |||
| 797a3e6ea4 | |||
| bbd443d397 | |||
| 4e1597c614 | |||
| 75e338d5df | |||
| 1919f873c0 | |||
| a1f35355f6 | |||
| c4c17e8036 | |||
| 3024c1ce3d | |||
| b79530b10c | |||
| 778c63a6d3 | |||
| f623db06ea | |||
| 026673dc05 | |||
| 6893da5dd3 | |||
| d5a9c185f0 | |||
| cbdeacd22d |
@@ -61,3 +61,10 @@ target/
|
||||
|
||||
# Sublime Text 2
|
||||
*.sublime*
|
||||
|
||||
# unitests files
|
||||
telegram.mp3
|
||||
telegram.mp4
|
||||
telegram.ogg
|
||||
telegram.png
|
||||
telegram.webp
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
- repo: git://github.com/pre-commit/mirrors-yapf
|
||||
sha: 'v0.7.1'
|
||||
hooks:
|
||||
- id: yapf
|
||||
args: ['-i']
|
||||
|
||||
- repo: git://github.com/pre-commit/pre-commit-hooks
|
||||
sha: 'v0.5.0'
|
||||
hooks:
|
||||
- id: flake8
|
||||
args: ['telegram']
|
||||
|
||||
- repo: git://github.com/pre-commit/mirrors-pylint
|
||||
sha: 'v1.5.5'
|
||||
hooks:
|
||||
- id: pylint
|
||||
args: ['--errors-only', '--disable=no-name-in-module,import-error', 'telegram']
|
||||
+7
-1
@@ -4,11 +4,17 @@ python:
|
||||
- "2.7"
|
||||
- "3.3"
|
||||
- "3.4"
|
||||
- "3.5"
|
||||
- "pypy"
|
||||
- "pypy3"
|
||||
install:
|
||||
- pip install coveralls
|
||||
- pip install -r requirements.txt
|
||||
- pip install -r requirements-dev.txt
|
||||
script:
|
||||
nosetests --with-coverage --cover-package telegram/
|
||||
- nosetests -v --with-flaky --no-flaky-report --with-coverage --cover-package=telegram/
|
||||
- 'if [ $TRAVIS_PYTHON_VERSION != 2.6 ] && [ $TRAVIS_PYTHON_VERSION != 3.3 ] && [ $TRAVIS_PYTHON_VERSION != pypy3 ]; then yapf -r telegram; fi'
|
||||
- flake8 telegram
|
||||
- 'if [ $TRAVIS_PYTHON_VERSION != 2.6 ]; then pylint -E telegram --disable=no-name-in-module,import-error; fi'
|
||||
after_success:
|
||||
coveralls
|
||||
|
||||
@@ -9,14 +9,21 @@ Contributors
|
||||
The following wonderful people contributed directly or indirectly to this project:
|
||||
|
||||
- `Avanatiker <https://github.com/Avanatiker>`_
|
||||
- `Balduro <https://github.com/Balduro>`_
|
||||
- `bimmlerd <https://github.com/bimmlerd>`_
|
||||
- `ErgoZ Riftbit Vaper <https://github.com/ergoz>`_
|
||||
- `franciscod <https://github.com/franciscod>`_
|
||||
- `JASON0916 <https://github.com/JASON0916>`_
|
||||
- `jh0ker <https://github.com/jh0ker>`_
|
||||
- `JRoot3D <https://github.com/JRoot3D>`_
|
||||
- `jlmadurga <https://github.com/jlmadurga>`_
|
||||
- `macrojames <https://github.com/macrojames>`_
|
||||
- `naveenvhegde <https://github.com/naveenvhegde>`_
|
||||
- `njittam <https://github.com/njittam>`_
|
||||
- `Noam Meltzer <https://github.com/tsnoam>`_
|
||||
- `Oleg Shlyazhko <https://github.com/ollmer>`_
|
||||
- `Rahiel Kasim <https://github.com/rahiel>`_
|
||||
- `Shelomentsev D <https://github.com/shelomentsevd>`_
|
||||
- `sooyhwang <https://github.com/sooyhwang>`_
|
||||
- `wjt <https://github.com/wjt>`_
|
||||
|
||||
|
||||
+317
-97
@@ -1,158 +1,378 @@
|
||||
2015-09-05
|
||||
Released 2.8.2
|
||||
Fix regression on Telegram ReplyMarkup
|
||||
Add certificate to is_inputfile method
|
||||
**2016-05-16**
|
||||
|
||||
*Released 4.1.1*
|
||||
|
||||
- Fix deprecation warning in ``Dispatcher``
|
||||
|
||||
**2016-05-15**
|
||||
|
||||
*Released 4.1*
|
||||
|
||||
- Implement API changes from May 6, 2016
|
||||
- Fix bug when ``start_polling`` with ``clean=True``
|
||||
- Methods now have snake_case equivalent, for example ``telegram.Bot.send_message`` is the same as ``telegram.Bot.sendMessage``
|
||||
|
||||
**2016-05-01**
|
||||
|
||||
*Released 4.0.3*
|
||||
|
||||
- Add missing attribute ``location`` to ``InlineQuery``
|
||||
|
||||
**2016-04-29**
|
||||
|
||||
*Released 4.0.2*
|
||||
|
||||
- Bugfixes
|
||||
- ``KeyboardReplyMarkup`` now accepts ``str`` again
|
||||
|
||||
**2016-04-27**
|
||||
|
||||
*Released 4.0.1*
|
||||
|
||||
- Implement Bot API 2.0
|
||||
- Almost complete recode of ``Dispatcher``
|
||||
- Please read the `Transistion Guide to 4.0 <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Transistion-guide-to-Version-4.0>`_
|
||||
- **Changes from 4.0rc1**
|
||||
- The syntax of filters for ``MessageHandler`` (upper/lower cases)
|
||||
- Handler groups are now identified by ``int`` only, and ordered
|
||||
- **Note:** v4.0 has been skipped due to a PyPI accident
|
||||
|
||||
**2016-04-22**
|
||||
|
||||
*Released 4.0rc1*
|
||||
|
||||
- Implement Bot API 2.0
|
||||
- Almost complete recode of ``Dispatcher``
|
||||
- Please read the `Transistion Guide to 4.0 <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Transistion-guide-to-Version-4.0>`_
|
||||
|
||||
**2016-03-22**
|
||||
|
||||
*Released 3.4*
|
||||
|
||||
- Move ``Updater``, ``Dispatcher`` and ``JobQueue`` to new ``telegram.ext`` submodule (thanks to @rahiel)
|
||||
- Add ``disable_notification`` parameter (thanks to @aidarbiktimirov)
|
||||
- Fix bug where commands sent by Telegram Web would not be recognized (thanks to @shelomentsevd)
|
||||
- Add option to skip old updates on bot startup
|
||||
- Send files from ``BufferedReader``
|
||||
|
||||
**2016-02-28**
|
||||
|
||||
*Released 3.3*
|
||||
|
||||
- Inline bots
|
||||
- Send any file by URL
|
||||
- Specialized exceptions: ``Unauthorized``, ``InvalidToken``, ``NetworkError`` and ``TimedOut``
|
||||
- Integration for botan.io (thanks to @ollmer)
|
||||
- HTML Parsemode (thanks to @jlmadurga)
|
||||
- Bugfixes and under-the-hood improvements
|
||||
|
||||
**Very special thanks to Noam Meltzer (@tsnoam) for all of his work!**
|
||||
|
||||
**2016-01-09**
|
||||
|
||||
*Released 3.3b1*
|
||||
|
||||
- Implement inline bots (beta)
|
||||
|
||||
**2016-01-05**
|
||||
|
||||
*Released 3.2.0*
|
||||
|
||||
- Introducing ``JobQueue`` (original author: @franciscod)
|
||||
- Streamlining all exceptions to ``TelegramError`` (Special thanks to @tsnoam)
|
||||
- Proper locking of ``Updater`` and ``Dispatcher`` ``start`` and ``stop`` methods
|
||||
- Small bugfixes
|
||||
|
||||
**2015-12-29**
|
||||
|
||||
*Released 3.1.2*
|
||||
|
||||
- Fix custom path for file downloads
|
||||
- Don't stop the dispatcher thread on uncaught errors in handlers
|
||||
|
||||
**2015-12-21**
|
||||
|
||||
*Released 3.1.1*
|
||||
|
||||
- Fix a bug where asynchronous handlers could not have additional arguments
|
||||
- Add ``groups`` and ``groupdict`` as additional arguments for regex-based handlers
|
||||
|
||||
**2015-12-16**
|
||||
|
||||
*Released 3.1.0*
|
||||
|
||||
- The ``chat``-field in ``Message`` is now of type ``Chat``. (API update Oct 8 2015)
|
||||
- ``Message`` now contains the optional fields ``supergroup_chat_created``, ``migrate_to_chat_id``, ``migrate_from_chat_id`` and ``channel_chat_created``. (API update Nov 2015)
|
||||
|
||||
**2015-12-08**
|
||||
|
||||
*Released 3.0.0*
|
||||
|
||||
- Introducing the ``Updater`` and ``Dispatcher`` classes
|
||||
|
||||
**2015-11-11**
|
||||
|
||||
*Released 2.9.2*
|
||||
|
||||
- Error handling on request timeouts has been improved
|
||||
|
||||
**2015-11-10**
|
||||
|
||||
*Released 2.9.1*
|
||||
|
||||
- Add parameter ``network_delay`` to Bot.getUpdates for slow connections
|
||||
|
||||
**2015-11-10**
|
||||
|
||||
*Released 2.9*
|
||||
|
||||
- Emoji class now uses ``bytes_to_native_str`` from ``future`` 3rd party lib
|
||||
- Make ``user_from`` optional to work with channels
|
||||
- Raise exception if Telegram times out on long-polling
|
||||
|
||||
*Special thanks to @jh0ker for all hard work*
|
||||
|
||||
|
||||
2015-09-05
|
||||
Released 2.8.1
|
||||
Fix regression on Telegram objects with thumb properties
|
||||
**2015-10-08**
|
||||
|
||||
*Released 2.8.7*
|
||||
|
||||
- Type as optional for ``GroupChat`` class
|
||||
|
||||
|
||||
2015-09-04
|
||||
Released 2.8
|
||||
TelegramError when chat_id is empty for send* methods
|
||||
setWebhook now supports sending self-signed certificate
|
||||
Huge redesign of existing Telegram classes
|
||||
Added support for PyPy
|
||||
Added docstring for existing classes
|
||||
**2015-10-08**
|
||||
|
||||
*Released 2.8.6*
|
||||
|
||||
- Adds type to ``User`` and ``GroupChat`` classes (pre-release Telegram feature)
|
||||
|
||||
|
||||
2015-08-19
|
||||
Released 2.7.1
|
||||
Fixed JSON serialization for message
|
||||
**2015-09-24**
|
||||
|
||||
*Released 2.8.5*
|
||||
|
||||
- Handles HTTP Bad Gateway (503) errors on request
|
||||
- Fixes regression on ``Audio`` and ``Document`` for unicode fields
|
||||
|
||||
|
||||
2015-08-17
|
||||
Released 2.7
|
||||
Added support for Voice object and sendVoice method
|
||||
Due backward compatibility performer or/and title will be required for sendAudio
|
||||
Fixed JSON serialization when forwarded message
|
||||
**2015-09-20**
|
||||
|
||||
*Released 2.8.4*
|
||||
|
||||
- ``getFile`` and ``File.download`` is now fully supported
|
||||
|
||||
|
||||
2015-08-15
|
||||
Released 2.6.1
|
||||
Fixed parsing image header issue on < Python 2.7.3
|
||||
**2015-09-10**
|
||||
|
||||
*Released 2.8.3*
|
||||
|
||||
- Moved ``Bot._requestURL`` to its own class (``telegram.utils.request``)
|
||||
- Much better, such wow, Telegram Objects tests
|
||||
- Add consistency for ``str`` properties on Telegram Objects
|
||||
- Better design to test if ``chat_id`` is invalid
|
||||
- Add ability to set custom filename on ``Bot.sendDocument(..,filename='')``
|
||||
- Fix Sticker as ``InputFile``
|
||||
- Send JSON requests over urlencoded post data
|
||||
- Markdown support for ``Bot.sendMessage(..., parse_mode=ParseMode.MARKDOWN)``
|
||||
- Refactor of ``TelegramError`` class (no more handling ``IOError`` or ``URLError``)
|
||||
|
||||
|
||||
2015-08-14
|
||||
Released 2.6.0
|
||||
Depreciation of require_authentication and clearCredentials methods
|
||||
Giving AUTHORS the proper credits for their contribution for this project
|
||||
Message.date and Message.forward_date are now datetime objects
|
||||
**2015-09-05**
|
||||
|
||||
*Released 2.8.2*
|
||||
|
||||
- Fix regression on Telegram ReplyMarkup
|
||||
- Add certificate to ``is_inputfile`` method
|
||||
|
||||
|
||||
2015-08-12
|
||||
Released 2.5.3
|
||||
telegram.Bot now supports to be unpickled
|
||||
**2015-09-05**
|
||||
|
||||
*Released 2.8.1*
|
||||
|
||||
- Fix regression on Telegram objects with thumb properties
|
||||
|
||||
|
||||
2015-08-11
|
||||
Released 2.5.2
|
||||
New changes from Telegram Bot API have been applied
|
||||
telegram.Bot now supports to be pickled
|
||||
Return empty str instead None when message.text is empty
|
||||
**2015-09-04**
|
||||
|
||||
*Released 2.8*
|
||||
|
||||
- TelegramError when ``chat_id`` is empty for send* methods
|
||||
- ``setWebhook`` now supports sending self-signed certificate
|
||||
- Huge redesign of existing Telegram classes
|
||||
- Added support for PyPy
|
||||
- Added docstring for existing classes
|
||||
|
||||
|
||||
2015-08-10
|
||||
Released 2.5.1
|
||||
Moved from GPLv2 to LGPLv3
|
||||
**2015-08-19**
|
||||
|
||||
*Released 2.7.1*
|
||||
|
||||
- Fixed JSON serialization for ``message``
|
||||
|
||||
|
||||
2015-08-09
|
||||
Released 2.5
|
||||
Fixes logging calls in API
|
||||
**2015-08-17**
|
||||
|
||||
*Released 2.7*
|
||||
|
||||
- Added support for ``Voice`` object and ``sendVoice`` method
|
||||
- Due backward compatibility performer or/and title will be required for ``sendAudio``
|
||||
- Fixed JSON serialization when forwarded message
|
||||
|
||||
|
||||
2015-08-08
|
||||
Released 2.4
|
||||
Fixes Emoji class for Python 3
|
||||
PEP8 improvements
|
||||
**2015-08-15**
|
||||
|
||||
*Released 2.6.1*
|
||||
|
||||
- Fixed parsing image header issue on < Python 2.7.3
|
||||
|
||||
|
||||
2015-08-08
|
||||
Released 2.3
|
||||
Fixes ForceReply class
|
||||
Remove logging.basicConfig from library
|
||||
**2015-08-14**
|
||||
|
||||
*Released 2.6.0*
|
||||
|
||||
- Depreciation of ``require_authentication`` and ``clearCredentials`` methods
|
||||
- Giving ``AUTHORS`` the proper credits for their contribution for this project
|
||||
- ``Message.date`` and ``Message.forward_date`` are now ``datetime`` objects
|
||||
|
||||
|
||||
2015-07-25
|
||||
Released 2.2
|
||||
Allows debug=True when initializing telegram.Bot
|
||||
**2015-08-12**
|
||||
|
||||
*Released 2.5.3*
|
||||
|
||||
- ``telegram.Bot`` now supports to be unpickled
|
||||
|
||||
|
||||
2015-07-20
|
||||
Released 2.1
|
||||
Fix to_dict for Document and Video
|
||||
**2015-08-11**
|
||||
|
||||
*Released 2.5.2*
|
||||
|
||||
- New changes from Telegram Bot API have been applied
|
||||
- ``telegram.Bot`` now supports to be pickled
|
||||
- Return empty ``str`` instead ``None`` when ``message.text`` is empty
|
||||
|
||||
|
||||
2015-07-19
|
||||
**2015-08-10**
|
||||
|
||||
Released 2.0
|
||||
Fixes bugs
|
||||
Improves __str__ over to_json()
|
||||
Creates abstractclass TelegramObject
|
||||
*Released 2.5.1*
|
||||
|
||||
- Moved from GPLv2 to LGPLv3
|
||||
|
||||
|
||||
2015-07-15
|
||||
**2015-08-09**
|
||||
|
||||
Released 1.9
|
||||
Python 3 officially supported
|
||||
PEP8 improvements
|
||||
*Released 2.5*
|
||||
|
||||
- Fixes logging calls in API
|
||||
|
||||
|
||||
2015-07-12
|
||||
**2015-08-08**
|
||||
|
||||
Released 1.8
|
||||
Fixes crash when replying an unicode text message (special thanks to JRoot3D)
|
||||
*Released 2.4*
|
||||
|
||||
- Fixes ``Emoji`` class for Python 3
|
||||
- ``PEP8`` improvements
|
||||
|
||||
|
||||
2015-07-11
|
||||
**2015-08-08**
|
||||
|
||||
Released 1.7
|
||||
Fixes crash when username is not defined on chat (special thanks to JRoot3D)
|
||||
*Released 2.3*
|
||||
|
||||
- Fixes ``ForceReply`` class
|
||||
- Remove ``logging.basicConfig`` from library
|
||||
|
||||
|
||||
2015-07-10
|
||||
**2015-07-25**
|
||||
|
||||
Released 1.6
|
||||
Improvements for GAE support
|
||||
*Released 2.2*
|
||||
|
||||
- Allows ``debug=True`` when initializing ``telegram.Bot``
|
||||
|
||||
|
||||
2015-07-10
|
||||
**2015-07-20**
|
||||
|
||||
Released 1.5
|
||||
Fixes randomly unicode issues when using InputFile
|
||||
*Released 2.1*
|
||||
|
||||
- Fix ``to_dict`` for ``Document`` and ``Video``
|
||||
|
||||
|
||||
2015-07-10
|
||||
**2015-07-19**
|
||||
|
||||
Released 1.4
|
||||
requests lib is no longer required
|
||||
Google App Engine (GAE) is supported
|
||||
*Released 2.0*
|
||||
|
||||
- Fixes bugs
|
||||
- Improves ``__str__`` over ``to_json()``
|
||||
- Creates abstract class ``TelegramObject``
|
||||
|
||||
|
||||
2015-07-10
|
||||
**2015-07-15**
|
||||
|
||||
Released 1.3
|
||||
Added support to setWebhook (special thanks to macrojames)
|
||||
*Released 1.9*
|
||||
|
||||
- Python 3 officially supported
|
||||
- ``PEP8`` improvements
|
||||
|
||||
|
||||
2015-07-09
|
||||
**2015-07-12**
|
||||
|
||||
Released 1.2
|
||||
CustomKeyboard classes now available
|
||||
Emojis available
|
||||
PEP8 improvements
|
||||
*Released 1.8*
|
||||
|
||||
- Fixes crash when replying an unicode text message (special thanks to JRoot3D)
|
||||
|
||||
|
||||
2015-07-08
|
||||
**2015-07-11**
|
||||
|
||||
Released 1.1
|
||||
PyPi package now available
|
||||
*Released 1.7*
|
||||
|
||||
- Fixes crash when ``username`` is not defined on ``chat`` (special thanks to JRoot3D)
|
||||
|
||||
|
||||
2015-07-08
|
||||
**2015-07-10**
|
||||
|
||||
Released 1.0
|
||||
Initial checkin of python-telegram-bot
|
||||
*Released 1.6*
|
||||
|
||||
- Improvements for GAE support
|
||||
|
||||
|
||||
**2015-07-10**
|
||||
|
||||
*Released 1.5*
|
||||
|
||||
- Fixes randomly unicode issues when using ``InputFile``
|
||||
|
||||
|
||||
**2015-07-10**
|
||||
|
||||
*Released 1.4*
|
||||
|
||||
- ``requests`` lib is no longer required
|
||||
- Google App Engine (GAE) is supported
|
||||
|
||||
|
||||
**2015-07-10**
|
||||
|
||||
*Released 1.3*
|
||||
|
||||
- Added support to ``setWebhook`` (special thanks to macrojames)
|
||||
|
||||
|
||||
**2015-07-09**
|
||||
|
||||
*Released 1.2*
|
||||
|
||||
- ``CustomKeyboard`` classes now available
|
||||
- Emojis available
|
||||
- ``PEP8`` improvements
|
||||
|
||||
|
||||
**2015-07-08**
|
||||
|
||||
*Released 1.1*
|
||||
|
||||
- PyPi package now available
|
||||
|
||||
|
||||
**2015-07-08**
|
||||
|
||||
*Released 1.0*
|
||||
|
||||
- Initial checkin of python-telegram-bot
|
||||
|
||||
+126
-25
@@ -1,39 +1,140 @@
|
||||
How To Contribute
|
||||
=================
|
||||
|
||||
Every open source project lives from the generous help by contributors that sacrifice their time and ``python-telegram-bot`` is no different.
|
||||
Every open source project lives from the generous help by contributors that sacrifice their time and ``python-telegram-bot`` is no different. To make participation as pleasant as possible, this project adheres to the `Code of Conduct`_ by the Python Software Foundation.
|
||||
|
||||
To make participation as pleasant as possible, this project adheres to the `Code of Conduct`_ by the Python Software Foundation.
|
||||
Setting things up
|
||||
-----------------
|
||||
|
||||
Here are a few guidelines to get you started:
|
||||
1. Fork the ``python-telegram-bot`` repository to your GitHub account.
|
||||
|
||||
- Add yourself to the AUTHORS.rst_ file in an alphabetical fashion.
|
||||
Every contribution is valuable and shall be credited.
|
||||
- If your change is noteworthy, add an entry to the CHANGES_.
|
||||
- No contribution is too small; please submit as many fixes for typos and grammar bloopers as you can!
|
||||
- Don’t break backward compatibility.
|
||||
- *Always* add tests and docs for your code.
|
||||
This is a hard rule; patches with missing tests or documentation won’t be merged.
|
||||
If a feature is not tested or documented, it doesn’t exist.
|
||||
- Obey `PEP 8`_ and `PEP 257`_.
|
||||
- Follow `Google Python Style Guide`_ and `Google Python Style Docstrings`_.
|
||||
- Write `good commit messages`_.
|
||||
2. Clone your forked repository of ``python-telegram-bot`` to your computer:
|
||||
|
||||
.. note::
|
||||
If you have something great but aren’t sure whether it adheres -- or even can adhere -- to the rules above: **please submit a pull request anyway**!
|
||||
``$ git clone https://github.com/<your username>/python-telegram-bot``
|
||||
|
||||
In the best case, we can mold it into something, in the worst case the pull request gets politely closed.
|
||||
There’s absolutely nothing to fear.
|
||||
``$ cd python-telegram-bot``
|
||||
|
||||
Thank you for considering to contribute to ``python-telegram-bot``!
|
||||
If you have any question or concerns, feel free to reach out to me.
|
||||
3. Add a track to the original repository:
|
||||
|
||||
``$ git remote add upstream https://github.com/python-telegram-bot/python-telegram-bot``
|
||||
|
||||
4. Install dependencies:
|
||||
|
||||
``$ pip install -r requirements.txt -r requirements-dev.txt``
|
||||
|
||||
|
||||
.. _`PEP 8`: https://www.python.org/dev/peps/pep-0008/
|
||||
.. _`PEP 257`: https://www.python.org/dev/peps/pep-0257/
|
||||
.. _`good commit messages`: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
|
||||
5. Install pre-commit hooks:
|
||||
|
||||
``$ pre-commit install``
|
||||
|
||||
Finding something to do
|
||||
-----------------------
|
||||
|
||||
If you already know what you'd like to work on, you can skip this section.
|
||||
|
||||
If you have an idea for something to do, first check if it's already been filed on the `issue tracker`_. If so, add a comment to the issue saying you'd like to work on it, and we'll help you get started! Otherwise, please file a new issue and assign yourself to it.
|
||||
|
||||
Another great way to start contributing is by writing tests. Tests are really important because they help prevent developers from accidentally breaking existing code, allowing them to build cool things faster. If you're interested in helping out, let the development team know by posting to the `developers' mailing list`_, and we'll help you get started.
|
||||
|
||||
Instructions for making a code change
|
||||
-------------------------------------
|
||||
|
||||
The central development branch is ``master``, which should be clean and ready for release at any time. In general, all changes should be done as feature branches based off of ``master``.
|
||||
|
||||
Here's how to make a one-off code change.
|
||||
|
||||
1. **Choose a descriptive branch name.** It should be lowercase, hyphen-separated, and a noun describing the change (so, ``fuzzy-rules``, but not ``implement-fuzzy-rules``). Also, it shouldn't start with ``hotfix`` or ``release``.
|
||||
|
||||
2. **Create a new branch with this name, starting from** ``master``. In other words, run:
|
||||
|
||||
``$ git fetch upstream``
|
||||
|
||||
``$ git checkout master``
|
||||
|
||||
``$ git merge upstream/master``
|
||||
|
||||
``$ git checkout -b your-branch-name``
|
||||
|
||||
3. **Make a commit to your feature branch**. Each commit should be self-contained and have a descriptive commit message that helps other developers understand why the changes were made.
|
||||
|
||||
- You can refer to relevant issues in the commit message by writing, e.g., "#105".
|
||||
|
||||
- Your code should adhere to the `PEP 8 Style Guide`_, with the exception that we have a maximum line length of 99.
|
||||
|
||||
- For consistency, please conform to `Google Python Style Guide`_ and `Google Python Style Docstrings`_. In addition, code should be formatted consistently with other code around it.
|
||||
|
||||
- The following exceptions to the above (Google's) style guides applies:
|
||||
|
||||
- Documenting types of global variables and complex types of class members can be done using the Sphinx docstring convention.
|
||||
|
||||
- Please ensure that the code you write is well-tested.
|
||||
|
||||
- Don’t break backward compatibility.
|
||||
|
||||
- Add yourself to the AUTHORS.rst_ file in an alphabetical fashion.
|
||||
|
||||
- Before making a commit ensure that all automated tests still pass:
|
||||
|
||||
``$ make test``
|
||||
|
||||
- To actually make the commit (this will trigger tests for yapf, lint and pep8 automatically):
|
||||
|
||||
``$ git add your-file-changed.py``
|
||||
|
||||
- yapf may change code formatting, make sure to re-add them to your commit.
|
||||
|
||||
``$ git commit -a -m "your-commit-message-here"``
|
||||
|
||||
- Finally, push it to your GitHub fork, run:
|
||||
|
||||
``$ git push origin your-branch-name``
|
||||
|
||||
4. **When your feature is ready to merge, create a pull request.**
|
||||
|
||||
- Go to your fork on GitHub, select your branch from the dropdown menu, and click "New pull request".
|
||||
|
||||
- Add a descriptive comment explaining the purpose of the branch (e.g. "Add the new API feature to create inline bot queries."). This will tell the reviewer what the purpose of the branch is.
|
||||
|
||||
- Click "Create pull request". An admin will assign a reviewer to your commit.
|
||||
|
||||
5. **Address review comments until all reviewers give LGTM ('looks good to me').**
|
||||
|
||||
- When your reviewer has reviewed the code, you'll get an email. You'll need to respond in two ways:
|
||||
|
||||
- Make a new commit addressing the comments you agree with, and push it to the same branch. Ideally, the commit message would explain what the commit does (e.g. "Fix lint error"), but if there are lots of disparate review comments, it's fine to refer to the original commit message and add something like "(address review comments)".
|
||||
|
||||
- In addition, please reply to each comment. Each reply should be either "Done" or a response explaining why the corresponding suggestion wasn't implemented. All comments must be resolved before LGTM can be given.
|
||||
|
||||
- Resolve any merge conflicts that arise. To resolve conflicts between 'your-branch-name' (in your fork) and 'master' (in the ``python-telegram-bot`` repository), run:
|
||||
|
||||
``$ git checkout your-branch-name``
|
||||
|
||||
``$ git fetch upstream``
|
||||
|
||||
``$ git merge upstream/master``
|
||||
|
||||
``$ ...[fix the conflicts]...``
|
||||
|
||||
``$ ...[make sure the tests pass before committing]...``
|
||||
|
||||
``$ git commit -a``
|
||||
|
||||
``$ git push origin your-branch-name``
|
||||
|
||||
- At the end, the reviewer will merge the pull request.
|
||||
|
||||
6. **Tidy up!** Delete the feature branch from both your local clone and the GitHub repository:
|
||||
|
||||
``$ git branch -D your-branch-name``
|
||||
|
||||
``$ git push origin --delete your-branch-name``
|
||||
|
||||
7. **Celebrate.** Congratulations, you have contributed to ``python-telegram-bot``!
|
||||
|
||||
.. _`Code of Conduct`: https://www.python.org/psf/codeofconduct/
|
||||
.. _`issue tracker`: https://github.com/python-telegram-bot/python-telegram-bot/issues
|
||||
.. _`developers' mailing list`: mailto:devs@python-telegram-bot.org
|
||||
.. _`PEP 8 Style Guide`: https://www.python.org/dev/peps/pep-0008/
|
||||
.. _`Google Python Style Guide`: https://google-styleguide.googlecode.com/svn/trunk/pyguide.html
|
||||
.. _`Google Python Style Docstrings`: http://sphinx-doc.org/latest/ext/example_google.html
|
||||
.. _CHANGES: https://github.com/leandrotoledo/python-telegram-bot/blob/master/CHANGES
|
||||
.. _AUTHORS.rst: https://github.com/leandrotoledo/python-telegram-bot/blob/master/AUTHORS.rst
|
||||
.. _AUTHORS.rst: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/AUTHORS.rst
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
include LICENSE LICENSE.lesser Makefile
|
||||
include LICENSE LICENSE.lesser Makefile requirements.txt
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
.PHONY: clean pep8 lint test
|
||||
.DEFAULT_GOAL := help
|
||||
.PHONY: clean pep257 pep8 yapf lint test install
|
||||
|
||||
PYLINT := pylint
|
||||
NOSETESTS := nosetests
|
||||
PEP257 := pep257
|
||||
PEP8 := flake8
|
||||
YAPF := yapf
|
||||
PIP := pip
|
||||
|
||||
clean:
|
||||
rm -fr build
|
||||
@@ -6,19 +14,39 @@ clean:
|
||||
find . -name '*.pyc' -exec rm -f {} \;
|
||||
find . -name '*.pyo' -exec rm -f {} \;
|
||||
find . -name '*~' -exec rm -f {} \;
|
||||
find . -regex "./telegram.\(mp3\|mp4\|ogg\|png\|webp\)" -exec rm {} \;
|
||||
|
||||
pep257:
|
||||
$(PEP257) telegram
|
||||
|
||||
pep8:
|
||||
flake8 telegram
|
||||
$(PEP8) telegram
|
||||
|
||||
yapf:
|
||||
$(YAPF) -r telegram
|
||||
|
||||
lint:
|
||||
pylint -E telegram
|
||||
$(PYLINT) -E telegram --disable=no-name-in-module,import-error
|
||||
|
||||
test:
|
||||
nosetests
|
||||
$(NOSETESTS) -v
|
||||
|
||||
install:
|
||||
$(PIP) install -r requirements.txt -r requirements-dev.txt
|
||||
|
||||
help:
|
||||
@echo "Available targets:"
|
||||
@echo "- clean Clean up the source directory"
|
||||
@echo "- pep257 Check docstring style with pep257"
|
||||
@echo "- pep8 Check style with flake8"
|
||||
@echo "- lint Check style with pylint"
|
||||
@echo "- yapf Check style with yapf"
|
||||
@echo "- test Run tests"
|
||||
@echo
|
||||
@echo "Available variables:"
|
||||
@echo "- PYLINT default: $(PYLINT)"
|
||||
@echo "- NOSETESTS default: $(NOSETESTS)"
|
||||
@echo "- PEP257 default: $(PEP257)"
|
||||
@echo "- PEP8 default: $(PEP8)"
|
||||
@echo "- YAPF default: $(YAPF)"
|
||||
@echo "- PIP default: $(PIP)"
|
||||
|
||||
+336
-109
@@ -1,48 +1,51 @@
|
||||
Python Telegram Bot
|
||||
.. image:: https://github.com/python-telegram-bot/logos/blob/master/logo-text/png/ptb-logo-text_768.png?raw=true
|
||||
:align: center
|
||||
:target: https://github.com/python-telegram-bot/logos
|
||||
:alt: python-telegram-bot Logo
|
||||
|
||||
A Python wrapper around the Telegram Bot API.
|
||||
Not **just** a Python wrapper around the Telegram Bot API
|
||||
|
||||
By `Leandro Toledo <leandrotoledodesouza@gmail.com>`_
|
||||
*Stay tuned for library updates and new releases on our* `Telegram Channel <https://telegram.me/pythontelegrambotchannel>`_.
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/python-telegram-bot.svg
|
||||
:target: https://pypi.python.org/pypi/python-telegram-bot
|
||||
:alt: PyPi Package Version
|
||||
|
||||
.. image:: https://img.shields.io/pypi/dm/python-telegram-bot.svg
|
||||
.. image:: https://img.shields.io/pypi/pyversions/python-telegram-bot.svg
|
||||
:target: https://pypi.python.org/pypi/python-telegram-bot
|
||||
:alt: PyPi Package Monthly Download
|
||||
:alt: Supported python versions
|
||||
|
||||
.. image:: https://readthedocs.org/projects/python-telegram-bot/badge/?version=latest
|
||||
:target: https://readthedocs.org/projects/python-telegram-bot/?badge=latest
|
||||
:alt: Documentation Status
|
||||
|
||||
.. image:: https://img.shields.io/github/license/leandrotoledo/python-telegram-bot.svg
|
||||
:target: http://www.gnu.org/licenses/lgpl-3.0.html
|
||||
.. image:: https://img.shields.io/pypi/l/python-telegram-bot.svg
|
||||
:target: https://www.gnu.org/licenses/lgpl-3.0.html
|
||||
:alt: LGPLv3 License
|
||||
|
||||
.. image:: https://travis-ci.org/leandrotoledo/python-telegram-bot.svg?branch=master
|
||||
:target: https://travis-ci.org/leandrotoledo/python-telegram-bot
|
||||
.. image:: https://travis-ci.org/python-telegram-bot/python-telegram-bot.svg?branch=master
|
||||
:target: https://travis-ci.org/python-telegram-bot/python-telegram-bot
|
||||
:alt: Travis CI Status
|
||||
|
||||
.. image:: https://codeclimate.com/github/leandrotoledo/python-telegram-bot/badges/gpa.svg
|
||||
:target: https://codeclimate.com/github/leandrotoledo/python-telegram-bot
|
||||
.. image:: https://codeclimate.com/github/python-telegram-bot/python-telegram-bot/badges/gpa.svg
|
||||
:target: https://codeclimate.com/github/python-telegram-bot/python-telegram-bot
|
||||
:alt: Code Climate
|
||||
|
||||
.. image:: https://coveralls.io/repos/leandrotoledo/python-telegram-bot/badge.svg?branch=master&service=github
|
||||
:target: https://coveralls.io/github/leandrotoledo/python-telegram-bot?branch=master
|
||||
.. image:: https://coveralls.io/repos/python-telegram-bot/python-telegram-bot/badge.svg?branch=master&service=github
|
||||
:target: https://coveralls.io/github/python-telegram-bot/python-telegram-bot?branch=master
|
||||
:alt: Coveralls
|
||||
|
||||
.. image:: https://img.shields.io/badge/Telegram-Group-blue.svg
|
||||
:target: https://telegram.me/pythontelegrambotgroup
|
||||
:alt: Telegram Group
|
||||
|
||||
=================
|
||||
Table of contents
|
||||
=================
|
||||
|
||||
- `Introduction`_
|
||||
|
||||
- `Status`_
|
||||
|
||||
1. `Telegram API support`_
|
||||
|
||||
2. `Python Version support`_
|
||||
- `Telegram API support`_
|
||||
|
||||
- `Installing`_
|
||||
|
||||
@@ -50,33 +53,33 @@ Table of contents
|
||||
|
||||
- `Getting started`_
|
||||
|
||||
1. `API`_
|
||||
#. `Learning by example`_
|
||||
|
||||
2. `Logging`_
|
||||
#. `API`_
|
||||
|
||||
3. `Examples`_
|
||||
#. `Extensions`_
|
||||
|
||||
4. `Documentation`_
|
||||
#. `JobQueue`_
|
||||
|
||||
#. `Logging`_
|
||||
|
||||
#. `Documentation`_
|
||||
|
||||
- `Getting help`_
|
||||
|
||||
- `Contributing`_
|
||||
|
||||
- `License`_
|
||||
|
||||
- `Contact`_
|
||||
|
||||
- `TODO`_
|
||||
|
||||
===============
|
||||
_`Introduction`
|
||||
===============
|
||||
|
||||
This library provides a pure Python interface for the `Telegram Bot API <https://core.telegram.org/bots/api>`_. It works with Python versions from 2.6+. It also works with `Google App Engine <https://cloud.google.com/appengine>`_.
|
||||
|
||||
=========
|
||||
_`Status`
|
||||
=========
|
||||
|
||||
-----------------------
|
||||
=======================
|
||||
_`Telegram API support`
|
||||
-----------------------
|
||||
=======================
|
||||
|
||||
========================= ============
|
||||
Telegram Bot API Method *Supported?*
|
||||
@@ -94,33 +97,24 @@ sendLocation Yes
|
||||
sendChatAction Yes
|
||||
getUpdates Yes
|
||||
getUserProfilePhotos Yes
|
||||
getFile Yes
|
||||
setWebhook Yes
|
||||
answerInlineQuery Yes
|
||||
kickChatMember Yes
|
||||
unbanChatMember Yes
|
||||
answerCallbackQuery Yes
|
||||
editMessageText Yes
|
||||
editMessageCaption Yes
|
||||
editMessageReplyMarkup Yes
|
||||
========================= ============
|
||||
|
||||
-------------------------
|
||||
_`Python Version support`
|
||||
-------------------------
|
||||
|
||||
============== ============
|
||||
Python Version *Supported?*
|
||||
============== ============
|
||||
2.6 Yes
|
||||
2.7 Yes
|
||||
3.3 Yes
|
||||
3.4 Yes
|
||||
PyPy Yes
|
||||
PyPy3 Yes
|
||||
============== ============
|
||||
|
||||
=============
|
||||
_`Installing`
|
||||
=============
|
||||
|
||||
You can install python-telegram-bot using::
|
||||
You can install or upgrade python-telegram-bot with:
|
||||
|
||||
$ pip install python-telegram-bot
|
||||
|
||||
Or upgrade to the latest version::
|
||||
.. code:: shell
|
||||
|
||||
$ pip install python-telegram-bot --upgrade
|
||||
|
||||
@@ -128,18 +122,30 @@ Or upgrade to the latest version::
|
||||
_`Getting the code`
|
||||
===================
|
||||
|
||||
The code is hosted at https://github.com/leandrotoledo/python-telegram-bot
|
||||
The code is hosted at https://github.com/python-telegram-bot/python-telegram-bot
|
||||
|
||||
Check out the latest development version anonymously with::
|
||||
Check out the latest development version anonymously with:
|
||||
|
||||
$ git clone https://github.com/leandrotoledo/python-telegram-bot
|
||||
.. code:: shell
|
||||
|
||||
$ git clone https://github.com/python-telegram-bot/python-telegram-bot
|
||||
$ cd python-telegram-bot
|
||||
|
||||
Install dependencies:
|
||||
|
||||
.. code:: shell
|
||||
|
||||
$ pip install -r requirements.txt -r requirements-dev.txt
|
||||
|
||||
Run tests:
|
||||
|
||||
.. code:: shell
|
||||
|
||||
$ make test
|
||||
|
||||
To see other options available, run:
|
||||
To see other available options, run:
|
||||
|
||||
.. code:: shell
|
||||
|
||||
$ make help
|
||||
|
||||
@@ -149,133 +155,354 @@ _`Getting started`
|
||||
|
||||
View the last release API documentation at: https://core.telegram.org/bots/api
|
||||
|
||||
This library uses the `logging` module. To set up logging to standard output, put:
|
||||
|
||||
.. code:: python
|
||||
|
||||
import logging
|
||||
logging.basicConfig(level=logging.DEBUG,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
||||
|
||||
at the beginning of your script.
|
||||
|
||||
**Note:** The ``telegram.ext`` module will catch errors that would cause the bot to crash. All these are logged to the ``logging`` module, so it's recommended to use this if you are looking for error causes.
|
||||
|
||||
----------------------
|
||||
_`Learning by example`
|
||||
----------------------
|
||||
|
||||
We believe that the best way to learn and understand this simple package is by example. So here are some examples for you to review. Even if it's not your approach for learning, please take a look at ``echobot2`` (below), it is de facto the base for most of the bots out there. Best of all, the code for these examples are released to the public domain, so you can start by grabbing the code and building on top of it.
|
||||
|
||||
- `clibot <https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/clibot.py>`_ has a command line interface.
|
||||
|
||||
- `echobot2 <https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/echobot2.py>`_ replies back messages.
|
||||
|
||||
- `inlinebot <https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/inlinebot.py>`_ basic example of an `inline bot <https://core.telegram.org/bots/inline>`_
|
||||
|
||||
- `state machine bot <https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/state_machine_bot.py>`_ keeps the state for individual users, useful for multipart conversations
|
||||
|
||||
- `timerbot <https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/timerbot.py>`_ uses the ``JobQueue`` to send timed messages.
|
||||
|
||||
Examples using only the API:
|
||||
|
||||
- `echobot <https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/legacy/echobot.py>`_ replies back messages.
|
||||
|
||||
- `roboed <https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/legacy/roboed.py>`_ talks to `Robô Ed <http://www.ed.conpet.gov.br/br/converse.php>`_.
|
||||
|
||||
Look at the examples on the `wiki <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Examples>`_ to see other bots the community has built.
|
||||
|
||||
------
|
||||
_`API`
|
||||
------
|
||||
|
||||
The API is exposed via the ``telegram.Bot`` class.
|
||||
Note: Using the ``Bot`` class directly is the 'old' method, we have an easier way to make bots described in the next section. All of this is however still important information, even if you're using the ``telegram.ext`` submodule!
|
||||
|
||||
To generate an Access Token you have to talk to `BotFather <https://telegram.me/botfather>`_ and follow a few simple steps (described `here <https://core.telegram.org/bots#botfather>`_).
|
||||
The API is exposed via the ``telegram.Bot`` class. The methods have names as described in the official `Telegram Bot API <https://core.telegram.org/bots/api>`_, but equivalent snake_case methods are available for `PEP8 <https://www.python.org/dev/peps/pep-0008/>`_ enthusiasts. So for example ``telegram.Bot.send_message`` is the same as ``telegram.Bot.sendMessage``.
|
||||
|
||||
To generate an Access Token you have to talk to `BotFather <https://telegram.me/botfather>`_ and follow a few simple steps (described `here <https://core.telegram.org/bots#6-botfather>`_).
|
||||
|
||||
For full details see the `Bots: An introduction for developers <https://core.telegram.org/bots>`_.
|
||||
|
||||
To create an instance of the ``telegram.Bot``::
|
||||
To create an instance of the ``telegram.Bot``:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> import telegram
|
||||
>>> bot = telegram.Bot(token='token')
|
||||
|
||||
To see if your credentials are successful::
|
||||
To see if your credentials are successful:
|
||||
|
||||
>>> print bot.getMe()
|
||||
.. code:: python
|
||||
|
||||
>>> print(bot.getMe())
|
||||
{"first_name": "Toledo's Palace Bot", "username": "ToledosPalaceBot"}
|
||||
|
||||
Bots can't initiate conversations with users. A user must either add them to a group or send them a message first. People can use ``telegram.me/<bot_username>`` links or username search to find your bot.
|
||||
|
||||
To fetch text messages sent to your Bot::
|
||||
To fetch text messages sent to your Bot:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> updates = bot.getUpdates()
|
||||
>>> print [u.message.text for u in updates]
|
||||
>>> print([u.message.text for u in updates])
|
||||
|
||||
To fetch images sent to your Bot::
|
||||
To fetch images sent to your Bot:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> updates = bot.getUpdates()
|
||||
>>> print [u.message.photo for u in updates if u.message.photo]
|
||||
>>> print([u.message.photo for u in updates if u.message.photo])
|
||||
|
||||
To reply messages you'll always need the chat_id::
|
||||
To reply messages you'll always need the ``chat_id``:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> chat_id = bot.getUpdates()[-1].message.chat_id
|
||||
|
||||
To post a text message::
|
||||
To post a text message:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> bot.sendMessage(chat_id=chat_id, text="I'm sorry Dave I'm afraid I can't do that.")
|
||||
|
||||
To post a text message with markdown::
|
||||
To post a text message with markdown:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> bot.sendMessage(chat_id=chat_id, text="*bold* _italic_ [link](http://google.com).", parse_mode=telegram.ParseMode.MARKDOWN)
|
||||
|
||||
To post an Emoji (special thanks to `Tim Whitlock <http://apps.timwhitlock.info/emoji/tables/unicode>`_)::
|
||||
To post a text message with Html style:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> bot.sendMessage(chat_id=chat_id, text='<b>bold</b> <i>italic</i> <a href="http://google.com">link</a>.', parse_mode=telegram.ParseMode.HTML)
|
||||
|
||||
To post an Emoji (special thanks to `Tim Whitlock <http://apps.timwhitlock.info/emoji/tables/unicode>`_):
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> bot.sendMessage(chat_id=chat_id, text=telegram.Emoji.PILE_OF_POO)
|
||||
|
||||
To post an image file via URL (right now only sendPhoto supports this)::
|
||||
To post an image file via URL:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> bot.sendPhoto(chat_id=chat_id, photo='https://telegram.org/img/t_logo.png')
|
||||
|
||||
To post a voice file::
|
||||
To post an image file from disk:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> bot.sendPhoto(chat_id=chat_id, photo=open('tests/test.png', 'rb'))
|
||||
|
||||
To post a voice file from disk:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> bot.sendVoice(chat_id=chat_id, voice=open('tests/telegram.ogg', 'rb'))
|
||||
|
||||
To tell the user that something is happening on bot's side::
|
||||
To tell the user that something is happening on bot's side:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> bot.sendChatAction(chat_id=chat_id, action=telegram.ChatAction.TYPING)
|
||||
|
||||
To create `Custom Keyboards <https://core.telegram.org/bots#keyboards>`_::
|
||||
To create `Custom Keyboards <https://core.telegram.org/bots#keyboards>`_:
|
||||
|
||||
>>> custom_keyboard = [[ telegram.Emoji.THUMBS_UP_SIGN, telegram.Emoji.THUMBS_DOWN_SIGN ]]
|
||||
.. code:: python
|
||||
|
||||
>>> custom_keyboard = [[ telegram.KeyboardButton(telegram.Emoji.THUMBS_UP_SIGN),
|
||||
... telegram.KeyboardButton(telegram.Emoji.THUMBS_DOWN_SIGN) ]]
|
||||
>>> reply_markup = telegram.ReplyKeyboardMarkup(custom_keyboard)
|
||||
>>> bot.sendMessage(chat_id=chat_id, text="Stay here, I'll be back.", reply_markup=reply_markup)
|
||||
|
||||
To hide `Custom Keyboards <https://core.telegram.org/bots#keyboards>`_::
|
||||
To hide `Custom Keyboards <https://core.telegram.org/bots#keyboards>`_:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> reply_markup = telegram.ReplyKeyboardHide()
|
||||
>>> bot.sendMessage(chat_id=chat_id, text="I'm back.", reply_markup=reply_markup)
|
||||
|
||||
There are many more API methods, to read the full API documentation::
|
||||
To download a file (you will need its ``file_id``):
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> file_id = message.voice.file_id
|
||||
>>> newFile = bot.getFile(file_id)
|
||||
>>> newFile.download('voice.ogg')
|
||||
|
||||
There are many more API methods, to read the full API documentation:
|
||||
|
||||
.. code:: shell
|
||||
|
||||
$ pydoc telegram.Bot
|
||||
|
||||
-------------
|
||||
_`Extensions`
|
||||
-------------
|
||||
|
||||
The ``telegram.ext`` submodule is built on top of the bare-metal API. It provides an easy-to-use interface to the ``telegram.Bot`` by caring about getting new updates with the ``Updater`` class from telegram and forwarding them to the ``Dispatcher`` class. We can register handler functions in the ``Dispatcher`` to make our bot react to Telegram commands, messages and even arbitrary updates.
|
||||
|
||||
We'll need an Access Token. **Note:** If you have done this in the previous step, you can use that one. To generate an Access Token, we have to talk to `BotFather <https://telegram.me/botfather>`_ and follow a few simple steps (described `here <https://core.telegram.org/bots#botfather>`_).
|
||||
|
||||
First, we create an ``Updater`` object:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> from telegram.ext import Updater
|
||||
>>> updater = Updater(token='token')
|
||||
|
||||
For quicker access to the ``Dispatcher`` used by our ``Updater``, we can introduce it locally:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> dispatcher = updater.dispatcher
|
||||
|
||||
Now, we need to define a function that should process a specific type of update:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> def start(bot, update):
|
||||
... bot.sendMessage(chat_id=update.message.chat_id, text="I'm a bot, please talk to me!")
|
||||
|
||||
We want this function to be called on a Telegram message that contains the ``/start`` command. To do that, we have to use a ``CommandHandler`` object and register it in the dispatcher:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> from telegram.ext import CommandHandler
|
||||
>>> start_handler = CommandHandler('start', start)
|
||||
>>> dispatcher.add_handler(start_handler)
|
||||
|
||||
The last step is to tell the ``Updater`` to start working:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> updater.start_polling()
|
||||
|
||||
Our bot is now up and running (go ahead and try it)! It's not doing anything yet, besides answering to the ``/start`` command. Let's add another handler that listens for regular messages. We're using the `MessageHandler` here to echo to all text messages:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> def echo(bot, update):
|
||||
... bot.sendMessage(chat_id=update.message.chat_id, text=update.message.text)
|
||||
...
|
||||
>>> from telegram.ext import MessageHandler, Filters
|
||||
>>> echo_handler = MessageHandler([Filters.text], echo)
|
||||
>>> dispatcher.add_handler(echo_handler)
|
||||
|
||||
Our bot should now reply to all text messages that are not a command with a message that has the same content.
|
||||
|
||||
Let's add some functionality to our bot. We want to add the ``/caps`` command, that will take some text as parameter and return it in all caps. We can get the arguments that were passed to a command in the handler function:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> def caps(bot, update, args):
|
||||
... text_caps = ' '.join(args).upper()
|
||||
... bot.sendMessage(chat_id=update.message.chat_id, text=text_caps)
|
||||
...
|
||||
>>> caps_handler = CommandHandler('caps', caps, pass_args=True)
|
||||
>>> dispatcher.add_handler(caps_handler)
|
||||
|
||||
To enable our bot to respond to inline queries, we can add the following (you will also have to talk to BotFather):
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> from telegram import InlineQueryResultArticle
|
||||
>>> def inline_caps(bot, update):
|
||||
... query = bot.update.inline_query.query
|
||||
... results = list()
|
||||
... results.append(InlineQueryResultArticle(query.upper(), 'Caps', query.upper()))
|
||||
... bot.answerInlineQuery(update.inline_query.id, results)
|
||||
...
|
||||
>>> from telegram.ext import InlineQueryHandler
|
||||
>>> inline_caps_handler = InlineQueryHandler(inline_caps)
|
||||
>>> dispatcher.add_handler(inline_caps_handler)
|
||||
|
||||
People might try to send commands to the bot that it doesn't understand, so we can use a ``RegexHandler`` to recognize all commands that were not recognized by the previous handlers. **Note:** This handler has to be added last, else it will be triggered before the ``CommandHandlers`` had a chance to look at the update:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> def unknown(bot, update):
|
||||
... bot.sendMessage(chat_id=update.message.chat_id, text="Sorry, I didn't understand that command.")
|
||||
...
|
||||
>>> from telegram.ext import RegexHandler
|
||||
>>> unknown_handler = RegexHandler(r'/.*', unknown)
|
||||
>>> dispatcher.add_handler(unknown_handler)
|
||||
|
||||
If you're done playing around, stop the bot with this:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> updater.stop()
|
||||
|
||||
Check out more examples in the `examples folder <https://github.com/python-telegram-bot/python-telegram-bot/tree/master/examples>`_!
|
||||
|
||||
-----------
|
||||
_`Logging`
|
||||
_`JobQueue`
|
||||
-----------
|
||||
|
||||
You can get logs in your main application by calling `logging` and setting the log level you want::
|
||||
The ``JobQueue`` allows you to perform tasks with a delay or even periodically. The ``Updater`` will create one for you:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> from telegram.ext import Updater
|
||||
>>> u = Updater('TOKEN')
|
||||
>>> j = u.job_queue
|
||||
|
||||
The job queue uses functions for tasks, so we define one and add it to the queue. Usually, when the first job is added to the queue, it wil start automatically. We can prevent this by setting ``prevent_autostart=True``:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> def job1(bot):
|
||||
... bot.sendMessage(chat_id='@examplechannel', text='One message every minute')
|
||||
>>> j.put(job1, 60, next_t=0, prevent_autostart=True)
|
||||
|
||||
You can also have a job that will not be executed repeatedly:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> def job2(bot):
|
||||
... bot.sendMessage(chat_id='@examplechannel', text='A single message with 30s delay')
|
||||
>>> j.put(job2, 30, repeat=False)
|
||||
|
||||
Now, because we didn't prevent the auto start this time, the queue will start ticking. It runs in a seperate thread, so it is non-blocking. When we stop the Updater, the related queue will be stopped as well:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> u.stop()
|
||||
|
||||
We can also stop the job queue by itself:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> j.stop()
|
||||
|
||||
----------
|
||||
_`Logging`
|
||||
----------
|
||||
|
||||
You can get logs in your main application by calling `logging` and setting the log level you want:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> import logging
|
||||
>>> logger = logging.getLogger()
|
||||
>>> logger.setLevel(logging.INFO)
|
||||
|
||||
If you want DEBUG logs instead::
|
||||
If you want DEBUG logs instead:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> logger.setLevel(logging.DEBUG)
|
||||
|
||||
-----------
|
||||
_`Examples`
|
||||
-----------
|
||||
|
||||
Here follows some examples to help you to get your own Bot up to speed:
|
||||
|
||||
- `echobot <https://github.com/leandrotoledo/python-telegram-bot/blob/master/examples/echobot.py>`_ replies back messages.
|
||||
|
||||
- `roboed <https://github.com/leandrotoledo/python-telegram-bot/blob/master/examples/roboed.py>`_ talks to `Robô Ed <http://www.ed.conpet.gov.br/br/converse.php>`_.
|
||||
|
||||
- `Simple-Echo-Telegram-Bot <https://github.com/sooyhwang/Simple-Echo-Telegram-Bot>`_ simple Python Telegram bot that echoes your input with Flask microframework, setWebhook method, and Google App Engine (optional) - by @sooyhwang.
|
||||
|
||||
- `DevOps Reaction Bot <https://github.com/leandrotoledo/gae-devops-reaction-telegram-bot>`_ sends latest or random posts from `DevOps Reaction <http://devopsreactions.tumblr.com/>`_. Running on `Google App Engine <https://cloud.google.com/appengine>`_ (billing has to be enabled for fully Socket API support).
|
||||
|
||||
================
|
||||
_`Documentation`
|
||||
================
|
||||
|
||||
``python-telegram-bot``'s documentation lives at `Read the Docs <http://python-telegram-bot.readthedocs.org/en/latest/>`_.
|
||||
``python-telegram-bot``'s documentation lives at `Read the Docs <https://python-telegram-bot.readthedocs.org/en/latest/>`_.
|
||||
|
||||
===============
|
||||
_`Getting help`
|
||||
===============
|
||||
|
||||
You can get help in several ways:
|
||||
|
||||
1. We have a vibrant community of developers helping each other in our `Telegram group <https://telegram.me/pythontelegrambotgroup>`_. Join us!
|
||||
|
||||
2. You can ask for help on Stack Overflow using the `python-telegram-bot tag <https://stackoverflow.com/questions/tagged/python-telegram-bot>`_.
|
||||
|
||||
3. As last resort, the developers are ready to help you with `serious issues <https://github.com/python-telegram-bot/python-telegram-bot/issues/new>`_.
|
||||
|
||||
|
||||
===============
|
||||
_`Contributing`
|
||||
===============
|
||||
|
||||
Contributions of all sizes are welcome. Please review our `contribution guidelines <https://github.com/python-telegram-bot/python-telegram-bot/blob/master/CONTRIBUTING.rst>`_ to get started. You can also help by `reporting bugs <https://github.com/python-telegram-bot/python-telegram-bot/issues/new>`_.
|
||||
|
||||
==========
|
||||
_`License`
|
||||
==========
|
||||
|
||||
You may copy, distribute and modify the software provided that modifications are described and licensed for free under `LGPL-3 <http://www.gnu.org/licenses/lgpl-3.0.html>`_. Derivatives works (including modifications or anything statically linked to the library) can only be redistributed under `LGPL-3 <http://www.gnu.org/licenses/lgpl-3.0.html>`_, but applications that use the library don't have to be.
|
||||
|
||||
==========
|
||||
_`Contact`
|
||||
==========
|
||||
|
||||
Feel free to join to our `Telegram group <https://telegram.me/joinchat/00b9c0f802509b946b2e8e98b73e19be>`_.
|
||||
|
||||
If you face trouble joining in the group please ping me `via Telegram <https://telegram.me/leandrotoledo>`_, I'll be glad to add you.
|
||||
|
||||
=======
|
||||
_`TODO`
|
||||
=======
|
||||
|
||||
Patches and bug reports are `welcome <https://github.com/leandrotoledo/python-telegram-bot/issues/new>`_, just please keep the style consistent with the original source.
|
||||
|
||||
- Add commands handler.
|
||||
You may copy, distribute and modify the software provided that modifications are described and licensed for free under `LGPL-3 <https://www.gnu.org/licenses/lgpl-3.0.html>`_. Derivatives works (including modifications or anything statically linked to the library) can only be redistributed under `LGPL-3 <https://www.gnu.org/licenses/lgpl-3.0.html>`_, but applications that use the library don't have to be.
|
||||
|
||||
+3
-3
@@ -50,7 +50,7 @@ master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'Python Telegram Bot'
|
||||
copyright = u'2015, Leandro Toledo'
|
||||
copyright = u'2015-2016, Leandro Toledo'
|
||||
author = u'Leandro Toledo'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
@@ -58,9 +58,9 @@ author = u'Leandro Toledo'
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '2.8'
|
||||
version = '4.1'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '2.8.2'
|
||||
release = '4.1.1'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
||||
@@ -3,5 +3,4 @@ telegram.bot module
|
||||
|
||||
.. automodule:: telegram.bot
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
telegram.groupchat module
|
||||
telegram.chat module
|
||||
=========================
|
||||
|
||||
.. automodule:: telegram.groupchat
|
||||
.. automodule:: telegram.chat
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.choseninlineresult module
|
||||
==================================
|
||||
|
||||
.. automodule:: telegram.choseninlineresult
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.ext.handler module
|
||||
===========================
|
||||
|
||||
.. automodule:: telegram.ext.handler
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.ext.choseninlineresulthandler module
|
||||
=============================================
|
||||
|
||||
.. automodule:: telegram.ext.choseninlineresulthandler
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.ext.commandhandler module
|
||||
==================================
|
||||
|
||||
.. automodule:: telegram.ext.commandhandler
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.ext.dispatcher module
|
||||
==============================
|
||||
|
||||
.. automodule:: telegram.ext.dispatcher
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.ext.handler module
|
||||
===========================
|
||||
|
||||
.. automodule:: telegram.ext.handler
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.ext.inlinequeryhandler module
|
||||
======================================
|
||||
|
||||
.. automodule:: telegram.ext.inlinequeryhandler
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.ext.jobqueue module
|
||||
============================
|
||||
|
||||
.. automodule:: telegram.ext.jobqueue
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.ext.messagehandler module
|
||||
==================================
|
||||
|
||||
.. automodule:: telegram.ext.messagehandler
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.ext.regexhandler module
|
||||
================================
|
||||
|
||||
.. automodule:: telegram.ext.regexhandler
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,28 @@
|
||||
telegram.ext package
|
||||
====================
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
.. toctree::
|
||||
|
||||
telegram.ext.updater
|
||||
telegram.ext.dispatcher
|
||||
telegram.ext.jobqueue
|
||||
telegram.ext.handler
|
||||
telegram.ext.choseninlineresulthandler
|
||||
telegram.ext.commandhandler
|
||||
telegram.ext.inlinequeryhandler
|
||||
telegram.ext.messagehandler
|
||||
telegram.ext.regexhandler
|
||||
telegram.ext.stringcommandhandler
|
||||
telegram.ext.stringregexhandler
|
||||
telegram.ext.typehandler
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. automodule:: telegram.ext
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.ext.stringcommandhandler module
|
||||
========================================
|
||||
|
||||
.. automodule:: telegram.ext.stringcommandhandler
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.ext.stringregexhandler module
|
||||
======================================
|
||||
|
||||
.. automodule:: telegram.ext.stringregexhandler
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.ext.typehandler module
|
||||
===============================
|
||||
|
||||
.. automodule:: telegram.ext.typehandler
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.ext.updater module
|
||||
===========================
|
||||
|
||||
.. automodule:: telegram.ext.updater
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inlinekeyboardbutton module
|
||||
===========================
|
||||
|
||||
.. automodule:: telegram.inlinekeyboardbutton
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inlinekeyboardmarkup module
|
||||
==========================
|
||||
|
||||
.. automodule:: telegram.inlinekeyboardmarkup
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inlinequery module
|
||||
===========================
|
||||
|
||||
.. automodule:: telegram.inlinequery
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inlinequeryresult module
|
||||
=================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresult
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inlinequeryresultarticle module
|
||||
=================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultarticle
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inlinequeryresultaudio module
|
||||
=================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultaudio
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inlinequeryresultcachedaudio module
|
||||
=================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultcachedaudio
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inlinequeryresultcacheddocument module
|
||||
=================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultcacheddocument
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inlinequeryresultcachedgif module
|
||||
=================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultcachedgif
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inlinequeryresultcachedmpeg4gif module
|
||||
=================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultcachedmpeg4gif
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inlinequeryresultcachedphoto module
|
||||
=================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultcachedphoto
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inlinequeryresultcachedsticker module
|
||||
=================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultcachedsticker
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inlinequeryresultcachedvideo module
|
||||
=================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultcachedvideo
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inlinequeryresultcachedvoice module
|
||||
=================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultcachedvoice
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inlinequeryresultcontact module
|
||||
=================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultcontact
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inlinequeryresultdocument module
|
||||
=================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultdocument
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inlinequeryresultgif module
|
||||
=================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultgif
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inlinequeryresultlocation module
|
||||
=================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultlocation
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inlinequeryresultmpeg4gif module
|
||||
=================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultmpeg4gif
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inlinequeryresultphoto module
|
||||
=================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultphoto
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inlinequeryresultvenue module
|
||||
=================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultvenue
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inlinequeryresultvideo module
|
||||
=================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultvideo
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inlinequeryresultvoice module
|
||||
=================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultvoice
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -9,13 +9,38 @@ Submodules
|
||||
telegram.audio
|
||||
telegram.base
|
||||
telegram.bot
|
||||
telegram.ext
|
||||
telegram.inlinequery
|
||||
telegram.inlinequeryresult
|
||||
telegram.inlinekeyboardbutton
|
||||
telegram.inlinekeyboardmarkup
|
||||
telegram.inlinequeryresultarticle
|
||||
telegram.inlinequeryresultaudio
|
||||
telegram.inlinequeryresultcachedaudio
|
||||
telegram.inlinequeryresultcacheddocument
|
||||
telegram.inlinequeryresultcachedgif
|
||||
telegram.inlinequeryresultcachedmpeg4gif
|
||||
telegram.inlinequeryresultcachedphoto
|
||||
telegram.inlinequeryresultcachedsticker
|
||||
telegram.inlinequeryresultcachedvideo
|
||||
telegram.inlinequeryresultcachedvoice
|
||||
telegram.inlinequeryresultcontact
|
||||
telegram.inlinequeryresultdocument
|
||||
telegram.inlinequeryresultgif
|
||||
telegram.inlinequeryresultlocation
|
||||
telegram.inlinequeryresultmpeg4gif
|
||||
telegram.inlinequeryresultphoto
|
||||
telegram.inlinequeryresultvenue
|
||||
telegram.inlinequeryresultvideo
|
||||
telegram.inlinequeryresultvoice
|
||||
telegram.choseninlineresult
|
||||
telegram.chataction
|
||||
telegram.contact
|
||||
telegram.document
|
||||
telegram.emoji
|
||||
telegram.error
|
||||
telegram.forcereply
|
||||
telegram.groupchat
|
||||
telegram.chat
|
||||
telegram.inputfile
|
||||
telegram.location
|
||||
telegram.message
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
CC0 1.0 Universal
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator and
|
||||
subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for the
|
||||
purpose of contributing to a commons of creative, cultural and scientific
|
||||
works ("Commons") that the public can reliably and without fear of later
|
||||
claims of infringement build upon, modify, incorporate in other works, reuse
|
||||
and redistribute as freely as possible in any form whatsoever and for any
|
||||
purposes, including without limitation commercial purposes. These owners may
|
||||
contribute to the Commons to promote the ideal of a free culture and the
|
||||
further production of creative, cultural and scientific works, or to gain
|
||||
reputation or greater distribution for their Work in part through the use and
|
||||
efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any expectation
|
||||
of additional consideration or compensation, the person associating CC0 with a
|
||||
Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
|
||||
and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
|
||||
and publicly distribute the Work under its terms, with knowledge of his or her
|
||||
Copyright and Related Rights in the Work and the meaning and intended legal
|
||||
effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not limited
|
||||
to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display, communicate,
|
||||
and translate a Work;
|
||||
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
|
||||
iii. publicity and privacy rights pertaining to a person's image or likeness
|
||||
depicted in a Work;
|
||||
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data in
|
||||
a Work;
|
||||
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation thereof,
|
||||
including any amended or successor version of such directive); and
|
||||
|
||||
vii. other similar, equivalent or corresponding rights throughout the world
|
||||
based on applicable law or treaty, and any national implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention of,
|
||||
applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
|
||||
unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
|
||||
and Related Rights and associated claims and causes of action, whether now
|
||||
known or unknown (including existing as well as future claims and causes of
|
||||
action), in the Work (i) in all territories worldwide, (ii) for the maximum
|
||||
duration provided by applicable law or treaty (including future time
|
||||
extensions), (iii) in any current or future medium and for any number of
|
||||
copies, and (iv) for any purpose whatsoever, including without limitation
|
||||
commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
|
||||
the Waiver for the benefit of each member of the public at large and to the
|
||||
detriment of Affirmer's heirs and successors, fully intending that such Waiver
|
||||
shall not be subject to revocation, rescission, cancellation, termination, or
|
||||
any other legal or equitable action to disrupt the quiet enjoyment of the Work
|
||||
by the public as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason be
|
||||
judged legally invalid or ineffective under applicable law, then the Waiver
|
||||
shall be preserved to the maximum extent permitted taking into account
|
||||
Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
|
||||
is so judged Affirmer hereby grants to each affected person a royalty-free,
|
||||
non transferable, non sublicensable, non exclusive, irrevocable and
|
||||
unconditional license to exercise Affirmer's Copyright and Related Rights in
|
||||
the Work (i) in all territories worldwide, (ii) for the maximum duration
|
||||
provided by applicable law or treaty (including future time extensions), (iii)
|
||||
in any current or future medium and for any number of copies, and (iv) for any
|
||||
purpose whatsoever, including without limitation commercial, advertising or
|
||||
promotional purposes (the "License"). The License shall be deemed effective as
|
||||
of the date CC0 was applied by Affirmer to the Work. Should any part of the
|
||||
License for any reason be judged legally invalid or ineffective under
|
||||
applicable law, such partial invalidity or ineffectiveness shall not
|
||||
invalidate the remainder of the License, and in such case Affirmer hereby
|
||||
affirms that he or she will not (i) exercise any of his or her remaining
|
||||
Copyright and Related Rights in the Work or (ii) assert any associated claims
|
||||
and causes of action with respect to the Work, in either case contrary to
|
||||
Affirmer's express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
|
||||
b. Affirmer offers the Work as-is and makes no representations or warranties
|
||||
of any kind concerning the Work, express, implied, statutory or otherwise,
|
||||
including without limitation warranties of title, merchantability, fitness
|
||||
for a particular purpose, non infringement, or the absence of latent or
|
||||
other defects, accuracy, or the present or absence of errors, whether or not
|
||||
discoverable, all to the greatest extent permissible under applicable law.
|
||||
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without limitation
|
||||
any person's Copyright and Related Rights in the Work. Further, Affirmer
|
||||
disclaims responsibility for obtaining any necessary consents, permissions
|
||||
or other rights required for any use of the Work.
|
||||
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to this
|
||||
CC0 or use of the Work.
|
||||
|
||||
For more information, please see
|
||||
<http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
@@ -0,0 +1,170 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Example Bot to show some of the functionality of the library
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
This Bot uses the Updater class to handle the bot.
|
||||
|
||||
First, a few handler functions are defined. Then, those functions are passed to
|
||||
the Dispatcher and registered at their respective places.
|
||||
Then, the bot is started and the CLI-Loop is entered, where all text inputs are
|
||||
inserted into the update queue for the bot to handle.
|
||||
|
||||
Usage:
|
||||
Repeats messages with a delay.
|
||||
Reply to last chat from the command line by typing "/reply <text>"
|
||||
Type 'stop' on the command line to stop the bot.
|
||||
"""
|
||||
|
||||
from telegram.ext import Updater, StringCommandHandler, StringRegexHandler, \
|
||||
MessageHandler, CommandHandler, RegexHandler, Filters
|
||||
from telegram.ext.dispatcher import run_async
|
||||
from time import sleep
|
||||
import logging
|
||||
|
||||
from future.builtins import input
|
||||
|
||||
# Enable Logging
|
||||
logging.basicConfig(
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||
level=logging.INFO)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# We use this var to save the last chat id, so we can reply to it
|
||||
last_chat_id = 0
|
||||
|
||||
|
||||
# Define a few (command) handler callback functions. These usually take the
|
||||
# two arguments bot and update. Error handlers also receive the raised
|
||||
# TelegramError object in error.
|
||||
def start(bot, update):
|
||||
""" Answer in Telegram """
|
||||
bot.sendMessage(update.message.chat_id, text='Hi!')
|
||||
|
||||
|
||||
def help(bot, update):
|
||||
""" Answer in Telegram """
|
||||
bot.sendMessage(update.message.chat_id, text='Help!')
|
||||
|
||||
|
||||
def any_message(bot, update):
|
||||
""" Print to console """
|
||||
|
||||
# Save last chat_id to use in reply handler
|
||||
global last_chat_id
|
||||
last_chat_id = update.message.chat_id
|
||||
|
||||
logger.info("New message\nFrom: %s\nchat_id: %d\nText: %s" %
|
||||
(update.message.from_user,
|
||||
update.message.chat_id,
|
||||
update.message.text))
|
||||
|
||||
|
||||
@run_async
|
||||
def message(bot, update):
|
||||
"""
|
||||
Example for an asynchronous handler. It's not guaranteed that replies will
|
||||
be in order when using @run_async. Also, you have to include **kwargs in
|
||||
your parameter list. The kwargs contain all optional parameters that are
|
||||
"""
|
||||
|
||||
sleep(2) # IO-heavy operation here
|
||||
bot.sendMessage(update.message.chat_id, text='Echo: %s' %
|
||||
update.message.text)
|
||||
|
||||
|
||||
# These handlers are for updates of type str. We use them to react to inputs
|
||||
# on the command line interface
|
||||
def cli_reply(bot, update, args):
|
||||
"""
|
||||
For any update of type telegram.Update or str that contains a command, you
|
||||
can get the argument list by appending args to the function parameters.
|
||||
Here, we reply to the last active chat with the text after the command.
|
||||
"""
|
||||
if last_chat_id is not 0:
|
||||
bot.sendMessage(chat_id=last_chat_id, text=' '.join(args))
|
||||
|
||||
|
||||
def cli_noncommand(bot, update, update_queue):
|
||||
"""
|
||||
You can also get the update queue as an argument in any handler by
|
||||
appending it to the argument list. Be careful with this though.
|
||||
Here, we put the input string back into the queue, but as a command.
|
||||
|
||||
To learn more about those optional handler parameters, read the
|
||||
documentation of the Handler classes.
|
||||
"""
|
||||
update_queue.put('/%s' % update)
|
||||
|
||||
|
||||
def error(bot, update, error):
|
||||
""" Print error to console """
|
||||
logger.warn('Update %s caused error %s' % (update, error))
|
||||
|
||||
|
||||
def main():
|
||||
# Create the EventHandler and pass it your bot's token.
|
||||
token = 'TOKEN'
|
||||
updater = Updater(token, workers=10)
|
||||
|
||||
# Get the dispatcher to register handlers
|
||||
dp = updater.dispatcher
|
||||
|
||||
# This is how we add handlers for Telegram messages
|
||||
dp.add_handler(CommandHandler("start", start))
|
||||
dp.add_handler(CommandHandler("help", help))
|
||||
# Message handlers only receive updates that don't contain commands
|
||||
dp.add_handler(MessageHandler([Filters.text], message))
|
||||
# Regex handlers will receive all updates on which their regex matches,
|
||||
# but we have to add it in a separate group, since in one group,
|
||||
# only one handler will be executed
|
||||
dp.add_handler(RegexHandler('.*', any_message), group=1)
|
||||
|
||||
# String handlers work pretty much the same. Note that we have to tell
|
||||
# the handler to pass the args or update_queue parameter
|
||||
dp.add_handler(StringCommandHandler('reply', cli_reply, pass_args=True))
|
||||
dp.add_handler(StringRegexHandler('[^/].*', cli_noncommand,
|
||||
pass_update_queue=True))
|
||||
|
||||
# All TelegramErrors are caught for you and delivered to the error
|
||||
# handler(s). Other types of Errors are not caught.
|
||||
dp.add_error_handler(error)
|
||||
|
||||
# Start the Bot and store the update Queue, so we can insert updates
|
||||
update_queue = updater.start_polling(timeout=10)
|
||||
|
||||
'''
|
||||
# Alternatively, run with webhook:
|
||||
|
||||
update_queue = updater.start_webhook('0.0.0.0',
|
||||
443,
|
||||
url_path=token,
|
||||
cert='cert.pem',
|
||||
key='key.key',
|
||||
webhook_url='https://example.com/%s'
|
||||
% token)
|
||||
|
||||
# Or, if SSL is handled by a reverse proxy, the webhook URL is already set
|
||||
# and the reverse proxy is configured to deliver directly to port 6000:
|
||||
|
||||
update_queue = updater.start_webhook('0.0.0.0', 6000)
|
||||
'''
|
||||
|
||||
# Start CLI-Loop
|
||||
while True:
|
||||
text = input()
|
||||
|
||||
# Gracefully stop the event handler
|
||||
if text == 'stop':
|
||||
updater.stop()
|
||||
break
|
||||
|
||||
# else, put the text into the update queue to be handled by our handlers
|
||||
elif len(text) > 0:
|
||||
update_queue.put(text)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,66 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Simple Bot to reply Telegram messages
|
||||
# Copyright (C) 2015 Leandro Toledo de Souza <leandrotoeldodesouza@gmail.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
|
||||
|
||||
import logging
|
||||
import telegram
|
||||
|
||||
|
||||
LAST_UPDATE_ID = None
|
||||
|
||||
|
||||
def main():
|
||||
global LAST_UPDATE_ID
|
||||
|
||||
logging.basicConfig(
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
||||
|
||||
# Telegram Bot Authorization Token
|
||||
bot = telegram.Bot('TOKEN')
|
||||
|
||||
# This will be our global variable to keep the latest update_id when requesting
|
||||
# for updates. It starts with the latest update_id if available.
|
||||
try:
|
||||
LAST_UPDATE_ID = bot.getUpdates()[-1].update_id
|
||||
except IndexError:
|
||||
LAST_UPDATE_ID = None
|
||||
|
||||
while True:
|
||||
echo(bot)
|
||||
|
||||
|
||||
def echo(bot):
|
||||
global LAST_UPDATE_ID
|
||||
|
||||
# Request updates after the last updated_id
|
||||
for update in bot.getUpdates(offset=LAST_UPDATE_ID, timeout=10):
|
||||
# chat_id is required to reply any message
|
||||
chat_id = update.message.chat_id
|
||||
message = update.message.text.encode('utf-8')
|
||||
|
||||
if (message):
|
||||
# Reply the message
|
||||
bot.sendMessage(chat_id=chat_id,
|
||||
text=message)
|
||||
|
||||
# Updates global offset to get the new updates
|
||||
LAST_UPDATE_ID = update.update_id + 1
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Simple Bot to reply to Telegram messages
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
This Bot uses the Updater class to handle the bot.
|
||||
|
||||
First, a few handler functions are defined. Then, those functions are passed to
|
||||
the Dispatcher and registered at their respective places.
|
||||
Then, the bot is started and runs until we press Ctrl-C on the command line.
|
||||
|
||||
Usage:
|
||||
Basic Echobot example, repeats messages.
|
||||
Press Ctrl-C on the command line or send a signal to the process to stop the
|
||||
bot.
|
||||
"""
|
||||
|
||||
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters
|
||||
import logging
|
||||
|
||||
# Enable logging
|
||||
logging.basicConfig(
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||
level=logging.INFO)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# Define a few command handlers. These usually take the two arguments bot and
|
||||
# update. Error handlers also receive the raised TelegramError object in error.
|
||||
def start(bot, update):
|
||||
bot.sendMessage(update.message.chat_id, text='Hi!')
|
||||
|
||||
|
||||
def help(bot, update):
|
||||
bot.sendMessage(update.message.chat_id, text='Help!')
|
||||
|
||||
|
||||
def echo(bot, update):
|
||||
bot.sendMessage(update.message.chat_id, text=update.message.text)
|
||||
|
||||
|
||||
def error(bot, update, error):
|
||||
logger.warn('Update "%s" caused error "%s"' % (update, error))
|
||||
|
||||
|
||||
def main():
|
||||
# Create the EventHandler and pass it your bot's token.
|
||||
updater = Updater("TOKEN")
|
||||
|
||||
# Get the dispatcher to register handlers
|
||||
dp = updater.dispatcher
|
||||
|
||||
# on different commands - answer in Telegram
|
||||
dp.add_handler(CommandHandler("start", start))
|
||||
dp.add_handler(CommandHandler("help", help))
|
||||
|
||||
# on noncommand i.e message - echo the message on Telegram
|
||||
dp.add_handler(MessageHandler([Filters.text], echo))
|
||||
|
||||
# log all errors
|
||||
dp.add_error_handler(error)
|
||||
|
||||
# Start the Bot
|
||||
updater.start_polling()
|
||||
|
||||
# Run the bot until the you presses Ctrl-C or the process receives SIGINT,
|
||||
# SIGTERM or SIGABRT. This should be used most of the time, since
|
||||
# start_polling() is non-blocking and will stop the bot gracefully.
|
||||
updater.idle()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,108 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Simple Bot to reply to Telegram messages
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
This Bot uses the Updater class to handle the bot.
|
||||
|
||||
First, a few handler functions are defined. Then, those functions are passed to
|
||||
the Dispatcher and registered at their respective places.
|
||||
Then, the bot is started and runs until we press Ctrl-C on the command line.
|
||||
|
||||
Usage:
|
||||
Basic inline bot example. Applies different text transformations.
|
||||
Press Ctrl-C on the command line or send a signal to the process to stop the
|
||||
bot.
|
||||
"""
|
||||
from uuid import uuid4
|
||||
|
||||
import re
|
||||
|
||||
from telegram import InlineQueryResultArticle, ParseMode, \
|
||||
InputTextMessageContent
|
||||
from telegram.ext import Updater, InlineQueryHandler, CommandHandler
|
||||
import logging
|
||||
|
||||
# Enable logging
|
||||
logging.basicConfig(
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||
level=logging.INFO)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# Define a few command handlers. These usually take the two arguments bot and
|
||||
# update. Error handlers also receive the raised TelegramError object in error.
|
||||
def start(bot, update):
|
||||
bot.sendMessage(update.message.chat_id, text='Hi!')
|
||||
|
||||
|
||||
def help(bot, update):
|
||||
bot.sendMessage(update.message.chat_id, text='Help!')
|
||||
|
||||
|
||||
def escape_markdown(text):
|
||||
"""Helper function to escape telegram markup symbols"""
|
||||
escape_chars = '\*_`\['
|
||||
return re.sub(r'([%s])' % escape_chars, r'\\\1', text)
|
||||
|
||||
|
||||
def inlinequery(bot, update):
|
||||
query = update.inline_query.query
|
||||
results = list()
|
||||
|
||||
results.append(InlineQueryResultArticle(
|
||||
id=uuid4(),
|
||||
title="Caps",
|
||||
input_message_content=InputTextMessageContent(query.upper())))
|
||||
|
||||
results.append(InlineQueryResultArticle(
|
||||
id=uuid4(),
|
||||
title="Bold",
|
||||
input_message_content=InputTextMessageContent(
|
||||
"*%s*" % escape_markdown(query),
|
||||
parse_mode=ParseMode.MARKDOWN)))
|
||||
|
||||
results.append(InlineQueryResultArticle(
|
||||
id=uuid4(),
|
||||
title="Italic",
|
||||
input_message_content=InputTextMessageContent(
|
||||
"_%s_" % escape_markdown(query),
|
||||
parse_mode=ParseMode.MARKDOWN)))
|
||||
|
||||
bot.answerInlineQuery(update.inline_query.id, results=results)
|
||||
|
||||
|
||||
def error(bot, update, error):
|
||||
logger.warn('Update "%s" caused error "%s"' % (update, error))
|
||||
|
||||
|
||||
def main():
|
||||
# Create the Updater and pass it your bot's token.
|
||||
updater = Updater("TOKEN")
|
||||
|
||||
# Get the dispatcher to register handlers
|
||||
dp = updater.dispatcher
|
||||
|
||||
# on different commands - answer in Telegram
|
||||
dp.add_handler(CommandHandler("start", start))
|
||||
dp.add_handler(CommandHandler("help", help))
|
||||
|
||||
# on noncommand i.e message - echo the message on Telegram
|
||||
dp.add_handler(InlineQueryHandler(inlinequery))
|
||||
|
||||
# log all errors
|
||||
dp.add_error_handler(error)
|
||||
|
||||
# Start the Bot
|
||||
updater.start_polling()
|
||||
|
||||
# Block until the user presses Ctrl-C or the process receives SIGINT,
|
||||
# SIGTERM or SIGABRT. This should be used most of the time, since
|
||||
# start_polling() is non-blocking and will stop the bot gracefully.
|
||||
updater.idle()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,120 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Basic example for a bot that awaits an answer from the user. It's built upon
|
||||
# the state_machine_bot.py example
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
import logging
|
||||
from telegram import Emoji, ForceReply, InlineKeyboardButton, \
|
||||
InlineKeyboardMarkup
|
||||
from telegram.ext import Updater, CommandHandler, MessageHandler, \
|
||||
CallbackQueryHandler, Filters
|
||||
|
||||
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - '
|
||||
'%(message)s',
|
||||
level=logging.DEBUG)
|
||||
|
||||
# Define the different states a chat can be in
|
||||
MENU, AWAIT_CONFIRMATION, AWAIT_INPUT = range(3)
|
||||
|
||||
# Python 2 and 3 unicode differences
|
||||
try:
|
||||
YES, NO = (Emoji.THUMBS_UP_SIGN.decode('utf-8'),
|
||||
Emoji.THUMBS_DOWN_SIGN.decode('utf-8'))
|
||||
except AttributeError:
|
||||
YES, NO = (Emoji.THUMBS_UP_SIGN, Emoji.THUMBS_DOWN_SIGN)
|
||||
|
||||
# States are saved in a dict that maps chat_id -> state
|
||||
state = dict()
|
||||
# Sometimes you need to save data temporarily
|
||||
context = dict()
|
||||
# This dict is used to store the settings value for the chat.
|
||||
# Usually, you'd use persistence for this (e.g. sqlite).
|
||||
values = dict()
|
||||
|
||||
|
||||
# Example handler. Will be called on the /set command and on regular messages
|
||||
def set_value(bot, update):
|
||||
chat_id = update.message.chat_id
|
||||
user_id = update.message.from_user.id
|
||||
user_state = state.get(chat_id, MENU)
|
||||
|
||||
if user_state == MENU:
|
||||
state[user_id] = AWAIT_INPUT # set the state
|
||||
bot.sendMessage(chat_id,
|
||||
text="Please enter your settings value",
|
||||
reply_markup=ForceReply())
|
||||
|
||||
|
||||
def entered_value(bot, update):
|
||||
chat_id = update.message.chat_id
|
||||
user_id = update.message.from_user.id
|
||||
chat_state = state.get(user_id, MENU)
|
||||
|
||||
# Check if we are waiting for input
|
||||
if chat_state == AWAIT_INPUT:
|
||||
state[user_id] = AWAIT_CONFIRMATION
|
||||
|
||||
# Save the user id and the answer to context
|
||||
context[user_id] = update.message.text
|
||||
reply_markup = InlineKeyboardMarkup(
|
||||
[[InlineKeyboardButton(YES, callback_data=YES),
|
||||
InlineKeyboardButton(NO, callback_data=NO)]])
|
||||
bot.sendMessage(chat_id, text="Are you sure?",
|
||||
reply_markup=reply_markup)
|
||||
|
||||
|
||||
def confirm_value(bot, update):
|
||||
query = update.callback_query
|
||||
chat_id = query.message.chat_id
|
||||
user_id = query.from_user.id
|
||||
text = query.data
|
||||
user_state = state.get(user_id, MENU)
|
||||
user_context = context.get(user_id, None)
|
||||
|
||||
# Check if we are waiting for confirmation and the right user answered
|
||||
if user_state == AWAIT_CONFIRMATION:
|
||||
del state[user_id]
|
||||
del context[user_id]
|
||||
bot.answerCallbackQuery(query.id, text="Ok!")
|
||||
if text == YES:
|
||||
values[user_id] = user_context
|
||||
bot.editMessageText(text="Changed value to %s." % values[user_id],
|
||||
chat_id=chat_id,
|
||||
message_id=
|
||||
query.message.message_id)
|
||||
else:
|
||||
bot.editMessageText(text="Alright, value is still %s."
|
||||
% values.get(user_id, 'not set'),
|
||||
chat_id=chat_id,
|
||||
message_id=
|
||||
query.message.message_id)
|
||||
|
||||
|
||||
def help(bot, update):
|
||||
bot.sendMessage(update.message.chat_id, text="Use /set to test this bot.")
|
||||
|
||||
|
||||
def error(bot, update, error):
|
||||
logging.warning('Update "%s" caused error "%s"' % (update, error))
|
||||
|
||||
# Create the Updater and pass it your bot's token.
|
||||
updater = Updater("TOKEN")
|
||||
|
||||
# The command
|
||||
updater.dispatcher.addHandler(CommandHandler('set', set_value))
|
||||
# The answer
|
||||
updater.dispatcher.add_handler(MessageHandler([Filters.text], entered_value))
|
||||
# The confirmation
|
||||
updater.dispatcher.add_handler(CallbackQueryHandler(confirm_value))
|
||||
updater.dispatcher.add_handler(CommandHandler('start', help))
|
||||
updater.dispatcher.add_handler(CommandHandler('help', help))
|
||||
updater.dispatcher.add_error_handler(error)
|
||||
|
||||
# Start the Bot
|
||||
updater.start_polling()
|
||||
|
||||
# Run the bot until the user presses Ctrl-C or the process receives SIGINT,
|
||||
# SIGTERM or SIGABRT
|
||||
updater.idle()
|
||||
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Simple Bot to reply to Telegram messages
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
import logging
|
||||
import telegram
|
||||
from telegram.error import NetworkError, Unauthorized
|
||||
from time import sleep
|
||||
|
||||
|
||||
def main():
|
||||
# Telegram Bot Authorization Token
|
||||
bot = telegram.Bot('TOKEN')
|
||||
|
||||
# get the first pending update_id, this is so we can skip over it in case
|
||||
# we get an "Unauthorized" exception.
|
||||
try:
|
||||
update_id = bot.getUpdates()[0].update_id
|
||||
except IndexError:
|
||||
update_id = None
|
||||
|
||||
logging.basicConfig(
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
||||
|
||||
while True:
|
||||
try:
|
||||
update_id = echo(bot, update_id)
|
||||
except NetworkError:
|
||||
sleep(1)
|
||||
except Unauthorized:
|
||||
# The user has removed or blocked the bot.
|
||||
update_id += 1
|
||||
|
||||
|
||||
def echo(bot, update_id):
|
||||
|
||||
# Request updates after the last update_id
|
||||
for update in bot.getUpdates(offset=update_id, timeout=10):
|
||||
# chat_id is required to reply to any message
|
||||
chat_id = update.message.chat_id
|
||||
update_id = update.update_id + 1
|
||||
message = update.message.text
|
||||
|
||||
if message:
|
||||
# Reply to the message
|
||||
bot.sendMessage(chat_id=chat_id,
|
||||
text=message)
|
||||
|
||||
return update_id
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -2,23 +2,7 @@
|
||||
# encoding: utf-8
|
||||
#
|
||||
# Robô Ed Telegram Bot
|
||||
# Copyright (C) 2015 Leandro Toledo de Souza <leandrotoeldodesouza@gmail.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
|
||||
|
||||
__author__ = 'leandrotoledodesouza@gmail.com'
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
import logging
|
||||
import telegram
|
||||
@@ -0,0 +1,106 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Basic example for a bot that awaits an answer from the user
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
import logging
|
||||
from telegram import Emoji, ForceReply, ReplyKeyboardMarkup, KeyboardButton
|
||||
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters
|
||||
|
||||
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - '
|
||||
'%(message)s',
|
||||
level=logging.INFO)
|
||||
|
||||
# Define the different states a chat can be in
|
||||
MENU, AWAIT_CONFIRMATION, AWAIT_INPUT = range(3)
|
||||
|
||||
# Python 2 and 3 unicode differences
|
||||
try:
|
||||
YES, NO = (Emoji.THUMBS_UP_SIGN.decode('utf-8'),
|
||||
Emoji.THUMBS_DOWN_SIGN.decode('utf-8'))
|
||||
except AttributeError:
|
||||
YES, NO = (Emoji.THUMBS_UP_SIGN, Emoji.THUMBS_DOWN_SIGN)
|
||||
|
||||
# States are saved in a dict that maps chat_id -> state
|
||||
state = dict()
|
||||
# Sometimes you need to save data temporarily
|
||||
context = dict()
|
||||
# This dict is used to store the settings value for the chat.
|
||||
# Usually, you'd use persistence for this (e.g. sqlite).
|
||||
values = dict()
|
||||
|
||||
|
||||
# Example handler. Will be called on the /set command and on regular messages
|
||||
def set_value(bot, update):
|
||||
chat_id = update.message.chat_id
|
||||
user_id = update.message.from_user.id
|
||||
text = update.message.text
|
||||
chat_state = state.get(chat_id, MENU)
|
||||
chat_context = context.get(chat_id, None)
|
||||
|
||||
# Since the handler will also be called on messages, we need to check if
|
||||
# the message is actually a command
|
||||
if chat_state == MENU and text[0] == '/':
|
||||
state[chat_id] = AWAIT_INPUT # set the state
|
||||
context[chat_id] = user_id # save the user id to context
|
||||
bot.sendMessage(chat_id,
|
||||
text="Please enter your settings value or send "
|
||||
"/cancel to abort",
|
||||
reply_markup=ForceReply())
|
||||
|
||||
# If we are waiting for input and the right user answered
|
||||
elif chat_state == AWAIT_INPUT and chat_context == user_id:
|
||||
state[chat_id] = AWAIT_CONFIRMATION
|
||||
|
||||
# Save the user id and the answer to context
|
||||
context[chat_id] = (user_id, update.message.text)
|
||||
reply_markup = ReplyKeyboardMarkup(
|
||||
[[KeyboardButton(YES), KeyboardButton(NO)]],
|
||||
one_time_keyboard=True)
|
||||
bot.sendMessage(chat_id, text="Are you sure?",
|
||||
reply_markup=reply_markup)
|
||||
|
||||
# If we are waiting for confirmation and the right user answered
|
||||
elif chat_state == AWAIT_CONFIRMATION and chat_context[0] == user_id:
|
||||
del state[chat_id]
|
||||
del context[chat_id]
|
||||
if text == YES:
|
||||
values[chat_id] = chat_context[1]
|
||||
bot.sendMessage(chat_id,
|
||||
text="Changed value to %s." % values[chat_id])
|
||||
else:
|
||||
bot.sendMessage(chat_id,
|
||||
text="Value not changed: %s."
|
||||
% values.get(chat_id, '<not set>'))
|
||||
|
||||
|
||||
# Handler for the /cancel command.
|
||||
# Sets the state back to MENU and clears the context
|
||||
def cancel(bot, update):
|
||||
chat_id = update.message.chat_id
|
||||
del state[chat_id]
|
||||
del context[chat_id]
|
||||
|
||||
|
||||
def help(bot, update):
|
||||
bot.sendMessage(update.message.chat_id, text="Use /set to test this bot.")
|
||||
|
||||
|
||||
# Create the Updater and pass it your bot's token.
|
||||
updater = Updater("TOKEN")
|
||||
|
||||
# The command
|
||||
updater.dispatcher.add_handler(CommandHandler('set', set_value))
|
||||
# The answer and confirmation
|
||||
updater.dispatcher.add_handler(MessageHandler([Filters.text], set_value))
|
||||
updater.dispatcher.add_handler(CommandHandler('cancel', cancel))
|
||||
updater.dispatcher.add_handler(CommandHandler('start', help))
|
||||
updater.dispatcher.add_handler(CommandHandler('help', help))
|
||||
|
||||
# Start the Bot
|
||||
updater.start_polling()
|
||||
|
||||
# Run the bot until the user presses Ctrl-C or the process receives SIGINT,
|
||||
# SIGTERM or SIGABRT
|
||||
updater.idle()
|
||||
@@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Simple Bot to send timed Telegram messages
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
This Bot uses the Updater class to handle the bot and the JobQueue to send
|
||||
timed messages.
|
||||
|
||||
First, a few handler functions are defined. Then, those functions are passed to
|
||||
the Dispatcher and registered at their respective places.
|
||||
Then, the bot is started and runs until we press Ctrl-C on the command line.
|
||||
|
||||
Usage:
|
||||
Basic Alarm Bot example, sends a message after a set time.
|
||||
Press Ctrl-C on the command line or send a signal to the process to stop the
|
||||
bot.
|
||||
"""
|
||||
|
||||
from telegram.ext import Updater, CommandHandler
|
||||
import logging
|
||||
|
||||
# Enable logging
|
||||
logging.basicConfig(
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||
level=logging.INFO)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
job_queue = None
|
||||
|
||||
|
||||
# Define a few command handlers. These usually take the two arguments bot and
|
||||
# update. Error handlers also receive the raised TelegramError object in error.
|
||||
def start(bot, update):
|
||||
bot.sendMessage(update.message.chat_id, text='Hi! Use /set <seconds> to '
|
||||
'set a timer')
|
||||
|
||||
|
||||
def set(bot, update, args):
|
||||
""" Adds a job to the queue """
|
||||
chat_id = update.message.chat_id
|
||||
try:
|
||||
# args[0] should contain the time for the timer in seconds
|
||||
due = int(args[0])
|
||||
if due < 0:
|
||||
bot.sendMessage(chat_id, text='Sorry we can not go back to future!')
|
||||
def alarm(bot):
|
||||
""" Inner function to send the alarm message """
|
||||
bot.sendMessage(chat_id, text='Beep!')
|
||||
|
||||
# Add job to queue
|
||||
job_queue.put(alarm, due, repeat=False)
|
||||
bot.sendMessage(chat_id, text='Timer successfully set!')
|
||||
|
||||
except IndexError:
|
||||
bot.sendMessage(chat_id, text='Usage: /set <seconds>')
|
||||
except ValueError:
|
||||
bot.sendMessage(chat_id, text='Usage: /set <seconds>')
|
||||
|
||||
|
||||
def error(bot, update, error):
|
||||
logger.warn('Update "%s" caused error "%s"' % (update, error))
|
||||
|
||||
|
||||
def main():
|
||||
global job_queue
|
||||
|
||||
updater = Updater("TOKEN")
|
||||
job_queue = updater.job_queue
|
||||
|
||||
# Get the dispatcher to register handlers
|
||||
dp = updater.dispatcher
|
||||
|
||||
# on different commands - answer in Telegram
|
||||
dp.add_handler(CommandHandler("start", start))
|
||||
dp.add_handler(CommandHandler("help", start))
|
||||
dp.add_handler(CommandHandler("set", set, pass_args=True))
|
||||
|
||||
# log all errors
|
||||
dp.add_error_handler(error)
|
||||
|
||||
# Start the Bot
|
||||
updater.start_polling()
|
||||
|
||||
# Block until the you presses Ctrl-C or the process receives SIGINT,
|
||||
# SIGTERM or SIGABRT. This should be used most of the time, since
|
||||
# start_polling() is non-blocking and will stop the bot gracefully.
|
||||
updater.idle()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,9 @@
|
||||
flake8
|
||||
nose
|
||||
pep257
|
||||
pylint
|
||||
unittest2
|
||||
flaky
|
||||
yapf
|
||||
pre-commit
|
||||
pre-commit-hooks
|
||||
@@ -0,0 +1 @@
|
||||
future
|
||||
@@ -8,3 +8,10 @@ all_files = 1
|
||||
|
||||
[upload_sphinx]
|
||||
upload-dir = docs/build/html
|
||||
|
||||
[flake8]
|
||||
max-line-length = 99
|
||||
|
||||
[yapf]
|
||||
based_on_style = google
|
||||
column_limit = 99
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''The setup and build script for the python-telegram-bot library.'''
|
||||
|
||||
import os
|
||||
@@ -13,33 +12,43 @@ def read(*paths):
|
||||
return f.read()
|
||||
|
||||
|
||||
setup(
|
||||
name='python-telegram-bot',
|
||||
version='2.8.2',
|
||||
author='Leandro Toledo',
|
||||
author_email='leandrotoledodesouza@gmail.com',
|
||||
license='LGPLv3',
|
||||
url='https://github.com/leandrotoledo/python-telegram-bot',
|
||||
keywords='telegram bot api',
|
||||
description='A Python wrapper around the Telegram Bot API',
|
||||
long_description=(read('README.rst')),
|
||||
packages=find_packages(exclude=['tests*']),
|
||||
include_package_data=True,
|
||||
classifiers=[
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
'Intended Audience :: Developers',
|
||||
'License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)',
|
||||
'Operating System :: OS Independent',
|
||||
'Topic :: Software Development :: Libraries :: Python Modules',
|
||||
'Topic :: Communications :: Chat',
|
||||
'Topic :: Internet',
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Python :: 2',
|
||||
'Programming Language :: Python :: 2.6',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.2',
|
||||
'Programming Language :: Python :: 3.3',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
],
|
||||
)
|
||||
def requirements():
|
||||
"""Build the requirements list for this project"""
|
||||
requirements_list = []
|
||||
|
||||
with open('requirements.txt') as requirements:
|
||||
for install in requirements:
|
||||
requirements_list.append(install.strip())
|
||||
|
||||
return requirements_list
|
||||
|
||||
|
||||
setup(name='python-telegram-bot',
|
||||
version='4.1.1',
|
||||
author='Leandro Toledo',
|
||||
author_email='devs@python-telegram-bot.org',
|
||||
license='LGPLv3',
|
||||
url='https://github.com/python-telegram-bot/python-telegram-bot',
|
||||
keywords='python telegram bot api wrapper',
|
||||
description='A Python wrapper around the Telegram Bot API',
|
||||
long_description=(read('README.rst')),
|
||||
packages=find_packages(exclude=['tests*']),
|
||||
install_requires=requirements(),
|
||||
include_package_data=True,
|
||||
classifiers=[
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
'Intended Audience :: Developers',
|
||||
'License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)',
|
||||
'Operating System :: OS Independent',
|
||||
'Topic :: Software Development :: Libraries :: Python Modules',
|
||||
'Topic :: Communications :: Chat',
|
||||
'Topic :: Internet',
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Python :: 2',
|
||||
'Programming Language :: Python :: 2.6',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.3',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
],)
|
||||
|
||||
+61
-11
@@ -1,7 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015 Leandro Toledo de Souza <leandrotoeldodesouza@gmail.com>
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
@@ -15,15 +16,13 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
|
||||
"""A library that provides a Python interface to the Telegram Bot API"""
|
||||
|
||||
__author__ = 'leandrotoledodesouza@gmail.com'
|
||||
__version__ = '2.8.2'
|
||||
from sys import version_info
|
||||
|
||||
from .base import TelegramObject
|
||||
from .user import User
|
||||
from .groupchat import GroupChat
|
||||
from .chat import Chat
|
||||
from .photosize import PhotoSize
|
||||
from .audio import Audio
|
||||
from .voice import Voice
|
||||
@@ -32,24 +31,75 @@ from .sticker import Sticker
|
||||
from .video import Video
|
||||
from .contact import Contact
|
||||
from .location import Location
|
||||
from .venue import Venue
|
||||
from .chataction import ChatAction
|
||||
from .userprofilephotos import UserProfilePhotos
|
||||
from .keyboardbutton import KeyboardButton
|
||||
from .replymarkup import ReplyMarkup
|
||||
from .replykeyboardmarkup import ReplyKeyboardMarkup
|
||||
from .replykeyboardhide import ReplyKeyboardHide
|
||||
from .forcereply import ForceReply
|
||||
from .error import TelegramError
|
||||
from .inputfile import InputFile
|
||||
from .file import File
|
||||
from .nullhandler import NullHandler
|
||||
from .emoji import Emoji
|
||||
from .parsemode import ParseMode
|
||||
from .messageentity import MessageEntity
|
||||
from .message import Message
|
||||
from .inputmessagecontent import InputMessageContent
|
||||
from .callbackquery import CallbackQuery
|
||||
from .choseninlineresult import ChosenInlineResult
|
||||
from .inlinekeyboardbutton import InlineKeyboardButton
|
||||
from .inlinekeyboardmarkup import InlineKeyboardMarkup
|
||||
from .inlinequery import InlineQuery
|
||||
from .inlinequeryresult import InlineQueryResult
|
||||
from .inlinequeryresultarticle import InlineQueryResultArticle
|
||||
from .inlinequeryresultaudio import InlineQueryResultAudio
|
||||
from .inlinequeryresultcachedaudio import InlineQueryResultCachedAudio
|
||||
from .inlinequeryresultcacheddocument import InlineQueryResultCachedDocument
|
||||
from .inlinequeryresultcachedgif import InlineQueryResultCachedGif
|
||||
from .inlinequeryresultcachedmpeg4gif import InlineQueryResultCachedMpeg4Gif
|
||||
from .inlinequeryresultcachedphoto import InlineQueryResultCachedPhoto
|
||||
from .inlinequeryresultcachedsticker import InlineQueryResultCachedSticker
|
||||
from .inlinequeryresultcachedvideo import InlineQueryResultCachedVideo
|
||||
from .inlinequeryresultcachedvoice import InlineQueryResultCachedVoice
|
||||
from .inlinequeryresultcontact import InlineQueryResultContact
|
||||
from .inlinequeryresultdocument import InlineQueryResultDocument
|
||||
from .inlinequeryresultgif import InlineQueryResultGif
|
||||
from .inlinequeryresultlocation import InlineQueryResultLocation
|
||||
from .inlinequeryresultmpeg4gif import InlineQueryResultMpeg4Gif
|
||||
from .inlinequeryresultphoto import InlineQueryResultPhoto
|
||||
from .inlinequeryresultvenue import InlineQueryResultVenue
|
||||
from .inlinequeryresultvideo import InlineQueryResultVideo
|
||||
from .inlinequeryresultvoice import InlineQueryResultVoice
|
||||
from .inputtextmessagecontent import InputTextMessageContent
|
||||
from .inputlocationmessagecontent import InputLocationMessageContent
|
||||
from .inputvenuemessagecontent import InputVenueMessageContent
|
||||
from .inputcontactmessagecontent import InputContactMessageContent
|
||||
from .update import Update
|
||||
from .bot import Bot
|
||||
|
||||
__all__ = ['Bot', 'Emoji', 'TelegramError', 'InputFile', 'ReplyMarkup',
|
||||
'ForceReply', 'ReplyKeyboardHide', 'ReplyKeyboardMarkup',
|
||||
'UserProfilePhotos', 'ChatAction', 'Location', 'Contact',
|
||||
'Video', 'Sticker', 'Document', 'Audio', 'PhotoSize', 'GroupChat',
|
||||
'Update', 'ParseMode', 'Message', 'User', 'TelegramObject',
|
||||
'NullHandler', 'Voice']
|
||||
__author__ = 'devs@python-telegram-bot.org'
|
||||
__version__ = '4.1.1'
|
||||
__all__ = ['Audio', 'Bot', 'Chat', 'ChatAction', 'ChosenInlineResult', 'CallbackQuery', 'Contact',
|
||||
'Document', 'Emoji', 'File', 'ForceReply', 'InlineKeyboardButton',
|
||||
'InlineKeyboardMarkup', 'InlineQuery', 'InlineQueryResult', 'InlineQueryResult',
|
||||
'InlineQueryResultArticle', 'InlineQueryResultAudio', 'InlineQueryResultCachedAudio',
|
||||
'InlineQueryResultCachedDocument', 'InlineQueryResultCachedGif',
|
||||
'InlineQueryResultCachedMpeg4Gif', 'InlineQueryResultCachedPhoto',
|
||||
'InlineQueryResultCachedSticker', 'InlineQueryResultCachedVideo',
|
||||
'InlineQueryResultCachedVoice', 'InlineQueryResultContact', 'InlineQueryResultDocument',
|
||||
'InlineQueryResultGif', 'InlineQueryResultLocation', 'InlineQueryResultMpeg4Gif',
|
||||
'InlineQueryResultPhoto', 'InlineQueryResultVenue', 'InlineQueryResultVideo',
|
||||
'InlineQueryResultVoice', 'InputContactMessageContent', 'InputFile',
|
||||
'InputLocationMessageContent', 'InputMessageContent', 'InputTextMessageContent',
|
||||
'InputVenueMessageContent', 'KeyboardButton', 'Location', 'Message', 'MessageEntity',
|
||||
'NullHandler', 'ParseMode', 'PhotoSize', 'ReplyKeyboardHide', 'ReplyKeyboardMarkup',
|
||||
'ReplyMarkup', 'Sticker', 'TelegramError', 'TelegramObject', 'Update', 'User',
|
||||
'UserProfilePhotos', 'Venue', 'Video', 'Voice']
|
||||
|
||||
if version_info < (2, 7):
|
||||
from warnings import warn
|
||||
warn("python-telegram-bot will stop supporting Python 2.6 in a future release. "
|
||||
"Please upgrade your Python!")
|
||||
|
||||
+6
-9
@@ -1,7 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015 Leandro Toledo de Souza <leandrotoeldodesouza@gmail.com>
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
@@ -15,8 +16,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
|
||||
"""This module contains a object that represents a Telegram Audio"""
|
||||
"""This module contains a object that represents a Telegram Audio."""
|
||||
|
||||
from telegram import TelegramObject
|
||||
|
||||
@@ -44,16 +44,13 @@ class Audio(TelegramObject):
|
||||
file_size (Optional[int]):
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
file_id,
|
||||
duration,
|
||||
**kwargs):
|
||||
def __init__(self, file_id, duration, **kwargs):
|
||||
# Required
|
||||
self.file_id = str(file_id)
|
||||
self.duration = int(duration)
|
||||
# Optionals
|
||||
self.performer = str(kwargs.get('performer', ''))
|
||||
self.title = str(kwargs.get('title', ''))
|
||||
self.performer = kwargs.get('performer', '')
|
||||
self.title = kwargs.get('title', '')
|
||||
self.mime_type = str(kwargs.get('mime_type', ''))
|
||||
self.file_size = int(kwargs.get('file_size', 0))
|
||||
|
||||
|
||||
+13
-7
@@ -1,7 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015 Leandro Toledo de Souza <leandrotoeldodesouza@gmail.com>
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
@@ -15,15 +16,14 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
|
||||
"""Base class for Telegram Objects"""
|
||||
"""Base class for Telegram Objects."""
|
||||
|
||||
import json
|
||||
from abc import ABCMeta
|
||||
|
||||
|
||||
class TelegramObject(object):
|
||||
"""Base class for most telegram objects"""
|
||||
"""Base class for most telegram objects."""
|
||||
|
||||
__metaclass__ = ABCMeta
|
||||
|
||||
@@ -42,7 +42,12 @@ class TelegramObject(object):
|
||||
Returns:
|
||||
telegram.TelegramObject:
|
||||
"""
|
||||
raise NotImplementedError
|
||||
if not data:
|
||||
return None
|
||||
|
||||
data = data.copy()
|
||||
|
||||
return data
|
||||
|
||||
def to_json(self):
|
||||
"""
|
||||
@@ -58,8 +63,9 @@ class TelegramObject(object):
|
||||
"""
|
||||
data = dict()
|
||||
|
||||
for key, value in self.__dict__.items():
|
||||
if value:
|
||||
for key in iter(self.__dict__):
|
||||
value = self.__dict__[key]
|
||||
if value is not None:
|
||||
if hasattr(value, 'to_dict'):
|
||||
data[key] = value.to_dict()
|
||||
else:
|
||||
|
||||
+846
-253
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains a object that represents a Telegram
|
||||
CallbackQuery"""
|
||||
|
||||
from telegram import TelegramObject, Message, User
|
||||
|
||||
|
||||
class CallbackQuery(TelegramObject):
|
||||
"""This object represents a Telegram CallbackQuery."""
|
||||
|
||||
def __init__(self, id, from_user, data, **kwargs):
|
||||
# Required
|
||||
self.id = id
|
||||
self.from_user = from_user
|
||||
self.data = data
|
||||
# Optionals
|
||||
self.message = kwargs.get('message')
|
||||
self.inline_message_id = kwargs.get('inline_message_id', '')
|
||||
|
||||
@staticmethod
|
||||
def de_json(data):
|
||||
if not data:
|
||||
return None
|
||||
|
||||
data['from_user'] = User.de_json(data.get('from'))
|
||||
data['message'] = Message.de_json(data.get('message'))
|
||||
|
||||
return CallbackQuery(**data)
|
||||
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=C0103,W0622
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains a object that represents a Telegram Chat."""
|
||||
|
||||
from telegram import TelegramObject
|
||||
|
||||
|
||||
class Chat(TelegramObject):
|
||||
"""This object represents a Telegram Chat.
|
||||
|
||||
Attributes:
|
||||
id (int):
|
||||
type (str): Can be 'private', 'group', 'supergroup' or 'channel'
|
||||
title (str): Title, for channels and group chats
|
||||
username (str): Username, for private chats and channels if available
|
||||
first_name (str): First name of the other party in a private chat
|
||||
last_name (str): Last name of the other party in a private chat
|
||||
|
||||
Args:
|
||||
id (int):
|
||||
type (str):
|
||||
**kwargs: Arbitrary keyword arguments.
|
||||
|
||||
Keyword Args:
|
||||
type (Optional[str]):
|
||||
"""
|
||||
|
||||
def __init__(self, id, type, **kwargs):
|
||||
# Required
|
||||
self.id = int(id)
|
||||
self.type = type
|
||||
# Optionals
|
||||
self.title = kwargs.get('title', '')
|
||||
self.username = kwargs.get('username', '')
|
||||
self.first_name = kwargs.get('first_name', '')
|
||||
self.last_name = kwargs.get('last_name', '')
|
||||
|
||||
@staticmethod
|
||||
def de_json(data):
|
||||
"""
|
||||
Args:
|
||||
data (dict):
|
||||
|
||||
Returns:
|
||||
telegram.Chat:
|
||||
"""
|
||||
if not data:
|
||||
return None
|
||||
|
||||
return Chat(**data)
|
||||
@@ -2,7 +2,8 @@
|
||||
# pylint: disable=R0903
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015 Leandro Toledo de Souza <leandrotoeldodesouza@gmail.com>
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
@@ -16,8 +17,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
|
||||
"""This module contains a object that represents a Telegram ChatAction"""
|
||||
"""This module contains a object that represents a Telegram ChatAction."""
|
||||
|
||||
|
||||
class ChatAction(object):
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=R0902,R0912,R0913
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015 Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""
|
||||
This module contains a object that represents a Telegram ChosenInlineResult
|
||||
"""
|
||||
|
||||
from telegram import TelegramObject, User, Location
|
||||
|
||||
|
||||
class ChosenInlineResult(TelegramObject):
|
||||
"""This object represents a Telegram ChosenInlineResult.
|
||||
|
||||
Note:
|
||||
* In Python `from` is a reserved word, use `from_user` instead.
|
||||
|
||||
Attributes:
|
||||
result_id (str):
|
||||
from_user (:class:`telegram.User`):
|
||||
query (str):
|
||||
|
||||
Args:
|
||||
result_id (str):
|
||||
from_user (:class:`telegram.User`):
|
||||
query (str):
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, result_id, from_user, query, location=None, inline_message_id=None):
|
||||
# Required
|
||||
self.result_id = result_id
|
||||
self.from_user = from_user
|
||||
self.query = query
|
||||
# Optionals
|
||||
self.location = location
|
||||
self.inline_message_id = inline_message_id
|
||||
|
||||
@staticmethod
|
||||
def de_json(data):
|
||||
"""
|
||||
Args:
|
||||
data (dict):
|
||||
|
||||
Returns:
|
||||
telegram.ChosenInlineResult:
|
||||
"""
|
||||
if not data:
|
||||
return None
|
||||
|
||||
# Required
|
||||
data['from_user'] = User.de_json(data.pop('from'))
|
||||
# Optionals
|
||||
data['location'] = Location.de_json(data.get('location'))
|
||||
|
||||
return ChosenInlineResult(**data)
|
||||
|
||||
def to_dict(self):
|
||||
"""
|
||||
Returns:
|
||||
dict:
|
||||
"""
|
||||
data = super(ChosenInlineResult, self).to_dict()
|
||||
|
||||
# Required
|
||||
data['from'] = data.pop('from_user', None)
|
||||
|
||||
return data
|
||||
+4
-7
@@ -1,7 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015 Leandro Toledo de Souza <leandrotoeldodesouza@gmail.com>
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
@@ -15,8 +16,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
|
||||
"""This module contains a object that represents a Telegram Contact"""
|
||||
"""This module contains a object that represents a Telegram Contact."""
|
||||
|
||||
from telegram import TelegramObject
|
||||
|
||||
@@ -40,10 +40,7 @@ class Contact(TelegramObject):
|
||||
user_id (Optional[int]):
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
phone_number,
|
||||
first_name,
|
||||
**kwargs):
|
||||
def __init__(self, phone_number, first_name, **kwargs):
|
||||
# Required
|
||||
self.phone_number = str(phone_number)
|
||||
self.first_name = first_name
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015 Leandro Toledo de Souza <leandrotoeldodesouza@gmail.com>
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
@@ -15,8 +16,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
|
||||
"""This module contains a object that represents a Telegram Document"""
|
||||
"""This module contains a object that represents a Telegram Document."""
|
||||
|
||||
from telegram import PhotoSize, TelegramObject
|
||||
|
||||
@@ -42,14 +42,12 @@ class Document(TelegramObject):
|
||||
file_size (Optional[int]):
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
file_id,
|
||||
**kwargs):
|
||||
def __init__(self, file_id, **kwargs):
|
||||
# Required
|
||||
self.file_id = str(file_id)
|
||||
# Optionals
|
||||
self.thumb = kwargs.get('thumb')
|
||||
self.file_name = str(kwargs.get('file_name', ''))
|
||||
self.file_name = kwargs.get('file_name', '')
|
||||
self.mime_type = str(kwargs.get('mime_type', ''))
|
||||
self.file_size = int(kwargs.get('file_size', 0))
|
||||
|
||||
|
||||
+858
-855
File diff suppressed because it is too large
Load Diff
+50
-9
@@ -1,7 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015 Leandro Toledo de Souza <leandrotoeldodesouza@gmail.com>
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
@@ -15,10 +16,24 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains a object that represents a Telegram Error."""
|
||||
|
||||
"""This module contains a object that represents a Telegram Error"""
|
||||
|
||||
import re
|
||||
def _lstrip_str(in_s, lstr):
|
||||
"""
|
||||
Args:
|
||||
in_s (str): in string
|
||||
lstr (str): substr to strip from left side
|
||||
|
||||
Returns:
|
||||
str:
|
||||
|
||||
"""
|
||||
if in_s.startswith(lstr):
|
||||
res = in_s[len(lstr):]
|
||||
else:
|
||||
res = in_s
|
||||
return res
|
||||
|
||||
|
||||
class TelegramError(Exception):
|
||||
@@ -26,16 +41,42 @@ class TelegramError(Exception):
|
||||
|
||||
def __init__(self, message):
|
||||
"""
|
||||
Args:
|
||||
message (str):
|
||||
|
||||
Returns:
|
||||
str:
|
||||
|
||||
"""
|
||||
super(TelegramError, self).__init__()
|
||||
|
||||
api_error = re.match(r'^Error: (?P<message>.*)', message)
|
||||
if api_error:
|
||||
self.message = api_error.group('message').capitalize()
|
||||
else:
|
||||
self.message = message
|
||||
msg = _lstrip_str(message, 'Error: ')
|
||||
msg = _lstrip_str(msg, '[Error]: ')
|
||||
if msg != message:
|
||||
# api_error - capitalize the msg...
|
||||
msg = msg.capitalize()
|
||||
self.message = msg
|
||||
|
||||
def __str__(self):
|
||||
return '%s' % (self.message)
|
||||
|
||||
|
||||
class Unauthorized(TelegramError):
|
||||
|
||||
def __init__(self):
|
||||
super(Unauthorized, self).__init__('Unauthorized')
|
||||
|
||||
|
||||
class InvalidToken(TelegramError):
|
||||
|
||||
def __init__(self):
|
||||
super(InvalidToken, self).__init__('Invalid token')
|
||||
|
||||
|
||||
class NetworkError(TelegramError):
|
||||
pass
|
||||
|
||||
|
||||
class TimedOut(NetworkError):
|
||||
|
||||
def __init__(self):
|
||||
super(TimedOut, self).__init__('Timed out')
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""Extensions over the Telegram Bot API to facilitate bot making"""
|
||||
|
||||
from .dispatcher import Dispatcher
|
||||
from .jobqueue import JobQueue
|
||||
from .updater import Updater
|
||||
from .callbackqueryhandler import CallbackQueryHandler
|
||||
from .choseninlineresulthandler import ChosenInlineResultHandler
|
||||
from .commandhandler import CommandHandler
|
||||
from .handler import Handler
|
||||
from .inlinequeryhandler import InlineQueryHandler
|
||||
from .messagehandler import MessageHandler, Filters
|
||||
from .regexhandler import RegexHandler
|
||||
from .stringcommandhandler import StringCommandHandler
|
||||
from .stringregexhandler import StringRegexHandler
|
||||
from .typehandler import TypeHandler
|
||||
|
||||
__all__ = ('Dispatcher', 'JobQueue', 'Updater', 'CallbackQueryHandler',
|
||||
'ChosenInlineResultHandler', 'CommandHandler', 'Handler', 'InlineQueryHandler',
|
||||
'MessageHandler', 'Filters', 'RegexHandler', 'StringCommandHandler',
|
||||
'StringRegexHandler', 'TypeHandler')
|
||||
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
""" This module contains the CallbackQueryHandler class """
|
||||
|
||||
from .handler import Handler
|
||||
from telegram import Update
|
||||
from telegram.utils.deprecate import deprecate
|
||||
|
||||
|
||||
class CallbackQueryHandler(Handler):
|
||||
"""
|
||||
Handler class to handle Telegram callback queries.
|
||||
|
||||
Args:
|
||||
callback (function): A function that takes ``bot, update`` as
|
||||
positional arguments. It will be called when the ``check_update``
|
||||
has determined that an update should be processed by this handler.
|
||||
pass_update_queue (optional[bool]): If the handler should be passed the
|
||||
update queue as a keyword argument called ``update_queue``. It can
|
||||
be used to insert updates. Default is ``False``
|
||||
"""
|
||||
|
||||
def __init__(self, callback, pass_update_queue=False):
|
||||
super(CallbackQueryHandler, self).__init__(callback, pass_update_queue)
|
||||
|
||||
def check_update(self, update):
|
||||
return isinstance(update, Update) and update.callback_query
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
optional_args = self.collect_optional_args(dispatcher)
|
||||
|
||||
self.callback(dispatcher.bot, update, **optional_args)
|
||||
|
||||
# old non-PEP8 Handler methods
|
||||
m = "telegram.CallbackQueryHandler."
|
||||
checkUpdate = deprecate(check_update, m + "checkUpdate", m + "check_update")
|
||||
handleUpdate = deprecate(handle_update, m + "handleUpdate", m + "handle_update")
|
||||
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
""" This module contains the ChosenInlineResultHandler class """
|
||||
|
||||
from .handler import Handler
|
||||
from telegram import Update
|
||||
from telegram.utils.deprecate import deprecate
|
||||
|
||||
|
||||
class ChosenInlineResultHandler(Handler):
|
||||
"""
|
||||
Handler class to handle Telegram updates that contain a chosen inline
|
||||
result.
|
||||
|
||||
Args:
|
||||
callback (function): A function that takes ``bot, update`` as
|
||||
positional arguments. It will be called when the ``check_update``
|
||||
has determined that an update should be processed by this handler.
|
||||
pass_update_queue (optional[bool]): If the handler should be passed the
|
||||
update queue as a keyword argument called ``update_queue``. It can
|
||||
be used to insert updates. Default is ``False``
|
||||
"""
|
||||
|
||||
def __init__(self, callback, pass_update_queue=False):
|
||||
super(ChosenInlineResultHandler, self).__init__(callback, pass_update_queue)
|
||||
|
||||
def check_update(self, update):
|
||||
return isinstance(update, Update) and update.chosen_inline_result
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
optional_args = self.collect_optional_args(dispatcher)
|
||||
|
||||
self.callback(dispatcher.bot, update, **optional_args)
|
||||
|
||||
# old non-PEP8 Handler methods
|
||||
m = "telegram.ChosenInlineResultHandler."
|
||||
checkUpdate = deprecate(check_update, m + "checkUpdate", m + "check_update")
|
||||
handleUpdate = deprecate(handle_update, m + "handleUpdate", m + "handle_update")
|
||||
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
""" This module contains the CommandHandler class """
|
||||
|
||||
from .handler import Handler
|
||||
from telegram import Update
|
||||
from telegram.utils.deprecate import deprecate
|
||||
|
||||
|
||||
class CommandHandler(Handler):
|
||||
"""
|
||||
Handler class to handle Telegram commands. Commands are Telegram messages
|
||||
that start with ``/``, optionally followed by an ``@`` and the bot's
|
||||
name and/or some additional text.
|
||||
|
||||
Args:
|
||||
command (str): The name of the command this handler should listen for.
|
||||
callback (function): A function that takes ``bot, update`` as
|
||||
positional arguments. It will be called when the ``check_update``
|
||||
has determined that an update should be processed by this handler.
|
||||
pass_args (optional[bool]): If the handler should be passed the
|
||||
arguments passed to the command as a keyword argument called `
|
||||
``args``. It will contain a list of strings, which is the text
|
||||
following the command split on spaces. Default is ``False``
|
||||
pass_update_queue (optional[bool]): If the handler should be passed the
|
||||
update queue as a keyword argument called ``update_queue``. It can
|
||||
be used to insert updates. Default is ``False``
|
||||
"""
|
||||
|
||||
def __init__(self, command, callback, pass_args=False, pass_update_queue=False):
|
||||
super(CommandHandler, self).__init__(callback, pass_update_queue)
|
||||
self.command = command
|
||||
self.pass_args = pass_args
|
||||
|
||||
def check_update(self, update):
|
||||
return (isinstance(update, Update) and update.message and update.message.text and
|
||||
update.message.text.startswith('/') and
|
||||
update.message.text[1:].split(' ')[0].split('@')[0] == self.command)
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
optional_args = self.collect_optional_args(dispatcher)
|
||||
|
||||
if self.pass_args:
|
||||
optional_args['args'] = update.message.text.split(' ')[1:]
|
||||
|
||||
self.callback(dispatcher.bot, update, **optional_args)
|
||||
|
||||
# old non-PEP8 Handler methods
|
||||
m = "telegram.CommandHandler."
|
||||
checkUpdate = deprecate(check_update, m + "checkUpdate", m + "check_update")
|
||||
handleUpdate = deprecate(handle_update, m + "handleUpdate", m + "handle_update")
|
||||
@@ -0,0 +1,292 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains the Dispatcher class."""
|
||||
|
||||
import logging
|
||||
from functools import wraps
|
||||
from threading import Thread, BoundedSemaphore, Lock, Event, current_thread
|
||||
from time import sleep
|
||||
|
||||
from queue import Empty
|
||||
|
||||
from telegram import (TelegramError, NullHandler)
|
||||
from telegram.ext.handler import Handler
|
||||
from telegram.utils.deprecate import deprecate
|
||||
|
||||
logging.getLogger(__name__).addHandler(NullHandler())
|
||||
|
||||
semaphore = None
|
||||
async_threads = set()
|
||||
""":type: set[Thread]"""
|
||||
async_lock = Lock()
|
||||
DEFAULT_GROUP = 0
|
||||
|
||||
|
||||
def run_async(func):
|
||||
"""
|
||||
Function decorator that will run the function in a new thread.
|
||||
|
||||
Args:
|
||||
func (function): The function to run in the thread.
|
||||
|
||||
Returns:
|
||||
function:
|
||||
"""
|
||||
|
||||
# TODO: handle exception in async threads
|
||||
# set a threading.Event to notify caller thread
|
||||
|
||||
@wraps(func)
|
||||
def pooled(*pargs, **kwargs):
|
||||
"""
|
||||
A wrapper to run a thread in a thread pool
|
||||
"""
|
||||
try:
|
||||
result = func(*pargs, **kwargs)
|
||||
finally:
|
||||
semaphore.release()
|
||||
|
||||
with async_lock:
|
||||
async_threads.remove(current_thread())
|
||||
return result
|
||||
|
||||
@wraps(func)
|
||||
def async_func(*pargs, **kwargs):
|
||||
"""
|
||||
A wrapper to run a function in a thread
|
||||
"""
|
||||
thread = Thread(target=pooled, args=pargs, kwargs=kwargs)
|
||||
semaphore.acquire()
|
||||
with async_lock:
|
||||
async_threads.add(thread)
|
||||
thread.start()
|
||||
return thread
|
||||
|
||||
return async_func
|
||||
|
||||
|
||||
class Dispatcher(object):
|
||||
"""
|
||||
This class dispatches all kinds of updates to its registered handlers.
|
||||
|
||||
Args:
|
||||
bot (telegram.Bot): The bot object that should be passed to the
|
||||
handlers
|
||||
update_queue (Queue): The synchronized queue that will contain the
|
||||
updates.
|
||||
"""
|
||||
|
||||
def __init__(self, bot, update_queue, workers=4, exception_event=None):
|
||||
self.bot = bot
|
||||
self.update_queue = update_queue
|
||||
|
||||
self.handlers = {}
|
||||
""":type: dict[int, list[Handler]"""
|
||||
self.groups = []
|
||||
""":type: list[int]"""
|
||||
self.error_handlers = []
|
||||
|
||||
self.logger = logging.getLogger(__name__)
|
||||
self.running = False
|
||||
self.__stop_event = Event()
|
||||
self.__exception_event = exception_event or Event()
|
||||
|
||||
global semaphore
|
||||
if not semaphore:
|
||||
semaphore = BoundedSemaphore(value=workers)
|
||||
else:
|
||||
self.logger.debug('Semaphore already initialized, skipping.')
|
||||
|
||||
def start(self):
|
||||
"""
|
||||
Thread target of thread 'dispatcher'. Runs in background and processes
|
||||
the update queue.
|
||||
"""
|
||||
|
||||
if self.running:
|
||||
self.logger.warning('already running')
|
||||
return
|
||||
|
||||
if self.__exception_event.is_set():
|
||||
msg = 'reusing dispatcher after exception event is forbidden'
|
||||
self.logger.error(msg)
|
||||
raise TelegramError(msg)
|
||||
|
||||
self.running = True
|
||||
self.logger.debug('Dispatcher started')
|
||||
|
||||
while True:
|
||||
try:
|
||||
# Pop update from update queue.
|
||||
update = self.update_queue.get(True, 1)
|
||||
except Empty:
|
||||
if self.__stop_event.is_set():
|
||||
self.logger.debug('orderly stopping')
|
||||
break
|
||||
elif self.__exception_event.is_set():
|
||||
self.logger.critical('stopping due to exception in another thread')
|
||||
break
|
||||
continue
|
||||
|
||||
self.logger.debug('Processing Update: %s' % update)
|
||||
self.processUpdate(update)
|
||||
|
||||
self.running = False
|
||||
self.logger.debug('Dispatcher thread stopped')
|
||||
|
||||
def stop(self):
|
||||
"""
|
||||
Stops the thread
|
||||
"""
|
||||
if self.running:
|
||||
self.__stop_event.set()
|
||||
while self.running:
|
||||
sleep(0.1)
|
||||
self.__stop_event.clear()
|
||||
|
||||
def processUpdate(self, update):
|
||||
"""
|
||||
Processes a single update.
|
||||
|
||||
Args:
|
||||
update (object):
|
||||
"""
|
||||
|
||||
# An error happened while polling
|
||||
if isinstance(update, TelegramError):
|
||||
self.dispatchError(None, update)
|
||||
|
||||
else:
|
||||
for group in self.groups:
|
||||
for handler in self.handlers[group]:
|
||||
try:
|
||||
if handler.check_update(update):
|
||||
handler.handle_update(update, self)
|
||||
break
|
||||
# Dispatch any errors
|
||||
except TelegramError as te:
|
||||
self.logger.warn('A TelegramError was raised while processing the '
|
||||
'Update.')
|
||||
|
||||
try:
|
||||
self.dispatchError(update, te)
|
||||
except Exception:
|
||||
self.logger.exception('An uncaught error was raised while '
|
||||
'handling the error')
|
||||
finally:
|
||||
break
|
||||
|
||||
# Errors should not stop the thread
|
||||
except Exception:
|
||||
self.logger.exception('An uncaught error was raised while '
|
||||
'processing the update')
|
||||
break
|
||||
|
||||
def add_handler(self, handler, group=DEFAULT_GROUP):
|
||||
"""
|
||||
Register a handler.
|
||||
|
||||
TL;DR: Order and priority counts. 0 or 1 handlers per group will be
|
||||
used.
|
||||
|
||||
A handler must be an instance of a subclass of
|
||||
telegram.ext.Handler. All handlers are organized in groups with a
|
||||
numeric value. The default group is 0. All groups will be evaluated for
|
||||
handling an update, but only 0 or 1 handler per group will be used.
|
||||
|
||||
The priority/order of handlers is determined as follows:
|
||||
|
||||
* Priority of the group (lower group number == higher priority)
|
||||
|
||||
* The first handler in a group which should handle an update will be
|
||||
used. Other handlers from the group will not be used. The order in
|
||||
which handlers were added to the group defines the priority.
|
||||
|
||||
Args:
|
||||
handler (Handler): A Handler instance
|
||||
group (Optional[int]): The group identifier. Default is 0
|
||||
"""
|
||||
|
||||
if not isinstance(handler, Handler):
|
||||
raise TypeError('handler is not an instance of {0}'.format(Handler.__name__))
|
||||
if not isinstance(group, int):
|
||||
raise TypeError('group is not int')
|
||||
|
||||
if group not in self.handlers:
|
||||
self.handlers[group] = list()
|
||||
self.groups.append(group)
|
||||
self.groups = sorted(self.groups)
|
||||
|
||||
self.handlers[group].append(handler)
|
||||
|
||||
def remove_handler(self, handler, group=DEFAULT_GROUP):
|
||||
"""
|
||||
Remove a handler from the specified group
|
||||
|
||||
Args:
|
||||
handler (Handler): A Handler instance
|
||||
group (optional[object]): The group identifier. Default is 0
|
||||
"""
|
||||
if handler in self.handlers[group]:
|
||||
self.handlers[group].remove(handler)
|
||||
if not self.handlers[group]:
|
||||
del self.handlers[group]
|
||||
self.groups.remove(group)
|
||||
|
||||
def add_error_handler(self, callback):
|
||||
"""
|
||||
Registers an error handler in the Dispatcher.
|
||||
|
||||
Args:
|
||||
handler (function): A function that takes ``Bot, Update,
|
||||
TelegramError`` as arguments.
|
||||
"""
|
||||
|
||||
self.error_handlers.append(callback)
|
||||
|
||||
def remove_error_handler(self, callback):
|
||||
"""
|
||||
De-registers an error handler.
|
||||
|
||||
Args:
|
||||
handler (function):
|
||||
"""
|
||||
|
||||
if callback in self.error_handlers:
|
||||
self.error_handlers.remove(callback)
|
||||
|
||||
def dispatchError(self, update, error):
|
||||
"""
|
||||
Dispatches an error.
|
||||
|
||||
Args:
|
||||
update (object): The update that caused the error
|
||||
error (telegram.TelegramError): The Telegram error that was raised.
|
||||
"""
|
||||
|
||||
for callback in self.error_handlers:
|
||||
callback(self.bot, update, error)
|
||||
|
||||
# old non-PEP8 Dispatcher methods
|
||||
m = "telegram.dispatcher."
|
||||
addHandler = deprecate(add_handler, m + "AddHandler", m + "add_handler")
|
||||
removeHandler = deprecate(remove_handler, m + "removeHandler", m + "remove_handler")
|
||||
addErrorHandler = deprecate(add_error_handler, m + "addErrorHandler", m + "add_error_handler")
|
||||
removeErrorHandler = deprecate(remove_error_handler, m + "removeErrorHandler",
|
||||
m + "remove_error_handler")
|
||||
@@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
""" This module contains the base class for handlers as used by the
|
||||
Dispatcher """
|
||||
|
||||
from telegram.utils.deprecate import deprecate
|
||||
|
||||
|
||||
class Handler(object):
|
||||
"""
|
||||
The base class for all update handlers. You can create your own handlers
|
||||
by inheriting from this class.
|
||||
|
||||
Args:
|
||||
callback (function): A function that takes ``bot, update`` as
|
||||
positional arguments. It will be called when the ``check_update``
|
||||
has determined that an update should be processed by this handler.
|
||||
pass_update_queue (optional[bool]): If the callback should be passed
|
||||
the update queue as a keyword argument called ``update_queue``. It
|
||||
can be used to insert updates. Default is ``False``
|
||||
"""
|
||||
|
||||
def __init__(self, callback, pass_update_queue=False):
|
||||
self.callback = callback
|
||||
self.pass_update_queue = pass_update_queue
|
||||
|
||||
def check_update(self, update):
|
||||
"""
|
||||
This method is called to determine if an update should be handled by
|
||||
this handler instance. It should always be overridden.
|
||||
|
||||
Args:
|
||||
update (object): The update to be tested
|
||||
|
||||
Returns:
|
||||
bool
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
"""
|
||||
This method is called if it was determined that an update should indeed
|
||||
be handled by this instance. It should also be overridden, but in most
|
||||
cases call self.callback(dispatcher.bot, update), possibly along with
|
||||
optional arguments.
|
||||
|
||||
Args:
|
||||
update (object): The update to be handled
|
||||
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def collect_optional_args(self, dispatcher):
|
||||
"""
|
||||
Prepares the optional arguments that are the same for all types of
|
||||
handlers
|
||||
|
||||
Args:
|
||||
dispatcher (Dispatcher):
|
||||
"""
|
||||
optional_args = dict()
|
||||
if self.pass_update_queue:
|
||||
optional_args['update_queue'] = dispatcher.update_queue
|
||||
|
||||
return optional_args
|
||||
|
||||
# old non-PEP8 Handler methods
|
||||
m = "telegram.Handler."
|
||||
checkUpdate = deprecate(check_update, m + "checkUpdate", m + "check_update")
|
||||
handleUpdate = deprecate(handle_update, m + "handleUpdate", m + "handle_update")
|
||||
collectOptionalArgs = deprecate(collect_optional_args, m + "collectOptionalArgs",
|
||||
m + "collect_optional_args")
|
||||
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
""" This module contains the InlineQueryHandler class """
|
||||
|
||||
from .handler import Handler
|
||||
from telegram import Update
|
||||
from telegram.utils.deprecate import deprecate
|
||||
|
||||
|
||||
class InlineQueryHandler(Handler):
|
||||
"""
|
||||
Handler class to handle Telegram inline queries.
|
||||
|
||||
Args:
|
||||
callback (function): A function that takes ``bot, update`` as
|
||||
positional arguments. It will be called when the ``check_update``
|
||||
has determined that an update should be processed by this handler.
|
||||
pass_update_queue (optional[bool]): If the handler should be passed the
|
||||
update queue as a keyword argument called ``update_queue``. It can
|
||||
be used to insert updates. Default is ``False``
|
||||
"""
|
||||
|
||||
def __init__(self, callback, pass_update_queue=False):
|
||||
super(InlineQueryHandler, self).__init__(callback, pass_update_queue)
|
||||
|
||||
def check_update(self, update):
|
||||
return isinstance(update, Update) and update.inline_query
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
optional_args = self.collect_optional_args(dispatcher)
|
||||
|
||||
self.callback(dispatcher.bot, update, **optional_args)
|
||||
|
||||
# old non-PEP8 Handler methods
|
||||
m = "telegram.InlineQueryHandler."
|
||||
checkUpdate = deprecate(check_update, m + "checkUpdate", m + "check_update")
|
||||
handleUpdate = deprecate(handle_update, m + "handleUpdate", m + "handle_update")
|
||||
@@ -0,0 +1,154 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains the class JobQueue."""
|
||||
|
||||
import logging
|
||||
import time
|
||||
from threading import Thread, Lock
|
||||
from queue import PriorityQueue
|
||||
|
||||
|
||||
class JobQueue(object):
|
||||
"""
|
||||
This class allows you to periodically perform tasks with the bot.
|
||||
|
||||
Attributes:
|
||||
tick_interval (float):
|
||||
queue (PriorityQueue):
|
||||
bot (Bot):
|
||||
running (bool):
|
||||
|
||||
Args:
|
||||
bot (Bot): The bot instance that should be passed to the jobs
|
||||
tick_interval (Optional[float]): The interval this queue should check
|
||||
the newest task in seconds. Defaults to 1.0
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, bot, tick_interval=1.0):
|
||||
self.tick_interval = tick_interval
|
||||
self.queue = PriorityQueue()
|
||||
self.bot = bot
|
||||
self.logger = logging.getLogger(__name__)
|
||||
self.__lock = Lock()
|
||||
self.running = False
|
||||
|
||||
def put(self, run, interval, repeat=True, next_t=None, prevent_autostart=False):
|
||||
"""
|
||||
Queue a new job. If the JobQueue is not running, it will be started.
|
||||
|
||||
Args:
|
||||
run (function): A function that takes the parameter `bot`
|
||||
interval (float): The interval in seconds in which `run` should be
|
||||
executed
|
||||
repeat (Optional[bool]): If `False`, job will only be executed once
|
||||
next_t (Optional[float]): Time in seconds in which run should be
|
||||
executed first. Defaults to `interval`
|
||||
prevent_autostart (Optional[bool]): If `True`, the job queue will
|
||||
not be started automatically if it is not running.
|
||||
"""
|
||||
name = run.__name__
|
||||
|
||||
job = JobQueue.Job()
|
||||
job.run = run
|
||||
job.interval = interval
|
||||
job.name = name
|
||||
job.repeat = repeat
|
||||
|
||||
if next_t is None:
|
||||
next_t = interval
|
||||
|
||||
next_t += time.time()
|
||||
|
||||
self.logger.debug('Putting a %s with t=%f' % (job.name, next_t))
|
||||
self.queue.put((next_t, job))
|
||||
|
||||
if not self.running and not prevent_autostart:
|
||||
self.logger.debug('Auto-starting JobQueue')
|
||||
self.start()
|
||||
|
||||
def tick(self):
|
||||
"""
|
||||
Run all jobs that are due and re-enqueue them with their interval
|
||||
"""
|
||||
now = time.time()
|
||||
|
||||
self.logger.debug('Ticking jobs with t=%f' % now)
|
||||
while not self.queue.empty():
|
||||
t, j = self.queue.queue[0]
|
||||
self.logger.debug('Peeked at %s with t=%f' % (j.name, t))
|
||||
|
||||
if t < now:
|
||||
self.queue.get()
|
||||
self.logger.debug('Running job %s' % j.name)
|
||||
try:
|
||||
j.run(self.bot)
|
||||
except:
|
||||
self.logger.exception('An uncaught error was raised while '
|
||||
'executing job %s' % j.name)
|
||||
if j.repeat:
|
||||
self.put(j.run, j.interval)
|
||||
continue
|
||||
|
||||
self.logger.debug('Next task isn\'t due yet. Finished!')
|
||||
break
|
||||
|
||||
def start(self):
|
||||
"""
|
||||
Starts the job_queue thread.
|
||||
"""
|
||||
self.__lock.acquire()
|
||||
if not self.running:
|
||||
self.running = True
|
||||
self.__lock.release()
|
||||
job_queue_thread = Thread(target=self._start, name="job_queue")
|
||||
job_queue_thread.start()
|
||||
self.logger.debug('Job Queue thread started')
|
||||
else:
|
||||
self.__lock.release()
|
||||
|
||||
def _start(self):
|
||||
"""
|
||||
Thread target of thread 'job_queue'. Runs in background and performs
|
||||
ticks on the job queue.
|
||||
"""
|
||||
while self.running:
|
||||
self.tick()
|
||||
time.sleep(self.tick_interval)
|
||||
|
||||
self.logger.debug('Job Queue thread stopped')
|
||||
|
||||
def stop(self):
|
||||
"""
|
||||
Stops the thread
|
||||
"""
|
||||
with self.__lock:
|
||||
self.running = False
|
||||
|
||||
class Job(object):
|
||||
""" Inner class that represents a job """
|
||||
interval = None
|
||||
name = None
|
||||
repeat = None
|
||||
|
||||
def run(self):
|
||||
pass
|
||||
|
||||
def __lt__(self, other):
|
||||
return False
|
||||
@@ -0,0 +1,132 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
""" This module contains the MessageHandler class """
|
||||
|
||||
from .handler import Handler
|
||||
from telegram import Update
|
||||
from telegram.utils.deprecate import deprecate
|
||||
|
||||
|
||||
class Filters(object):
|
||||
"""
|
||||
Convenient namespace (class) & methods for the filter funcs of the
|
||||
MessageHandler class.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def text(update):
|
||||
return update.message.text and not update.message.text.startswith('/')
|
||||
|
||||
@staticmethod
|
||||
def command(update):
|
||||
return update.message.text and update.message.text.startswith('/')
|
||||
|
||||
@staticmethod
|
||||
def audio(update):
|
||||
return bool(update.message.audio)
|
||||
|
||||
@staticmethod
|
||||
def document(update):
|
||||
return bool(update.message.document)
|
||||
|
||||
@staticmethod
|
||||
def photo(update):
|
||||
return bool(update.message.photo)
|
||||
|
||||
@staticmethod
|
||||
def sticker(update):
|
||||
return bool(update.message.sticker)
|
||||
|
||||
@staticmethod
|
||||
def video(update):
|
||||
return bool(update.message.video)
|
||||
|
||||
@staticmethod
|
||||
def voice(update):
|
||||
return bool(update.message.voice)
|
||||
|
||||
@staticmethod
|
||||
def contact(update):
|
||||
return bool(update.message.contact)
|
||||
|
||||
@staticmethod
|
||||
def location(update):
|
||||
return bool(update.message.location)
|
||||
|
||||
@staticmethod
|
||||
def venue(update):
|
||||
return bool(update.message.venue)
|
||||
|
||||
@staticmethod
|
||||
def status_update(update):
|
||||
# yapf: disable
|
||||
# https://github.com/google/yapf/issues/252
|
||||
return bool(update.message.new_chat_member or update.message.left_chat_member or
|
||||
update.message.new_chat_title or update.message.new_chat_photo or
|
||||
update.message.delete_chat_photo or update.message.group_chat_created or
|
||||
update.message.supergroup_chat_created or
|
||||
update.message.channel_chat_created or update.message.migrate_to_chat_id or
|
||||
update.message.migrate_from_chat_id or update.message.pinned_message)
|
||||
# yapf: enable
|
||||
|
||||
|
||||
class MessageHandler(Handler):
|
||||
"""
|
||||
Handler class to handle telegram messages. Messages are Telegram Updates
|
||||
that do not contain a command. They might contain text, media or status
|
||||
updates.
|
||||
|
||||
Args:
|
||||
filters (list[function]): A list of filter functions. Standard filters
|
||||
can be found in the Filters class above.
|
||||
| Each `function` takes ``Update`` as arg and returns ``bool``.
|
||||
| All messages that match at least one of those filters will be
|
||||
accepted. If ``bool(filters)`` evaluates to ``False``, messages are
|
||||
not filtered.
|
||||
callback (function): A function that takes ``bot, update`` as
|
||||
positional arguments. It will be called when the ``check_update``
|
||||
has determined that an update should be processed by this handler.
|
||||
pass_update_queue (optional[bool]): If the handler should be passed the
|
||||
update queue as a keyword argument called ``update_queue``. It can
|
||||
be used to insert updates. Default is ``False``
|
||||
"""
|
||||
|
||||
def __init__(self, filters, callback, pass_update_queue=False):
|
||||
super(MessageHandler, self).__init__(callback, pass_update_queue)
|
||||
self.filters = filters
|
||||
|
||||
def check_update(self, update):
|
||||
if isinstance(update, Update) and update.message:
|
||||
if not self.filters:
|
||||
res = True
|
||||
else:
|
||||
res = any(func(update) for func in self.filters)
|
||||
else:
|
||||
res = False
|
||||
return res
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
optional_args = self.collect_optional_args(dispatcher)
|
||||
|
||||
self.callback(dispatcher.bot, update, **optional_args)
|
||||
|
||||
# old non-PEP8 Handler methods
|
||||
m = "telegram.MessageHandler."
|
||||
checkUpdate = deprecate(check_update, m + "checkUpdate", m + "check_update")
|
||||
handleUpdate = deprecate(handle_update, m + "handleUpdate", m + "handle_update")
|
||||
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
""" This module contains the RegexHandler class """
|
||||
|
||||
import re
|
||||
|
||||
from future.utils import string_types
|
||||
|
||||
from .handler import Handler
|
||||
from telegram import Update
|
||||
from telegram.utils.deprecate import deprecate
|
||||
|
||||
|
||||
class RegexHandler(Handler):
|
||||
"""
|
||||
Handler class to handle Telegram updates based on a regex. It uses a
|
||||
regular expression to check text messages. Read the documentation of the
|
||||
``re`` module for more information. The ``re.match`` function is used to
|
||||
determine if an update should be handled by this handler.
|
||||
|
||||
Args:
|
||||
pattern (str or Pattern): The regex pattern.
|
||||
callback (function): A function that takes ``bot, update`` as
|
||||
positional arguments. It will be called when the ``check_update``
|
||||
has determined that an update should be processed by this handler.
|
||||
pass_groups (optional[bool]): If the callback should be passed the
|
||||
result of ``re.match(pattern, text).groups()`` as a keyword
|
||||
argument called ``groups``. Default is ``False``
|
||||
pass_groupdict (optional[bool]): If the callback should be passed the
|
||||
result of ``re.match(pattern, text).groupdict()`` as a keyword
|
||||
argument called ``groupdict``. Default is ``False``
|
||||
pass_update_queue (optional[bool]): If the handler should be passed the
|
||||
update queue as a keyword argument called ``update_queue``. It can
|
||||
be used to insert updates. Default is ``False``
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
pattern,
|
||||
callback,
|
||||
pass_groups=False,
|
||||
pass_groupdict=False,
|
||||
pass_update_queue=False):
|
||||
super(RegexHandler, self).__init__(callback, pass_update_queue)
|
||||
|
||||
if isinstance(pattern, string_types):
|
||||
pattern = re.compile(pattern)
|
||||
|
||||
self.pattern = pattern
|
||||
self.pass_groups = pass_groups
|
||||
self.pass_groupdict = pass_groupdict
|
||||
|
||||
def check_update(self, update):
|
||||
if (isinstance(update, Update) and update.message and update.message.text):
|
||||
match = re.match(self.pattern, update.message.text)
|
||||
return bool(match)
|
||||
else:
|
||||
return False
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
optional_args = self.collect_optional_args(dispatcher)
|
||||
match = re.match(self.pattern, update.message.text)
|
||||
|
||||
if self.pass_groups:
|
||||
optional_args['groups'] = match.groups()
|
||||
if self.pass_groupdict:
|
||||
optional_args['groupdict'] = match.groupdict()
|
||||
|
||||
self.callback(dispatcher.bot, update, **optional_args)
|
||||
|
||||
# old non-PEP8 Handler methods
|
||||
m = "telegram.RegexHandler."
|
||||
checkUpdate = deprecate(check_update, m + "checkUpdate", m + "check_update")
|
||||
handleUpdate = deprecate(handle_update, m + "handleUpdate", m + "handle_update")
|
||||
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
""" This module contains the StringCommandHandler class """
|
||||
|
||||
from .handler import Handler
|
||||
from telegram.utils.deprecate import deprecate
|
||||
|
||||
|
||||
class StringCommandHandler(Handler):
|
||||
"""
|
||||
Handler class to handle string commands. Commands are string updates
|
||||
that start with ``/``.
|
||||
|
||||
Args:
|
||||
command (str): The name of the command this handler should listen for.
|
||||
callback (function): A function that takes ``bot, update`` as
|
||||
positional arguments. It will be called when the ``check_update``
|
||||
has determined that an update should be processed by this handler.
|
||||
pass_args (optional[bool]): If the handler should be passed the
|
||||
arguments passed to the command as a keyword argument called `
|
||||
``args``. It will contain a list of strings, which is the text
|
||||
following the command split on spaces. Default is ``False``
|
||||
pass_update_queue (optional[bool]): If the handler should be passed the
|
||||
update queue as a keyword argument called ``update_queue``. It can
|
||||
be used to insert updates. Default is ``False``
|
||||
"""
|
||||
|
||||
def __init__(self, command, callback, pass_args=False, pass_update_queue=False):
|
||||
super(StringCommandHandler, self).__init__(callback, pass_update_queue)
|
||||
self.command = command
|
||||
self.pass_args = pass_args
|
||||
|
||||
def check_update(self, update):
|
||||
return (isinstance(update, str) and update.startswith('/') and
|
||||
update[1:].split(' ')[0] == self.command)
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
optional_args = self.collect_optional_args(dispatcher)
|
||||
|
||||
if self.pass_args:
|
||||
optional_args['args'] = update.split(' ')[1:]
|
||||
|
||||
self.callback(dispatcher.bot, update, **optional_args)
|
||||
|
||||
# old non-PEP8 Handler methods
|
||||
m = "telegram.StringCommandHandler."
|
||||
checkUpdate = deprecate(check_update, m + "checkUpdate", m + "check_update")
|
||||
handleUpdate = deprecate(handle_update, m + "handleUpdate", m + "handle_update")
|
||||
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
""" This module contains the StringRegexHandler class """
|
||||
|
||||
import re
|
||||
|
||||
from future.utils import string_types
|
||||
|
||||
from .handler import Handler
|
||||
from telegram.utils.deprecate import deprecate
|
||||
|
||||
|
||||
class StringRegexHandler(Handler):
|
||||
"""
|
||||
Handler class to handle string updates based on a regex. It uses a
|
||||
regular expression to check update content. Read the documentation of the
|
||||
``re`` module for more information. The ``re.match`` function is used to
|
||||
determine if an update should be handled by this handler.
|
||||
|
||||
Args:
|
||||
pattern (str or Pattern): The regex pattern.
|
||||
callback (function): A function that takes ``bot, update`` as
|
||||
positional arguments. It will be called when the ``check_update``
|
||||
has determined that an update should be processed by this handler.
|
||||
pass_groups (optional[bool]): If the callback should be passed the
|
||||
result of ``re.match(pattern, update).groups()`` as a keyword
|
||||
argument called ``groups``. Default is ``False``
|
||||
pass_groupdict (optional[bool]): If the callback should be passed the
|
||||
result of ``re.match(pattern, update).groupdict()`` as a keyword
|
||||
argument called ``groupdict``. Default is ``False``
|
||||
pass_update_queue (optional[bool]): If the handler should be passed the
|
||||
update queue as a keyword argument called ``update_queue``. It can
|
||||
be used to insert updates. Default is ``False``
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
pattern,
|
||||
callback,
|
||||
pass_groups=False,
|
||||
pass_groupdict=False,
|
||||
pass_update_queue=False):
|
||||
super(StringRegexHandler, self).__init__(callback, pass_update_queue)
|
||||
|
||||
if isinstance(pattern, string_types):
|
||||
pattern = re.compile(pattern)
|
||||
|
||||
self.pattern = pattern
|
||||
self.pass_groups = pass_groups
|
||||
self.pass_groupdict = pass_groupdict
|
||||
|
||||
def check_update(self, update):
|
||||
return isinstance(update, string_types) and bool(re.match(self.pattern, update))
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
optional_args = self.collect_optional_args(dispatcher)
|
||||
match = re.match(self.pattern, update)
|
||||
|
||||
if self.pass_groups:
|
||||
optional_args['groups'] = match.groups()
|
||||
if self.pass_groupdict:
|
||||
optional_args['groupdict'] = match.groupdict()
|
||||
|
||||
self.callback(dispatcher.bot, update, **optional_args)
|
||||
|
||||
# old non-PEP8 Handler methods
|
||||
m = "telegram.StringRegexHandler."
|
||||
checkUpdate = deprecate(check_update, m + "checkUpdate", m + "check_update")
|
||||
handleUpdate = deprecate(handle_update, m + "handleUpdate", m + "handle_update")
|
||||
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
""" This module contains the TypeHandler class """
|
||||
|
||||
from .handler import Handler
|
||||
from telegram.utils.deprecate import deprecate
|
||||
|
||||
|
||||
class TypeHandler(Handler):
|
||||
"""
|
||||
Handler class to handle updates of custom types.
|
||||
|
||||
Args:
|
||||
type (type): The ``type`` of updates this handler should process, as
|
||||
determined by ``isinstance``
|
||||
callback (function): A function that takes ``bot, update`` as
|
||||
positional arguments. It will be called when the ``check_update``
|
||||
has determined that an update should be processed by this handler.
|
||||
strict (optional[bool]): Use ``type`` instead of ``isinstance``.
|
||||
Default is ``False``
|
||||
pass_update_queue (optional[bool]): If the handler should be passed the
|
||||
update queue as a keyword argument called ``update_queue``. It can
|
||||
be used to insert updates. Default is ``False``
|
||||
"""
|
||||
|
||||
def __init__(self, type, callback, strict=False, pass_update_queue=False):
|
||||
super(TypeHandler, self).__init__(callback, pass_update_queue)
|
||||
self.type = type
|
||||
self.strict = strict
|
||||
|
||||
def check_update(self, update):
|
||||
if not self.strict:
|
||||
return isinstance(update, self.type)
|
||||
else:
|
||||
return type(update) is self.type
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
optional_args = self.collect_optional_args(dispatcher)
|
||||
|
||||
self.callback(dispatcher.bot, update, **optional_args)
|
||||
|
||||
# old non-PEP8 Handler methods
|
||||
m = "telegram.TypeHandler."
|
||||
checkUpdate = deprecate(check_update, m + "checkUpdate", m + "check_update")
|
||||
handleUpdate = deprecate(handle_update, m + "handleUpdate", m + "handle_update")
|
||||
@@ -0,0 +1,412 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains the class Updater, which tries to make creating
|
||||
Telegram bots intuitive."""
|
||||
|
||||
import logging
|
||||
import os
|
||||
import ssl
|
||||
from threading import Thread, Lock, current_thread, Event
|
||||
from time import sleep
|
||||
import subprocess
|
||||
from signal import signal, SIGINT, SIGTERM, SIGABRT
|
||||
from queue import Queue
|
||||
|
||||
from telegram import Bot, TelegramError, NullHandler
|
||||
from telegram.ext import dispatcher, Dispatcher, JobQueue
|
||||
from telegram.error import Unauthorized, InvalidToken
|
||||
from telegram.utils.webhookhandler import (WebhookServer, WebhookHandler)
|
||||
|
||||
logging.getLogger(__name__).addHandler(NullHandler())
|
||||
|
||||
|
||||
class Updater(object):
|
||||
"""
|
||||
This class, which employs the Dispatcher class, provides a frontend to
|
||||
telegram.Bot to the programmer, so they can focus on coding the bot. Its
|
||||
purpose is to receive the updates from Telegram and to deliver them to said
|
||||
dispatcher. It also runs in a separate thread, so the user can interact
|
||||
with the bot, for example on the command line. The dispatcher supports
|
||||
handlers for different kinds of data: Updates from Telegram, basic text
|
||||
commands and even arbitrary types.
|
||||
The updater can be started as a polling service or, for production, use a
|
||||
webhook to receive updates. This is achieved using the WebhookServer and
|
||||
WebhookHandler classes.
|
||||
|
||||
|
||||
Attributes:
|
||||
|
||||
Args:
|
||||
token (Optional[str]): The bot's token given by the @BotFather
|
||||
base_url (Optional[str]):
|
||||
workers (Optional[int]): Amount of threads in the thread pool for
|
||||
functions decorated with @run_async
|
||||
bot (Optional[Bot]):
|
||||
job_queue_tick_interval(Optional[float]): The interval the queue should
|
||||
be checked for new tasks. Defaults to 1.0
|
||||
|
||||
Raises:
|
||||
ValueError: If both `token` and `bot` are passed or none of them.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
token=None,
|
||||
base_url=None,
|
||||
workers=4,
|
||||
bot=None,
|
||||
job_queue_tick_interval=1.0):
|
||||
if (token is None) and (bot is None):
|
||||
raise ValueError('`token` or `bot` must be passed')
|
||||
if (token is not None) and (bot is not None):
|
||||
raise ValueError('`token` and `bot` are mutually exclusive')
|
||||
|
||||
if bot is not None:
|
||||
self.bot = bot
|
||||
else:
|
||||
self.bot = Bot(token, base_url)
|
||||
self.update_queue = Queue()
|
||||
self.job_queue = JobQueue(self.bot, job_queue_tick_interval)
|
||||
self.__exception_event = Event()
|
||||
self.dispatcher = Dispatcher(self.bot, self.update_queue, workers, self.__exception_event)
|
||||
self.last_update_id = 0
|
||||
self.logger = logging.getLogger(__name__)
|
||||
self.running = False
|
||||
self.is_idle = False
|
||||
self.httpd = None
|
||||
self.__lock = Lock()
|
||||
self.__threads = []
|
||||
""":type: list[Thread]"""
|
||||
|
||||
def _init_thread(self, target, name, *args, **kwargs):
|
||||
thr = Thread(target=self._thread_wrapper, name=name, args=(target,) + args, kwargs=kwargs)
|
||||
thr.start()
|
||||
self.__threads.append(thr)
|
||||
|
||||
def _thread_wrapper(self, target, *args, **kwargs):
|
||||
thr_name = current_thread().name
|
||||
self.logger.debug('{0} - started'.format(thr_name))
|
||||
try:
|
||||
target(*args, **kwargs)
|
||||
except Exception:
|
||||
self.__exception_event.set()
|
||||
self.logger.exception('unhandled exception')
|
||||
raise
|
||||
self.logger.debug('{0} - ended'.format(thr_name))
|
||||
|
||||
def start_polling(self,
|
||||
poll_interval=0.0,
|
||||
timeout=10,
|
||||
network_delay=2,
|
||||
clean=False,
|
||||
bootstrap_retries=0):
|
||||
"""
|
||||
Starts polling updates from Telegram.
|
||||
|
||||
Args:
|
||||
poll_interval (Optional[float]): Time to wait between polling
|
||||
updates from Telegram in seconds. Default is 0.0
|
||||
timeout (Optional[float]): Passed to Bot.getUpdates
|
||||
network_delay (Optional[float]): Passed to Bot.getUpdates
|
||||
clean (Optional[bool]): Whether to clean any pending updates on
|
||||
Telegram servers before actually starting to poll. Default is
|
||||
False.
|
||||
bootstrap_retries (Optional[int[): Whether the bootstrapping phase
|
||||
of the `Updater` will retry on failures on the Telegram server.
|
||||
|
||||
| < 0 - retry indefinitely
|
||||
| 0 - no retries (default)
|
||||
| > 0 - retry up to X times
|
||||
|
||||
Returns:
|
||||
Queue: The update queue that can be filled from the main thread
|
||||
|
||||
"""
|
||||
with self.__lock:
|
||||
if not self.running:
|
||||
self.running = True
|
||||
|
||||
# Create & start threads
|
||||
self._init_thread(self.dispatcher.start, "dispatcher")
|
||||
self._init_thread(self._start_polling, "updater", poll_interval, timeout,
|
||||
network_delay, bootstrap_retries, clean)
|
||||
|
||||
# Return the update queue so the main thread can insert updates
|
||||
return self.update_queue
|
||||
|
||||
def start_webhook(self,
|
||||
listen='127.0.0.1',
|
||||
port=80,
|
||||
url_path='',
|
||||
cert=None,
|
||||
key=None,
|
||||
clean=False,
|
||||
bootstrap_retries=0,
|
||||
webhook_url=None):
|
||||
"""
|
||||
Starts a small http server to listen for updates via webhook. If cert
|
||||
and key are not provided, the webhook will be started directly on
|
||||
http://listen:port/url_path, so SSL can be handled by another
|
||||
application. Else, the webhook will be started on
|
||||
https://listen:port/url_path
|
||||
|
||||
Args:
|
||||
listen (Optional[str]): IP-Address to listen on
|
||||
port (Optional[int]): Port the bot should be listening on
|
||||
url_path (Optional[str]): Path inside url
|
||||
cert (Optional[str]): Path to the SSL certificate file
|
||||
key (Optional[str]): Path to the SSL key file
|
||||
clean (Optional[bool]): Whether to clean any pending updates on
|
||||
Telegram servers before actually starting the webhook. Default
|
||||
is False.
|
||||
bootstrap_retries (Optional[int[): Whether the bootstrapping phase
|
||||
of the `Updater` will retry on failures on the Telegram server.
|
||||
|
||||
| < 0 - retry indefinitely
|
||||
| 0 - no retries (default)
|
||||
| > 0 - retry up to X times
|
||||
webhook_url (Optional[str]): Explicitly specifiy the webhook url.
|
||||
Useful behind NAT, reverse proxy, etc. Default is derived from
|
||||
`listen`, `port` & `url_path`.
|
||||
|
||||
Returns:
|
||||
Queue: The update queue that can be filled from the main thread
|
||||
|
||||
"""
|
||||
with self.__lock:
|
||||
if not self.running:
|
||||
self.running = True
|
||||
|
||||
# Create & start threads
|
||||
self._init_thread(self.dispatcher.start, "dispatcher"),
|
||||
self._init_thread(self._start_webhook, "updater", listen, port, url_path, cert,
|
||||
key, bootstrap_retries, clean, webhook_url)
|
||||
|
||||
# Return the update queue so the main thread can insert updates
|
||||
return self.update_queue
|
||||
|
||||
def _start_polling(self, poll_interval, timeout, network_delay, bootstrap_retries, clean):
|
||||
"""
|
||||
Thread target of thread 'updater'. Runs in background, pulls
|
||||
updates from Telegram and inserts them in the update queue of the
|
||||
Dispatcher.
|
||||
|
||||
"""
|
||||
cur_interval = poll_interval
|
||||
self.logger.debug('Updater thread started')
|
||||
|
||||
self._bootstrap(bootstrap_retries, clean=clean, webhook_url='')
|
||||
|
||||
while self.running:
|
||||
try:
|
||||
updates = self.bot.getUpdates(self.last_update_id,
|
||||
timeout=timeout,
|
||||
network_delay=network_delay)
|
||||
except TelegramError as te:
|
||||
self.logger.error("Error while getting Updates: {0}".format(te))
|
||||
|
||||
# Put the error into the update queue and let the Dispatcher
|
||||
# broadcast it
|
||||
self.update_queue.put(te)
|
||||
|
||||
cur_interval = self._increase_poll_interval(cur_interval)
|
||||
else:
|
||||
if not self.running:
|
||||
if len(updates) > 0:
|
||||
self.logger.debug('Updates ignored and will be pulled '
|
||||
'again on restart.')
|
||||
break
|
||||
|
||||
if updates:
|
||||
for update in updates:
|
||||
self.update_queue.put(update)
|
||||
self.last_update_id = updates[-1].update_id + 1
|
||||
|
||||
cur_interval = poll_interval
|
||||
|
||||
sleep(cur_interval)
|
||||
|
||||
@staticmethod
|
||||
def _increase_poll_interval(current_interval):
|
||||
# increase waiting times on subsequent errors up to 30secs
|
||||
if current_interval == 0:
|
||||
current_interval = 1
|
||||
elif current_interval < 30:
|
||||
current_interval += current_interval / 2
|
||||
elif current_interval > 30:
|
||||
current_interval = 30
|
||||
return current_interval
|
||||
|
||||
def _start_webhook(self, listen, port, url_path, cert, key, bootstrap_retries, clean,
|
||||
webhook_url):
|
||||
self.logger.debug('Updater thread started')
|
||||
use_ssl = cert is not None and key is not None
|
||||
if not url_path.startswith('/'):
|
||||
url_path = '/{0}'.format(url_path)
|
||||
|
||||
# Create and start server
|
||||
self.httpd = WebhookServer((listen, port), WebhookHandler, self.update_queue, url_path)
|
||||
|
||||
if use_ssl:
|
||||
self._check_ssl_cert(cert, key)
|
||||
|
||||
# DO NOT CHANGE: Only set webhook if SSL is handled by library
|
||||
if not webhook_url:
|
||||
webhook_url = self._gen_webhook_url(listen, port, url_path)
|
||||
|
||||
self._bootstrap(max_retries=bootstrap_retries,
|
||||
clean=clean,
|
||||
webhook_url=webhook_url,
|
||||
cert=open(cert, 'rb'))
|
||||
elif clean:
|
||||
self.logger.warning("cleaning updates is not supported if "
|
||||
"SSL-termination happens elsewhere; skipping")
|
||||
|
||||
self.httpd.serve_forever(poll_interval=1)
|
||||
|
||||
def _check_ssl_cert(self, cert, key):
|
||||
# Check SSL-Certificate with openssl, if possible
|
||||
try:
|
||||
exit_code = subprocess.call(
|
||||
["openssl", "x509", "-text", "-noout", "-in", cert],
|
||||
stdout=open(os.devnull, 'wb'),
|
||||
stderr=subprocess.STDOUT)
|
||||
except OSError:
|
||||
exit_code = 0
|
||||
if exit_code is 0:
|
||||
try:
|
||||
self.httpd.socket = ssl.wrap_socket(self.httpd.socket,
|
||||
certfile=cert,
|
||||
keyfile=key,
|
||||
server_side=True)
|
||||
except ssl.SSLError as error:
|
||||
self.logger.exception('Failed to init SSL socket')
|
||||
raise TelegramError(str(error))
|
||||
else:
|
||||
raise TelegramError('SSL Certificate invalid')
|
||||
|
||||
@staticmethod
|
||||
def _gen_webhook_url(listen, port, url_path):
|
||||
return 'https://{listen}:{port}{path}'.format(listen=listen, port=port, path=url_path)
|
||||
|
||||
def _bootstrap(self, max_retries, clean, webhook_url, cert=None):
|
||||
retries = 0
|
||||
while True:
|
||||
|
||||
try:
|
||||
if clean:
|
||||
# Disable webhook for cleaning
|
||||
self.bot.setWebhook(webhook_url='')
|
||||
self._clean_updates()
|
||||
|
||||
self.bot.setWebhook(webhook_url=webhook_url, certificate=cert)
|
||||
except (Unauthorized, InvalidToken):
|
||||
raise
|
||||
except TelegramError:
|
||||
msg = 'error in bootstrap phase; try={0} max_retries={1}'\
|
||||
.format(retries, max_retries)
|
||||
if max_retries < 0 or retries < max_retries:
|
||||
self.logger.warning(msg)
|
||||
retries += 1
|
||||
else:
|
||||
self.logger.exception(msg)
|
||||
raise
|
||||
else:
|
||||
break
|
||||
sleep(1)
|
||||
|
||||
def _clean_updates(self):
|
||||
self.logger.debug('Cleaning updates from Telegram server')
|
||||
updates = self.bot.getUpdates()
|
||||
while updates:
|
||||
updates = self.bot.getUpdates(updates[-1].update_id + 1)
|
||||
|
||||
def stop(self):
|
||||
"""
|
||||
Stops the polling/webhook thread, the dispatcher and the job queue
|
||||
"""
|
||||
|
||||
self.job_queue.stop()
|
||||
with self.__lock:
|
||||
if self.running:
|
||||
self.logger.debug('Stopping Updater and Dispatcher...')
|
||||
|
||||
self.running = False
|
||||
|
||||
self._stop_httpd()
|
||||
self._stop_dispatcher()
|
||||
self._join_threads()
|
||||
# async threads must be join()ed only after the dispatcher
|
||||
# thread was joined, otherwise we can still have new async
|
||||
# threads dispatched
|
||||
self._join_async_threads()
|
||||
|
||||
def _stop_httpd(self):
|
||||
if self.httpd:
|
||||
self.logger.debug('Waiting for current webhook connection to be '
|
||||
'closed... Send a Telegram message to the bot to exit '
|
||||
'immediately.')
|
||||
self.httpd.shutdown()
|
||||
self.httpd = None
|
||||
|
||||
def _stop_dispatcher(self):
|
||||
self.logger.debug('Requesting Dispatcher to stop...')
|
||||
self.dispatcher.stop()
|
||||
|
||||
def _join_async_threads(self):
|
||||
with dispatcher.async_lock:
|
||||
threads = list(dispatcher.async_threads)
|
||||
total = len(threads)
|
||||
for i, thr in enumerate(threads):
|
||||
self.logger.debug('Waiting for async thread {0}/{1} to end'.format(i, total))
|
||||
thr.join()
|
||||
self.logger.debug('async thread {0}/{1} has ended'.format(i, total))
|
||||
|
||||
def _join_threads(self):
|
||||
for thr in self.__threads:
|
||||
self.logger.debug('Waiting for {0} thread to end'.format(thr.name))
|
||||
thr.join()
|
||||
self.logger.debug('{0} thread has ended'.format(thr.name))
|
||||
self.__threads = []
|
||||
|
||||
def signal_handler(self, signum, frame):
|
||||
self.is_idle = False
|
||||
if self.running:
|
||||
self.stop()
|
||||
else:
|
||||
self.logger.warning('Exiting immediately!')
|
||||
import os
|
||||
os._exit(1)
|
||||
|
||||
def idle(self, stop_signals=(SIGINT, SIGTERM, SIGABRT)):
|
||||
"""
|
||||
Blocks until one of the signals are received and stops the updater
|
||||
|
||||
Args:
|
||||
stop_signals: Iterable containing signals from the signal module
|
||||
that should be subscribed to. Updater.stop() will be called on
|
||||
receiving one of those signals. Defaults to (SIGINT, SIGTERM,
|
||||
SIGABRT)
|
||||
"""
|
||||
for sig in stop_signals:
|
||||
signal(sig, self.signal_handler)
|
||||
|
||||
self.is_idle = True
|
||||
|
||||
while self.is_idle:
|
||||
sleep(1)
|
||||
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains a object that represents a Telegram File."""
|
||||
|
||||
from os.path import basename
|
||||
|
||||
from telegram import TelegramObject
|
||||
from telegram.utils.request import download as _download
|
||||
|
||||
|
||||
class File(TelegramObject):
|
||||
"""This object represents a Telegram File.
|
||||
|
||||
Attributes:
|
||||
file_id (str):
|
||||
file_size (str):
|
||||
file_path (str):
|
||||
|
||||
Args:
|
||||
file_id (str):
|
||||
**kwargs: Arbitrary keyword arguments.
|
||||
|
||||
Keyword Args:
|
||||
file_size (Optional[int]):
|
||||
file_path (Optional[str]):
|
||||
"""
|
||||
|
||||
def __init__(self, file_id, **kwargs):
|
||||
# Required
|
||||
self.file_id = str(file_id)
|
||||
# Optionals
|
||||
self.file_size = int(kwargs.get('file_size', 0))
|
||||
self.file_path = str(kwargs.get('file_path', ''))
|
||||
|
||||
@staticmethod
|
||||
def de_json(data):
|
||||
"""
|
||||
Args:
|
||||
data (str):
|
||||
|
||||
Returns:
|
||||
telegram.File:
|
||||
"""
|
||||
if not data:
|
||||
return None
|
||||
|
||||
return File(**data)
|
||||
|
||||
def download(self, custom_path=None):
|
||||
"""
|
||||
Args:
|
||||
custom_path (str):
|
||||
"""
|
||||
url = self.file_path
|
||||
|
||||
if custom_path:
|
||||
filename = custom_path
|
||||
else:
|
||||
filename = basename(url)
|
||||
|
||||
_download(url, filename)
|
||||
@@ -1,7 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015 Leandro Toledo de Souza <leandrotoeldodesouza@gmail.com>
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
@@ -15,8 +16,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
|
||||
"""This module contains a object that represents a Telegram ForceReply"""
|
||||
"""This module contains a object that represents a Telegram ForceReply."""
|
||||
|
||||
from telegram import ReplyMarkup
|
||||
|
||||
@@ -36,9 +36,7 @@ class ForceReply(ReplyMarkup):
|
||||
selective (Optional[bool]):
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
force_reply=True,
|
||||
**kwargs):
|
||||
def __init__(self, force_reply=True, **kwargs):
|
||||
# Required
|
||||
self.force_reply = bool(force_reply)
|
||||
# Optionals
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains a object that represents a Telegram
|
||||
InlineKeyboardButton"""
|
||||
|
||||
from telegram import TelegramObject
|
||||
|
||||
|
||||
class InlineKeyboardButton(TelegramObject):
|
||||
"""This object represents a Telegram InlineKeyboardButton.
|
||||
|
||||
Attributes:
|
||||
text (str):
|
||||
url (str):
|
||||
callback_data (str):
|
||||
switch_inline_query (str):
|
||||
|
||||
Args:
|
||||
text (str):
|
||||
**kwargs: Arbitrary keyword arguments.
|
||||
|
||||
Keyword Args:
|
||||
url (Optional[str]):
|
||||
callback_data (Optional[str]):
|
||||
switch_inline_query (Optional[str]):
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, text, **kwargs):
|
||||
# Required
|
||||
self.text = text
|
||||
|
||||
# Optionals
|
||||
self.url = kwargs.get('url')
|
||||
self.callback_data = kwargs.get('callback_data')
|
||||
self.switch_inline_query = kwargs.get('switch_inline_query')
|
||||
|
||||
@staticmethod
|
||||
def de_json(data):
|
||||
data = super(InlineKeyboardButton, InlineKeyboardButton).de_json(data)
|
||||
|
||||
if not data:
|
||||
return None
|
||||
|
||||
return InlineKeyboardButton(**data)
|
||||
|
||||
@staticmethod
|
||||
def de_list(data):
|
||||
if not data:
|
||||
return []
|
||||
|
||||
inline_keyboards = list()
|
||||
for inline_keyboard in data:
|
||||
inline_keyboards.append(InlineKeyboardButton.de_json(inline_keyboard))
|
||||
|
||||
return inline_keyboards
|
||||
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains a object that represents a Telegram
|
||||
InlineKeyboardMarkup"""
|
||||
|
||||
from telegram import ReplyMarkup, InlineKeyboardButton
|
||||
|
||||
|
||||
class InlineKeyboardMarkup(ReplyMarkup):
|
||||
"""This object represents a Telegram InlineKeyboardMarkup.
|
||||
|
||||
Attributes:
|
||||
inline_keyboard (List[List[:class:`telegram.InlineKeyboardButton`]]):
|
||||
|
||||
Args:
|
||||
inline_keyboard (List[List[:class:`telegram.InlineKeyboardButton`]]):
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, inline_keyboard):
|
||||
# Required
|
||||
self.inline_keyboard = inline_keyboard
|
||||
|
||||
@staticmethod
|
||||
def de_json(data):
|
||||
data = super(InlineKeyboardMarkup, InlineKeyboardMarkup).de_json(data)
|
||||
|
||||
if not data:
|
||||
return None
|
||||
|
||||
data['inline_keyboard'] = [InlineKeyboardButton.de_list(inline_keyboard)
|
||||
for inline_keyboard in data['inline_keyboard']]
|
||||
|
||||
return InlineKeyboardMarkup(**data)
|
||||
|
||||
def to_dict(self):
|
||||
data = super(InlineKeyboardMarkup, self).to_dict()
|
||||
|
||||
data['inline_keyboard'] = []
|
||||
for inline_keyboard in self.inline_keyboard:
|
||||
data['inline_keyboard'].append([x.to_dict() for x in inline_keyboard])
|
||||
|
||||
return data
|
||||
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=R0902,R0912,R0913
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015 Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains a object that represents a Telegram InlineQuery"""
|
||||
|
||||
from telegram import TelegramObject, User, Location
|
||||
|
||||
|
||||
class InlineQuery(TelegramObject):
|
||||
"""This object represents a Telegram InlineQuery.
|
||||
|
||||
Note:
|
||||
* In Python `from` is a reserved word, use `from_user` instead.
|
||||
|
||||
Attributes:
|
||||
id (str):
|
||||
from_user (:class:`telegram.User`):
|
||||
query (str):
|
||||
offset (str):
|
||||
|
||||
Args:
|
||||
id (int):
|
||||
from_user (:class:`telegram.User`):
|
||||
query (str):
|
||||
offset (str):
|
||||
**kwargs: Arbitrary keyword arguments.
|
||||
|
||||
Keyword Args:
|
||||
location (optional[:class:`telegram.Location`]):
|
||||
"""
|
||||
|
||||
def __init__(self, id, from_user, query, offset, **kwargs):
|
||||
# Required
|
||||
self.id = id
|
||||
self.from_user = from_user
|
||||
self.query = query
|
||||
self.offset = offset
|
||||
|
||||
# Optional
|
||||
self.location = kwargs.get('location')
|
||||
|
||||
@staticmethod
|
||||
def de_json(data):
|
||||
"""
|
||||
Args:
|
||||
data (dict):
|
||||
|
||||
Returns:
|
||||
telegram.InlineQuery:
|
||||
"""
|
||||
data = super(InlineQuery, InlineQuery).de_json(data)
|
||||
|
||||
if not data:
|
||||
return None
|
||||
|
||||
data['from_user'] = User.de_json(data.get('from'))
|
||||
data['location'] = Location.de_json(data.get('location'))
|
||||
|
||||
return InlineQuery(**data)
|
||||
|
||||
def to_dict(self):
|
||||
"""
|
||||
Returns:
|
||||
dict:
|
||||
"""
|
||||
data = super(InlineQuery, self).to_dict()
|
||||
|
||||
# Required
|
||||
data['from'] = data.pop('from_user', None)
|
||||
|
||||
return data
|
||||
@@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=C0103,W0622
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015 Leandro Toledo de Souza <leandrotoeldodesouza@gmail.com>
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
@@ -16,41 +16,30 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
|
||||
"""This module contains a object that represents a Telegram GroupChat"""
|
||||
"""This module contains the classes that represent Telegram
|
||||
InlineQueryResult"""
|
||||
|
||||
from telegram import TelegramObject
|
||||
|
||||
|
||||
class GroupChat(TelegramObject):
|
||||
"""This object represents a Telegram GroupChat.
|
||||
class InlineQueryResult(TelegramObject):
|
||||
"""This object represents a Telegram InlineQueryResult.
|
||||
|
||||
Attributes:
|
||||
id (int):
|
||||
title (str):
|
||||
type (str):
|
||||
id (str):
|
||||
|
||||
Args:
|
||||
id (int):
|
||||
title (str):
|
||||
type (str):
|
||||
id (str): Unique identifier for this result, 1-64 Bytes
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
id,
|
||||
title):
|
||||
def __init__(self, type, id):
|
||||
# Required
|
||||
self.id = int(id)
|
||||
self.title = title
|
||||
self.type = str(type)
|
||||
self.id = str(id)
|
||||
|
||||
@staticmethod
|
||||
def de_json(data):
|
||||
"""
|
||||
Args:
|
||||
data (str):
|
||||
|
||||
Returns:
|
||||
telegram.GroupChat:
|
||||
"""
|
||||
if not data:
|
||||
return None
|
||||
|
||||
return GroupChat(**data)
|
||||
return super(InlineQueryResult, InlineQueryResult).de_json(data)
|
||||
@@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains the classes that represent Telegram
|
||||
InlineQueryResultArticle"""
|
||||
|
||||
from telegram import InlineQueryResult, InlineKeyboardMarkup, InputMessageContent
|
||||
|
||||
|
||||
class InlineQueryResultArticle(InlineQueryResult):
|
||||
"""This object represents a Telegram InlineQueryResultArticle.
|
||||
|
||||
Attributes:
|
||||
id (str):
|
||||
title (str):
|
||||
input_message_content (:class:`telegram.InputMessageContent`):
|
||||
reply_markup (:class:`telegram.ReplyMarkup`):
|
||||
url (str):
|
||||
hide_url (bool):
|
||||
description (str):
|
||||
thumb_url (str):
|
||||
thumb_width (int):
|
||||
thumb_height (int):
|
||||
|
||||
Deprecated: 4.0
|
||||
message_text (str): Use :class:`InputTextMessageContent` instead.
|
||||
|
||||
parse_mode (str): Use :class:`InputTextMessageContent` instead.
|
||||
|
||||
disable_web_page_preview (bool): Use :class:`InputTextMessageContent`
|
||||
instead.
|
||||
|
||||
Args:
|
||||
id (str): Unique identifier for this result, 1-64 Bytes
|
||||
title (str):
|
||||
reply_markup (:class:`telegram.ReplyMarkup`):
|
||||
|
||||
Keyword Args:
|
||||
url (Optional[str]):
|
||||
hide_url (Optional[bool]):
|
||||
description (Optional[str]):
|
||||
thumb_url (Optional[str]):
|
||||
thumb_width (Optional[int]):
|
||||
thumb_height (Optional[int]):
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
id,
|
||||
title,
|
||||
input_message_content,
|
||||
reply_markup=None,
|
||||
url=None,
|
||||
hide_url=None,
|
||||
description=None,
|
||||
thumb_url=None,
|
||||
thumb_width=None,
|
||||
thumb_height=None,
|
||||
**kwargs):
|
||||
|
||||
# Required
|
||||
super(InlineQueryResultArticle, self).__init__('article', id)
|
||||
self.title = title
|
||||
self.input_message_content = input_message_content
|
||||
|
||||
# Optional
|
||||
if reply_markup:
|
||||
self.reply_markup = reply_markup
|
||||
if url:
|
||||
self.url = url
|
||||
if hide_url:
|
||||
self.hide_url = hide_url
|
||||
if description:
|
||||
self.description = description
|
||||
if thumb_url:
|
||||
self.thumb_url = thumb_url
|
||||
if thumb_width:
|
||||
self.thumb_width = thumb_width
|
||||
if thumb_height:
|
||||
self.thumb_height = thumb_height
|
||||
|
||||
@staticmethod
|
||||
def de_json(data):
|
||||
data = super(InlineQueryResultArticle, InlineQueryResultArticle).de_json(data)
|
||||
|
||||
data['reply_markup'] = InlineKeyboardMarkup.de_json(data.get('reply_markup'))
|
||||
data['input_message_content'] = InputMessageContent.de_json(data.get(
|
||||
'input_message_content'))
|
||||
|
||||
return InlineQueryResultArticle(**data)
|
||||
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains the classes that represent Telegram
|
||||
InlineQueryResultAudio"""
|
||||
|
||||
from telegram import InlineQueryResult, InlineKeyboardMarkup, InputMessageContent
|
||||
|
||||
|
||||
class InlineQueryResultAudio(InlineQueryResult):
|
||||
"""Represents a link to an mp3 audio file. By default, this audio file will
|
||||
be sent by the user. Alternatively, you can use input_message_content to
|
||||
send a message with the specified content instead of the audio.
|
||||
|
||||
Attributes:
|
||||
id (str):
|
||||
audio_url (str):
|
||||
title (str):
|
||||
performer (Optional[str]):
|
||||
audio_duration (Optional[str]):
|
||||
reply_markup (Optional[:class:`telegram.InlineKeyboardMarkup`]):
|
||||
input_message_content (Optional[
|
||||
:class:`telegram.input_message_content`]):
|
||||
|
||||
Deprecated: 4.0
|
||||
message_text (str): Use :class:`InputTextMessageContent` instead.
|
||||
|
||||
parse_mode (str): Use :class:`InputTextMessageContent` instead.
|
||||
|
||||
disable_web_page_preview (bool): Use :class:`InputTextMessageContent`
|
||||
instead.
|
||||
|
||||
Args:
|
||||
audio_url (str):
|
||||
title (str):
|
||||
**kwargs: Arbitrary keyword arguments.
|
||||
|
||||
Keyword Args:
|
||||
performer (Optional[str]):
|
||||
audio_duration (Optional[str]):
|
||||
reply_markup (Optional[:class:`telegram.InlineKeyboardMarkup`]):
|
||||
input_message_content (Optional[
|
||||
:class:`telegram.input_message_content`]):
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
id,
|
||||
audio_url,
|
||||
title,
|
||||
performer=None,
|
||||
audio_duration=None,
|
||||
reply_markup=None,
|
||||
input_message_content=None,
|
||||
**kwargs):
|
||||
|
||||
# Required
|
||||
super(InlineQueryResultAudio, self).__init__('audio', id)
|
||||
self.audio_url = audio_url
|
||||
self.title = title
|
||||
|
||||
# Optionals
|
||||
if performer:
|
||||
self.performer = performer
|
||||
if audio_duration:
|
||||
self.audio_duration = audio_duration
|
||||
if reply_markup:
|
||||
self.reply_markup = reply_markup
|
||||
if input_message_content:
|
||||
self.input_message_content = input_message_content
|
||||
|
||||
@staticmethod
|
||||
def de_json(data):
|
||||
data = super(InlineQueryResultAudio, InlineQueryResultAudio).de_json(data)
|
||||
|
||||
data['reply_markup'] = InlineKeyboardMarkup.de_json(data.get('reply_markup'))
|
||||
data['input_message_content'] = InputMessageContent.de_json(data.get(
|
||||
'input_message_content'))
|
||||
|
||||
return InlineQueryResultAudio(**data)
|
||||
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains the classes that represent Telegram
|
||||
InlineQueryResultCachedAudio"""
|
||||
|
||||
from telegram import InlineQueryResult, InlineKeyboardMarkup, InputMessageContent
|
||||
|
||||
|
||||
class InlineQueryResultCachedAudio(InlineQueryResult):
|
||||
"""Represents a link to an mp3 audio file stored on the Telegram
|
||||
servers. By default, this audio file will be sent by the user.
|
||||
Alternatively, you can use input_message_content to send a message with
|
||||
the specified content instead of the audio.
|
||||
|
||||
Attributes:
|
||||
id (str):
|
||||
audio_file_id (str):
|
||||
reply_markup (Optional[:class:`telegram.InlineKeyboardMarkup`]):
|
||||
input_message_content (Optional[
|
||||
:class:`telegram.input_message_content`]):
|
||||
|
||||
Deprecated: 4.0
|
||||
message_text (str): Use :class:`InputTextMessageContent` instead.
|
||||
|
||||
parse_mode (str): Use :class:`InputTextMessageContent` instead.
|
||||
|
||||
disable_web_page_preview (bool): Use :class:`InputTextMessageContent`
|
||||
instead.
|
||||
|
||||
Args:
|
||||
audio_file_id (str):
|
||||
**kwargs: Arbitrary keyword arguments.
|
||||
|
||||
Keyword Args:
|
||||
reply_markup (Optional[:class:`telegram.InlineKeyboardMarkup`]):
|
||||
input_message_content (Optional[
|
||||
:class:`telegram.input_message_content`]):
|
||||
"""
|
||||
|
||||
def __init__(self, id, audio_file_id, reply_markup=None, input_message_content=None, **kwargs):
|
||||
# Required
|
||||
super(InlineQueryResultCachedAudio, self).__init__('audio', id)
|
||||
self.audio_file_id = audio_file_id
|
||||
|
||||
# Optionals
|
||||
if reply_markup:
|
||||
self.reply_markup = reply_markup
|
||||
if input_message_content:
|
||||
self.input_message_content = input_message_content
|
||||
|
||||
@staticmethod
|
||||
def de_json(data):
|
||||
data = super(InlineQueryResultCachedAudio, InlineQueryResultCachedAudio).de_json(data)
|
||||
|
||||
data['reply_markup'] = InlineKeyboardMarkup.de_json(data.get('reply_markup'))
|
||||
data['input_message_content'] = InputMessageContent.de_json(data.get(
|
||||
'input_message_content'))
|
||||
|
||||
return InlineQueryResultCachedAudio(**data)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user