Compare commits

...

492 Commits

Author SHA1 Message Date
_run e10517e088
Merge pull request #2017 from Artin-GH/patch-1
Fix backslash (\) issue in escape_markdown
2023-07-30 23:19:57 +05:00
Artin GH 1946393c36
Fix backslash (\) issue in escape_markdown 2023-07-14 16:39:50 +03:30
Badiboy 0f52ca688f
Merge pull request #2015 from Badiboy/master
Fix aioredis version check for regular redis
2023-07-14 13:00:03 +03:00
Badiboy b18bcd494a Fix aioredis version check for regular redis 2023-07-12 19:48:22 +03:00
Badiboy 8f41df0ee4
Merge pull request #2012 from Kourva/master
Update README.md
2023-07-10 19:01:09 +03:00
Kourva cb7f6a8c99
Update README.md 2023-07-10 03:05:34 +03:30
_run 3960115ec7
Merge pull request #2009 from coder2020official/fileupload
Fixes #1944: uploading file from memory
2023-07-09 00:06:02 +05:00
_run 916569cdc5
Fixes #1944: uploading file from memory 2023-07-08 23:42:47 +05:00
_run 75d3fa2eba
Merge pull request #2008 from coder2020official/middleware
Fix issue with post_process in async not receiving the error
2023-07-08 23:25:05 +05:00
_run 67e3774e8e
Fix issue with post_process in async not receiving the error 2023-07-08 23:23:23 +05:00
_run f799157314
Merge pull request #2007 from coder2020official/master
Updated all russian docstrings, currently without translation.
2023-07-08 23:15:05 +05:00
coder2020official af3a98057f Updated all russian docstrings, currently without translation. 2023-07-08 23:10:41 +05:00
_run 447fc1d461
Merge pull request #2006 from coder2020official/master
Fixed deprecation warning for readthedocs.org
2023-07-08 23:01:57 +05:00
_run fb98df3dfe
Fixed deprecation warning for readthedocs.org 2023-07-08 22:57:13 +05:00
Badiboy 0b34da3900
Merge pull request #1996 from artemetra/master
Fix typo in docs
2023-06-18 23:19:00 +03:00
Artem Lukin 5ea1abaadd
fix typo in docs 2023-06-18 01:57:08 +02:00
Badiboy 5a81353420
Merge pull request #1991 from eternnoir/dependabot/pip/requests-2.31.0
Bump requests from 2.20.0 to 2.31.0
2023-05-28 22:27:49 +03:00
dependabot[bot] eaf90cce7f
Bump requests from 2.20.0 to 2.31.0
Bumps [requests](https://github.com/psf/requests) from 2.20.0 to 2.31.0.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.20.0...v2.31.0)

---
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-22 21:33:40 +00:00
Badiboy b219218c8d
Merge pull request #1988 from Badiboy/master
Bump version to 4.12.0
2023-05-18 18:09:13 +03:00
Badiboy 2dac17aa75 Bump version to 4.12.0 2023-05-18 18:07:09 +03:00
Badiboy 48377ac905
Merge pull request #1947 from alex75311/edit_antiflood_method
redesigned the antiflood method for guaranteed message delivery
2023-05-08 09:10:28 +03:00
Alexey Isaev 14294d1aa3 redesigned the antiflood method for guaranteed message delivery 2023-05-04 23:08:10 +03:00
_run ea3c159044
Merge pull request #1975 from engAmirEng/feature/async-func-filter
bring back the async func message_filter
2023-05-02 20:43:48 +04:00
AmirW 58d53e1a54 bring back the async func message_filter
-fixes #1974
- related commits: c84896391e f69a2ba044
2023-04-28 16:12:23 +03:30
Badiboy abec3dc60e
Merge pull request #1969 from coder2020official/botapi6.7
Bot API 6.7 - Not much to do, just minor improvements
2023-04-24 09:38:21 +03:00
coder2020official ecb5d9b4f6 Added tests for __html_text, fixed the bug, added custom_emoji for entities 2023-04-22 22:53:57 +04:00
coder2020official 26575dc5e7 Added support for launching Web Apps from inline query results by replacing the parameters switch_pm_text and switch_pm_parameter of the method answerInlineQuery with the parameter button of type InlineQueryResultsButton. 2023-04-22 20:51:08 +04:00
coder2020official be69feb252 * Added a test for message entity __html_text function. #1971 should be fixed and then todo can be done. 2023-04-22 20:38:05 +04:00
coder2020official 1d62adc262 Added the ability to get the current bot name in the given language as the class BotName using the method getMyName. 2023-04-22 18:30:46 +04:00
coder2020official 77e1928628 Added the ability to set different bot names for different user languages using the method setMyName. 2023-04-22 18:25:24 +04:00
coder2020official d6f4987197 Added the field via_chat_folder_invite_link to the class ChatMemberUpdated. 2023-04-21 22:30:32 +04:00
coder2020official 966b451869 Added the field switch_inline_query_chosen_chat of the type SwitchInlineQueryChosenChat to the class InlineKeyboardButton, which allows bots to switch to inline mode in a chosen chat of the given type. 2023-04-21 22:28:20 +04:00
coder2020official d1417e5616 Added the field web_app_name to the class WriteAccessAllowed. 2023-04-21 22:14:16 +04:00
_run a7cafd1f24
Update README.md 2023-04-21 21:27:08 +04:00
Badiboy 92907ced30
Merge pull request #1966 from Badiboy/master
Bump version to 4.11.0
2023-04-15 22:40:59 +03:00
Badiboy 1b2ed0e2f7 Bump version to 4.11.0 2023-04-15 22:39:14 +03:00
_run 370f0370c7
Merge pull request #1964 from Cub11k/add_state_list
Add state_list to StatesGroup
2023-04-15 01:53:00 +05:00
Cub11k e4bddd91cb Define state_list in __init_subclass__ 2023-04-14 22:11:08 +03:00
Cub11k d466da3542 Add state_list to StatesGroup 2023-04-14 22:00:42 +03:00
Badiboy e64c06b7bc
Merge pull request #1951 from mikelei8291/doc-fix
Fix documentation for `InlineKeyboardMarkup` and `quick_markup`
2023-04-03 19:10:10 +03:00
Badiboy 7d168ebbd8
Merge pull request #1961 from fcoagz/patch-2
Update README.md
2023-04-03 18:56:38 +03:00
Francisco Griman c5689f383b
edit 2023-04-03 11:49:21 -04:00
Francisco Griman 8796168efb
Update README.md 2023-04-03 11:27:15 -04:00
_run 100659fecd
Merge pull request #1958 from coder2020official/master
Fix storage not saving data sometimes
2023-04-03 01:01:11 +05:00
_run 7bf87a306a
Update redis_storage.py 2023-04-03 01:00:48 +05:00
_run 351d021e01
Update redis_storage.py 2023-04-03 01:00:29 +05:00
Badiboy 4ffe0f8833
Merge pull request #1952 from Badiboy/master
More changes from review of bot api 6.6
2023-03-27 23:17:24 +03:00
Badiboy 3f07dc4ce8
thumb
Co-authored-by: _run <khumogo1@gmail.com>
2023-03-26 20:04:29 +03:00
Badiboy 2e589ab6e1 Thumb type spec 2023-03-26 18:00:35 +03:00
Badiboy 8b63f6a6ef Merge branch 'master' of https://github.com/Badiboy/pyTelegramBotAPI 2023-03-26 17:41:25 +03:00
Badiboy dc98aca173 Merge remote-tracking branch 'upstream/master' 2023-03-26 17:40:55 +03:00
Badiboy 39360e0640
send_video thumbnail hint
Co-authored-by: _run <khumogo1@gmail.com>
2023-03-25 16:38:16 +03:00
Badiboy b1c172c421
send_document thumbnail hint
Co-authored-by: _run <khumogo1@gmail.com>
2023-03-25 16:38:05 +03:00
Badiboy 6b5c263ee8
send_animtion thumbnail hint
Co-authored-by: _run <khumogo1@gmail.com>
2023-03-25 16:37:46 +03:00
Badiboy 46100edd97
send_video_note thumbnail hint
Co-authored-by: _run <khumogo1@gmail.com>
2023-03-25 16:37:22 +03:00
Badiboy 018b89cdc0
send_document thumbnail
Co-authored-by: _run <khumogo1@gmail.com>
2023-03-25 16:37:03 +03:00
Badiboy f3486b3730
send_document thumbnail
Co-authored-by: _run <khumogo1@gmail.com>
2023-03-25 16:36:36 +03:00
Badiboy b0e64d828c
send_video thumbnail hint
Co-authored-by: _run <khumogo1@gmail.com>
2023-03-25 16:36:10 +03:00
Badiboy 14434b398e
send_animation thumbnail hint
Co-authored-by: _run <khumogo1@gmail.com>
2023-03-25 16:34:08 +03:00
_run 1d62bf2ac8
Merge pull request #1949 from codebyzen/master
I added CalendarIT Telegram bot (with link to bot), can post acquainted with what is happening today, tomorrow or what happened 20 years ago to channel.
2023-03-25 16:40:46 +04:00
Badiboy fe2e9a7a30 thumb_url etc. converted to properties 2023-03-25 15:22:30 +03:00
Badiboy c9ef0d71f0 Deprecation warnings equalisation 2023-03-25 15:17:29 +03:00
Badiboy b0740a920a Set "thumb" as property in types 2023-03-25 15:08:40 +03:00
Badiboy 6a9c25cf80 Fix set_sticker_set_thumb and set_sticker_set_thumbnail 2023-03-25 14:56:31 +03:00
Badiboy e56c60ac00 thumb deprecation typo and thumb->thumbnail param rename 2023-03-25 14:44:50 +03:00
Badiboy 7c7a063fb6 Fix some code hints 2023-03-25 14:38:02 +03:00
Mike Lei bd69492ed4
Fix documentation for `InlineKeyboardMarkup` and `quick_markup` 2023-03-23 18:52:40 +00:00
C̷̱̺͙͓̪͔̹͉͉̯̖̟̀͆́̽̔̈̚͠͝o̶̥̻̻̖̮͚͒̂̒͌̾̇͗͘͝d̸̢̡͈̮̦͈͙̖͔̦̭̩̰͎͉̣̰͆̈́͘͝e̸͖͆̎̏͒̀̈́͛́̍̀̀̿̚͝B̵̨̯̹̝͙͉̲̟̳̟͎̪̫̪̤̒͋̉̑̐̒̅̅̋͜y̵̞͚͕̭̤̱͖̟̫̜̓͐̏̕ͅZ̸͎̫̖͍̪̓̐͆e̶͈͇̽̔͂̉͊̈́ņ̶̣̣͎̤̯͖͉͍̳͇͈̘̳̗͚́̄̊̂̊̏̄͐͐̿̓́̽̃̄̚͝ 37cdb52ed2 Merge branch 'master' of https://github.com/eternnoir/pyTelegramBotAPI 2023-03-19 17:39:29 +03:00
C̷̱̺͙͓̪͔̹͉͉̯̖̟̀͆́̽̔̈̚͠͝o̶̥̻̻̖̮͚͒̂̒͌̾̇͗͘͝d̸̢̡͈̮̦͈͙̖͔̦̭̩̰͎͉̣̰͆̈́͘͝e̸͖͆̎̏͒̀̈́͛́̍̀̀̿̚͝B̵̨̯̹̝͙͉̲̟̳̟͎̪̫̪̤̒͋̉̑̐̒̅̅̋͜y̵̞͚͕̭̤̱͖̟̫̜̓͐̏̕ͅZ̸͎̫̖͍̪̓̐͆e̶͈͇̽̔͂̉͊̈́ņ̶̣̣͎̤̯͖͉͍̳͇͈̘̳̗͚́̄̊̂̊̏̄͐͐̿̓́̽̃̄̚͝ d8569394b0 Update README.md
I added CalendarIT Telegram bot, can post acquainted with what is happening today, tomorrow or what happened 20 years ago to channel.
2023-03-19 17:39:24 +03:00
_run da57174635
Merge pull request #1948 from coder2020official/botapi6.6
Changes from review of bot api 6.6
2023-03-19 18:25:37 +04:00
_run 776ce0a7eb
Merge pull request #1942 from arashnm80/master
add SpotSeekBot
2023-03-19 17:36:48 +04:00
coder2020official 886806135e Merge branch 'botapi6.6' of https://github.com/coder2020official/pyTelegramBotAPI into botapi6.6 2023-03-19 17:31:55 +04:00
coder2020official 1e450ebd15 Bot API 6.6 review changes 2023-03-19 17:31:53 +04:00
_run 41521f5618
Merge pull request #1937 from coder2020official/botapi6.6
I'm back: Bot API 6.6 Update
2023-03-19 13:27:52 +04:00
_run 603a7cf9f2
Update telebot/asyncio_helper.py 2023-03-15 05:48:41 +04:00
_run 535a14ca0c
Update telebot/apihelper.py 2023-03-15 05:48:16 +04:00
_run 67a52b2e98
Apply suggestions from code review 2023-03-15 05:46:03 +04:00
Arash Nemat Zadeh c47c26d2b0
Update README.md 2023-03-14 17:29:51 +03:30
coder2020official 9d2f7c02a4 Fixing tests attempt 1 2023-03-11 23:54:57 +04:00
coder2020official 991679bedc Renamed all necessary thumbs to thumbnails in types.py 2023-03-11 23:53:16 +04:00
coder2020official 3b4e6fed04 Renamed the method setStickerSetThumb to setStickerSetThumbnail and its parameter thumb to thumbnail. 2023-03-11 23:37:32 +04:00
coder2020official 5c6b867582 Renamed the field thumb in the classes Animation, Audio, Document, Sticker, Video, VideoNote, InputMediaAnimation, InputMediaAudio, InputMediaDocument, InputMediaVideo, StickerSet to thumbnail. Renamed the parameter thumb in the methods sendAnimation, sendAudio, sendDocument, sendVideo, sendVideoNote to thumbnail. 2023-03-11 23:34:17 +04:00
coder2020official 715aabaf49 Added the method setStickerMaskPosition for changing the mask position of a mask sticker. 2023-03-11 23:06:57 +04:00
coder2020official 9fa5b91e58 Added the method setStickerKeywords for changing the search keywords assigned to a sticker. 2023-03-11 22:58:41 +04:00
coder2020official de5a32e45c Fixed custom_emoji_ids and added set_sticker_emoji_list, and and fixed some typehints 2023-03-11 22:53:33 +04:00
coder2020official db087427fc Added the method deleteStickerSet for complete deletion of a given sticker set that was created by the bot. 2023-03-11 22:27:37 +04:00
coder2020official 385fc6a6da Added the method setStickerSetTitle for editing the title of sticker sets created by the bot. 2023-03-11 22:24:34 +04:00
coder2020official ac0b386625 Added the method setCustomEmojiStickerSetThumbnail for editing the thumbnail of custom emoji sticker sets created by the bot. 2023-03-11 22:19:49 +04:00
coder2020official ae44b0022d Added support for .WEBP, .TGS, and .WEBM files in uploadStickerFile by replacing the parameter png_sticker in the method uploadStickerFile with the parameters sticker and sticker_format. 2023-03-11 22:15:31 +04:00
coder2020official 73135d6012 Added support for .WEBP files in createNewStickerSet and addStickerToSet. 2023-03-11 22:03:37 +04:00
coder2020official 19dcce0d5b Added support for the creation of sticker sets with multiple initial stickers in createNewStickerSet by replacing the parameters png_sticker, tgs_sticker, webm_sticker, emojis and mask_position with the parameters stickers and sticker_format. 2023-03-11 21:59:22 +04:00
coder2020official f527fc91f6 Replaced the parameters png_sticker, tgs_sticker, webm_sticker, emojis and mask_position in the method addStickerToSet with the parameter sticker of the type InputSticker. 2023-03-11 18:18:07 +04:00
coder2020official c0185dad44 Added the field needs_repainting to the class Sticker. 2023-03-11 16:41:19 +04:00
coder2020official 8a858cac4e Added the parameter needs_repainting to the method createNewStickerSet to automatically change the color of emoji based on context (e.g., use text color in messages, accent color in statuses, etc.). 2023-03-11 16:39:04 +04:00
coder2020official f30457bd75 Added support for the creation of custom emoji sticker sets in createNewStickerSet. 2023-03-11 16:33:02 +04:00
coder2020official 54caf30f69 Added the parameter emoji to the method sendSticker to specify an emoji for just uploaded stickers. 2023-03-11 15:50:09 +04:00
coder2020official 09e4a2a437 Added the ability to get the current bot short description in the given language as the class BotShortDescription using the method getMyShortDescription. 2023-03-11 15:46:35 +04:00
coder2020official 9b81a29a6a Added the ability to set different bot short descriptions for different user languages using the method setMyShortDescription. 2023-03-11 15:40:54 +04:00
coder2020official 65dcd67140 Added the ability to get the current bot description in the given language as the class BotDescription using the method getMyDescription. 2023-03-11 15:35:00 +04:00
coder2020official c84b771e5a Added the ability to set different bot descriptions for different user languages using the method setMyDescription. 2023-03-10 21:36:44 +04:00
_run 2bd81a5f5c
I'm back: Bot API Update too :) 2023-03-10 15:21:07 +04:00
Badiboy 5d9a76b0dd
Merge pull request #1917 from S1RANN/master
Add a function to extract contents of entities from messages
2023-03-03 11:00:03 +03:00
Badiboy 6459f13f25
Merge pull request #1927 from Badiboy/master
New content types added + typo fix
2023-02-22 09:51:22 +03:00
Badiboy c9b6d3f868 New content types added + typo fix 2023-02-22 09:49:29 +03:00
Badiboy 80c1a4798d
Merge pull request #1921 from zeldpol/patch-1
Fix .webm upload
2023-02-18 23:46:03 +03:00
Dmitry 7a67d5f9f9
Fix .webm async upload 2023-02-18 22:36:29 +02:00
zeldpol d12ea91e12
Fix .webm upload
No need to pass file content as a header, it causes the http error "431 Request Header Fields Too Large".
2023-02-17 19:23:11 +02:00
orocane 4f2c89c4a8 Add a function to extract contents of entities from messages 2023-02-15 17:24:39 +08:00
_run fb7d60f09d
Merge pull request #1913 from coder2020official/botapi6.5
Fix #1912
2023-02-09 19:49:17 +04:00
coder2020official 8dc4e77287 Update asyncio_helper.py 2023-02-09 19:27:05 +04:00
Badiboy a999161384
Merge pull request #1911 from Badiboy/master
restrict_chat_member fix
2023-02-09 17:58:28 +03:00
Badiboy b4196f5891 restrict_chat_member fix 2023-02-09 17:56:10 +03:00
Badiboy e55fe962ca
Merge pull request #1906 from Badiboy/master
Bump version to 4.10.0
2023-02-05 13:14:08 +03:00
Badiboy 3d2c5c9590 Bump version to 4.10.0 2023-02-05 13:11:07 +03:00
_run 40567570e8
Merge pull request #1902 from coder2020official/botapi6.5
Bot API 6.5 update 🔥
2023-02-05 13:07:47 +04:00
coder2020official 4179e502c3 Fix description 2023-02-05 11:13:31 +04:00
coder2020official a9b878107c Fix can_send_media_messages param, added warnings 2023-02-04 22:24:26 +04:00
coder2020official 2094120ec7 Added user_chat_id to ChatJoinRequest; And, i corrected typehints 2023-02-04 20:07:01 +04:00
coder2020official d1348606e3 Added use_independent_chat_permissions to setchatpermissions 2023-02-04 20:04:07 +04:00
coder2020official d0d03d0c09 Added use_independent_chat_permissions for restrictchatmember 2023-02-04 19:59:49 +04:00
Badiboy fdd82a5e4b
Merge pull request #1894 from Muhammad-Aadil/master
Added poll_example.py in the examples
2023-02-04 18:46:39 +03:00
coder2020official 9e68f76f5d Replaced the fields can_send_media_messages in the classes ChatMemberRestricted and ChatPermissions with separate fields can_send_audios, can_send_documents, can_send_photos, can_send_videos, can_send_video_notes, and can_send_voice_notes for different media types. 2023-02-04 18:57:06 +04:00
coder2020official 4000c9fb48 Added chat_shared and chatshared 2023-02-04 16:58:48 +04:00
coder2020official ae42d0b1fe Added usershared and user_shared 2023-02-04 16:54:43 +04:00
coder2020official a3891ff363 Pep 0563 proposed change
https://peps.python.org/pep-0563/
2023-02-04 16:29:48 +04:00
coder2020official 4d7f5310fb Added the class KeyboardButtonRequestChat and the field request_chat to the class KeyboardButton. 2023-02-04 16:24:05 +04:00
_run 3e0d69f7f4
fixed checks x1 2023-02-04 16:16:34 +04:00
coder2020official 2e5fb10430 Added the class KeyboardButtonRequestUser and the field request_user to the class KeyboardButton. 2023-02-04 16:02:18 +04:00
_run c39c050abf
Update README.md 2023-02-04 15:32:55 +04:00
Muhammad Aadil ed6d6cc03f add poll answer handler to poll_example.py to show the example to send next poll or log user answers 2023-02-04 11:22:49 +05:00
Muhammad Aadil 10a80e1cfa add only quiz type poll example to the poll_example.py 2023-02-04 10:27:29 +05:00
Badiboy d99f48f975
Merge pull request #1893 from artyl/master
RuntimeError("cannot join current thread")
2023-01-31 20:52:59 +03:00
_run dae2790c61
Merge pull request #1898 from Badiboy/master
Async allowed_updates fix
2023-01-31 20:59:35 +04:00
Badiboy f5eac56afa Async allowed_updates fix 2023-01-31 11:19:11 +03:00
_run 268c3a9210
Merge pull request #1890 from iamnalinor/master
Fix "invite link must be non-empty" error
2023-01-28 19:35:02 +04:00
Muhammad Aadil ad7e4bbaf7 Added poll_example.py in the examples 2023-01-28 18:20:58 +05:00
Artem Lavrenov b9bedef73f Avoid raise RuntimeError(cannot join current thread) 2023-01-28 12:26:25 +03:00
Badiboy 9fb5f89f18
Merge pull request #1892 from bgelov/patch-1
Update README.md
2023-01-27 09:24:07 +03:00
Oleg Belov 409ff49603
Update README.md
Change _handeler() to _handler() in readme
2023-01-26 22:49:41 -03:00
Albert 5e0da40fcd Fix "invite link must be non-empty" error
`bot.edit_chat_invite_link` method contained a mistake: `invite_link` and `name` were supposed to be vice-versa in `apihelper.edit_chat_invite_link(...)` call. This caused to be invite_link empty or contain invalid value, resulting to get `Bad Request: invite link must be non-empty` error.
This also affected the async version.
2023-01-21 17:00:36 +04:00
Badiboy b743aa5813
Merge pull request #1884 from Cub11k/master
Remove redundant function from util
2023-01-16 16:58:58 +03:00
Cub11k 1797f076dc Remove redundant function 2023-01-16 15:45:59 +02:00
_run 68c1fe8cb5
Merge pull request #1883 from Cub11k/master
Fix type of attribute id of InlineQuery from int to str
2023-01-15 17:22:22 +04:00
Cub11k 1eda7cafd4 Fix type of attribute id of InlineQuery from int to str 2023-01-15 15:04:07 +02:00
Badiboy 291566908b
Merge pull request #1882 from CommanderCRM/patch-1
Added a bot with public source code to the list
2023-01-13 15:58:55 +03:00
Ilya Krivoshein bef29d9318
Added a bot with public source code to the list 2023-01-13 19:14:10 +07:00
Badiboy a5af586a46
Merge pull request #1881 from Cub11k/master
Create method get_media_file_id() in util.py
2023-01-10 20:48:50 +03:00
Cub11k 93dcbbeb02 Create method get_media_file_id()
Method is used to get file id of different types of media
2023-01-10 19:35:36 +02:00
Badiboy bd94d8d91c
Merge pull request #1873 from coder2020official/circular_import_fix
Little code style improvement in service_utils
2023-01-08 09:55:33 +03:00
_run 6b399ab8cd
Being specific with except block 2023-01-08 10:49:27 +04:00
_run 8744402efc
Removed built-in io module from try/except block 2023-01-08 10:48:45 +04:00
Badiboy d5bbaa900e
Merge pull request #1870 from Cub11k/master
Make create_dir() method of StatePickleStorage cross-platform instead of POSIX only.
2023-01-07 13:02:26 +03:00
Konstantin Ostashenko 02ae255701
Revert changes in util.py 2023-01-06 22:39:27 +02:00
Cub11k c27f60b94b Make create_dir() method cross-platform instead of POSIX only.
Fix for issue #1869
2023-01-06 22:36:08 +02:00
Badiboy a781929a2d
Merge pull request #1868 from Cub11k/master
Fix circular import
2023-01-06 22:51:52 +03:00
Cub11k e6f8acadf4 rename _util.py to service_utils.py 2023-01-06 21:41:30 +02:00
Cub11k c298d95d0f Move functions, required in types.py to _util.py
Add __all__ to util.py for sphinx to generate docs properly
2023-01-06 19:27:25 +02:00
Cub11k 8aee5372ee Update README.md - add link to ru docs 2023-01-05 16:25:16 +02:00
_run df105ab1d8
Merge pull request #1867 from Cub11k/master
Translated into russian files: index.po, calldata.po
2023-01-05 18:20:30 +04:00
Cub11k b93ec5d0e0 Translated calldata.po to russian 2023-01-05 16:13:00 +02:00
Cub11k f201df3275 Translated index.po to russian 2023-01-05 16:03:14 +02:00
_run 206e4e024b
Merge pull request #1865 from coder2020official/master
Fix docs issues
2023-01-04 18:08:35 +04:00
coder2020official bd1290592b Fix docs issues 2023-01-04 18:07:29 +04:00
_run 9b9eb775f7
Merge pull request #1863 from Cub11k/master
Finished translations into russian of files: sync_version.po, async_version.po
2023-01-04 17:39:34 +04:00
Konstantin Ostashenko 3cfa24f9c0
Fix msgid for forward_message:5 in async_version.po 2023-01-04 15:35:09 +02:00
Konstantin Ostashenko b540a6c4d4
Fix msgid for forward_message:5 in sync_version.po 2023-01-04 15:33:18 +02:00
Cub11k a0ba5ae9af Finished translations on sync and async versions.
Spelling fixes
2023-01-04 00:43:42 +02:00
Cub11k 651db29cb2 Fix typehints for stop_poll reply markup 2023-01-03 23:45:59 +02:00
Cub11k 490168f3f6 Some translations
Up to lines sync_version.po:4527 and async_version.po:4448
2023-01-03 19:43:36 +02:00
Cub11k bf38071e8f Some translations
Up to lines sync_version.po:3691 and async_version.po:3609
2023-01-03 17:32:31 +02:00
Konstantin Ostashenko e8aaa524fe
Merge branch 'sync_and_async_upd' into master 2023-01-02 17:41:48 +02:00
Konstantin Ostashenko e2e754fdff
Merge pull request #3 from eternnoir/master
Update fork
2023-01-02 17:35:04 +02:00
_run d64f305fd4
Merge pull request #1861 from coder2020official/docs
Updated documentation locales
2023-01-02 19:29:40 +04:00
coder2020official 611bf4235c Updated documentation locales 2023-01-02 19:27:57 +04:00
Konstantin Ostashenko fe0dc6930c
Merge pull request #2 from Cub11k/master
Update branch from master
2023-01-02 17:14:33 +02:00
Konstantin Ostashenko 6d4d3f8005
Merge pull request #1 from eternnoir/master
Update fork
2023-01-02 17:12:49 +02:00
Cub11k 0f7464e8c4 Some translations
Up to lines sync_version.po:3008 and async_version.po:3122
2023-01-02 17:09:48 +02:00
Badiboy 6f86382e33
Merge pull request #1860 from Badiboy/master
Bump version to 4.9/0
2023-01-02 18:00:39 +03:00
Badiboy 43cc203654 Bump version to 4.9/0 2023-01-02 18:00:20 +03:00
Badiboy 3b62ad4765
Merge pull request #1855 from coder2020official/botapi6.4
Bot API 6.4
2023-01-02 17:55:32 +03:00
_run 3be5015f9e
Update telebot/types.py 2023-01-02 17:55:30 +04:00
_run 267a33c329
Update telebot/types.py 2023-01-02 17:55:14 +04:00
_run 667e82d073
Update telebot/types.py 2023-01-02 17:54:35 +04:00
Cub11k dd50273c95 Some translations
Up to lines sync_version.po:2709 and async_version.po:2853
2022-12-31 14:16:13 +02:00
Cub11k 8e9d566d5c Minor fixes and some translations
Up to lines sync_version.po:2382 and async_version.po:2528
2022-12-31 00:56:38 +02:00
_run 79bc869143
Merge pull request #1856 from Cub11k/master
Copied translations from sync_version.po to async_version.po
2022-12-30 23:56:32 +04:00
Konstantin Ostashenko 68edb4990c
Fix async_version.po 2022-12-30 21:42:50 +02:00
Cub11k 19544ecc58 Copied translations from sync_version.po to async_version.po
Minor fixes in sync_version.po, found while copying
2022-12-30 21:24:13 +02:00
coder2020official eed56be596 Added fields has_hidden_members and has_aggressive_anti_spam_enabled to class Chat 2022-12-30 20:38:26 +04:00
coder2020official 9f8256607a Added the parameter message_thread_id to the method sendChatAction for sending chat actions to a specific message thread or a forum topic.
Added the parameter message_thread_id to the method sendChatAction for sending chat actions to a specific message thread or a forum topic.
2022-12-30 20:23:53 +04:00
coder2020official f297ad23c7 Added methods for topic management
Added the methods editGeneralForumTopic, closeGeneralForumTopic, reopenGeneralForumTopic, hideGeneralForumTopic, unhideGeneralForumTopic for managing the General topic in forums.
2022-12-30 20:19:50 +04:00
coder2020official a20a3ae321 topic events and write_access_allowed
Added the classes ForumTopicEdited, GeneralForumTopicHidden, GeneralForumTopicUnhidden, and WriteAccessAllowed and the fields forum_topic_edited, general_forum_topic_hidden, general_forum_topic_unhidden, and write_access_allowed to the class Message.
2022-12-30 20:07:38 +04:00
coder2020official 107f92314b icon_custom_emoji_id and name parameters made optional for edit_forum_topic
The parameters name and icon_custom_emoji_id of the method editForumTopic are now optional. If they are omitted, the existing values are kept.
2022-12-30 19:50:14 +04:00
coder2020official 9f5d9861a4 Added the field has_media_spoiler to the class Message.
Added the field has_media_spoiler to the class Message.
2022-12-30 19:41:46 +04:00
coder2020official 4537b237c8 has_spoiler for types.py
Added the field has_spoiler to the classes InputMediaPhoto, InputMediaVideo, and InputMediaAnimation.
2022-12-30 19:27:38 +04:00
coder2020official 4d11e97c25 has_spoiler parameter
Added the parameter has_spoiler to the methods sendPhoto, sendVideo, and sendAnimation.
2022-12-30 19:20:23 +04:00
coder2020official f0a1cefdda Added the field is_persistent to the class ReplyKeyboardMarkup
Added the field is_persistent to the class ReplyKeyboardMarkup, allowing to control when the keyboard is shown.
2022-12-30 19:08:37 +04:00
_run 24cd014410
Update README.md 2022-12-30 18:52:00 +04:00
Badiboy ba64180b5f
Merge pull request #1854 from Cub11k/master
Fixed typehints for reply markup in editing methods
2022-12-30 16:44:31 +03:00
Cub11k 3812fd05e3 Fixed typehints for reply markup in editing methods (async) 2022-12-30 14:04:12 +02:00
Cub11k 69afd7232e Fixed typehints for reply markup in editing methods 2022-12-30 14:02:02 +02:00
Badiboy 81600cf27e
Merge pull request #1849 from eternnoir/dependabot/pip/wheel-0.38.1
Bump wheel from 0.24.0 to 0.38.1
2022-12-30 00:02:27 +03:00
_run bb8023ecc6
Merge pull request #1852 from Cub11k/master
Fixed typehints for register_<any>_handler()
2022-12-28 22:14:50 +04:00
Cub11k a50a6e2e54 Fixed typehints for register_<any>_handler() 2022-12-28 20:00:06 +02:00
Badiboy 0329e5adb8
Merge pull request #1850 from ayitinya/patch-1
Update README.md
2022-12-27 09:17:26 +03:00
Rudy Ayitinya Sulley 2f25b56659
Update README.md
Adds a bot to Bots using this library list
2022-12-27 02:46:07 +00:00
dependabot[bot] 2aaab08517
Bump wheel from 0.24.0 to 0.38.1
Bumps [wheel](https://github.com/pypa/wheel) from 0.24.0 to 0.38.1.
- [Release notes](https://github.com/pypa/wheel/releases)
- [Changelog](https://github.com/pypa/wheel/blob/main/docs/news.rst)
- [Commits](https://github.com/pypa/wheel/compare/0.24.0...0.38.1)

---
updated-dependencies:
- dependency-name: wheel
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-26 19:49:24 +00:00
_run a6a22c351a
Merge pull request #1845 from Cub11k/master
Partly translated files: sync_version.po
2022-12-21 17:14:55 +04:00
Cub11k d211db90cf Update sync_version.po 2022-12-21 15:04:43 +02:00
_run f2c211616c
Merge pull request #1844 from coder2020official/master
✉️ Fixed escape_markdown: now it should escape { and } characters in a string as well.
2022-12-21 16:59:03 +04:00
_run c5e733a4c1
Escape both metachars 2022-12-20 23:47:12 +04:00
_run 925f7012f1
Update formatting.py 2022-12-20 23:44:32 +04:00
_run 625ae09573
Merge pull request #1839 from coder2020official/master
Fix bug with asyncwebhooks
2022-12-19 17:35:23 +04:00
coder2020official 5b279b7ad9 (A)SyncWebhookListener changes 2022-12-19 17:28:05 +04:00
_run 247cddf23d
Merge pull request #1831 from coder2020official/reloader_fix
Update reloader.py
2022-12-19 17:17:11 +04:00
_run 171172d12e
Update async_telebot.py 2022-12-19 17:12:15 +04:00
_run c3c12b93dd
Merge pull request #1832 from coder2020official/master
Fix bug related to get_user_profile_photos
2022-12-14 14:18:18 +04:00
_run add240adfd
Update asyncio_helper.py 2022-12-14 12:41:30 +04:00
_run 45fe2ea319
Update reloader.py 2022-12-13 18:44:41 +04:00
Badiboy 6373af78f3
Merge pull request #1824 from reddere/patch-3
fixing escape()
2022-12-03 16:48:16 +03:00
reddere 4ed460b137
Update util.py 2022-12-03 14:23:10 +01:00
reddere ae20cb9f31
Update util.py 2022-12-03 14:21:31 +01:00
reddere 669c18fdc0
update
updated "== None" to "is None" and adjusted the else statement
2022-12-03 14:11:07 +01:00
reddere 34acae9a59
fixing escape()
fixing escape() as replacing a None would throw an exception 'NoneType' object has no attribute 'replace'. useful in case of escaping a None string given from message.from_user.last_name as you dont know wether the user has a last name or not
2022-12-03 13:33:22 +01:00
Badiboy 109ae69f27
Merge pull request #1823 from Badiboy/master
Fixed register_next_step_handler_by_chat_id chat_id description
2022-12-03 00:01:57 +03:00
Badiboy 43abedbff7 Fixed register_next_step_handler_by_chat_id chat_id description 2022-12-02 23:59:59 +03:00
Badiboy 42d162f732
Merge pull request #1822 from Badiboy/master
Fix caption_entities miss in InputMediaXXX
2022-12-02 23:52:54 +03:00
Badiboy cd4dc899a1 Fix caption_entities miss in InputMediaXXX 2022-12-02 23:46:26 +03:00
_run 5066626692
Merge pull request #1818 from Cub11k/master
Translated to russian file: util.po
2022-12-01 12:46:16 +04:00
Konstantin Ostashenko e255d9cbab
Update docs/source/locales/ru/LC_MESSAGES/util.po
Co-authored-by: _run <khumogo1@gmail.com>
2022-11-30 23:12:33 +02:00
Konstantin Ostashenko 8e1c8a2742
Update docs/source/locales/ru/LC_MESSAGES/util.po
Co-authored-by: _run <khumogo1@gmail.com>
2022-11-30 23:12:25 +02:00
Cub11k e358abc1bd Update util.po 2022-11-30 21:07:46 +02:00
_run 42da2d1794
Merge pull request #1816 from Cub11k/master
Translated into russian file: formatting.po
2022-11-30 19:44:24 +04:00
Cub11k feaef2b2b8 Merge remote-tracking branch 'origin/master' 2022-11-30 17:33:28 +02:00
Cub11k 6cf60a3dcb Update formatting.po according to comments 2022-11-30 17:33:06 +02:00
Konstantin Ostashenko 91ff06eeba
Update docs/source/locales/ru/LC_MESSAGES/formatting.po
Co-authored-by: _run <khumogo1@gmail.com>
2022-11-30 16:49:46 +02:00
Cub1tor 1c2111d689 Update formatting.po 2022-11-29 20:19:25 +02:00
_run bf039df122
Merge pull request #1815 from coder2020official/master
Update install.po
2022-11-29 19:25:40 +04:00
_run 44309797d1
Update install.po 2022-11-29 19:21:05 +04:00
_run 8489383eb4
Merge pull request #1814 from abdullaev388/master
Translated into russian files:  install.po, quick_start.po
2022-11-29 19:12:54 +04:00
abdullaev388 848a2cc7ec
Update docs/source/locales/ru/LC_MESSAGES/install.po
Co-authored-by: _run <khumogo1@gmail.com>
2022-11-29 10:11:27 -05:00
abdullaev388 cc87dbce50
Update docs/source/locales/ru/LC_MESSAGES/install.po
Co-authored-by: _run <khumogo1@gmail.com>
2022-11-29 10:11:21 -05:00
abdullaev388 15f6bbeacb
Update docs/source/locales/ru/LC_MESSAGES/install.po
Co-authored-by: _run <khumogo1@gmail.com>
2022-11-29 10:09:48 -05:00
abdullaev388 29befa4d0c
Update install.po
translated into russian
2022-11-29 09:25:10 -05:00
abdullaev388 cce03dab78
Update quick_start.po
translated into russian
2022-11-29 09:21:24 -05:00
_run 7702d63fd7
Merge pull request #1813 from coder2020official/docs
Base of ru documentation added.
2022-11-29 17:39:30 +04:00
_run d636cdf88b
Update doc_req.txt 2022-11-29 17:37:16 +04:00
_run 06a28380d7
Update doc_req.txt 2022-11-29 17:33:42 +04:00
coder2020official d7e9d3accc Update conf.py 2022-11-29 14:59:17 +04:00
coder2020official 736c03fe84 Update conf.py 2022-11-29 14:49:32 +04:00
coder2020official 7502d26b1a Added locales 2022-11-29 14:45:51 +04:00
Badiboy b4d59fdf0a
Merge pull request #1812 from Badiboy/master
Bump version to 4.8.0 and update Python versions
2022-11-28 19:24:46 +03:00
Badiboy 8d723bdcb3 Python 3.6 removed, Python 3.11 added 2022-11-28 19:17:23 +03:00
Badiboy a169404a7c Bump version to 4.8.0 2022-11-28 19:14:07 +03:00
Badiboy 7a20017dfb
Merge pull request #1811 from coder2020official/continuehandling-fix
Continuehandling fix
2022-11-27 11:30:37 +03:00
_run 8d82b3d56b
Update async_telebot.py 2022-11-26 20:08:00 +04:00
_run 0759c8e081
Update __init__.py 2022-11-26 20:07:08 +04:00
_run 8992db1d24
Merge pull request #1808 from coder2020official/master
Fix #1804
2022-11-26 20:05:00 +04:00
_run deb2099396
Update types.py 2022-11-22 18:36:15 +04:00
_run 8a74198276
Merge pull request #1801 from coder2020official/master
Fixed bot api bug
2022-11-18 23:22:39 +04:00
_run 15bd5f991a
Update types.py 2022-11-18 23:21:06 +04:00
_run 25571b581c
Update types.py 2022-11-18 23:12:03 +04:00
Badiboy bf617ab8da
Merge pull request #1799 from Badiboy/master
content_type_media and content_type_service reviewed
2022-11-13 13:21:45 +03:00
Badiboy 74732f2eda content_type_media and content_type_service reviewed 2022-11-13 13:20:26 +03:00
Badiboy 0a79f7e4f3
Merge pull request #1783 from coder2020official/botapi-63
Bot API 6.3 Update
2022-11-13 12:39:38 +03:00
_run 8b735aa114
Update __init__.py 2022-11-13 13:34:54 +04:00
coder2020official ae1845f285 Added active_usernames and emoji_status_custom_emoji_id 2022-11-06 17:38:01 +04:00
coder2020official 0846852ea1 Added all necessary parameters
Added the parameter message_thread_id to the methods sendMessage, sendPhoto, sendVideo, sendAnimation, sendAudio, sendDocument, sendSticker, sendVideoNote, sendVoice, sendLocation, sendVenue, sendContact, sendPoll, sendDice, sendInvoice, sendGame, sendMediaGroup, copyMessage, forwardMessage to support sending of messages to a forum topic.
2022-11-06 17:31:49 +04:00
coder2020official 4825624d48 Added docs to types, added new methods
Added the methods createForumTopic, editForumTopic, closeForumTopic, reopenForumTopic, deleteForumTopic, unpinAllForumTopicMessages, and getForumTopicIconStickers for forum topic management.
2022-11-06 15:43:16 +04:00
coder2020official 876d679765 Added ForumTopic class and fixed previous classes by fixing de_json method. 2022-11-06 15:14:19 +04:00
coder2020official 7958d0dca7 Added can_manage_topics for promotechatmember
Added the parameter can_manage_topics to the method promoteChatMember.
2022-11-06 15:04:41 +04:00
coder2020official 4e2ea90db3 Added field can_manage_topics
Added the field can_manage_topics to the classes ChatAdministratorRights, ChatPermissions, ChatMemberAdministrator, and ChatMemberRestricted.
2022-11-06 15:00:20 +04:00
coder2020official 566aef1679 Fix wrong typehint for previous commit 2022-11-06 14:49:13 +04:00
Badiboy 2dad99ad95
Merge pull request #1761 from coder2020official/master
Extended exception handler behaviour for async
2022-11-06 09:23:02 +03:00
coder2020official f288470b43 Added the classes ForumTopicCreated, ForumTopicClosed, and ForumTopicReopened and the fields forum_topic_created, forum_topic_closed, and forum_topic_reopened to the class Message. Note that service messages about forum topic creation can't be deleted with the deleteMessage method.
Added the classes ForumTopicCreated, ForumTopicClosed, and ForumTopicReopened and the fields forum_topic_created, forum_topic_closed, and forum_topic_reopened to the class Message. Note that service messages about forum topic creation can't be deleted with the deleteMessage method.
2022-11-06 01:04:33 +04:00
coder2020official 475394d241 Added message_thread_id & is_topic_message 2022-11-05 23:23:00 +04:00
coder2020official 76f06cacfe Fix typo 2022-11-05 23:15:10 +04:00
coder2020official 77738b2537 Added is_forum 2022-11-05 23:14:37 +04:00
coder2020official 070479f7af Update async_telebot.py 2022-11-05 23:06:28 +04:00
coder2020official f1f18c6df2 Fix error description 2022-11-05 22:49:07 +04:00
_run 81c8ee5820
Update README.md 2022-11-05 22:20:11 +04:00
Badiboy 76a689d939
Merge pull request #1774 from batmanscode/master
fixes: `debug` removed from uvicorn #1767
2022-11-02 13:29:45 +03:00
batmanscode 92ecfdec48
fixes: `debug` removed from uvicorn #1767 2022-10-30 17:21:53 +00:00
Badiboy 20376168c1
Merge pull request #1772 from sijokun/master
Added example of running serverless on AWS Lambda
2022-10-29 12:02:31 +03:00
Yan Khachko 507d53efbd
Rename lambda_function.py to aws_lambda_function.py 2022-10-29 11:57:53 +03:00
Yan Khachko 1d8dc78c87
Added example of running serverless on AWS Lambda
Example of using of PyTelegramBotAPI in Amazon AWS Lambda
2022-10-29 01:18:52 +03:00
Badiboy ebec3bf5c1
Merge pull request #1762 from reddere/patch-1
Fixed InlineQueryResultVideo params in example.
2022-10-24 19:25:15 +03:00
reddere d11b9802da
Fixed InlineQueryResultVideo params in example.
Fixed InlineQueryResultVideo params in example. String "Video" was passed in stead of the thumbnail url, making the example not work, This has been tested working.
2022-10-24 16:02:59 +02:00
coder2020official 572f103db7 Extended exception handler behaviour for async 2022-10-22 21:48:29 +04:00
Badiboy 231371f1f8
Merge pull request #1759 from Badiboy/master
Bump version to 4.7.1
2022-10-21 10:58:23 +03:00
Badiboy 623d8b27ec Bump version to 4.7.1 2022-10-21 10:18:47 +03:00
Badiboy 31c3a2b2a3
Merge pull request #1742 from byehack/ContinueHandling
Support ContinueHandling
2022-10-11 19:03:44 +03:00
_run c45af810f9
Updated docstrings for ContinueHandling 2022-10-11 19:15:38 +04:00
_run 81f090cce6
Update asyncio_handler_backends.py 2022-10-11 19:15:01 +04:00
_run 5d16b8bd4a
Create continue_handling.py 2022-10-11 19:13:10 +04:00
_run 0fecf46201
Create continue_handling.py 2022-10-11 19:09:59 +04:00
_run 982e642c73
Update telebot/handler_backends.py 2022-10-11 19:05:55 +04:00
byehack 97bca49c00
ContinueHandling on asyncio_handler_backends 2022-10-09 02:28:05 +03:30
Badiboy e0ee087162
Merge pull request #1749 from Badiboy/master
Check CUSTOM_REQUEST_SENDER before RETRY_xxx.
2022-10-08 23:43:44 +03:00
Badiboy 620b1364a6 Check CUSTOM_REQUEST_SENDER before RETRY_xxx. 2022-10-08 23:41:41 +03:00
Badiboy c561cf3076
Merge pull request #1748 from coder2020official/master
Added warning for non_stop=False
2022-10-08 23:24:58 +03:00
coder2020official b3953d6249 ℹ️ Better description 2022-10-08 23:03:04 +04:00
coder2020official 2d7170feee Added warning for non_stop=False 2022-10-08 22:35:22 +04:00
Badiboy 0ca8007633
Merge pull request #1747 from coder2020official/master
Update __init__.py
2022-10-07 20:57:49 +03:00
_run c541533762
Update __init__.py 2022-10-07 21:50:51 +04:00
byehack 4798c26188
improve code quality 2022-10-02 12:05:20 +03:30
byehack 30aaf8d0f1
Support ContinueHandling 2022-10-02 03:27:06 +03:30
Badiboy 82ad37fed8
Merge pull request #1693 from coder2020official/conflicts
Logging improvements(still not 100%), file restarts on file changes(needs tests), and more
2022-10-01 22:30:49 +03:00
coder2020official 2d1f39085d Improved code readability x 2 2022-10-01 22:34:49 +04:00
coder2020official b523cec22f Improved code readability 2022-10-01 22:32:41 +04:00
coder2020official 27e0197855 Added examples and made it possible to specify --path path for path 2022-10-01 21:28:53 +04:00
coder2020official ea69b8093d Added some notes 2022-10-01 21:15:24 +04:00
coder2020official 04ff428bba Added option to specify path to watch 2022-10-01 21:02:40 +04:00
coder2020official eb576d83fb Fixed a bug, made improvements in reload system
Didn't test that much, there is still some stuff to do
2022-09-30 23:22:21 +04:00
_run d3080b6d4e
Merge branch 'master' into conflicts 2022-09-30 22:53:19 +04:00
Badiboy 7c9b01b10a
Merge pull request #1722 from Badiboy/master
Handlers and Middlewares processing union
2022-09-24 22:16:33 +03:00
Badiboy b3993bb019 Merge remote-tracking branch 'upstream/master' 2022-09-24 22:14:45 +03:00
Badiboy 36b889feab
Merge pull request #1736 from AntonGlyzin/antonglyzin-shopbotlist
Added a new bot to the list
2022-09-24 16:06:33 +03:00
Anton d943f40643 Added a new bot to the list 2022-09-24 15:33:11 +03:00
_run dafafd2ad2
Merge pull request #1735 from coder2020official/class_params
⚙️ Added some frequent parameters to classes(see full list)
2022-09-23 22:06:09 +04:00
coder2020official e002484a9b ⚙️ Added some frequent parameters to classes(see full list)
Added:
- disable_web_page_preview
- disable_notification
- protect_content
- allow_sending_without_reply
2022-09-23 21:52:40 +04:00
Badiboy 52e09637c2 Fix: do not call handler in one more task 2022-09-17 23:17:07 +03:00
Badiboy e7a96ec2ed Rename also in Async 2022-09-17 14:09:05 +03:00
Badiboy 598de25b6d Rename _check_middlewares to _get_middlewares 2022-09-17 12:55:55 +03:00
_run b841fc10ed
Merge pull request #1723 from byehack/patch-1
don't block loop
2022-09-17 13:42:57 +04:00
byehack c14760d81c
don't block loop 2022-09-17 13:58:28 +04:30
Badiboy da639dd1f6 Handlers and Middlewares processing union
Call for handlers now union in a single function for future extension.

Plus minor fixes in storages.
2022-09-17 11:57:12 +03:00
_run 96e137f5e6
Update setup.py 2022-09-16 22:39:40 +04:00
Badiboy 8d9dfcfac8
Merge pull request #1707 from S1RANN/master
raise other exceptions in antiflood function
2022-09-13 17:59:30 +03:00
_run a1c77db236
Merge pull request #1710 from coder2020official/bugfixes
Fixed difference between request_timeout and timeout.
2022-09-10 20:48:30 +04:00
coder2020official 4f97b26e81 Update asyncio_helper.py 2022-09-10 20:37:13 +04:00
coder2020official 0028feb4c5 Update asyncio_helper.py 2022-09-10 20:14:48 +04:00
orocane a06b4a1e9c raise other exceptions in antiflood 2022-09-10 21:46:16 +08:00
coder2020official da5084f53c Update asyncio_helper.py 2022-09-10 14:36:56 +04:00
coder2020official 2f8d878f06 Fixed difference between request_timeout and timeout.
getUpdates parameter may contain 2 parameters: request_timeout & timeout. other methods may contain timeout parameter that should be applied to ClientTimeout.
2022-09-10 14:34:56 +04:00
orocane 783beb165b raise other exceptions in antiflood 2022-09-10 15:59:40 +08:00
_run 4fd01e3ac8
Merge pull request #1703 from coder2020official/downloadfile
Fix #1702
2022-09-09 21:09:25 +04:00
_run b4c28de104
Update asyncio_helper.py 2022-09-07 20:44:39 +04:00
_run de344bd5e0
Merge pull request #1701 from coder2020official/states
#1699 fixed
2022-09-06 18:16:06 +04:00
_run e3a4fdff9a
Update asyncio_filters.py 2022-09-06 18:12:11 +04:00
_run 71d3ec8b42
Changed user id and chat id 2022-09-06 18:11:40 +04:00
coder2020official 1b1d6c8239 Improved asyncio helper's logger 2022-08-30 21:26:56 +04:00
coder2020official 9216f15c16 Logs, file restarts, loggers to async
Added colorful logs, file restarts on changes, improved logger, added cached version of user-bot to async
2022-08-30 21:26:41 +04:00
coder2020official 0f7ab0d05f Added colorful logs, file restarts on changes to sync 2022-08-30 21:25:41 +04:00
coder2020official e0ffe0b4f5 Added reloader to ext 2022-08-30 21:24:54 +04:00
Badiboy f4c5dd0d22
Merge pull request #1691 from ananthb/master
Starlette ASGI example
2022-08-30 15:55:28 +03:00
Ananth Bhaskararaman e4179ea65f
Add SSL cert 2022-08-30 17:27:43 +05:30
Ananth Bhaskararaman d7770bf670
Starlette ASGI example 2022-08-30 17:05:56 +05:30
_run 095bf03227
Merge pull request #1688 from ananthb/patch-1
Import aioredis from redis module too
2022-08-30 12:28:18 +04:00
_run 85bd174fdc
Update redis_storage.py 2022-08-30 12:26:34 +04:00
Ananth Bhaskararaman b86c38367a
Import aioredis from redis module too
aioredis is available in redis-py as of version 4.2.0rc1: https://github.com/aio-libs/aioredis-py#-aioredis-is-now-in-redis-py-420rc1-
Try importing from the new package as well.
2022-08-28 17:32:56 +05:30
Badiboy b8214d32d5
Merge pull request #1679 from Badiboy/master
Code simplify and sync/async unificatiion
2022-08-22 12:20:36 +03:00
Badiboy f4e66f6807 Added traceback for handlers exception 2022-08-21 22:27:02 +03:00
Badiboy b1a4136603 Code simplify and sync/async unificatiion 2022-08-21 20:32:37 +03:00
Badiboy 3d97b08289
Merge pull request #1678 from coder2020official/master
Fixed bug with searching a new handler after the execution of handler
2022-08-21 19:38:59 +03:00
_run 3d2576ca24 Fixed bug with searching a new handler after the execution of handler 2022-08-21 20:42:55 +05:00
Badiboy b2d2ab5c33
Merge pull request #1675 from coder2020official/master
Fixed #1650
2022-08-17 00:38:59 +03:00
_run c9a732e3dd
Merge branch 'eternnoir:master' into master 2022-08-16 21:39:55 +05:00
_run 01be1fb583 Fixes #1650 2022-08-16 21:39:20 +05:00
Badiboy 7b95874627
Merge pull request #1672 from Badiboy/master
Typo fix
2022-08-16 17:34:57 +03:00
Badiboy 426f9f3787 Typo fix
and minor code opt
2022-08-16 17:12:50 +03:00
Badiboy 47ae696528
Merge pull request #1668 from coder2020official/master
Update asyncio_helper.py
2022-08-13 13:03:47 +03:00
Badiboy a9b8baea2c
Merge pull request #1667 from Badiboy/master
Readme update
2022-08-13 12:59:57 +03:00
_run d3cab9cdba Update asyncio_helper.py 2022-08-13 14:59:57 +05:00
Badiboy d6ef67073e Readme fix 2022-08-13 12:59:13 +03:00
Badiboy 345fa3433c Readme update 2022-08-13 12:58:20 +03:00
_run c95ba8c9c2
Merge pull request #1666 from coder2020official/master
Update async_telebot.py
2022-08-13 14:58:11 +05:00
_run 20bdb54e94 Update async_telebot.py 2022-08-13 14:57:39 +05:00
Badiboy 124dfbf392
Merge pull request #1665 from Badiboy/master
Bump version to 4.7.0
2022-08-13 12:53:00 +03:00
Badiboy 9f9821bbe8 Bump version to 4.7.0 2022-08-13 12:52:38 +03:00
Badiboy c8d1dac61e
Merge pull request #1663 from coder2020official/master
Bot API 6.2
2022-08-13 12:44:33 +03:00
_run ffb34da610 Fix 2022-08-13 14:40:20 +05:00
_run 2647a02fc6 Contains_mask 2022-08-13 14:36:48 +05:00
_run dd4073fd74 Fixes regarding contains_masks 2022-08-13 13:22:25 +05:00
_run 737c3a439d Fix tests(1st attempt) 2022-08-12 22:13:54 +05:00
_run 40698408c9 Bot API 6.2 2022-08-12 22:10:08 +05:00
_run ffa1c37204
Update README.md 2022-08-12 20:12:44 +05:00
Badiboy d42c8e2961
Merge pull request #1652 from coder2020official/master
Added InputFile
2022-08-12 17:35:20 +03:00
_run 5471b88da6 Update apihelper.py 2022-08-12 19:25:46 +05:00
_run 26db76f207 Fix backward comptability 2022-08-12 15:25:51 +05:00
_run e860f114c6 Forgot to remove unnecessary import 2022-08-12 14:37:00 +05:00
_run c5a69944be Documentation improvements and file name fix 2022-08-12 14:33:24 +05:00
Badiboy 2fe5ba403e
Merge pull request #1662 from Peibolvig/add_web_app_data_content_type
Add 'web_app_data' content type to README
2022-08-12 10:14:03 +03:00
Badiboy d2a7f975de
Merge pull request #1661 from ablakely/patch-1
Update README.md
2022-08-12 10:08:09 +03:00
Pablo Vazquez Rodriguez 41b1519786 Add 'web_app_data' content type to README 2022-08-12 01:53:35 +02:00
Aaron Blakely 93e1813139
Update README.md
Added TeleServ
2022-08-11 18:17:06 -05:00
Badiboy dab5d7f632
Merge pull request #1660 from Mahakam20000/master
Example of async bot using webhook and aiohttp
2022-08-10 22:28:17 +03:00
Mahakam20000 1667b51034
Example of async bot using webhook and aiohttp
An async echo bot using aiohttp and webhoook
2022-08-10 19:57:30 +02:00
Badiboy 7d94e01009
Merge pull request #1655 from dasshit/master
Fix for token visibility in swagger in fastapi webhook example
2022-08-09 08:04:16 +03:00
v.korobov c0ed659f30 Minor code style fixes 2022-08-08 23:07:04 +03:00
v.korobov 047777fada Fixed TOKEN visibility in fastapi swagger 2022-08-08 23:04:36 +03:00
Badiboy 839aced912
Merge pull request #1646 from coder2020official/test_branch
Removed state storages and fixed a typo(for docs)
2022-08-01 13:24:29 +03:00
_run d03f3b2c52 Updated asyncio_helper to support InputFile and fixed unecessary methods 2022-08-01 14:09:44 +05:00
_run 65b353ffae Added InputFile 2022-08-01 12:40:43 +05:00
Badiboy 914c5fdf0c
Merge pull request #1649 from Badiboy/master
Bump version to 4.6.1
2022-07-27 17:19:53 +03:00
Badiboy 8aa3d052cc Bump version to 4.6.1 2022-07-27 17:18:54 +03:00
_run 5beb51f907 Removed state storages and fixed a typo 2022-07-27 13:48:20 +05:00
Badiboy c145b7ef8f
Merge pull request #1644 from coder2020official/test_branch
Updated all docstrings(visual)
2022-07-26 21:31:27 +03:00
_run 6303ecc7c6 Little fix 2022-07-26 20:45:32 +05:00
_run fc01ec50fc Added .ext file to documentation 2022-07-26 16:30:51 +05:00
_run 51b2ec701d Removed unecessary methods from documentation(to_json, de_json, to_dict) 2022-07-26 16:27:15 +05:00
_run 3d7f334d79 Updated all docstrings for types(visual) 2022-07-26 16:16:35 +05:00
Badiboy a61508ca0c
Merge pull request #1643 from robz-tirtlib/patch-1
small fix
2022-07-25 21:42:22 +03:00
robz-tirtlib 9d9e76e724
small fix
Fixed "ERROR - TeleBot: "message_handler: Commands filter should be list of strings (commands), unknown type supplied to the 'commands' filter list. Not able to use the supplied type."
2022-07-25 15:49:33 +03:00
_run b0e06253ff Completed docstrings for all files except types.py 2022-07-24 23:14:09 +05:00
Badiboy 7c12162576
Merge pull request #1640 from coder2020official/master
Updated all docstrings / typehints in __init__.py(visual)
2022-07-20 11:35:40 +03:00
_run f0feb45e87 Completed all docstrings / typehints up to 100%(visual) 2022-07-19 23:51:25 +05:00
_run c2cfe24426 Typehints & Docstrings completed for sync version up to 100%(visual) 2022-07-19 23:49:05 +05:00
_run f6ec3493ad Fixed 45% of typehints/docstrings for sync telebot 2022-07-19 00:27:21 +05:00
Badiboy e553f3aa1d
Merge pull request #1638 from coder2020official/master
Fixes #1637, #1636
2022-07-18 18:14:52 +03:00
_run 49d3b463ed Fixes #1636 2022-07-18 14:01:14 +05:00
_run 147278733b Fix #1637 2022-07-18 13:47:14 +05:00
Badiboy 54ad1582aa
Merge pull request #1635 from coder2020official/master
Fixed description
2022-07-17 00:42:55 +03:00
_run e379708af6
Update __init__.py 2022-07-16 20:12:38 +05:00
_run 9f7b113e2f
Merge branch 'master' into master 2022-07-16 20:11:40 +05:00
_run 482498e1e5 Merge branch 'master' of https://github.com/coder2020official/pyTelegramBotAPI 2022-07-16 20:09:54 +05:00
_run 22beead3b5 Update __init__.py 2022-07-16 20:09:52 +05:00
Badiboy 2b01765627
Merge pull request #1633 from coder2020official/master
Update async_telebot.py
2022-07-16 18:04:52 +03:00
Badiboy 5dbe1b3523
Merge pull request #1631 from coder2020official/newfeatures
update_sensitive field for middlewares
2022-07-16 12:46:12 +03:00
_run 3ffd06fcca
Add feedback-bot to `Bots using this library` section 2022-07-15 23:26:55 +05:00
_run ea1efad1ea Update asyncio_helper.py 2022-07-15 22:28:43 +05:00
_run 1efe465e9d
Update async_telebot.py 2022-07-15 22:06:18 +05:00
_run 0c6f84c79a update_sensitive field for middlewares 2022-07-15 16:24:15 +05:00
Badiboy bf415e4bd7
Merge pull request #1624 from coder2020official/master
Set request_timeout to default aiohttp's timeout(5 minutes)
2022-07-13 20:01:30 +03:00
_run 2fcfdc2584
Merge branch 'eternnoir:master' into master 2022-07-13 21:52:57 +05:00
_run 659501efef
Update async_telebot.py 2022-07-13 21:52:48 +05:00
Badiboy 92654ee970
Merge pull request #1623 from Badiboy/master
Fix exception with typed_middleware_handlers
2022-07-13 15:08:12 +03:00
Badiboy a1bcd3c42e use_class_middlewares checks added 2022-07-13 13:10:16 +03:00
Badiboy b276bfacaf Fix exception with typed_middleware_handlers
+ some additional checks
2022-07-13 12:30:13 +03:00
Badiboy 726b203724
Merge pull request #1621 from Badiboy/master
Typo
2022-07-12 22:48:01 +03:00
Badiboy 16703161aa Typo 2022-07-12 22:44:25 +03:00
Badiboy a3a55e7393
Merge pull request #1617 from coder2020official/bugfixes
Extended exception handler behaviour with middlewares for synchronous version as well
2022-07-12 22:12:20 +03:00
Badiboy 1c11898ea1
Merge pull request #1612 from coder2020official/newfeatures
run_webhooks() built in function to listen and process webhook requests.
2022-07-11 23:33:39 +03:00
_run 8c6f81546c A typo fixed 2022-07-11 23:24:22 +05:00
_run 194bf6e95d Merge branch 'bugfixes' of https://github.com/coder2020official/pyTelegramBotAPI into bugfixes 2022-07-11 23:23:10 +05:00
_run 124606fdcb Extend exception handler behaviour with middlewares 2022-07-11 23:22:11 +05:00
_run 90a90d4a34 Divided async and sync versions into aio & sync folders 2022-07-09 22:30:36 +05:00
_run d67ee2a5c5 Delete webhooks.py 2022-07-08 21:16:01 +05:00
_run 970b9d6be4 SyncWebhookListener was rewritten under fastapi. Extensions folder was divided into 2(namings are long, might be changed) 2022-07-08 21:13:07 +05:00
Badiboy 0b5b7ad39a
Merge pull request #1614 from Badiboy/master
parse_web_app_data function fix
2022-07-08 11:19:35 +03:00
Badiboy a7c420aa14 parse_web_app_data function fix 2022-07-08 11:15:50 +03:00
_run 0cf2a0fe77 Added extra dependencies and fixed tests 2022-07-07 23:02:51 +05:00
_run 2f32236680 Added run_webhooks for asynctelebot 2022-07-07 22:56:13 +05:00
_run f8f147f9f4 Fix certificate for webhooks 2022-07-07 15:53:27 +05:00
_run 140befc132 Typehint fix if there is no flask installed 2022-07-07 15:15:24 +05:00
_run 36fbb13663 Merge branch 'newfeatures' of https://github.com/coder2020official/pyTelegramBotAPI into newfeatures 2022-07-07 15:09:45 +05:00
_run e353572c03 Update webhooks listeners. 2022-07-07 15:09:02 +05:00
_run ebca668979
Create __init__.py 2022-07-06 23:35:59 +05:00
_run 7b8c98d731 Test 2022-07-06 23:15:22 +05:00
_run 3cf5305845 Rename 2022-07-06 22:06:49 +05:00
_run eb4cd7aba0 Webhook processing function using flask for sync 2022-07-06 21:31:03 +05:00
Badiboy 01f9e3b710
Merge pull request #1607 from coder2020official/newfeatures
ReadME update and filter updates
2022-07-05 22:40:54 +03:00
_run e1094c6f02
Update README.md 2022-07-05 21:50:11 +05:00
_run 174bbf9c84
Merge branch 'eternnoir:master' into newfeatures 2022-07-05 21:19:21 +05:00
_run 1df19e3b2d CallbackQuery fixes for custom filters
Now some custom filters support callback query messages
2022-07-05 21:18:42 +05:00
Badiboy e0e6eee374
Merge pull request #1605 from Badiboy/master
ChatMember is now typed
2022-07-05 00:01:38 +03:00
Badiboy 78251cdf43 ChatMember type checking reordered 2022-07-04 22:41:01 +03:00
Badiboy 81cbddb8cd Added source data (json_string) to CallbackQuery 2022-07-04 22:36:42 +03:00
Badiboy 0aa9f0fb42 Update type fix 2022-07-04 22:26:24 +03:00
Badiboy f3b1f97362 ChatMember is now typed
https://core.telegram.org/bots/api#chatmember
2022-07-03 23:33:55 +03:00
Badiboy df1977911e
Merge pull request #1603 from coder2020official/master
#1594 & fixes regarding handler execution in async
2022-07-02 23:12:49 +03:00
_run d861fd0042
Merge branch 'eternnoir:master' into master 2022-07-02 21:07:23 +05:00
_run 1fb14e28d4 Fix handler execution and #1594 2022-07-02 21:07:00 +05:00
Badiboy b691a467c0
Merge pull request #1602 from GooGuJiang/patch-1
Add bot to README.md
2022-07-02 11:18:04 +03:00
咕谷酱 badf982147
Update README.md 2022-07-02 15:08:06 +08:00
咕谷酱 6d52090ef9
Update README.md 2022-07-02 15:06:46 +08:00
咕谷酱 cf3a85d699
Update README.md 2022-07-02 14:31:37 +08:00
咕谷酱 ef86453126
Update README.md 2022-07-02 14:23:31 +08:00
Badiboy d9ab5b0d28
Merge pull request #1599 from coder2020official/master
Fix group and supergroup issues with states
2022-07-01 13:55:48 +03:00
_run c920809fa9
Update asyncio_helper.py 2022-07-01 15:39:42 +05:00
_run 5939e754bb
Update asyncio_helper.py 2022-07-01 15:29:34 +05:00
_run 3019b71f7f
Merge branch 'eternnoir:master' into master 2022-06-30 17:54:25 +05:00
_run 0bdf925fbe Merge branch 'master' of https://github.com/coder2020official/pyTelegramBotAPI 2022-06-30 17:54:16 +05:00
_run d14064a84d Fix group and supergroup issues 2022-06-30 17:51:58 +05:00
Badiboy 49c93b6027
Merge pull request #1598 from coder2020official/master
Fix typehint for set_state
2022-06-30 15:32:30 +03:00
_run 36749cbdd9
Merge branch 'eternnoir:master' into master 2022-06-30 17:10:25 +05:00
_run 6d12b1f2a7
Update callback_data.py 2022-06-30 17:10:14 +05:00
_run 419bc5878f Fix typehint for ```set_state``` 2022-06-30 17:06:39 +05:00
Badiboy b9b4885568
Merge pull request #1597 from Badiboy/master
Copyright update
2022-06-29 19:25:40 +03:00
Badiboy ce0a974c91 Copyright update 2022-06-29 19:24:27 +03:00
_run c36f3a228e Update callback_data.py 2022-06-29 21:17:57 +05:00
_run ca525b5bea Copyright changes 2022-06-29 21:06:36 +05:00
Badiboy 6ff015689a
Merge pull request #1595 from coder2020official/master
Add the possibility to getbase class of a State object
2022-06-29 18:34:06 +03:00
_run 6459aded82
Merge branch 'eternnoir:master' into master 2022-06-29 20:22:59 +05:00
_run fec47cecaf Add the possibility to getbase class of a State object 2022-06-29 20:21:42 +05:00
Badiboy 3892b0fb80
Merge pull request #1593 from coder2020official/master
Fixed previous fix 🤦‍♂️
2022-06-29 12:58:43 +03:00
_run fbb9a73fc0 F###, forgot to put await 2022-06-29 14:52:37 +05:00
Badiboy db5c53b8e5
Merge pull request #1591 from coder2020official/master
Pass only the necessary data
2022-06-28 17:58:35 +03:00
_run 6e8abc709e Pass only the necessary data 2022-06-28 19:51:51 +05:00
Badiboy 752f35614c
Merge pull request #1587 from coder2020official/master
Middleware update: everything in data will be passed to handler if ne…
2022-06-26 12:09:38 +03:00
_run a2893945b2 Async changes and sync improvements 2022-06-25 22:15:53 +05:00
_run 1686ce4f44 Middleware update: everything in data will be passed to handler if needed. 2022-06-25 21:48:44 +05:00
68 changed files with 52520 additions and 2726 deletions

View File

@ -20,7 +20,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [ '3.6','3.7','3.8','3.9', '3.10', 'pypy-3.7', 'pypy-3.8', 'pypy-3.9']
python-version: [ '3.7', '3.8', '3.9', '3.10', '3.11', 'pypy-3.7', 'pypy-3.8', 'pypy-3.9']
name: ${{ matrix.python-version }} and tests
steps:
- uses: actions/checkout@v2

22
.readthedocs.yaml Normal file
View File

@ -0,0 +1,22 @@
# .readthedocs.yaml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the version of Python and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.9"
# Build documentation in the docs/ directory with Sphinx
sphinx:
configuration: docs/conf.py
# We recommend specifying your dependencies to enable reproducible builds:
# https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
install:
- requirements: docs/requirements.txt

View File

@ -4,6 +4,7 @@ python:
- "3.8"
- "3.9"
- "3.10"
- "3.11"
- "pypy3"
install: "pip install -r requirements.txt"
script:

View File

@ -2,7 +2,6 @@
[![PyPi Package Version](https://img.shields.io/pypi/v/pyTelegramBotAPI.svg)](https://pypi.python.org/pypi/pyTelegramBotAPI)
[![Supported Python versions](https://img.shields.io/pypi/pyversions/pyTelegramBotAPI.svg)](https://pypi.python.org/pypi/pyTelegramBotAPI)
[![Documentation Status](https://readthedocs.org/projects/pytba/badge/?version=latest)](https://pytba.readthedocs.io/en/latest/?badge=latest)
[![Build Status](https://travis-ci.org/eternnoir/pyTelegramBotAPI.svg?branch=master)](https://travis-ci.org/eternnoir/pyTelegramBotAPI)
[![PyPi downloads](https://img.shields.io/pypi/dm/pyTelegramBotAPI.svg)](https://pypi.org/project/pyTelegramBotAPI/)
[![PyPi status](https://img.shields.io/pypi/status/pytelegrambotapi.svg?style=flat-square)](https://pypi.python.org/pypi/pytelegrambotapi)
@ -11,9 +10,10 @@
<p align="center">A simple, but extensible Python implementation for the <a href="https://core.telegram.org/bots/api">Telegram Bot API</a>.</p>
<p align="center">Both synchronous and asynchronous.</p>
## <p align="center">Supported Bot API version: <a href="https://core.telegram.org/bots/api#june-20-2022">6.1</a>!
## <p align="center">Supported Bot API version: <a href="https://core.telegram.org/bots/api#april-21-2023">6.7</a>!
<h2><a href='https://pytba.readthedocs.io/en/latest/index.html'>Official documentation</a></h2>
<h2><a href='https://pytba.readthedocs.io/ru/latest/index.html'>Official ru documentation</a></h2>
## Contents
@ -56,7 +56,7 @@
* [Logging](#logging)
* [Proxy](#proxy)
* [Testing](#testing)
* [API conformance](#api-conformance)
* [API conformance limitations](#api-conformance-limitations)
* [AsyncTeleBot](#asynctelebot)
* [F.A.Q.](#faq)
* [How can I distinguish a User and a GroupChat in message.chat?](#how-can-i-distinguish-a-user-and-a-groupchat-in-messagechat)
@ -69,7 +69,7 @@
## Getting started
This API is tested with Python 3.6-3.10 and Pypy 3.
This API is tested with Python 3.7-3.11 and Pypy 3.
There are two ways to install the library:
* Installation using pip (a Python package manager):
@ -165,7 +165,7 @@ To start the bot, simply open up a terminal and enter `python echo_bot.py` to ru
All types are defined in types.py. They are all completely in line with the [Telegram API's definition of the types](https://core.telegram.org/bots/api#available-types), except for the Message's `from` field, which is renamed to `from_user` (because `from` is a Python reserved token). Thus, attributes such as `message_id` can be accessed directly with `message.message_id`. Note that `message.chat` can be either an instance of `User` or `GroupChat` (see [How can I distinguish a User and a GroupChat in message.chat?](#how-can-i-distinguish-a-user-and-a-groupchat-in-messagechat)).
The Message object also has a `content_type`attribute, which defines the type of the Message. `content_type` can be one of the following strings:
`text`, `audio`, `document`, `photo`, `sticker`, `video`, `video_note`, `voice`, `location`, `contact`, `new_chat_members`, `left_chat_member`, `new_chat_title`, `new_chat_photo`, `delete_chat_photo`, `group_chat_created`, `supergroup_chat_created`, `channel_chat_created`, `migrate_to_chat_id`, `migrate_from_chat_id`, `pinned_message`.
`text`, `audio`, `document`, `photo`, `sticker`, `video`, `video_note`, `voice`, `location`, `contact`, `new_chat_members`, `left_chat_member`, `new_chat_title`, `new_chat_photo`, `delete_chat_photo`, `group_chat_created`, `supergroup_chat_created`, `channel_chat_created`, `migrate_to_chat_id`, `migrate_from_chat_id`, `pinned_message`, `web_app_data`.
You can use some types in one function. Example:
@ -265,7 +265,7 @@ def test_callback(call): # <- passes a CallbackQuery type object to your functio
#### Shipping Query Handler
Handle shipping queries
`@bot.shipping_query_handeler() # <- passes a ShippingQuery type object to your function`
`@bot.shipping_query_handler() # <- passes a ShippingQuery type object to your function`
#### Pre Checkout Query Handler
Handle pre checkoupt queries
@ -398,7 +398,7 @@ Here is example of creating filter-class:
```python
class IsAdmin(telebot.custom_filters.SimpleCustomFilter):
# Class will check whether the user is admin or creator in group or not
key='is_admin'
key='is_chat_admin'
@staticmethod
def check(message: telebot.types.Message):
return bot.get_chat_member(message.chat.id,message.from_user.id).status in ['administrator','creator']
@ -407,7 +407,7 @@ class IsAdmin(telebot.custom_filters.SimpleCustomFilter):
bot.add_custom_filter(IsAdmin())
# Now, you can use it in handler.
@bot.message_handler(is_admin=True)
@bot.message_handler(is_chat_admin=True)
def admin_of_group(message):
bot.send_message(message.chat.id, 'You are admin of this group!')
@ -726,27 +726,10 @@ Result will be:
## API conformance
* ✔ [Bot API 6.1](https://core.telegram.org/bots/api#june-20-2022)
* ✔ [Bot API 6.0](https://core.telegram.org/bots/api#april-16-2022)
* ✔ [Bot API 5.7](https://core.telegram.org/bots/api#january-31-2022)
* ✔ [Bot API 5.6](https://core.telegram.org/bots/api#december-30-2021)
* ✔ [Bot API 5.5](https://core.telegram.org/bots/api#december-7-2021)
* ✔ [Bot API 5.4](https://core.telegram.org/bots/api#november-5-2021)
* [Bot API 5.3](https://core.telegram.org/bots/api#june-25-2021) - ChatMember* classes are full copies of ChatMember
* ✔ [Bot API 5.2](https://core.telegram.org/bots/api#april-26-2021)
* ✔ [Bot API 5.1](https://core.telegram.org/bots/api#march-9-2021)
* ✔ [Bot API 5.0](https://core.telegram.org/bots/api-changelog#november-4-2020)
* ✔ [Bot API 4.9](https://core.telegram.org/bots/api-changelog#june-4-2020)
* ✔ [Bot API 4.8](https://core.telegram.org/bots/api-changelog#april-24-2020)
* ✔ [Bot API 4.7](https://core.telegram.org/bots/api-changelog#march-30-2020)
* ✔ [Bot API 4.6](https://core.telegram.org/bots/api-changelog#january-23-2020)
## API conformance limitations
* [Bot API 4.5](https://core.telegram.org/bots/api-changelog#december-31-2019) - No nested MessageEntities and Markdown2 support
* ✔ [Bot API 4.4](https://core.telegram.org/bots/api-changelog#july-29-2019)
* ✔ [Bot API 4.3](https://core.telegram.org/bots/api-changelog#may-31-2019)
* ✔ [Bot API 4.2](https://core.telegram.org/bots/api-changelog#april-14-2019)
* [Bot API 4.1](https://core.telegram.org/bots/api-changelog#august-27-2018) - No Passport support
* [Bot API 4.0](https://core.telegram.org/bots/api-changelog#july-26-2018) - No Passport support
* [Bot API 4.1](https://core.telegram.org/bots/api-changelog#august-27-2018) - No Passport support
* [Bot API 4.0](https://core.telegram.org/bots/api-changelog#july-26-2018) - No Passport support
## AsyncTeleBot
@ -894,10 +877,20 @@ Here are some examples of template:
* [GrandQuiz Bot](https://github.com/Carlosma7/TFM-GrandQuiz) by [Carlosma7](https://github.com/Carlosma7). This bot is a trivia game that allows you to play with people from different ages. This project addresses the use of a system through chatbots to carry out a social and intergenerational game as an alternative to traditional game development.
* [Diccionario de la RAE](https://t.me/dleraebot) ([source](https://github.com/studentenherz/dleraebot)) This bot lets you find difinitions of words in Spanish using [RAE's dictionary](https://dle.rae.es/). It features direct message and inline search.
* [remoteTelegramShell](https://github.com/EnriqueMoran/remoteTelegramShell) by [EnriqueMoran](https://github.com/EnriqueMoran). Control your LinuxOS computer through Telegram.
* [Commerce Telegram Bot](https://github.com/ayitinya/commerce-telegram-bot/). Make purchases of items in a store with an Admin panel for data control and notifications.
* [Pyfram-telegram-bot](https://github.com/skelly37/pyfram-telegram-bot) Query wolframalpha.com and make use of its API through Telegram.
* [TranslateThisVideoBot](https://gitlab.com/WuerfelDev/translatethisvideo) This Bot can understand spoken text in videos and translate it to English
* [Zyprexa](https://t.me/mathemathicsBot) ([source](https://github.com/atif5/zyprexa)) Zyprexa can solve, help you solve any mathematical problem you encounter and convert your regular mathematical expressions into beautiful imagery using LaTeX.
* [Bincode-telegram-bot](https://github.com/tusharhero/bincode-telegram-bot) by [tusharhero](https://github.com/tusharhero) - Makes [bincodes](https://github.com/tusharhero/bincode) from text provides and also converts them back to text.
* [hydrolib_bot](https://github.com/Mayson90/hydrolib_bot) Toolset for Hydrophilia tabletop game (game cards, rules, structure...).
* [Gugumoe-bot](http://t.me/gugumoe_bot) ([source](https://github.com/GooGuJiang/Gugumoe-bot)) by [咕谷酱](https://gmoe.cc) GuXiaoJiang is a multi-functional robot, such as OSU game information query, IP test, animation screenshot search and other functions.
* [Feedback-bot](https://github.com/coder2020official/feedbackbot) A feedback bot for user-admin communication. Made on AsyncTeleBot, using [template](https://github.com/coder2020official/asynctelebot_template).
* [TeleServ](https://github.com/ablakely/TeleServ) by [ablakely](https://github.com/ablakely) This is a Telegram to IRC bridge which links as an IRC server and makes Telegram users appear as native IRC users.
* [Simple Store Bot](https://github.com/AntonGlyzin/myshopbot) by [Anton Glyzin](https://github.com/AntonGlyzin) This is a simple telegram-store with an admin panel. Designed according to a template.
* [Media Rating Bot](https://t.me/mediaratingbot) ([source](https://github.com/CommanderCRM/MediaRatingBot))by [CommanderCRM](https://github.com/CommanderCRM). This bot aggregates media (movies, TV series, etc.) ratings from IMDb, Rotten Tomatoes, Metacritic, TheMovieDB, FilmAffinity and also provides number of votes of said media on IMDb.
* [Spot Seek Bot](https://t.me/SpotSeekBot) ([source](https://github.com/arashnm80/spot-seek-bot)) by [Arashnm80](https://github.com/arashnm80). This is a free & open source telegram bot for downloading tracks, albums or playlists from spotify.
* [CalendarIT Bot](https://t.me/calendarit_bot) ([source](https://github.com/codebyzen/CalendarIT_Telegram_Bot))by [CodeByZen](https://github.com/codebyzen). A simple, but extensible Python Telegram bot, can post acquainted with what is happening today, tomorrow or what happened 20 years ago to channel.
* [DownloadMusicBOT](https://github.com/fcoagz/DownloadMusicBOT) by *Francisco Griman* - It is a simple bot that downloads audio from YouTube videos on Telegram.
* [AwesomeChatGPTBot](https://github.com/Kourva/AwesomeChatGPTBot) - Simple ChatGTP-3.5 bot. It is FREE and can remember chat history for a while With pre-defined roles!
**Want to have your bot listed here? Just make a pull request. Only bots with public source code are accepted.**

View File

@ -26,15 +26,6 @@ Asyncio filters
:undoc-members:
:show-inheritance:
Asynchronous storage for states
-------------------------------
.. automodule:: telebot.asyncio_storage
:members:
:undoc-members:
:show-inheritance:
Asyncio handler backends
------------------------
@ -46,4 +37,12 @@ Asyncio handler backends
:show-inheritance:
Extensions
------------------------
.. automodule:: telebot.ext.aio.webhooks
:members:
:undoc-members:
:show-inheritance:

View File

@ -18,11 +18,11 @@
# -- Project information -----------------------------------------------------
project = 'pyTelegramBotAPI Documentation'
copyright = '2022, coder2020official'
copyright = '2022-2023, coder2020official'
author = 'coder2020official'
# The full version, including alpha/beta/rc tags
release = '4.6.0'
release = '4.12.0'
# -- General configuration ---------------------------------------------------
@ -68,3 +68,5 @@ html_theme_options = {
"light_logo": "logo.png",
"dark_logo": "logo2.png",
}
locale_dirs = ["locales/"]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,127 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) 2022, coder2020official
# This file is distributed under the same license as the pyTelegramBotAPI
# Documentation package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: pyTelegramBotAPI Documentation \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-11-29 14:44+0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
#: ../../calldata.rst:4
msgid "Callback data factory"
msgstr ""
#: ../../calldata.rst:6
msgid "Callback data factory in pyTelegramBotAPI"
msgstr ""
#: ../../calldata.rst:6
msgid ""
"ptba, pytba, pyTelegramBotAPI, callbackdatafactory, guide, callbackdata, "
"factory"
msgstr ""
#: ../../calldata.rst:12
msgid "callback\\_data file"
msgstr ""
#: of telebot.callback_data:1
msgid "Callback data factory's file."
msgstr ""
#: of telebot.callback_data.CallbackData:1
#: telebot.callback_data.CallbackDataFilter:1
msgid "Bases: :py:class:`object`"
msgstr ""
#: of telebot.callback_data.CallbackData:1
msgid "Callback data factory This class will help you to work with CallbackQuery"
msgstr ""
#: of telebot.callback_data.CallbackData.filter:1
msgid "Generate filter"
msgstr ""
#: of telebot.callback_data.CallbackData.filter
#: telebot.callback_data.CallbackData.new
#: telebot.callback_data.CallbackData.parse
#: telebot.callback_data.CallbackDataFilter.check
msgid "Parameters"
msgstr ""
#: of telebot.callback_data.CallbackData.filter:3
msgid "specified named parameters will be checked with CallbackQuery.data"
msgstr ""
#: of telebot.callback_data.CallbackData.filter
#: telebot.callback_data.CallbackData.new
#: telebot.callback_data.CallbackData.parse
#: telebot.callback_data.CallbackDataFilter.check
msgid "Returns"
msgstr ""
#: of telebot.callback_data.CallbackData.filter:4
msgid "CallbackDataFilter class"
msgstr ""
#: of telebot.callback_data.CallbackData.new:1
msgid "Generate callback data"
msgstr ""
#: of telebot.callback_data.CallbackData.new:3
msgid "positional parameters of CallbackData instance parts"
msgstr ""
#: of telebot.callback_data.CallbackData.new:4
msgid "named parameters"
msgstr ""
#: of telebot.callback_data.CallbackData.new:5
msgid "str"
msgstr ""
#: of telebot.callback_data.CallbackData.parse:1
msgid "Parse data from the callback data"
msgstr ""
#: of telebot.callback_data.CallbackData.parse:3
msgid ""
"string, use to telebot.types.CallbackQuery to parse it from string to a "
"dict"
msgstr ""
#: of telebot.callback_data.CallbackData.parse:4
msgid "dict parsed from callback data"
msgstr ""
#: of telebot.callback_data.CallbackDataFilter:1
msgid "Filter for CallbackData."
msgstr ""
#: of telebot.callback_data.CallbackDataFilter.check:1
msgid "Checks if query.data appropriates to specified config"
msgstr ""
#: of telebot.callback_data.CallbackDataFilter.check:3
msgid "telebot.types.CallbackQuery"
msgstr ""
#: of telebot.callback_data.CallbackDataFilter.check:6
msgid "True if query.data appropriates to specified config"
msgstr ""
#: of telebot.callback_data.CallbackDataFilter.check
msgid "Return type"
msgstr ""

View File

@ -0,0 +1,251 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) 2022, coder2020official
# This file is distributed under the same license as the pyTelegramBotAPI
# Documentation package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: pyTelegramBotAPI Documentation \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-11-29 14:44+0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
#: ../../formatting.rst:3
msgid "Formatting options"
msgstr ""
#: ../../formatting.rst:5
msgid "Formatting options in pyTelegramBotAPI"
msgstr ""
#: ../../formatting.rst:5
msgid "html, markdown, parse_mode, formatting, ptba, pytba, pyTelegramBotAPI"
msgstr ""
#: of telebot.formatting:1
msgid "Markdown & HTML formatting functions."
msgstr ""
#: of telebot.formatting.escape_html:1
msgid "Escapes HTML characters in a string of HTML."
msgstr ""
#: of telebot.formatting.escape_html telebot.formatting.escape_markdown
#: telebot.formatting.format_text telebot.formatting.hbold
#: telebot.formatting.hcode telebot.formatting.hide_link
#: telebot.formatting.hitalic telebot.formatting.hlink telebot.formatting.hpre
#: telebot.formatting.hspoiler telebot.formatting.hstrikethrough
#: telebot.formatting.hunderline telebot.formatting.mbold
#: telebot.formatting.mcode telebot.formatting.mitalic telebot.formatting.mlink
#: telebot.formatting.mspoiler telebot.formatting.mstrikethrough
#: telebot.formatting.munderline
msgid "Parameters"
msgstr ""
#: of telebot.formatting.escape_html:3
msgid "The string of HTML to escape."
msgstr ""
#: of telebot.formatting.escape_html telebot.formatting.escape_markdown
#: telebot.formatting.format_text telebot.formatting.hbold
#: telebot.formatting.hcode telebot.formatting.hide_link
#: telebot.formatting.hitalic telebot.formatting.hlink telebot.formatting.hpre
#: telebot.formatting.hspoiler telebot.formatting.hstrikethrough
#: telebot.formatting.hunderline telebot.formatting.mbold
#: telebot.formatting.mcode telebot.formatting.mitalic telebot.formatting.mlink
#: telebot.formatting.mspoiler telebot.formatting.mstrikethrough
#: telebot.formatting.munderline
msgid "Returns"
msgstr ""
#: of telebot.formatting.escape_html:6 telebot.formatting.escape_markdown:8
msgid "The escaped string."
msgstr ""
#: of telebot.formatting.escape_html telebot.formatting.escape_markdown
#: telebot.formatting.format_text telebot.formatting.hbold
#: telebot.formatting.hcode telebot.formatting.hide_link
#: telebot.formatting.hitalic telebot.formatting.hlink telebot.formatting.hpre
#: telebot.formatting.hspoiler telebot.formatting.hstrikethrough
#: telebot.formatting.hunderline telebot.formatting.mbold
#: telebot.formatting.mcode telebot.formatting.mitalic telebot.formatting.mlink
#: telebot.formatting.mspoiler telebot.formatting.mstrikethrough
#: telebot.formatting.munderline
msgid "Return type"
msgstr ""
#: of telebot.formatting.escape_html:7 telebot.formatting.escape_markdown:9
#: telebot.formatting.format_text:17 telebot.formatting.hbold:10
#: telebot.formatting.hcode:10 telebot.formatting.hide_link:7
#: telebot.formatting.hitalic:10 telebot.formatting.hlink:13
#: telebot.formatting.hpre:10 telebot.formatting.hspoiler:10
#: telebot.formatting.hstrikethrough:10 telebot.formatting.hunderline:10
#: telebot.formatting.mbold:10 telebot.formatting.mcode:10
#: telebot.formatting.mitalic:10 telebot.formatting.mlink:13
#: telebot.formatting.mspoiler:10 telebot.formatting.mstrikethrough:10
#: telebot.formatting.munderline:10
msgid ":obj:`str`"
msgstr ""
#: of telebot.formatting.escape_markdown:1
msgid "Escapes Markdown characters in a string of Markdown."
msgstr ""
#: of telebot.formatting.escape_markdown:3
msgid "Credits to: simonsmh"
msgstr ""
#: of telebot.formatting.escape_markdown:5
msgid "The string of Markdown to escape."
msgstr ""
#: of telebot.formatting.format_text:1
msgid "Formats a list of strings into a single string."
msgstr ""
#: of telebot.formatting.format_text:10
msgid "Strings to format."
msgstr ""
#: of telebot.formatting.format_text:13
msgid "The separator to use between each string."
msgstr ""
#: of telebot.formatting.format_text:16 telebot.formatting.hbold:9
#: telebot.formatting.hcode:9 telebot.formatting.hitalic:9
#: telebot.formatting.hlink:12 telebot.formatting.hpre:9
#: telebot.formatting.hspoiler:9 telebot.formatting.hstrikethrough:9
#: telebot.formatting.hunderline:9 telebot.formatting.mbold:9
#: telebot.formatting.mcode:9 telebot.formatting.mitalic:9
#: telebot.formatting.mlink:12 telebot.formatting.mspoiler:9
#: telebot.formatting.mstrikethrough:9 telebot.formatting.munderline:9
msgid "The formatted string."
msgstr ""
#: of telebot.formatting.hbold:1
msgid "Returns an HTML-formatted bold string."
msgstr ""
#: of telebot.formatting.hbold:3 telebot.formatting.mbold:3
msgid "The string to bold."
msgstr ""
#: of telebot.formatting.hbold:6 telebot.formatting.hcode:6
#: telebot.formatting.hitalic:6 telebot.formatting.hlink:9
#: telebot.formatting.hpre:6 telebot.formatting.hspoiler:6
#: telebot.formatting.hstrikethrough:6 telebot.formatting.hunderline:6
#: telebot.formatting.mbold:6 telebot.formatting.mcode:6
#: telebot.formatting.mitalic:6 telebot.formatting.mlink:9
#: telebot.formatting.mspoiler:6 telebot.formatting.mstrikethrough:6
#: telebot.formatting.munderline:6
msgid "True if you need to escape special characters. Defaults to True."
msgstr ""
#: of telebot.formatting.hcode:1
msgid "Returns an HTML-formatted code string."
msgstr ""
#: of telebot.formatting.hcode:3 telebot.formatting.mcode:3
msgid "The string to code."
msgstr ""
#: of telebot.formatting.hide_link:1
msgid "Hide url of an image."
msgstr ""
#: of telebot.formatting.hide_link:3
msgid "The url of the image."
msgstr ""
#: of telebot.formatting.hide_link:6
msgid "The hidden url."
msgstr ""
#: of telebot.formatting.hitalic:1
msgid "Returns an HTML-formatted italic string."
msgstr ""
#: of telebot.formatting.hitalic:3 telebot.formatting.mitalic:3
msgid "The string to italicize."
msgstr ""
#: of telebot.formatting.hlink:1
msgid "Returns an HTML-formatted link string."
msgstr ""
#: of telebot.formatting.hlink:3 telebot.formatting.mlink:3
msgid "The string to link."
msgstr ""
#: of telebot.formatting.hlink:6 telebot.formatting.mlink:6
msgid "The URL to link to."
msgstr ""
#: of telebot.formatting.hpre:1
msgid "Returns an HTML-formatted preformatted string."
msgstr ""
#: of telebot.formatting.hpre:3
msgid "The string to preformatted."
msgstr ""
#: of telebot.formatting.hspoiler:1
msgid "Returns an HTML-formatted spoiler string."
msgstr ""
#: of telebot.formatting.hspoiler:3 telebot.formatting.mspoiler:3
msgid "The string to spoiler."
msgstr ""
#: of telebot.formatting.hstrikethrough:1
msgid "Returns an HTML-formatted strikethrough string."
msgstr ""
#: of telebot.formatting.hstrikethrough:3 telebot.formatting.mstrikethrough:3
msgid "The string to strikethrough."
msgstr ""
#: of telebot.formatting.hunderline:1
msgid "Returns an HTML-formatted underline string."
msgstr ""
#: of telebot.formatting.hunderline:3 telebot.formatting.munderline:3
msgid "The string to underline."
msgstr ""
#: of telebot.formatting.mbold:1
msgid "Returns a Markdown-formatted bold string."
msgstr ""
#: of telebot.formatting.mcode:1
msgid "Returns a Markdown-formatted code string."
msgstr ""
#: of telebot.formatting.mitalic:1
msgid "Returns a Markdown-formatted italic string."
msgstr ""
#: of telebot.formatting.mlink:1
msgid "Returns a Markdown-formatted link string."
msgstr ""
#: of telebot.formatting.mspoiler:1
msgid "Returns a Markdown-formatted spoiler string."
msgstr ""
#: of telebot.formatting.mstrikethrough:1
msgid "Returns a Markdown-formatted strikethrough string."
msgstr ""
#: of telebot.formatting.munderline:1
msgid "Returns a Markdown-formatted underline string."
msgstr ""

View File

@ -0,0 +1,120 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) 2022, coder2020official
# This file is distributed under the same license as the pyTelegramBotAPI
# Documentation package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: pyTelegramBotAPI Documentation \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-11-29 14:44+0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
#: ../../index.rst:8
msgid "Welcome to pyTelegramBotAPI's documentation!"
msgstr ""
#: ../../index.rst:10
msgid "Official documentation of pyTelegramBotAPI"
msgstr ""
#: ../../index.rst:10
msgid "ptba, pytba, pyTelegramBotAPI, documentation, guide"
msgstr ""
#: ../../index.rst:17
msgid "TeleBot"
msgstr ""
#: ../../index.rst:18
msgid ""
"TeleBot is synchronous and asynchronous implementation of `Telegram Bot "
"API <https://core.telegram.org/bots/api>`_."
msgstr ""
#: ../../index.rst:21
msgid "Chats"
msgstr ""
#: ../../index.rst:22
msgid ""
"English chat: `Private chat "
"<https://telegram.me/joinchat/Bn4ixj84FIZVkwhk2jag6A>`__"
msgstr ""
#: ../../index.rst:24
msgid ""
"Russian chat: `@pytelegrambotapi_talks_ru "
"<https://t.me/pytelegrambotapi_talks_ru>`__"
msgstr ""
#: ../../index.rst:26
msgid "News: `@pyTelegramBotAPI <https://t.me/pytelegrambotapi>`__"
msgstr ""
#: ../../index.rst:28
msgid "Pypi: `Pypi <https://pypi.org/project/pyTelegramBotAPI/>`__"
msgstr ""
#: ../../index.rst:30
msgid ""
"Source: `Github repository "
"<https://github.com/eternnoir/pyTelegramBotAPI>`__"
msgstr ""
#: ../../index.rst:33
msgid "Some features:"
msgstr ""
#: ../../index.rst:34
msgid "Easy to learn and use."
msgstr ""
#: ../../index.rst:36
msgid "Easy to understand."
msgstr ""
#: ../../index.rst:38
msgid "Both sync and async."
msgstr ""
#: ../../index.rst:40
msgid "Examples on features."
msgstr ""
#: ../../index.rst:42
msgid "States"
msgstr ""
#: ../../index.rst:44
msgid "And more..."
msgstr ""
#: ../../index.rst:47
msgid "Content"
msgstr ""
#: ../../index.rst:63
msgid "Indices and tables"
msgstr ""
#: ../../index.rst:65
msgid ":ref:`genindex`"
msgstr ""
#: ../../index.rst:66
msgid ":ref:`modindex`"
msgstr ""
#: ../../index.rst:67
msgid ":ref:`search`"
msgstr ""

View File

@ -0,0 +1,58 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) 2022, coder2020official
# This file is distributed under the same license as the pyTelegramBotAPI
# Documentation package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: pyTelegramBotAPI Documentation \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-11-29 14:44+0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
#: ../../install.rst:3
msgid "Installation Guide"
msgstr ""
#: ../../install.rst:5
msgid "Installation of pyTelegramBotAPI"
msgstr ""
#: ../../install.rst:5
msgid "ptba, pytba, pyTelegramBotAPI, installation, guide"
msgstr ""
#: ../../install.rst:11
msgid "Using PIP"
msgstr ""
#: ../../install.rst:17
msgid "Using pipenv"
msgstr ""
#: ../../install.rst:23
msgid "By cloning repository"
msgstr ""
#: ../../install.rst:31
msgid "Directly using pip"
msgstr ""
#: ../../install.rst:37
msgid "It is generally recommended to use the first option."
msgstr ""
#: ../../install.rst:39
msgid ""
"While the API is production-ready, it is still under development and it "
"has regular updates, do not forget to update it regularly by calling:"
msgstr ""

View File

@ -0,0 +1,40 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) 2022, coder2020official
# This file is distributed under the same license as the pyTelegramBotAPI
# Documentation package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: pyTelegramBotAPI Documentation \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-11-29 14:44+0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
#: ../../quick_start.rst:4
msgid "Quick start"
msgstr ""
#: ../../quick_start.rst:6
msgid "Quickstart guide"
msgstr ""
#: ../../quick_start.rst:6
msgid "ptba, pytba, pyTelegramBotAPI, quickstart, guide"
msgstr ""
#: ../../quick_start.rst:11
msgid "Synchronous TeleBot"
msgstr ""
#: ../../quick_start.rst:16
msgid "Asynchronous TeleBot"
msgstr ""

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,355 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) 2022, coder2020official
# This file is distributed under the same license as the pyTelegramBotAPI
# Documentation package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: pyTelegramBotAPI Documentation \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-07-08 23:07+0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
#: ../../source/util.rst:3
msgid "Utils"
msgstr ""
#: ../../source/util.rst:5
msgid "Utils in pyTelegramBotAPI"
msgstr ""
#: ../../source/util.rst:5
msgid "ptba, pytba, pyTelegramBotAPI, utils, guide"
msgstr ""
#: ../../source/util.rst:11
msgid "util file"
msgstr ""
#: of telebot.util.antiflood:1
msgid ""
"Use this function inside loops in order to avoid getting TooManyRequests "
"error. Example:"
msgstr ""
#: of telebot.service_utils.is_bytes telebot.service_utils.is_dict
#: telebot.service_utils.is_pil_image telebot.util.antiflood
#: telebot.util.escape telebot.util.extract_arguments
#: telebot.util.extract_command telebot.util.is_command
#: telebot.util.parse_web_app_data telebot.util.quick_markup
#: telebot.util.smart_split telebot.util.split_string telebot.util.user_link
#: telebot.util.validate_web_app_data telebot.util.webhook_google_functions
msgid "Parameters"
msgstr ""
#: of telebot.util.antiflood:10
msgid "The function to call"
msgstr ""
#: of telebot.util.antiflood:13
msgid "Number of retries to send"
msgstr ""
#: of telebot.util.antiflood:16
msgid "The arguments to pass to the function"
msgstr ""
#: of telebot.util.antiflood:19
msgid "The keyword arguments to pass to the function"
msgstr ""
#: of telebot.service_utils.generate_random_token
#: telebot.service_utils.is_bytes telebot.service_utils.is_dict
#: telebot.service_utils.is_pil_image telebot.util.antiflood
#: telebot.util.escape telebot.util.extract_arguments
#: telebot.util.extract_command telebot.util.is_command
#: telebot.util.parse_web_app_data telebot.util.quick_markup
#: telebot.util.smart_split telebot.util.split_string telebot.util.user_link
#: telebot.util.validate_web_app_data telebot.util.webhook_google_functions
msgid "Returns"
msgstr ""
#: of telebot.util.antiflood:22
msgid "None"
msgstr ""
#: of telebot.service_utils.chunks:1
msgid "Yield successive n-sized chunks from lst."
msgstr ""
#: ../../docstring of telebot.util.content_type_media:1
msgid "Contains all media content types."
msgstr ""
#: ../../docstring of telebot.util.content_type_service:1
msgid "Contains all service content types such as `User joined the group`."
msgstr ""
#: of telebot.util.escape:1
msgid ""
"Replaces the following chars in `text` ('&' with '&amp;', '<' with '&lt;'"
" and '>' with '&gt;')."
msgstr ""
#: of telebot.util.escape:3
msgid "the text to escape"
msgstr ""
#: of telebot.util.escape:4
msgid "the escaped text"
msgstr ""
#: of telebot.util.extract_arguments:1
msgid "Returns the argument after the command."
msgstr ""
#: of telebot.util.extract_arguments:3 telebot.util.extract_command:4
msgid "Examples:"
msgstr ""
#: of telebot.util.extract_arguments:10
msgid "String to extract the arguments from a command"
msgstr ""
#: of telebot.util.extract_arguments:13
msgid "the arguments if `text` is a command (according to is_command), else None."
msgstr ""
#: of telebot.service_utils.generate_random_token
#: telebot.service_utils.is_bytes telebot.service_utils.is_dict
#: telebot.service_utils.is_pil_image telebot.util.extract_arguments
#: telebot.util.extract_command telebot.util.is_command
#: telebot.util.quick_markup telebot.util.smart_split telebot.util.split_string
#: telebot.util.user_link
msgid "Return type"
msgstr ""
#: of telebot.util.extract_arguments:14 telebot.util.extract_command:16
msgid ":obj:`str` or :obj:`None`"
msgstr ""
#: of telebot.util.extract_command:1
msgid ""
"Extracts the command from `text` (minus the '/') if `text` is a command "
"(see is_command). If `text` is not a command, this function returns None."
msgstr ""
#: of telebot.util.extract_command:12
msgid "String to extract the command from"
msgstr ""
#: of telebot.util.extract_command:15
msgid "the command if `text` is a command (according to is_command), else None."
msgstr ""
#: of telebot.service_utils.generate_random_token:1
msgid ""
"Generates a random token consisting of letters and digits, 16 characters "
"long."
msgstr ""
#: of telebot.service_utils.generate_random_token:3
msgid "a random token"
msgstr ""
#: of telebot.service_utils.generate_random_token:4 telebot.util.user_link:22
msgid ":obj:`str`"
msgstr ""
#: of telebot.service_utils.is_bytes:1
msgid "Returns True if the given object is a bytes object."
msgstr ""
#: of telebot.service_utils.is_bytes:3 telebot.service_utils.is_dict:3
#: telebot.service_utils.is_pil_image:3
msgid "object to be checked"
msgstr ""
#: of telebot.service_utils.is_bytes:6
msgid "True if the given object is a bytes object."
msgstr ""
#: of telebot.service_utils.is_bytes:7 telebot.service_utils.is_dict:7
#: telebot.service_utils.is_pil_image:7 telebot.util.is_command:7
msgid ":obj:`bool`"
msgstr ""
#: of telebot.util.is_command:1
msgid ""
"Checks if `text` is a command. Telegram chat commands start with the '/' "
"character."
msgstr ""
#: of telebot.util.is_command:3
msgid "Text to check."
msgstr ""
#: of telebot.util.is_command:6
msgid "True if `text` is a command, else False."
msgstr ""
#: of telebot.service_utils.is_dict:1
msgid "Returns True if the given object is a dictionary."
msgstr ""
#: of telebot.service_utils.is_dict:6
msgid "True if the given object is a dictionary."
msgstr ""
#: of telebot.service_utils.is_pil_image:1
msgid "Returns True if the given object is a PIL.Image.Image object."
msgstr ""
#: of telebot.service_utils.is_pil_image:6
msgid "True if the given object is a PIL.Image.Image object."
msgstr ""
#: of telebot.service_utils.is_string:1
msgid "Returns True if the given object is a string."
msgstr ""
#: of telebot.util.parse_web_app_data:1
msgid "Parses web app data."
msgstr ""
#: of telebot.util.parse_web_app_data:3 telebot.util.validate_web_app_data:3
msgid "The bot token"
msgstr ""
#: of telebot.util.parse_web_app_data:6 telebot.util.validate_web_app_data:6
msgid "The raw init data"
msgstr ""
#: of telebot.util.parse_web_app_data:9 telebot.util.validate_web_app_data:9
msgid "The parsed init data"
msgstr ""
#: of telebot.util.quick_markup:1
msgid ""
"Returns a reply markup from a dict in this format: {'text': kwargs} This "
"is useful to avoid always typing 'btn1 = InlineKeyboardButton(...)' 'btn2"
" = InlineKeyboardButton(...)'"
msgstr ""
#: of telebot.util.quick_markup:4 telebot.util.user_link:5
msgid "Example:"
msgstr ""
#: of telebot.util.quick_markup:6
msgid "Using quick_markup:"
msgstr ""
#: of telebot.util.quick_markup:31
msgid ""
"a dict containing all buttons to create in this format: {text: kwargs} "
"{str:}"
msgstr ""
#: of telebot.util.quick_markup:34
msgid "number of :class:`telebot.types.InlineKeyboardButton` objects on each row"
msgstr ""
#: of telebot.util.quick_markup:37
msgid "InlineKeyboardMarkup"
msgstr ""
#: of telebot.util.quick_markup:38
msgid ":obj:`types.InlineKeyboardMarkup`"
msgstr ""
#: of telebot.util.smart_split:1
msgid ""
"Splits one string into multiple strings, with a maximum amount of "
"`chars_per_string` characters per string. This is very useful for "
"splitting one giant message into multiples. If `chars_per_string` > 4096:"
" `chars_per_string` = 4096. Splits by '\\n', '. ' or ' ' in exactly this "
"priority."
msgstr ""
#: of telebot.util.smart_split:6 telebot.util.split_string:4
msgid "The text to split"
msgstr ""
#: of telebot.util.smart_split:9
msgid "The number of maximum characters per part the text is split to."
msgstr ""
#: of telebot.util.smart_split:12 telebot.util.split_string:10
msgid "The splitted text as a list of strings."
msgstr ""
#: of telebot.util.smart_split:13 telebot.util.split_string:11
msgid ":obj:`list` of :obj:`str`"
msgstr ""
#: of telebot.util.split_string:1
msgid ""
"Splits one string into multiple strings, with a maximum amount of "
"`chars_per_string` characters per string. This is very useful for "
"splitting one giant message into multiples."
msgstr ""
#: of telebot.util.split_string:7
msgid "The number of characters per line the text is split into."
msgstr ""
#: ../../docstring of telebot.util.update_types:1
msgid "All update types, should be used for allowed_updates parameter in polling."
msgstr ""
#: of telebot.util.user_link:1
msgid ""
"Returns an HTML user link. This is useful for reports. Attention: Don't "
"forget to set parse_mode to 'HTML'!"
msgstr ""
#: of telebot.util.user_link:11
msgid ""
"You can use formatting.* for all other formatting options(bold, italic, "
"links, and etc.) This method is kept for backward compatibility, and it "
"is recommended to use formatting.* for more options."
msgstr ""
#: of telebot.util.user_link:15
msgid "the user (not the user_id)"
msgstr ""
#: of telebot.util.user_link:18
msgid "include the user_id"
msgstr ""
#: of telebot.util.user_link:21
msgid "HTML user link"
msgstr ""
#: of telebot.util.validate_web_app_data:1
msgid "Validates web app data."
msgstr ""
#: of telebot.util.webhook_google_functions:1
msgid "A webhook endpoint for Google Cloud Functions FaaS."
msgstr ""
#: of telebot.util.webhook_google_functions:3
msgid "The bot instance"
msgstr ""
#: of telebot.util.webhook_google_functions:6
msgid "The request object"
msgstr ""
#: of telebot.util.webhook_google_functions:9
msgid "The response object"
msgstr ""
#~ msgid "int row width"
#~ msgstr ""

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,130 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) 2022, coder2020official
# This file is distributed under the same license as the pyTelegramBotAPI
# Documentation package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: pyTelegramBotAPI Documentation \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-11-29 14:44+0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
#: ../../calldata.rst:4
msgid "Callback data factory"
msgstr "Фабрика callback data"
#: ../../calldata.rst:6
msgid "Callback data factory in pyTelegramBotAPI"
msgstr "Фабрика callback data в pyTelegramBotAPI"
#: ../../calldata.rst:6
msgid ""
"ptba, pytba, pyTelegramBotAPI, callbackdatafactory, guide, callbackdata, "
"factory"
msgstr ""
"ptba, pytba, pyTelegramBotAPI, callbackdatafactory, гайд, callbackdata, "
"фабрика"
#: ../../calldata.rst:12
msgid "callback\\_data file"
msgstr "Файл callback\\_data"
#: of telebot.callback_data:1
msgid "Callback data factory's file."
msgstr "Файл фабрики callback data."
#: of telebot.callback_data.CallbackData:1
#: telebot.callback_data.CallbackDataFilter:1
msgid "Bases: :py:class:`object`"
msgstr "Базовые классы: :py:class:`object`"
#: of telebot.callback_data.CallbackData:1
msgid "Callback data factory This class will help you to work with CallbackQuery"
msgstr "Фабрика Callback data. Этот класс поможет вам в работе с CallbackQuery"
#: of telebot.callback_data.CallbackData.filter:1
msgid "Generate filter"
msgstr "Сгенерировать фильтр"
#: of telebot.callback_data.CallbackData.filter
#: telebot.callback_data.CallbackData.new
#: telebot.callback_data.CallbackData.parse
#: telebot.callback_data.CallbackDataFilter.check
msgid "Parameters"
msgstr ""
#: of telebot.callback_data.CallbackData.filter:3
msgid "specified named parameters will be checked with CallbackQuery.data"
msgstr "заданные именованные параметры будут проверены в CallbackQuery.data"
#: of telebot.callback_data.CallbackData.filter
#: telebot.callback_data.CallbackData.new
#: telebot.callback_data.CallbackData.parse
#: telebot.callback_data.CallbackDataFilter.check
msgid "Returns"
msgstr ""
#: of telebot.callback_data.CallbackData.filter:4
msgid "CallbackDataFilter class"
msgstr "Класс CallbackDataFilter"
#: of telebot.callback_data.CallbackData.new:1
msgid "Generate callback data"
msgstr "Сгенерировать callback data"
#: of telebot.callback_data.CallbackData.new:3
msgid "positional parameters of CallbackData instance parts"
msgstr "позиционные параметры экземпляра CallbackData"
#: of telebot.callback_data.CallbackData.new:4
msgid "named parameters"
msgstr "именованные параметры"
#: of telebot.callback_data.CallbackData.new:5
msgid "str"
msgstr ""
#: of telebot.callback_data.CallbackData.parse:1
msgid "Parse data from the callback data"
msgstr "Получить данные из callback data"
#: of telebot.callback_data.CallbackData.parse:3
msgid ""
"string, use to telebot.types.CallbackQuery to parse it from string to a "
"dict"
msgstr ""
"string, примените к telebot.types.CallbackQuery, чтобы преобразовать "
"callback_data из строки (str) в словарь (dict)"
#: of telebot.callback_data.CallbackData.parse:4
msgid "dict parsed from callback data"
msgstr "словарь (dict), полученный из callback data"
#: of telebot.callback_data.CallbackDataFilter:1
msgid "Filter for CallbackData."
msgstr "Фильтр для CallbackData."
#: of telebot.callback_data.CallbackDataFilter.check:1
msgid "Checks if query.data appropriates to specified config"
msgstr "Проверяет, соответствует ли query.data заданной конфигурации"
#: of telebot.callback_data.CallbackDataFilter.check:3
msgid "telebot.types.CallbackQuery"
msgstr ""
#: of telebot.callback_data.CallbackDataFilter.check:6
msgid "True if query.data appropriates to specified config"
msgstr "True, если query.data соответствует заданной конфигурации"
#: of telebot.callback_data.CallbackDataFilter.check
msgid "Return type"
msgstr ""

View File

@ -0,0 +1,251 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) 2022, coder2020official
# This file is distributed under the same license as the pyTelegramBotAPI
# Documentation package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: pyTelegramBotAPI Documentation \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-11-29 14:44+0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
#: ../../formatting.rst:3
msgid "Formatting options"
msgstr "Параметры форматирования"
#: ../../formatting.rst:5
msgid "Formatting options in pyTelegramBotAPI"
msgstr "Параметры форматирования в pyTelegramBotAPI"
#: ../../formatting.rst:5
msgid "html, markdown, parse_mode, formatting, ptba, pytba, pyTelegramBotAPI"
msgstr "html, markdown, parse_mode, форматирование, ptba, pytba, pyTelegramBotAPI"
#: of telebot.formatting:1
msgid "Markdown & HTML formatting functions."
msgstr "Функции форматирования Markdown & HTML."
#: of telebot.formatting.escape_html:1
msgid "Escapes HTML characters in a string of HTML."
msgstr "Пропускает HTML символы в HTML строке."
#: of telebot.formatting.escape_html telebot.formatting.escape_markdown
#: telebot.formatting.format_text telebot.formatting.hbold
#: telebot.formatting.hcode telebot.formatting.hide_link
#: telebot.formatting.hitalic telebot.formatting.hlink telebot.formatting.hpre
#: telebot.formatting.hspoiler telebot.formatting.hstrikethrough
#: telebot.formatting.hunderline telebot.formatting.mbold
#: telebot.formatting.mcode telebot.formatting.mitalic telebot.formatting.mlink
#: telebot.formatting.mspoiler telebot.formatting.mstrikethrough
#: telebot.formatting.munderline
msgid "Parameters"
msgstr ""
#: of telebot.formatting.escape_html:3
msgid "The string of HTML to escape."
msgstr "HTML строка, которую нужно пропустить."
#: of telebot.formatting.escape_html telebot.formatting.escape_markdown
#: telebot.formatting.format_text telebot.formatting.hbold
#: telebot.formatting.hcode telebot.formatting.hide_link
#: telebot.formatting.hitalic telebot.formatting.hlink telebot.formatting.hpre
#: telebot.formatting.hspoiler telebot.formatting.hstrikethrough
#: telebot.formatting.hunderline telebot.formatting.mbold
#: telebot.formatting.mcode telebot.formatting.mitalic telebot.formatting.mlink
#: telebot.formatting.mspoiler telebot.formatting.mstrikethrough
#: telebot.formatting.munderline
msgid "Returns"
msgstr ""
#: of telebot.formatting.escape_html:6 telebot.formatting.escape_markdown:8
msgid "The escaped string."
msgstr "Пропускаемая строка."
#: of telebot.formatting.escape_html telebot.formatting.escape_markdown
#: telebot.formatting.format_text telebot.formatting.hbold
#: telebot.formatting.hcode telebot.formatting.hide_link
#: telebot.formatting.hitalic telebot.formatting.hlink telebot.formatting.hpre
#: telebot.formatting.hspoiler telebot.formatting.hstrikethrough
#: telebot.formatting.hunderline telebot.formatting.mbold
#: telebot.formatting.mcode telebot.formatting.mitalic telebot.formatting.mlink
#: telebot.formatting.mspoiler telebot.formatting.mstrikethrough
#: telebot.formatting.munderline
msgid "Return type"
msgstr ""
#: of telebot.formatting.escape_html:7 telebot.formatting.escape_markdown:9
#: telebot.formatting.format_text:17 telebot.formatting.hbold:10
#: telebot.formatting.hcode:10 telebot.formatting.hide_link:7
#: telebot.formatting.hitalic:10 telebot.formatting.hlink:13
#: telebot.formatting.hpre:10 telebot.formatting.hspoiler:10
#: telebot.formatting.hstrikethrough:10 telebot.formatting.hunderline:10
#: telebot.formatting.mbold:10 telebot.formatting.mcode:10
#: telebot.formatting.mitalic:10 telebot.formatting.mlink:13
#: telebot.formatting.mspoiler:10 telebot.formatting.mstrikethrough:10
#: telebot.formatting.munderline:10
msgid ":obj:`str`"
msgstr ""
#: of telebot.formatting.escape_markdown:1
msgid "Escapes Markdown characters in a string of Markdown."
msgstr "Пропускает Markdown символы в Markdown строке."
#: of telebot.formatting.escape_markdown:3
msgid "Credits to: simonsmh"
msgstr ""
#: of telebot.formatting.escape_markdown:5
msgid "The string of Markdown to escape."
msgstr "Markdown строка, которую нужно пропустить."
#: of telebot.formatting.format_text:1
msgid "Formats a list of strings into a single string."
msgstr "Преобразовывает набор строк в одну."
#: of telebot.formatting.format_text:10
msgid "Strings to format."
msgstr "Строки для преобразования."
#: of telebot.formatting.format_text:13
msgid "The separator to use between each string."
msgstr "Символ для разделения строк."
#: of telebot.formatting.format_text:16 telebot.formatting.hbold:9
#: telebot.formatting.hcode:9 telebot.formatting.hitalic:9
#: telebot.formatting.hlink:12 telebot.formatting.hpre:9
#: telebot.formatting.hspoiler:9 telebot.formatting.hstrikethrough:9
#: telebot.formatting.hunderline:9 telebot.formatting.mbold:9
#: telebot.formatting.mcode:9 telebot.formatting.mitalic:9
#: telebot.formatting.mlink:12 telebot.formatting.mspoiler:9
#: telebot.formatting.mstrikethrough:9 telebot.formatting.munderline:9
msgid "The formatted string."
msgstr "Преобразованная строка."
#: of telebot.formatting.hbold:1
msgid "Returns an HTML-formatted bold string."
msgstr "Возвращает выделенную жирным шрифтом HTML строку."
#: of telebot.formatting.hbold:3 telebot.formatting.mbold:3
msgid "The string to bold."
msgstr "Строка для выделения жирным шрифтом."
#: of telebot.formatting.hbold:6 telebot.formatting.hcode:6
#: telebot.formatting.hitalic:6 telebot.formatting.hlink:9
#: telebot.formatting.hpre:6 telebot.formatting.hspoiler:6
#: telebot.formatting.hstrikethrough:6 telebot.formatting.hunderline:6
#: telebot.formatting.mbold:6 telebot.formatting.mcode:6
#: telebot.formatting.mitalic:6 telebot.formatting.mlink:9
#: telebot.formatting.mspoiler:6 telebot.formatting.mstrikethrough:6
#: telebot.formatting.munderline:6
msgid "True if you need to escape special characters. Defaults to True."
msgstr "True если вам нужно пропустить спец. символы. По умолчанию True."
#: of telebot.formatting.hcode:1
msgid "Returns an HTML-formatted code string."
msgstr "Возвращает выделенную как код HTML строку."
#: of telebot.formatting.hcode:3 telebot.formatting.mcode:3
msgid "The string to code."
msgstr "Строка для выделения как код."
#: of telebot.formatting.hide_link:1
msgid "Hide url of an image."
msgstr "Делает невидимым URL изображения."
#: of telebot.formatting.hide_link:3
msgid "The url of the image."
msgstr "URL изображения."
#: of telebot.formatting.hide_link:6
msgid "The hidden url."
msgstr "Невидимый URL."
#: of telebot.formatting.hitalic:1
msgid "Returns an HTML-formatted italic string."
msgstr "Возвращает выделенную курсивом HTML строку."
#: of telebot.formatting.hitalic:3 telebot.formatting.mitalic:3
msgid "The string to italicize."
msgstr "Строка для выделения курсивом."
#: of telebot.formatting.hlink:1
msgid "Returns an HTML-formatted link string."
msgstr "Возвращает HTML строку с гиперссылкой."
#: of telebot.formatting.hlink:3 telebot.formatting.mlink:3
msgid "The string to link."
msgstr "Строка для добавления гиперссылки."
#: of telebot.formatting.hlink:6 telebot.formatting.mlink:6
msgid "The URL to link to."
msgstr "URL для создания гиперссылки."
#: of telebot.formatting.hpre:1
msgid "Returns an HTML-formatted preformatted string."
msgstr "Возвращает предварительно отформатированную HTML строку."
#: of telebot.formatting.hpre:3
msgid "The string to preformatted."
msgstr "Строка для предварительного форматирования."
#: of telebot.formatting.hspoiler:1
msgid "Returns an HTML-formatted spoiler string."
msgstr "Возвращает выделенную как спойлер HTML строку."
#: of telebot.formatting.hspoiler:3 telebot.formatting.mspoiler:3
msgid "The string to spoiler."
msgstr "Строка для выделения как спойлер."
#: of telebot.formatting.hstrikethrough:1
msgid "Returns an HTML-formatted strikethrough string."
msgstr "Возвращает зачеркнутую HTML строку."
#: of telebot.formatting.hstrikethrough:3 telebot.formatting.mstrikethrough:3
msgid "The string to strikethrough."
msgstr "Строка для зачеркивания."
#: of telebot.formatting.hunderline:1
msgid "Returns an HTML-formatted underline string."
msgstr "Возвращает подчеркнутую HTML строку."
#: of telebot.formatting.hunderline:3 telebot.formatting.munderline:3
msgid "The string to underline."
msgstr "Строка для подчёркивания."
#: of telebot.formatting.mbold:1
msgid "Returns a Markdown-formatted bold string."
msgstr "Возвращает выделенную жирным шрифтом Markdown строку."
#: of telebot.formatting.mcode:1
msgid "Returns a Markdown-formatted code string."
msgstr "Возвращает выделенную как код Markdown строку."
#: of telebot.formatting.mitalic:1
msgid "Returns a Markdown-formatted italic string."
msgstr "Возвращает выделенную курсивом Markdown строку."
#: of telebot.formatting.mlink:1
msgid "Returns a Markdown-formatted link string."
msgstr "Возвращает Markdown строку с гиперссылкой."
#: of telebot.formatting.mspoiler:1
msgid "Returns a Markdown-formatted spoiler string."
msgstr "Возвращает выделенную как спойлер Markdown строку."
#: of telebot.formatting.mstrikethrough:1
msgid "Returns a Markdown-formatted strikethrough string."
msgstr "Возвращает зачеркнутую Markdown строку."
#: of telebot.formatting.munderline:1
msgid "Returns a Markdown-formatted underline string."
msgstr "Возвращает подчеркнутую Markdown строку."

View File

@ -0,0 +1,128 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) 2022, coder2020official
# This file is distributed under the same license as the pyTelegramBotAPI
# Documentation package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: pyTelegramBotAPI Documentation \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-11-29 14:44+0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
#: ../../index.rst:8
msgid "Welcome to pyTelegramBotAPI's documentation!"
msgstr "Добро пожаловать в документацию pyTelegramBotAPI!"
#: ../../index.rst:10
msgid "Official documentation of pyTelegramBotAPI"
msgstr "Официальная документация pyTelegramBotAPI"
#: ../../index.rst:10
msgid "ptba, pytba, pyTelegramBotAPI, documentation, guide"
msgstr "ptba, pytba, pyTelegramBotAPI, документация, гайд"
#: ../../index.rst:17
msgid "TeleBot"
msgstr ""
#: ../../index.rst:18
msgid ""
"TeleBot is synchronous and asynchronous implementation of `Telegram Bot "
"API <https://core.telegram.org/bots/api>`_."
msgstr ""
"TeleBot это синхронная и асинхронная реализация `Telegram Bot "
"API <https://core.telegram.org/bots/api>`_."
#: ../../index.rst:21
msgid "Chats"
msgstr "Чаты"
#: ../../index.rst:22
msgid ""
"English chat: `Private chat "
"<https://telegram.me/joinchat/Bn4ixj84FIZVkwhk2jag6A>`__"
msgstr ""
"Англоязычный чат: `Private chat "
"<https://telegram.me/joinchat/Bn4ixj84FIZVkwhk2jag6A>`__"
#: ../../index.rst:24
msgid ""
"Russian chat: `@pytelegrambotapi_talks_ru "
"<https://t.me/pytelegrambotapi_talks_ru>`__"
msgstr ""
"Русскоязычный чат: `@pytelegrambotapi_talks_ru "
"<https://t.me/pytelegrambotapi_talks_ru>`__"
#: ../../index.rst:26
msgid "News: `@pyTelegramBotAPI <https://t.me/pytelegrambotapi>`__"
msgstr "Новости: `@pyTelegramBotAPI <https://t.me/pytelegrambotapi>`__"
#: ../../index.rst:28
msgid "Pypi: `Pypi <https://pypi.org/project/pyTelegramBotAPI/>`__"
msgstr ""
#: ../../index.rst:30
msgid ""
"Source: `Github repository "
"<https://github.com/eternnoir/pyTelegramBotAPI>`__"
msgstr ""
"Исходники: `Github repository "
"<https://github.com/eternnoir/pyTelegramBotAPI>`__"
#: ../../index.rst:33
msgid "Some features:"
msgstr "Некоторые особенности:"
#: ../../index.rst:34
msgid "Easy to learn and use."
msgstr "Простой в изучении и использовании."
#: ../../index.rst:36
msgid "Easy to understand."
msgstr "Простой в понимании."
#: ../../index.rst:38
msgid "Both sync and async."
msgstr "И синхронный, и асинхронный."
#: ../../index.rst:40
msgid "Examples on features."
msgstr "Примеры возможностей."
#: ../../index.rst:42
msgid "States"
msgstr "Состояния (стейты, FSM)"
#: ../../index.rst:44
msgid "And more..."
msgstr "И другое..."
#: ../../index.rst:47
msgid "Content"
msgstr "Содержимое"
#: ../../index.rst:63
msgid "Indices and tables"
msgstr "Ссылки"
#: ../../index.rst:65
msgid ":ref:`genindex`"
msgstr ""
#: ../../index.rst:66
msgid ":ref:`modindex`"
msgstr ""
#: ../../index.rst:67
msgid ":ref:`search`"
msgstr ""

View File

@ -0,0 +1,59 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) 2022, coder2020official
# This file is distributed under the same license as the pyTelegramBotAPI
# Documentation package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: pyTelegramBotAPI Documentation \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-11-29 14:44+0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
#: ../../install.rst:3
msgid "Installation Guide"
msgstr "Гайд по установке"
#: ../../install.rst:5
msgid "Installation of pyTelegramBotAPI"
msgstr "Установка pyTelegramBotAPI"
#: ../../install.rst:5
msgid "ptba, pytba, pyTelegramBotAPI, installation, guide"
msgstr "ptba, pytba, pyTelegramBotAPI, установка, гайд"
#: ../../install.rst:11
msgid "Using PIP"
msgstr "Используя PIP"
#: ../../install.rst:17
msgid "Using pipenv"
msgstr "Используя pipenv"
#: ../../install.rst:23
msgid "By cloning repository"
msgstr "Клонируя репозиторий"
#: ../../install.rst:31
msgid "Directly using pip"
msgstr "Напрямую используя pip"
#: ../../install.rst:37
msgid "It is generally recommended to use the first option."
msgstr "Рекомендуется использовать первый вариант."
#: ../../install.rst:39
msgid ""
"While the API is production-ready, it is still under development and it "
"has regular updates, do not forget to update it regularly by calling:"
msgstr "Новые версии библиотеки имеют больше фич, улучшений и баг фиксов. Не забывайте"
" обновляться вызывая:"

View File

@ -0,0 +1,40 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) 2022, coder2020official
# This file is distributed under the same license as the pyTelegramBotAPI
# Documentation package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: pyTelegramBotAPI Documentation \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-11-29 14:44+0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
#: ../../quick_start.rst:4
msgid "Quick start"
msgstr "Быстрый старт"
#: ../../quick_start.rst:6
msgid "Quickstart guide"
msgstr "Быстрый старт - гайд"
#: ../../quick_start.rst:6
msgid "ptba, pytba, pyTelegramBotAPI, quickstart, guide"
msgstr "ptba, pytba, pyTelegramBotAPI, быстрый старт, гайд"
#: ../../quick_start.rst:11
msgid "Synchronous TeleBot"
msgstr "Синхронный телебот"
#: ../../quick_start.rst:16
msgid "Asynchronous TeleBot"
msgstr "Асинхронный телебот"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,393 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) 2022, coder2020official
# This file is distributed under the same license as the pyTelegramBotAPI
# Documentation package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: pyTelegramBotAPI Documentation \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-07-08 23:07+0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n"
#: ../../source/util.rst:3
msgid "Utils"
msgstr "Утилиты"
#: ../../source/util.rst:5
msgid "Utils in pyTelegramBotAPI"
msgstr "Утилиты в pyTelegramBotAPI"
#: ../../source/util.rst:5
msgid "ptba, pytba, pyTelegramBotAPI, utils, guide"
msgstr "ptba, pytba, pyTelegramBotAPI, утилиты, гайд"
#: ../../source/util.rst:11
msgid "util file"
msgstr "Файл util"
#: of telebot.util.antiflood:1
msgid ""
"Use this function inside loops in order to avoid getting TooManyRequests "
"error. Example:"
msgstr ""
"Используйте эту функцию в циклах, чтобы избежать ошибки TooManyRequests. "
"Пример:"
#: of telebot.service_utils.is_bytes telebot.service_utils.is_dict
#: telebot.service_utils.is_pil_image telebot.util.antiflood
#: telebot.util.escape telebot.util.extract_arguments
#: telebot.util.extract_command telebot.util.is_command
#: telebot.util.parse_web_app_data telebot.util.quick_markup
#: telebot.util.smart_split telebot.util.split_string telebot.util.user_link
#: telebot.util.validate_web_app_data telebot.util.webhook_google_functions
msgid "Parameters"
msgstr ""
#: of telebot.util.antiflood:10
msgid "The function to call"
msgstr "Вызываемая функция"
#: of telebot.util.antiflood:13
msgid "Number of retries to send"
msgstr ""
#: of telebot.util.antiflood:16
msgid "The arguments to pass to the function"
msgstr "Аргументы, для передачи в функцию"
#: of telebot.util.antiflood:19
msgid "The keyword arguments to pass to the function"
msgstr "Именованные аргументы для передачи в функцию"
#: of telebot.service_utils.generate_random_token
#: telebot.service_utils.is_bytes telebot.service_utils.is_dict
#: telebot.service_utils.is_pil_image telebot.util.antiflood
#: telebot.util.escape telebot.util.extract_arguments
#: telebot.util.extract_command telebot.util.is_command
#: telebot.util.parse_web_app_data telebot.util.quick_markup
#: telebot.util.smart_split telebot.util.split_string telebot.util.user_link
#: telebot.util.validate_web_app_data telebot.util.webhook_google_functions
msgid "Returns"
msgstr ""
#: of telebot.util.antiflood:22
msgid "None"
msgstr ""
#: of telebot.service_utils.chunks:1
msgid "Yield successive n-sized chunks from lst."
msgstr "Генерирует последовательные части списка, состоящие из n элементов."
#: ../../docstring of telebot.util.content_type_media:1
msgid "Contains all media content types."
msgstr "Содержит все виды медиа."
#: ../../docstring of telebot.util.content_type_service:1
msgid "Contains all service content types such as `User joined the group`."
msgstr "Содержит все виды сервисных сообщений, такие как `User joined the group`."
#: of telebot.util.escape:1
msgid ""
"Replaces the following chars in `text` ('&' with '&amp;', '<' with '&lt;'"
" and '>' with '&gt;')."
msgstr ""
"Заменяет следующие символы в `text` ('&' на '&amp;', '<' на '&lt;' и '>' "
"на '&gt;')."
#: of telebot.util.escape:3
msgid "the text to escape"
msgstr "Текст для замены символов"
#: of telebot.util.escape:4
msgid "the escaped text"
msgstr "Отформатированный текст"
#: of telebot.util.extract_arguments:1
msgid "Returns the argument after the command."
msgstr "Возвращает аргументы команды."
#: of telebot.util.extract_arguments:3 telebot.util.extract_command:4
msgid "Examples:"
msgstr "Примеры:"
#: of telebot.util.extract_arguments:10
msgid "String to extract the arguments from a command"
msgstr "Строка для извлечения аргументов команды"
#: of telebot.util.extract_arguments:13
msgid "the arguments if `text` is a command (according to is_command), else None."
msgstr ""
"Аргументы, если `text` является командой (согласно is_command), в "
"остальных случаях None."
#: of telebot.service_utils.generate_random_token
#: telebot.service_utils.is_bytes telebot.service_utils.is_dict
#: telebot.service_utils.is_pil_image telebot.util.extract_arguments
#: telebot.util.extract_command telebot.util.is_command
#: telebot.util.quick_markup telebot.util.smart_split telebot.util.split_string
#: telebot.util.user_link
msgid "Return type"
msgstr ""
#: of telebot.util.extract_arguments:14 telebot.util.extract_command:16
msgid ":obj:`str` or :obj:`None`"
msgstr ":obj:`str` или :obj:`None`"
#: of telebot.util.extract_command:1
msgid ""
"Extracts the command from `text` (minus the '/') if `text` is a command "
"(see is_command). If `text` is not a command, this function returns None."
msgstr ""
"Извлекает команду из `text` (исключает '/') если `text` является командой"
" (см. is_command). Если `text` не является командой, эта функция "
"возвращает None."
#: of telebot.util.extract_command:12
msgid "String to extract the command from"
msgstr "Строка, из которой нужно извлечь команду"
#: of telebot.util.extract_command:15
msgid "the command if `text` is a command (according to is_command), else None."
msgstr ""
"Команда, если `text` является командой (согласно is_command), в остальных"
" случаях None."
#: of telebot.service_utils.generate_random_token:1
msgid ""
"Generates a random token consisting of letters and digits, 16 characters "
"long."
msgstr ""
"Генерирует рандомный токен, состоящий из латинских букв и цифр длиной 16 "
"символов."
#: of telebot.service_utils.generate_random_token:3
msgid "a random token"
msgstr "Сгенерированный токен"
#: of telebot.service_utils.generate_random_token:4 telebot.util.user_link:22
msgid ":obj:`str`"
msgstr ""
#: of telebot.service_utils.is_bytes:1
msgid "Returns True if the given object is a bytes object."
msgstr "Возвращает True если полученный объект является bytes."
#: of telebot.service_utils.is_bytes:3 telebot.service_utils.is_dict:3
#: telebot.service_utils.is_pil_image:3
msgid "object to be checked"
msgstr "Объект для проверки"
#: of telebot.service_utils.is_bytes:6
msgid "True if the given object is a bytes object."
msgstr "True, если полученный объект является bytes."
#: of telebot.service_utils.is_bytes:7 telebot.service_utils.is_dict:7
#: telebot.service_utils.is_pil_image:7 telebot.util.is_command:7
msgid ":obj:`bool`"
msgstr ""
#: of telebot.util.is_command:1
msgid ""
"Checks if `text` is a command. Telegram chat commands start with the '/' "
"character."
msgstr ""
"Проверяет, является ли `text` командой. Команды в Telegram начинаются с "
"символа '/'."
#: of telebot.util.is_command:3
msgid "Text to check."
msgstr "Текст для проверки."
#: of telebot.util.is_command:6
msgid "True if `text` is a command, else False."
msgstr "True, если `text` является командой, иначе False."
#: of telebot.service_utils.is_dict:1
msgid "Returns True if the given object is a dictionary."
msgstr "Возвращает True, если полученный объект является словарём (dict)."
#: of telebot.service_utils.is_dict:6
msgid "True if the given object is a dictionary."
msgstr "True, если полученный объект является словарём (dict)."
#: of telebot.service_utils.is_pil_image:1
msgid "Returns True if the given object is a PIL.Image.Image object."
msgstr "Возвращает True, если полученный объект является PIL.Image.Image."
#: of telebot.service_utils.is_pil_image:6
msgid "True if the given object is a PIL.Image.Image object."
msgstr "True, если полученный объект является PIL.Image.Image."
#: of telebot.service_utils.is_string:1
msgid "Returns True if the given object is a string."
msgstr "Возвращает True, если полученный объект является строкой (str)."
#: of telebot.util.parse_web_app_data:1
msgid "Parses web app data."
msgstr "Обрабатывает данные, полученные от web app."
#: of telebot.util.parse_web_app_data:3 telebot.util.validate_web_app_data:3
msgid "The bot token"
msgstr "Токен бота"
#: of telebot.util.parse_web_app_data:6 telebot.util.validate_web_app_data:6
msgid "The raw init data"
msgstr "Необработанные данные"
#: of telebot.util.parse_web_app_data:9 telebot.util.validate_web_app_data:9
msgid "The parsed init data"
msgstr "Обработанные данные"
#: of telebot.util.quick_markup:1
msgid ""
"Returns a reply markup from a dict in this format: {'text': kwargs} This "
"is useful to avoid always typing 'btn1 = InlineKeyboardButton(...)' 'btn2"
" = InlineKeyboardButton(...)'"
msgstr ""
"Возвращает reply markup из словаря следующего формата: {'text': kwargs}. "
"Удобно использовать вместо постоянного использования 'btn1 = "
"InlineKeyboardButton(...)' 'btn2 = InlineKeyboardButton(...)'"
#: of telebot.util.quick_markup:4 telebot.util.user_link:5
msgid "Example:"
msgstr "Пример:"
#: of telebot.util.quick_markup:6
msgid "Using quick_markup:"
msgstr "Используя quick_markup:"
#: of telebot.util.quick_markup:31
msgid ""
"a dict containing all buttons to create in this format: {text: kwargs} "
"{str:}"
msgstr ""
"Словарь, содержащий все кнопки для создания reply markup в следующем "
"формате: {text: kwargs} {str:}"
#: of telebot.util.quick_markup:34
msgid "number of :class:`telebot.types.InlineKeyboardButton` objects on each row"
msgstr ""
#: of telebot.util.quick_markup:37
msgid "InlineKeyboardMarkup"
msgstr ""
#: of telebot.util.quick_markup:38
msgid ":obj:`types.InlineKeyboardMarkup`"
msgstr ""
#: of telebot.util.smart_split:1
msgid ""
"Splits one string into multiple strings, with a maximum amount of "
"`chars_per_string` characters per string. This is very useful for "
"splitting one giant message into multiples. If `chars_per_string` > 4096:"
" `chars_per_string` = 4096. Splits by '\\n', '. ' or ' ' in exactly this "
"priority."
msgstr ""
"Разбивает строку на несколько, каждая из которых будет не длиннее "
"`characters_per_string`. Удобно использовать для разбиения одного "
"гигантского сообщения на несколько. Если `chars_per_string` > 4096: "
"`chars_per_string` = 4096. Разбивает строку по '\\n', '. ' или ' ' именно"
" в таком порядке."
#: of telebot.util.smart_split:6 telebot.util.split_string:4
msgid "The text to split"
msgstr "Текст для разбиения"
#: of telebot.util.smart_split:9
msgid "The number of maximum characters per part the text is split to."
msgstr ""
"Максимальное количество символов в части текста, на которые он будет "
"разбит."
#: of telebot.util.smart_split:12 telebot.util.split_string:10
msgid "The splitted text as a list of strings."
msgstr "Список частей разбитого текста."
#: of telebot.util.smart_split:13 telebot.util.split_string:11
msgid ":obj:`list` of :obj:`str`"
msgstr ""
#: of telebot.util.split_string:1
msgid ""
"Splits one string into multiple strings, with a maximum amount of "
"`chars_per_string` characters per string. This is very useful for "
"splitting one giant message into multiples."
msgstr ""
"Разбивает одну строку на несколько, каждая из которых будет не длиннее "
"`characters_per_string`. Удобно использовать для разбиения одного "
"гигантского сообщения на несколько."
#: of telebot.util.split_string:7
msgid "The number of characters per line the text is split into."
msgstr "Количество символов в одной строке, на которые будет разбит текст."
#: ../../docstring of telebot.util.update_types:1
msgid "All update types, should be used for allowed_updates parameter in polling."
msgstr ""
"Все виды апдейтов, рекомендуется использовать в качестве параметра "
"allowed_updates функции polling."
#: of telebot.util.user_link:1
msgid ""
"Returns an HTML user link. This is useful for reports. Attention: Don't "
"forget to set parse_mode to 'HTML'!"
msgstr ""
"Возвращает HTML ссылку на пользователя. Удобно использовать для отчетов. "
"Важно: Не забудьте установить значение 'HTML' в parse_mode!"
#: of telebot.util.user_link:11
msgid ""
"You can use formatting.* for all other formatting options(bold, italic, "
"links, and etc.) This method is kept for backward compatibility, and it "
"is recommended to use formatting.* for more options."
msgstr ""
"Вы можете использовать formatting.* во всех остальных вариантах "
"форматирования(bold, italic, links, и прочее). Этот метод сохранён для "
"обратной совместимости, рекомендуется использовать formatting.* для "
"большего количества вариантов."
#: of telebot.util.user_link:15
msgid "the user (not the user_id)"
msgstr "Пользователь (не id пользователя)"
#: of telebot.util.user_link:18
msgid "include the user_id"
msgstr "Добавить id пользователя"
#: of telebot.util.user_link:21
msgid "HTML user link"
msgstr "Ссылка на пользователя в формате HTML"
#: of telebot.util.validate_web_app_data:1
msgid "Validates web app data."
msgstr "Проверяет данные, полученные от web app."
#: of telebot.util.webhook_google_functions:1
msgid "A webhook endpoint for Google Cloud Functions FaaS."
msgstr "Endpoint вебхука для Google Cloud Functions FaaS."
#: of telebot.util.webhook_google_functions:3
msgid "The bot instance"
msgstr "Инстанс бота"
#: of telebot.util.webhook_google_functions:6
msgid "The request object"
msgstr "HTTP-запрос"
#: of telebot.util.webhook_google_functions:9
msgid "The response object"
msgstr "Объект, полученный в качестве ответа"
#~ msgid "int row width"
#~ msgstr "Количество кнопок в одной строке, int"

View File

@ -21,14 +21,6 @@ custom_filters file
:undoc-members:
:show-inheritance:
Synchronous storage for states
-------------------------------
.. automodule:: telebot.storage
:members:
:undoc-members:
:show-inheritance:
handler_backends file
--------------------------------
@ -37,3 +29,13 @@ handler_backends file
:undoc-members:
:show-inheritance:
Extensions
------------------------
.. automodule:: telebot.ext.sync.webhooks
:members:
:undoc-members:
:show-inheritance:

View File

@ -0,0 +1,27 @@
from telebot.async_telebot import AsyncTeleBot
from telebot.asyncio_handler_backends import ContinueHandling
bot = AsyncTeleBot('TOKEN')
@bot.message_handler(commands=['start'])
async def start(message):
await bot.send_message(message.chat.id, 'Hello World!')
return ContinueHandling()
@bot.message_handler(commands=['start'])
async def start2(message):
"""
This handler comes after the first one, but it will never be called.
But you can call it by returning ContinueHandling() in the first handler.
If you return ContinueHandling() in the first handler, the next
registered handler with appropriate filters will be called.
"""
await bot.send_message(message.chat.id, 'Hello World2!')
import asyncio
asyncio.run(bot.polling()) # just a reminder that infinity polling
# wraps polling into try/except block just as sync version,
# but you can use any of them because neither of them stops if you
# pass non_stop=True

View File

@ -0,0 +1,28 @@
#!/usr/bin/python
# This is a simple echo bot using the decorator mechanism.
# It echoes any incoming text messages.
from telebot.async_telebot import AsyncTeleBot
bot = AsyncTeleBot('TOKEN')
# Handle '/start' and '/help'
@bot.message_handler(commands=['help', 'start'])
async def send_welcome(message):
await bot.reply_to(message, """\
Hi there, I am EchoBot.
I am here to echo your kind words back to you. Just say anything nice and I'll say the exact same thing to you!\
""")
# Handle all other messages with content_type 'text' (content_types defaults to ['text'])
@bot.message_handler(func=lambda message: True)
async def echo_message(message):
await bot.reply_to(message, message.text)
import asyncio
# only for versions 4.7.0+
asyncio.run(bot.polling(restart_on_change=True))

View File

@ -0,0 +1,93 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This is an async echo bot using decorators and webhook with aiohttp
# It echoes any incoming text messages and does not use the polling method.
import logging
import ssl
import asyncio
from aiohttp import web
import telebot
from telebot.async_telebot import AsyncTeleBot
API_TOKEN = '<api_token>'
WEBHOOK_HOST = '<ip/host where the bot is running>'
WEBHOOK_PORT = 8443 # 443, 80, 88 or 8443 (port need to be 'open')
WEBHOOK_LISTEN = '0.0.0.0' # In some VPS you may need to put here the IP addr
WEBHOOK_SSL_CERT = './webhook_cert.pem' # Path to the ssl certificate
WEBHOOK_SSL_PRIV = './webhook_pkey.pem' # Path to the ssl private key
WEBHOOK_URL_BASE = "https://{}:{}".format(WEBHOOK_HOST, WEBHOOK_PORT)
WEBHOOK_URL_PATH = "/{}/".format(API_TOKEN)
# Quick'n'dirty SSL certificate generation:
#
# openssl genrsa -out webhook_pkey.pem 2048
# openssl req -new -x509 -days 3650 -key webhook_pkey.pem -out webhook_cert.pem
#
# When asked for "Common Name (e.g. server FQDN or YOUR name)" you should reply
# with the same value in you put in WEBHOOK_HOST
logger = telebot.logger
telebot.logger.setLevel(logging.INFO)
bot = AsyncTeleBot(API_TOKEN)
# Process webhook calls
async def handle(request):
if request.match_info.get('token') == bot.token:
request_body_dict = await request.json()
update = telebot.types.Update.de_json(request_body_dict)
asyncio.ensure_future(bot.process_new_updates([update]))
return web.Response()
else:
return web.Response(status=403)
# Handle '/start' and '/help'
@bot.message_handler(commands=['help', 'start'])
async def send_welcome(message):
await bot.reply_to(message,
("Hi there, I am EchoBot.\n"
"I am here to echo your kind words back to you."))
# Handle all other messages
@bot.message_handler(func=lambda message: True, content_types=['text'])
async def echo_message(message):
await bot.reply_to(message, message.text)
# Remove webhook and closing session before exiting
async def shutdown(app):
logger.info('Shutting down: removing webhook')
await bot.remove_webhook()
logger.info('Shutting down: closing session')
await bot.close_session()
async def setup():
# Remove webhook, it fails sometimes the set if there is a previous webhook
logger.info('Starting up: removing old webhook')
await bot.remove_webhook()
# Set webhook
logger.info('Starting up: setting webhook')
await bot.set_webhook(url=WEBHOOK_URL_BASE + WEBHOOK_URL_PATH,
certificate=open(WEBHOOK_SSL_CERT, 'r'))
app = web.Application()
app.router.add_post('/{token}/', handle)
app.on_cleanup.append(shutdown)
return app
if __name__ == '__main__':
# Build ssl context
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
context.load_cert_chain(WEBHOOK_SSL_CERT, WEBHOOK_SSL_PRIV)
# Start aiohttp server
web.run_app(
setup(),
host=WEBHOOK_LISTEN,
port=WEBHOOK_PORT,
ssl_context=context,
)

View File

@ -0,0 +1,45 @@
#!/usr/bin/python
# This is a simple echo bot using the decorator mechanism.
# It echoes any incoming text messages.
# Example on built-in function to receive and process webhooks.
from telebot.async_telebot import AsyncTeleBot
import asyncio
bot = AsyncTeleBot('TOKEN')
WEBHOOK_SSL_CERT = './webhook_cert.pem' # Path to the ssl certificate
WEBHOOK_SSL_PRIV = './webhook_pkey.pem' # Path to the ssl private key
DOMAIN = '1.2.3.4' # either domain, or ip address of vps
# Quick'n'dirty SSL certificate generation:
#
# openssl genrsa -out webhook_pkey.pem 2048
# openssl req -new -x509 -days 3650 -key webhook_pkey.pem -out webhook_cert.pem
#
# When asked for "Common Name (e.g. server FQDN or YOUR name)" you should reply
# with the same value in you put in WEBHOOK_HOST
# Handle '/start' and '/help'
@bot.message_handler(commands=['help', 'start'])
async def send_welcome(message):
await bot.reply_to(message, """\
Hi there, I am EchoBot.
I am here to echo your kind words back to you. Just say anything nice and I'll say the exact same thing to you!\
""")
# Handle all other messages with content_type 'text' (content_types defaults to ['text'])
@bot.message_handler(func=lambda message: True)
async def echo_message(message):
await bot.reply_to(message, message.text)
# it uses fastapi + uvicorn
asyncio.run(bot.run_webhooks(
listen=DOMAIN,
certificate=WEBHOOK_SSL_CERT,
certificate_key=WEBHOOK_SSL_PRIV
))

View File

@ -0,0 +1,89 @@
#!/usr/bin/env python
"""
Asynchronous Telegram Echo Bot example.
This is a simple bot that echoes each message that is received onto the chat.
It uses the Starlette ASGI framework to receive updates via webhook requests.
"""
import uvicorn
from starlette.applications import Starlette
from starlette.requests import Request
from starlette.responses import PlainTextResponse, Response
from starlette.routing import Route
from telebot.async_telebot import AsyncTeleBot
from telebot.types import Message, Update
API_TOKEN = "TOKEN"
WEBHOOK_HOST = "<ip/domain>"
WEBHOOK_PORT = 8443 # 443, 80, 88 or 8443 (port need to be 'open')
WEBHOOK_LISTEN = "0.0.0.0"
WEBHOOK_SSL_CERT = "./webhook_cert.pem" # Path to the ssl certificate
WEBHOOK_SSL_PRIV = "./webhook_pkey.pem" # Path to the ssl private key
WEBHOOK_URL = f"https://{WEBHOOK_HOST}:{WEBHOOK_PORT}/telegram"
WEBHOOK_SECRET_TOKEN = "SECRET_TOKEN"
logger = telebot.logger
telebot.logger.setLevel(logging.INFO)
bot = AsyncTeleBot(token=API_TOKEN)
# BOT HANDLERS
@bot.message_handler(commands=["help", "start"])
async def send_welcome(message: Message):
"""
Handle '/start' and '/help'
"""
await bot.reply_to(
message,
("Hi there, I am EchoBot.\n" "I am here to echo your kind words back to you."),
)
@bot.message_handler(func=lambda _: True, content_types=["text"])
async def echo_message(message: Message):
"""
Handle all other messages
"""
await bot.reply_to(message, message.text)
# WEBSERVER HANDLERS
async def telegram(request: Request) -> Response:
"""Handle incoming Telegram updates."""
token_header_name = "X-Telegram-Bot-Api-Secret-Token"
if request.headers.get(token_header_name) != WEBHOOK_SECRET_TOKEN:
return PlainTextResponse("Forbidden", status_code=403)
await bot.process_new_updates([Update.de_json(await request.json())])
return Response()
async def startup() -> None:
"""Register webhook for telegram updates."""
webhook_info = await bot.get_webhook_info(30)
if WEBHOOK_URL != webhook_info.url:
logger.debug(
f"updating webhook url, old: {webhook_info.url}, new: {WEBHOOK_URL}"
)
if not await bot.set_webhook(
url=WEBHOOK_URL, secret_token=WEBHOOK_SECRET_TOKEN
):
raise RuntimeError("unable to set webhook")
app = Starlette(
routes=[
Route("/telegram", telegram, methods=["POST"]),
],
on_startup=[startup],
)
uvicorn.run(
app,
host=WEBHOOK_HOST,
port=WEBHOOK_LISTEN,
ssl_certfile=WEBHOOK_SSL_CERT,
ssl_keyfile=WEBHOOK_SSL_PRIV,
)

View File

@ -0,0 +1,23 @@
from telebot import TeleBot
from telebot.handler_backends import ContinueHandling
bot = TeleBot('TOKEN')
@bot.message_handler(commands=['start'])
def start(message):
bot.send_message(message.chat.id, 'Hello World!')
return ContinueHandling()
@bot.message_handler(commands=['start'])
def start2(message):
"""
This handler comes after the first one, but it will never be called.
But you can call it by returning ContinueHandling() in the first handler.
If you return ContinueHandling() in the first handler, the next
registered handler with appropriate filters will be called.
"""
bot.send_message(message.chat.id, 'Hello World2!')
bot.infinity_polling()

View File

@ -47,7 +47,7 @@ def start_ex(message):
# Any state
@bot.message_handler(state="*", commands='cancel')
@bot.message_handler(state="*", commands=['cancel'])
def any_state(message):
"""
Cancel state

View File

@ -0,0 +1,28 @@
#!/usr/bin/python
# This is a simple echo bot using the decorator mechanism.
# It echoes any incoming text messages.
import telebot
API_TOKEN = '<api_token>'
bot = telebot.TeleBot(API_TOKEN)
# Handle '/start' and '/help'
@bot.message_handler(commands=['help', 'start'])
def send_welcome(message):
bot.reply_to(message, """\
Hi there, I am EchoBot.
I am here to echo your kind words back to you. Just say anything nice and I'll say the exact same thing to you!\
""")
# Handle all other messages with content_type 'text' (content_types defaults to ['text'])
@bot.message_handler(func=lambda message: True)
def echo_message(message):
bot.reply_to(message, message.text)
# only for versions 4.7.0+
bot.infinity_polling(restart_on_change=True)

View File

@ -42,7 +42,7 @@ def query_video(inline_query):
try:
r = types.InlineQueryResultVideo('1',
'https://github.com/eternnoir/pyTelegramBotAPI/blob/master/tests/test_data/test_video.mp4?raw=true',
'video/mp4', 'Video',
'video/mp4',
'https://raw.githubusercontent.com/eternnoir/pyTelegramBotAPI/master/examples/detailed_example/rooster.jpg',
'Title'
)

32
examples/poll_example.py Normal file
View File

@ -0,0 +1,32 @@
#!/usr/bin/python
# This is an example file to create quiz polls
import telebot
API_TOKEN = "<api_token>"
bot = telebot.TeleBot(API_TOKEN)
@bot.message_handler(commands=["poll"])
def create_poll(message):
bot.send_message(message.chat.id, "English Article Test")
answer_options = ["a", "an", "the", "-"]
bot.send_poll(
chat_id=message.chat.id,
question="We are going to '' park.",
options=answer_options,
type="quiz",
correct_option_id=2,
is_anonymous=False,
)
@bot.poll_answer_handler()
def handle_poll(poll):
# This handler can be used to log User answers and to send next poll
pass
bot.infinity_polling()

View File

@ -0,0 +1,50 @@
"""
Example of running PyTelegramBotAPI serverless in Amazon AWS Lambdaю
You have to set your lambda's url as telegram webhook manually https://core.telegram.org/bots/api#setwebhook
"""
import logging
import telebot
import json
import os
API_TOKEN = os.environ['TELEGRAM_TOKEN']
logger = telebot.logger
telebot.logger.setLevel(logging.INFO)
bot = telebot.TeleBot(API_TOKEN, threaded=False)
def process_event(event):
# Get telegram webhook json from event
request_body_dict = json.loads(event['body'])
# Parse updates from json
update = telebot.types.Update.de_json(request_body_dict)
# Run handlers and etc for updates
bot.process_new_updates([update])
def lambda_handler(event, context):
# Process event from aws and respond
process_event(event)
return {
'statusCode': 200
}
# Handle '/start' and '/help'
@bot.message_handler(commands=['help', 'start'])
def send_welcome(message):
bot.reply_to(message,
("Hi there, I am EchoBot.\n"
"I am here to echo your kind words back to you."))
# Handle all other messages
@bot.message_handler(func=lambda message: True, content_types=['text'])
def echo_message(message):
bot.reply_to(message, message.text)

View File

@ -0,0 +1,45 @@
#!/usr/bin/python
# This is a simple echo bot using the decorator mechanism.
# It echoes any incoming text messages.
# Example on built-in function to receive and process webhooks.
import telebot
API_TOKEN = 'TOKEN'
bot = telebot.TeleBot(API_TOKEN)
WEBHOOK_SSL_CERT = './webhook_cert.pem' # Path to the ssl certificate
WEBHOOK_SSL_PRIV = './webhook_pkey.pem' # Path to the ssl private key
DOMAIN = '1.2.3.4' # either domain, or ip address of vps
# Quick'n'dirty SSL certificate generation:
#
# openssl genrsa -out webhook_pkey.pem 2048
# openssl req -new -x509 -days 3650 -key webhook_pkey.pem -out webhook_cert.pem
#
# When asked for "Common Name (e.g. server FQDN or YOUR name)" you should reply
# with the same value in you put in WEBHOOK_HOST
# Handle '/start' and '/help'
@bot.message_handler(commands=['help', 'start'])
def send_welcome(message):
bot.reply_to(message, """\
Hi there, I am EchoBot.
I am here to echo your kind words back to you. Just say anything nice and I'll say the exact same thing to you!\
""")
# Handle all other messages with content_type 'text' (content_types defaults to ['text'])
@bot.message_handler(func=lambda message: True)
def echo_message(message):
bot.reply_to(message, message.text)
bot.run_webhooks(
listen=DOMAIN,
certificate=WEBHOOK_SSL_CERT,
certificate_key=WEBHOOK_SSL_PRIV
)

View File

@ -6,6 +6,7 @@
import logging
import fastapi
import uvicorn
import telebot
API_TOKEN = 'TOKEN'
@ -33,12 +34,14 @@ telebot.logger.setLevel(logging.INFO)
bot = telebot.TeleBot(API_TOKEN)
app = fastapi.FastAPI()
app = fastapi.FastAPI(docs=None, redoc_url=None)
# Process webhook calls
@app.post(f'/{API_TOKEN}/')
def process_webhook(update: dict):
"""
Process webhook calls
"""
if update:
update = telebot.types.Update.de_json(update)
bot.process_new_updates([update])
@ -46,18 +49,21 @@ def process_webhook(update: dict):
return
# Handle '/start' and '/help'
@bot.message_handler(commands=['help', 'start'])
def send_welcome(message):
"""
Handle '/start' and '/help'
"""
bot.reply_to(message,
("Hi there, I am EchoBot.\n"
"I am here to echo your kind words back to you."))
# Handle all other messages
@bot.message_handler(func=lambda message: True, content_types=['text'])
def echo_message(message):
"""
Handle all other messages
"""
bot.reply_to(message, message.text)
@ -65,11 +71,12 @@ def echo_message(message):
bot.remove_webhook()
# Set webhook
bot.set_webhook(url=WEBHOOK_URL_BASE + WEBHOOK_URL_PATH,
certificate=open(WEBHOOK_SSL_CERT, 'r'))
bot.set_webhook(
url=WEBHOOK_URL_BASE + WEBHOOK_URL_PATH,
certificate=open(WEBHOOK_SSL_CERT, 'r')
)
import uvicorn
uvicorn.run(
app,
host=WEBHOOK_LISTEN,

View File

@ -1,4 +1,4 @@
pytest
requests==2.20.0
wheel==0.24.0
requests==2.31.0
wheel==0.38.1
aiohttp>=3.8.0,<3.9.0

View File

@ -27,7 +27,13 @@ setup(name='pyTelegramBotAPI',
'json': 'ujson',
'PIL': 'Pillow',
'redis': 'redis>=3.4.1',
'aioredis': 'aioredis',
'aiohttp': 'aiohttp',
'fastapi': 'fastapi',
'uvicorn': 'uvicorn',
'psutil': 'psutil',
'coloredlogs': 'coloredlogs',
'watchdog': 'watchdog'
},
classifiers=[
'Development Status :: 5 - Production/Stable',

File diff suppressed because it is too large Load Diff

View File

@ -87,6 +87,15 @@ def _make_request(token, method_name, method='get', params=None, files=None):
logger.debug("Request: method={0} url={1} params={2} files={3}".format(method, request_url, params, files).replace(token, token.split(':')[0] + ":{TOKEN}"))
read_timeout = READ_TIMEOUT
connect_timeout = CONNECT_TIMEOUT
if files:
files_copy = dict(files)
# process types.InputFile
for key, value in files_copy.items():
if isinstance(value, types.InputFile):
files[key] = value.file
if files and format_header_param:
fields.format_header_param = _no_encode(format_header_param)
if params:
@ -102,7 +111,13 @@ def _make_request(token, method_name, method='get', params=None, files=None):
params = params or None # Set params to None if empty
result = None
if RETRY_ON_ERROR and RETRY_ENGINE == 1:
if CUSTOM_REQUEST_SENDER:
# noinspection PyCallingNonCallable
result = CUSTOM_REQUEST_SENDER(
method, request_url, params=params, files=files,
timeout=(connect_timeout, read_timeout), proxies=proxy)
elif RETRY_ON_ERROR and RETRY_ENGINE == 1:
got_result = False
current_try = 0
while not got_result and current_try<MAX_RETRIES-1:
@ -137,11 +152,6 @@ def _make_request(token, method_name, method='get', params=None, files=None):
result = http.request(
method, request_url, params=params, files=files,
timeout=(connect_timeout, read_timeout), proxies=proxy)
elif CUSTOM_REQUEST_SENDER:
# noinspection PyCallingNonCallable
result = CUSTOM_REQUEST_SENDER(
method, request_url, params=params, files=files,
timeout=(connect_timeout, read_timeout), proxies=proxy)
else:
result = _get_req_session().request(
method, request_url, params=params, files=files,
@ -227,23 +237,8 @@ def send_message(
token, chat_id, text,
disable_web_page_preview=None, reply_to_message_id=None, reply_markup=None,
parse_mode=None, disable_notification=None, timeout=None,
entities=None, allow_sending_without_reply=None, protect_content=None):
"""
Use this method to send text messages. On success, the sent Message is returned.
:param token:
:param chat_id:
:param text:
:param disable_web_page_preview:
:param reply_to_message_id:
:param reply_markup:
:param parse_mode:
:param disable_notification:
:param timeout:
:param entities:
:param allow_sending_without_reply:
:param protect_content:
:return:
"""
entities=None, allow_sending_without_reply=None, protect_content=None,
message_thread_id=None):
method_url = r'sendMessage'
payload = {'chat_id': str(chat_id), 'text': text}
if disable_web_page_preview is not None:
@ -264,6 +259,8 @@ def send_message(
payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id:
payload['message_thread_id'] = message_thread_id
return _make_request(token, method_url, params=payload, method='post')
@ -358,15 +355,15 @@ def get_chat_member_count(token, chat_id):
return _make_request(token, method_url, params=payload)
def set_sticker_set_thumb(token, name, user_id, thumb):
method_url = r'setStickerSetThumb'
def set_sticker_set_thumbnail(token, name, user_id, thumbnail):
method_url = r'setStickerSetThumbnail'
payload = {'name': name, 'user_id': user_id}
files = {}
if thumb:
if not isinstance(thumb, str):
files['thumb'] = thumb
if thumbnail:
if not isinstance(thumbnail, str):
files['thumbnail'] = thumbnail
else:
payload['thumb'] = thumb
payload['thumbnail'] = thumbnail
return _make_request(token, method_url, params=payload, files=files or None)
@ -390,7 +387,7 @@ def get_chat_member(token, chat_id, user_id):
def forward_message(
token, chat_id, from_chat_id, message_id,
disable_notification=None, timeout=None, protect_content=None):
disable_notification=None, timeout=None, protect_content=None, message_thread_id=None):
method_url = r'forwardMessage'
payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id}
if disable_notification is not None:
@ -399,12 +396,14 @@ def forward_message(
payload['timeout'] = timeout
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id:
payload['message_thread_id'] = message_thread_id
return _make_request(token, method_url, params=payload)
def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_mode=None, caption_entities=None,
disable_notification=None, reply_to_message_id=None, allow_sending_without_reply=None,
reply_markup=None, timeout=None, protect_content=None):
reply_markup=None, timeout=None, protect_content=None, message_thread_id=None):
method_url = r'copyMessage'
payload = {'chat_id': chat_id, 'from_chat_id': from_chat_id, 'message_id': message_id}
if caption is not None:
@ -425,13 +424,15 @@ def copy_message(token, chat_id, from_chat_id, message_id, caption=None, parse_m
payload['timeout'] = timeout
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id is not None:
payload['message_thread_id'] = message_thread_id
return _make_request(token, method_url, params=payload)
def send_dice(
token, chat_id,
emoji=None, disable_notification=None, reply_to_message_id=None,
reply_markup=None, timeout=None, allow_sending_without_reply=None, protect_content=None):
reply_markup=None, timeout=None, allow_sending_without_reply=None, protect_content=None, message_thread_id=None):
method_url = r'sendDice'
payload = {'chat_id': chat_id}
if emoji:
@ -448,6 +449,8 @@ def send_dice(
payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id:
payload['message_thread_id'] = message_thread_id
return _make_request(token, method_url, params=payload)
@ -455,7 +458,8 @@ def send_photo(
token, chat_id, photo,
caption=None, reply_to_message_id=None, reply_markup=None,
parse_mode=None, disable_notification=None, timeout=None,
caption_entities=None, allow_sending_without_reply=None, protect_content=None):
caption_entities=None, allow_sending_without_reply=None, protect_content=None,
message_thread_id=None, has_spoiler=None):
method_url = r'sendPhoto'
payload = {'chat_id': chat_id}
files = None
@ -483,13 +487,17 @@ def send_photo(
payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id is not None:
payload['message_thread_id'] = message_thread_id
if has_spoiler is not None:
payload['has_spoiler'] = has_spoiler
return _make_request(token, method_url, params=payload, files=files, method='post')
def send_media_group(
token, chat_id, media,
disable_notification=None, reply_to_message_id=None,
timeout=None, allow_sending_without_reply=None, protect_content=None):
timeout=None, allow_sending_without_reply=None, protect_content=None, message_thread_id=None):
method_url = r'sendMediaGroup'
media_json, files = convert_input_media_array(media)
payload = {'chat_id': chat_id, 'media': media_json}
@ -503,6 +511,8 @@ def send_media_group(
payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id is not None:
payload['message_thread_id'] = message_thread_id
return _make_request(
token, method_url, params=payload,
method='post' if files else 'get',
@ -514,7 +524,8 @@ def send_location(
live_period=None, reply_to_message_id=None,
reply_markup=None, disable_notification=None,
timeout=None, horizontal_accuracy=None, heading=None,
proximity_alert_radius=None, allow_sending_without_reply=None, protect_content=None):
proximity_alert_radius=None, allow_sending_without_reply=None, protect_content=None,
message_thread_id=None):
method_url = r'sendLocation'
payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude}
if live_period:
@ -537,6 +548,8 @@ def send_location(
payload['timeout'] = timeout
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id is not None:
payload['message_thread_id'] = message_thread_id
return _make_request(token, method_url, params=payload)
@ -588,7 +601,7 @@ def send_venue(
foursquare_id=None, foursquare_type=None, disable_notification=None,
reply_to_message_id=None, reply_markup=None, timeout=None,
allow_sending_without_reply=None, google_place_id=None,
google_place_type=None, protect_content=None):
google_place_type=None, protect_content=None, message_thread_id=None):
method_url = r'sendVenue'
payload = {'chat_id': chat_id, 'latitude': latitude, 'longitude': longitude, 'title': title, 'address': address}
if foursquare_id:
@ -611,13 +624,15 @@ def send_venue(
payload['google_place_type'] = google_place_type
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id is not None:
payload['message_thread_id'] = message_thread_id
return _make_request(token, method_url, params=payload)
def send_contact(
token, chat_id, phone_number, first_name, last_name=None, vcard=None,
disable_notification=None, reply_to_message_id=None, reply_markup=None, timeout=None,
allow_sending_without_reply=None, protect_content=None):
allow_sending_without_reply=None, protect_content=None, message_thread_id=None):
method_url = r'sendContact'
payload = {'chat_id': chat_id, 'phone_number': phone_number, 'first_name': first_name}
if last_name:
@ -636,21 +651,26 @@ def send_contact(
payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id is not None:
payload['message_thread_id'] = message_thread_id
return _make_request(token, method_url, params=payload)
def send_chat_action(token, chat_id, action, timeout=None):
def send_chat_action(token, chat_id, action, timeout=None, message_thread_id=None):
method_url = r'sendChatAction'
payload = {'chat_id': chat_id, 'action': action}
if timeout:
payload['timeout'] = timeout
if message_thread_id is not None:
payload['message_thread_id'] = message_thread_id
return _make_request(token, method_url, params=payload)
def send_video(token, chat_id, data, duration=None, caption=None, reply_to_message_id=None, reply_markup=None,
parse_mode=None, supports_streaming=None, disable_notification=None, timeout=None,
thumb=None, width=None, height=None, caption_entities=None, allow_sending_without_reply=None, protect_content=None):
parse_mode=None, supports_streaming=None, disable_notification=None, timeout=None,
thumbnail=None, width=None, height=None, caption_entities=None, allow_sending_without_reply=None, protect_content=None,
message_thread_id=None, has_spoiler=None):
method_url = r'sendVideo'
payload = {'chat_id': chat_id}
files = None
@ -674,14 +694,14 @@ def send_video(token, chat_id, data, duration=None, caption=None, reply_to_messa
payload['disable_notification'] = disable_notification
if timeout:
payload['timeout'] = timeout
if thumb:
if not util.is_string(thumb):
if thumbnail:
if not util.is_string(thumbnail):
if files:
files['thumb'] = thumb
files['thumbnail'] = thumbnail
else:
files = {'thumb': thumb}
files = {'thumbnail': thumbnail}
else:
payload['thumb'] = thumb
payload['thumbnail'] = thumbnail
if width:
payload['width'] = width
if height:
@ -692,13 +712,18 @@ def send_video(token, chat_id, data, duration=None, caption=None, reply_to_messa
payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id:
payload['message_thread_id'] = message_thread_id
if has_spoiler is not None:
payload['has_spoiler'] = has_spoiler
return _make_request(token, method_url, params=payload, files=files, method='post')
def send_animation(
token, chat_id, data, duration=None, caption=None, reply_to_message_id=None, reply_markup=None,
parse_mode=None, disable_notification=None, timeout=None, thumb=None, caption_entities=None,
allow_sending_without_reply=None, protect_content=None, width=None, height=None):
parse_mode=None, disable_notification=None, timeout=None, thumbnail=None, caption_entities=None,
allow_sending_without_reply=None, protect_content=None, width=None, height=None, message_thread_id=None,
has_spoiler=None):
method_url = r'sendAnimation'
payload = {'chat_id': chat_id}
files = None
@ -720,14 +745,14 @@ def send_animation(
payload['disable_notification'] = disable_notification
if timeout:
payload['timeout'] = timeout
if thumb:
if not util.is_string(thumb):
if thumbnail:
if not util.is_string(thumbnail):
if files:
files['thumb'] = thumb
files['thumbnail'] = thumbnail
else:
files = {'thumb': thumb}
files = {'thumbnail': thumbnail}
else:
payload['thumb'] = thumb
payload['thumbnail'] = thumbnail
if caption_entities:
payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities))
if allow_sending_without_reply is not None:
@ -738,12 +763,16 @@ def send_animation(
payload['width'] = width
if height:
payload['height'] = height
if message_thread_id:
payload['message_thread_id'] = message_thread_id
if has_spoiler is not None:
payload['has_spoiler'] = has_spoiler
return _make_request(token, method_url, params=payload, files=files, method='post')
def send_voice(token, chat_id, voice, caption=None, duration=None, reply_to_message_id=None, reply_markup=None,
parse_mode=None, disable_notification=None, timeout=None, caption_entities=None,
allow_sending_without_reply=None, protect_content=None):
allow_sending_without_reply=None, protect_content=None, message_thread_id=None):
method_url = r'sendVoice'
payload = {'chat_id': chat_id}
files = None
@ -771,11 +800,14 @@ def send_voice(token, chat_id, voice, caption=None, duration=None, reply_to_mess
payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id:
payload['message_thread_id'] = message_thread_id
return _make_request(token, method_url, params=payload, files=files, method='post')
def send_video_note(token, chat_id, data, duration=None, length=None, reply_to_message_id=None, reply_markup=None,
disable_notification=None, timeout=None, thumb=None, allow_sending_without_reply=None, protect_content=None):
disable_notification=None, timeout=None, thumbnail=None, allow_sending_without_reply=None, protect_content=None,
message_thread_id=None):
method_url = r'sendVideoNote'
payload = {'chat_id': chat_id}
files = None
@ -797,24 +829,26 @@ def send_video_note(token, chat_id, data, duration=None, length=None, reply_to_m
payload['disable_notification'] = disable_notification
if timeout:
payload['timeout'] = timeout
if thumb:
if not util.is_string(thumb):
if thumbnail:
if not util.is_string(thumbnail):
if files:
files['thumb'] = thumb
files['thumbnail'] = thumbnail
else:
files = {'thumb': thumb}
files = {'thumbnail': thumbnail}
else:
payload['thumb'] = thumb
payload['thumbnail'] = thumbnail
if allow_sending_without_reply is not None:
payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id:
payload['message_thread_id'] = message_thread_id
return _make_request(token, method_url, params=payload, files=files, method='post')
def send_audio(token, chat_id, audio, caption=None, duration=None, performer=None, title=None, reply_to_message_id=None,
reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumb=None,
caption_entities=None, allow_sending_without_reply=None, protect_content=None):
reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, thumbnail=None,
caption_entities=None, allow_sending_without_reply=None, protect_content=None, message_thread_id=None):
method_url = r'sendAudio'
payload = {'chat_id': chat_id}
files = None
@ -840,27 +874,29 @@ def send_audio(token, chat_id, audio, caption=None, duration=None, performer=Non
payload['disable_notification'] = disable_notification
if timeout:
payload['timeout'] = timeout
if thumb:
if not util.is_string(thumb):
if thumbnail:
if not util.is_string(thumbnail):
if files:
files['thumb'] = thumb
files['thumbnail'] = thumbnail
else:
files = {'thumb': thumb}
files = {'thumbnail': thumbnail}
else:
payload['thumb'] = thumb
payload['thumbnail'] = thumbnail
if caption_entities:
payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities))
if allow_sending_without_reply is not None:
payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id:
payload['message_thread_id'] = message_thread_id
return _make_request(token, method_url, params=payload, files=files, method='post')
def send_data(token, chat_id, data, data_type, reply_to_message_id=None, reply_markup=None, parse_mode=None,
disable_notification=None, timeout=None, caption=None, thumb=None, caption_entities=None,
disable_notification=None, timeout=None, caption=None, thumbnail=None, caption_entities=None,
allow_sending_without_reply=None, disable_content_type_detection=None, visible_file_name=None,
protect_content = None):
protect_content = None, message_thread_id=None, emoji=None):
method_url = get_method_by_type(data_type)
payload = {'chat_id': chat_id}
files = None
@ -883,14 +919,14 @@ def send_data(token, chat_id, data, data_type, reply_to_message_id=None, reply_m
payload['timeout'] = timeout
if caption:
payload['caption'] = caption
if thumb:
if not util.is_string(thumb):
if thumbnail:
if not util.is_string(thumbnail):
if files:
files['thumb'] = thumb
files['thumbnail'] = thumbnail
else:
files = {'thumb': thumb}
files = {'thumbnail': thumbnail}
else:
payload['thumb'] = thumb
payload['thumbnail'] = thumbnail
if caption_entities:
payload['caption_entities'] = json.dumps(types.MessageEntity.to_list_of_dicts(caption_entities))
if allow_sending_without_reply is not None:
@ -899,6 +935,10 @@ def send_data(token, chat_id, data, data_type, reply_to_message_id=None, reply_m
payload['protect_content'] = protect_content
if method_url == 'sendDocument' and disable_content_type_detection is not None:
payload['disable_content_type_detection'] = disable_content_type_detection
if message_thread_id:
payload['message_thread_id'] = message_thread_id
if emoji:
payload['emoji'] = emoji
return _make_request(token, method_url, params=payload, files=files, method='post')
@ -930,36 +970,19 @@ def unban_chat_member(token, chat_id, user_id, only_if_banned):
def restrict_chat_member(
token, chat_id, user_id, until_date=None,
can_send_messages=None, can_send_media_messages=None,
can_send_polls=None, can_send_other_messages=None,
can_add_web_page_previews=None, can_change_info=None,
can_invite_users=None, can_pin_messages=None):
token, chat_id, user_id, permissions, until_date=None,
use_independent_chat_permissions=None):
method_url = 'restrictChatMember'
permissions = {}
if can_send_messages is not None:
permissions['can_send_messages'] = can_send_messages
if can_send_media_messages is not None:
permissions['can_send_media_messages'] = can_send_media_messages
if can_send_polls is not None:
permissions['can_send_polls'] = can_send_polls
if can_send_other_messages is not None:
permissions['can_send_other_messages'] = can_send_other_messages
if can_add_web_page_previews is not None:
permissions['can_add_web_page_previews'] = can_add_web_page_previews
if can_change_info is not None:
permissions['can_change_info'] = can_change_info
if can_invite_users is not None:
permissions['can_invite_users'] = can_invite_users
if can_pin_messages is not None:
permissions['can_pin_messages'] = can_pin_messages
permissions_json = json.dumps(permissions)
payload = {'chat_id': chat_id, 'user_id': user_id, 'permissions': permissions_json}
payload = {'chat_id': chat_id, 'user_id': user_id, 'permissions': permissions.to_json()}
if use_independent_chat_permissions is not None:
payload['use_independent_chat_permissions'] = use_independent_chat_permissions
if until_date is not None:
if isinstance(until_date, datetime):
payload['until_date'] = until_date.timestamp()
else:
payload['until_date'] = until_date
return _make_request(token, method_url, params=payload, method='post')
@ -967,7 +990,8 @@ def promote_chat_member(
token, chat_id, user_id, can_change_info=None, can_post_messages=None,
can_edit_messages=None, can_delete_messages=None, can_invite_users=None,
can_restrict_members=None, can_pin_messages=None, can_promote_members=None,
is_anonymous=None, can_manage_chat=None, can_manage_video_chats=None):
is_anonymous=None, can_manage_chat=None, can_manage_video_chats=None,
can_manage_topics=None):
method_url = 'promoteChatMember'
payload = {'chat_id': chat_id, 'user_id': user_id}
if can_change_info is not None:
@ -992,6 +1016,8 @@ def promote_chat_member(
payload['can_manage_chat'] = can_manage_chat
if can_manage_video_chats is not None:
payload['can_manage_video_chats'] = can_manage_video_chats
if can_manage_topics is not None:
payload['can_manage_topics'] = can_manage_topics
return _make_request(token, method_url, params=payload, method='post')
@ -1015,12 +1041,14 @@ def unban_chat_sender_chat(token, chat_id, sender_chat_id):
return _make_request(token, method_url, params=payload, method='post')
def set_chat_permissions(token, chat_id, permissions):
def set_chat_permissions(token, chat_id, permissions, use_independent_chat_permissions=None):
method_url = 'setChatPermissions'
payload = {
'chat_id': chat_id,
'permissions': permissions.to_json()
}
if use_independent_chat_permissions is not None:
payload['use_independent_chat_permissions'] = use_independent_chat_permissions
return _make_request(token, method_url, params=payload, method='post')
@ -1126,6 +1154,39 @@ def set_chat_title(token, chat_id, title):
return _make_request(token, method_url, params=payload, method='post')
def set_my_description(token, description=None, language_code=None):
method_url = r'setMyDescription'
payload = {}
if description is not None:
payload['description'] = description
if language_code is not None:
payload['language_code'] = language_code
return _make_request(token, method_url, params=payload, method='post')
def get_my_description(token, language_code=None):
method_url = r'getMyDescription'
payload = {}
if language_code:
payload['language_code'] = language_code
return _make_request(token, method_url, params=payload)
def set_my_short_description(token, short_description=None, language_code=None):
method_url = r'setMyShortDescription'
payload = {}
if short_description is not None:
payload['short_description'] = short_description
if language_code is not None:
payload['language_code'] = language_code
return _make_request(token, method_url, params=payload, method='post')
def get_my_short_description(token, language_code=None):
method_url = r'getMyShortDescription'
payload = {}
if language_code:
payload['language_code'] = language_code
return _make_request(token, method_url, params=payload)
def get_my_commands(token, scope=None, language_code=None):
method_url = r'getMyCommands'
payload = {}
@ -1135,6 +1196,22 @@ def get_my_commands(token, scope=None, language_code=None):
payload['language_code'] = language_code
return _make_request(token, method_url, params=payload)
def set_my_name(token, name=None, language_code=None):
method_url = r'setMyName'
payload = {}
if name is not None:
payload['name'] = name
if language_code is not None:
payload['language_code'] = language_code
return _make_request(token, method_url, params=payload, method='post')
def get_my_name(token, language_code=None):
method_url = r'getMyName'
payload = {}
if language_code is not None:
payload['language_code'] = language_code
return _make_request(token, method_url, params=payload)
def set_chat_menu_button(token, chat_id=None, menu_button=None):
method_url = r'setChatMenuButton'
payload = {}
@ -1304,7 +1381,7 @@ def delete_message(token, chat_id, message_id, timeout=None):
def send_game(
token, chat_id, game_short_name,
disable_notification=None, reply_to_message_id=None, reply_markup=None, timeout=None,
allow_sending_without_reply=None, protect_content=None):
allow_sending_without_reply=None, protect_content=None, message_thread_id=None):
method_url = r'sendGame'
payload = {'chat_id': chat_id, 'game_short_name': game_short_name}
if disable_notification is not None:
@ -1319,6 +1396,8 @@ def send_game(
payload['allow_sending_without_reply'] = allow_sending_without_reply
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id:
payload['message_thread_id'] = message_thread_id
return _make_request(token, method_url, params=payload)
@ -1384,7 +1463,7 @@ def send_invoice(
send_phone_number_to_provider = None, send_email_to_provider = None, is_flexible=None,
disable_notification=None, reply_to_message_id=None, reply_markup=None, provider_data=None,
timeout=None, allow_sending_without_reply=None, max_tip_amount=None, suggested_tip_amounts=None,
protect_content=None):
protect_content=None, message_thread_id=None):
"""
Use this method to send invoices. On success, the sent Message is returned.
:param token: Bot's token (you don't need to fill this)
@ -1416,7 +1495,8 @@ def send_invoice(
:param max_tip_amount: The maximum accepted amount for tips in the smallest units of the currency
:param suggested_tip_amounts: A JSON-serialized array of suggested amounts of tips in the smallest units of the currency.
At most 4 suggested tip amounts can be specified. The suggested tip amounts must be positive, passed in a strictly increased order and must not exceed max_tip_amount.
:param protect_content:
:param protect_content: Protects the contents of the sent message from forwarding and saving
:param message_thread_id: Unique identifier for the target message thread (topic) of the forum; for forum supergroups only
:return:
"""
method_url = r'sendInvoice'
@ -1465,6 +1545,8 @@ def send_invoice(
payload['suggested_tip_amounts'] = json.dumps(suggested_tip_amounts)
if protect_content is not None:
payload['protect_content'] = protect_content
if message_thread_id:
payload['message_thread_id'] = message_thread_id
return _make_request(token, method_url, params=payload)
@ -1532,7 +1614,7 @@ def answer_callback_query(token, callback_query_id, text=None, show_alert=None,
def answer_inline_query(token, inline_query_id, results, cache_time=None, is_personal=None, next_offset=None,
switch_pm_text=None, switch_pm_parameter=None):
button=None):
method_url = 'answerInlineQuery'
payload = {'inline_query_id': inline_query_id, 'results': _convert_list_json_serializable(results)}
if cache_time is not None:
@ -1541,10 +1623,8 @@ def answer_inline_query(token, inline_query_id, results, cache_time=None, is_per
payload['is_personal'] = is_personal
if next_offset is not None:
payload['next_offset'] = next_offset
if switch_pm_text:
payload['switch_pm_text'] = switch_pm_text
if switch_pm_parameter:
payload['switch_pm_parameter'] = switch_pm_parameter
if button is not None:
payload["button"] = button.to_json()
return _make_request(token, method_url, params=payload, method='post')
@ -1552,57 +1632,88 @@ def get_sticker_set(token, name):
method_url = 'getStickerSet'
return _make_request(token, method_url, params={'name': name})
def get_custom_emoji_stickers(token, custom_emoji_ids):
method_url = r'getCustomEmojiStickers'
return _make_request(token, method_url, params={'custom_emoji_ids': json.dumps(custom_emoji_ids)})
def upload_sticker_file(token, user_id, png_sticker):
def set_sticker_keywords(token, sticker, keywords=None):
method_url = 'setStickerKeywords'
payload = {'sticker': sticker}
if keywords:
payload['keywords'] = json.dumps(keywords)
return _make_request(token, method_url, params=payload, method='post')
def set_sticker_mask_position(token, sticker, mask_position=None):
method_url = 'setStickerMaskPosition'
payload = {'sticker': sticker}
if mask_position:
payload['mask_position'] = mask_position.to_json()
return _make_request(token, method_url, params=payload, method='post')
def upload_sticker_file(token, user_id, sticker, sticker_format):
method_url = 'uploadStickerFile'
payload = {'user_id': user_id}
files = {'png_sticker': png_sticker}
payload = {'user_id': user_id, 'sticker_format': sticker_format}
files = {'sticker': sticker}
return _make_request(token, method_url, params=payload, files=files, method='post')
def set_custom_emoji_sticker_set_thumbnail(token, name, custom_emoji_id=None):
method_url = 'setCustomEmojiStickerSetThumbnail'
payload = {'name': name}
if custom_emoji_id is not None:
payload['custom_emoji_id'] = custom_emoji_id
return _make_request(token, method_url, params=payload, method='post')
def set_sticker_set_title(token, name, title):
method_url = 'setStickerSetTitle'
payload = {'name': name, 'title': title}
return _make_request(token, method_url, params=payload, method='post')
def delete_sticker_set(token, name):
method_url = 'deleteStickerSet'
payload = {'name': name}
return _make_request(token, method_url, params=payload, method='post')
def set_sticker_emoji_list(token, sticker, emoji_list):
method_url = 'setStickerEmojiList'
payload = {'sticker': sticker, 'emoji_list': json.dumps(emoji_list)}
return _make_request(token, method_url, params=payload, method='post')
def create_new_sticker_set(
token, user_id, name, title, emojis, png_sticker, tgs_sticker,
contains_masks=None, mask_position=None, webm_sticker=None):
token, user_id, name, title, stickers, sticker_format, sticker_type=None, needs_repainting=None):
method_url = 'createNewStickerSet'
payload = {'user_id': user_id, 'name': name, 'title': title, 'emojis': emojis}
if png_sticker:
stype = 'png_sticker'
elif webm_sticker:
stype = 'webm_sticker'
else:
stype = 'tgs_sticker'
sticker = png_sticker or tgs_sticker or webm_sticker
files = None
if not util.is_string(sticker):
files = {stype: sticker}
else:
payload[stype] = sticker
if contains_masks is not None:
payload['contains_masks'] = contains_masks
if mask_position:
payload['mask_position'] = mask_position.to_json()
if webm_sticker:
payload['webm_sticker'] = webm_sticker
payload = {'user_id': user_id, 'name': name, 'title': title, 'sticker_format': sticker_format}
if sticker_type:
payload['sticker_type'] = sticker_type
if needs_repainting:
payload['needs_repainting'] = needs_repainting
files = {}
lst = []
for sticker in stickers:
json_dict, file = sticker.convert_input_sticker()
json_dict = sticker.to_dict()
if file:
list_keys = list(file.keys())
files[list_keys[0]] = file[list_keys[0]]
lst.append(json_dict)
payload['stickers'] = json.dumps(lst)
return _make_request(token, method_url, params=payload, files=files, method='post')
def add_sticker_to_set(token, user_id, name, emojis, png_sticker, tgs_sticker, mask_position, webm_sticker):
def add_sticker_to_set(token, user_id, name, sticker):
method_url = 'addStickerToSet'
payload = {'user_id': user_id, 'name': name, 'emojis': emojis}
if png_sticker:
stype = 'png_sticker'
elif webm_sticker:
stype = 'webm_sticker'
else:
stype = 'tgs_sticker'
sticker = png_sticker or tgs_sticker or webm_sticker
files = None
if not util.is_string(sticker):
files = {stype: sticker}
else:
payload[stype] = sticker
if mask_position:
payload['mask_position'] = mask_position.to_json()
json_dict, files = sticker.convert_input_sticker()
payload = {'user_id': user_id, 'name': name, 'sticker': json_dict}
return _make_request(token, method_url, params=payload, files=files, method='post')
@ -1670,7 +1781,7 @@ def send_poll(
is_anonymous = None, type = None, allows_multiple_answers = None, correct_option_id = None,
explanation = None, explanation_parse_mode=None, open_period = None, close_date = None, is_closed = None,
disable_notification=False, reply_to_message_id=None, allow_sending_without_reply=None,
reply_markup=None, timeout=None, explanation_entities=None, protect_content=None):
reply_markup=None, timeout=None, explanation_entities=None, protect_content=None, message_thread_id=None):
method_url = r'sendPoll'
payload = {
'chat_id': str(chat_id),
@ -1714,8 +1825,51 @@ def send_poll(
types.MessageEntity.to_list_of_dicts(explanation_entities))
if protect_content:
payload['protect_content'] = protect_content
if message_thread_id:
payload['message_thread_id'] = message_thread_id
return _make_request(token, method_url, params=payload)
def create_forum_topic(token, chat_id, name, icon_color=None, icon_custom_emoji_id=None):
method_url = r'createForumTopic'
payload = {'chat_id': chat_id, 'name': name}
if icon_color:
payload['icon_color'] = icon_color
if icon_custom_emoji_id:
payload['icon_custom_emoji_id'] = icon_custom_emoji_id
return _make_request(token, method_url, params=payload)
def edit_forum_topic(token, chat_id, message_thread_id, name=None, icon_custom_emoji_id=None):
method_url = r'editForumTopic'
payload = {'chat_id': chat_id, 'message_thread_id': message_thread_id}
if name is not None:
payload['name'] = name
if icon_custom_emoji_id is not None:
payload['icon_custom_emoji_id'] = icon_custom_emoji_id
return _make_request(token, method_url, params=payload)
def close_forum_topic(token, chat_id, message_thread_id):
method_url = r'closeForumTopic'
payload = {'chat_id': chat_id, 'message_thread_id': message_thread_id}
return _make_request(token, method_url, params=payload)
def reopen_forum_topic(token, chat_id, message_thread_id):
method_url = r'reopenForumTopic'
payload = {'chat_id': chat_id, 'message_thread_id': message_thread_id}
return _make_request(token, method_url, params=payload)
def delete_forum_topic(token, chat_id, message_thread_id):
method_url = r'deleteForumTopic'
payload = {'chat_id': chat_id, 'message_thread_id': message_thread_id}
return _make_request(token, method_url, params=payload)
def unpin_all_forum_topic_messages(token, chat_id, message_thread_id):
method_url = r'unpinAllForumTopicMessages'
payload = {'chat_id': chat_id, 'message_thread_id': message_thread_id}
return _make_request(token, method_url, params=payload)
def get_forum_topic_icon_stickers(token):
method_url = r'getForumTopicIconStickers'
return _make_request(token, method_url)
def stop_poll(token, chat_id, message_id, reply_markup=None):
method_url = r'stopPoll'
@ -1724,6 +1878,31 @@ def stop_poll(token, chat_id, message_id, reply_markup=None):
payload['reply_markup'] = _convert_markup(reply_markup)
return _make_request(token, method_url, params=payload)
def edit_general_forum_topic(token, chat_id, name):
method_url = r'editGeneralForumTopic'
payload = {'chat_id': chat_id, 'name': name}
return _make_request(token, method_url, params=payload)
def close_general_forum_topic(token, chat_id):
method_url = r'closeGeneralForumTopic'
payload = {'chat_id': chat_id}
return _make_request(token, method_url, params=payload)
def reopen_general_forum_topic(token, chat_id):
method_url = r'reopenGeneralForumTopic'
payload = {'chat_id': chat_id}
return _make_request(token, method_url, params=payload)
def hide_general_forum_topic(token, chat_id):
method_url = r'hideGeneralForumTopic'
payload = {'chat_id': chat_id}
return _make_request(token, method_url, params=payload)
def unhide_general_forum_topic(token, chat_id):
method_url = r'unhideGeneralForumTopic'
payload = {'chat_id': chat_id}
return _make_request(token, method_url, params=payload)
def _convert_list_json_serializable(results):
ret = ''

File diff suppressed because it is too large Load Diff

View File

@ -10,8 +10,19 @@ class SimpleCustomFilter(ABC):
Simple Custom Filter base class.
Create child class with check() method.
Accepts only message, returns bool value, that is compared with given in handler.
Child classes should have .key property.
.. code-block:: python3
:caption: Example on creating a simple custom filter.
class ForwardFilter(SimpleCustomFilter):
# Check whether message was forwarded from channel or group.
key = 'is_forwarded'
def check(self, message):
return message.forward_date is not None
"""
key: str = None
@ -25,13 +36,23 @@ class SimpleCustomFilter(ABC):
class AdvancedCustomFilter(ABC):
"""
Simple Custom Filter base class.
Advanced Custom Filter base class.
Create child class with check() method.
Accepts two parameters, returns bool: True - filter passed, False - filter failed.
message: Message class
text: Filter value given in handler
Child classes should have .key property.
.. code-block:: python3
:caption: Example on creating an advanced custom filter.
class TextStartsFilter(AdvancedCustomFilter):
# Filter to check whether message starts with some text.
key = 'text_startswith'
def check(self, message, text):
return message.text.startswith(text)
"""
key: str = None
@ -48,6 +69,25 @@ class TextFilter:
Advanced text filter to check (types.Message, types.CallbackQuery, types.InlineQuery, types.Poll)
example of usage is in examples/asynchronous_telebot/custom_filters/advanced_text_filter.py
:param equals: string, True if object's text is equal to passed string
:type equals: :obj:`str`
:param contains: list[str] or tuple[str], True if any string element of iterable is in text
:type contains: list[str] or tuple[str]
:param starts_with: string, True if object's text starts with passed string
:type starts_with: :obj:`str`
:param ends_with: string, True if object's text starts with passed string
:type ends_with: :obj:`str`
:param ignore_case: bool (default False), case insensitive
:type ignore_case: :obj:`bool`
:raises ValueError: if incorrect value for a parameter was supplied
:return: None
"""
def __init__(self,
@ -56,13 +96,25 @@ class TextFilter:
starts_with: Optional[Union[str, list, tuple]] = None,
ends_with: Optional[Union[str, list, tuple]] = None,
ignore_case: bool = False):
"""
:param equals: string, True if object's text is equal to passed string
:type equals: :obj:`str`
:param contains: list[str] or tuple[str], True if any string element of iterable is in text
:type contains: list[str] or tuple[str]
:param starts_with: string, True if object's text starts with passed string
:type starts_with: :obj:`str`
:param ends_with: string, True if object's text starts with passed string
:type ends_with: :obj:`str`
:param ignore_case: bool (default False), case insensitive
:type ignore_case: :obj:`bool`
:raises ValueError: if incorrect value for a parameter was supplied
:return: None
"""
to_check = sum((pattern is not None for pattern in (equals, contains, starts_with, ends_with)))
@ -87,7 +139,9 @@ class TextFilter:
return iterable
async def check(self, obj: Union[types.Message, types.CallbackQuery, types.InlineQuery, types.Poll]):
"""
:meta private:
"""
if isinstance(obj, types.Poll):
text = obj.question
elif isinstance(obj, types.Message):
@ -135,15 +189,20 @@ class TextFilter:
class TextMatchFilter(AdvancedCustomFilter):
"""
Filter to check Text message.
key: text
Example:
@bot.message_handler(text=['account'])
.. code-block:: python3
:caption: Example on using this filter:
@bot.message_handler(text=['account'])
# your function
"""
key = 'text'
async def check(self, message, text):
"""
:meta private:
"""
if isinstance(text, TextFilter):
return await text.check(message)
elif type(text) is list:
@ -157,14 +216,21 @@ class TextContainsFilter(AdvancedCustomFilter):
Filter to check Text message.
key: text
Example:
# Will respond if any message.text contains word 'account'
@bot.message_handler(text_contains=['account'])
.. code-block:: python3
:caption: Example on using this filter:
# Will respond if any message.text contains word 'account'
@bot.message_handler(text_contains=['account'])
# your function
"""
key = 'text_contains'
async def check(self, message, text):
"""
:meta private:
"""
if not isinstance(text, str) and not isinstance(text, list) and not isinstance(text, tuple):
raise ValueError("Incorrect text_contains value")
elif isinstance(text, str):
@ -179,14 +245,20 @@ class TextStartsFilter(AdvancedCustomFilter):
"""
Filter to check whether message starts with some text.
Example:
# Will work if message.text starts with 'Sir'.
@bot.message_handler(text_startswith='Sir')
.. code-block:: python3
:caption: Example on using this filter:
# Will work if message.text starts with 'sir'.
@bot.message_handler(text_startswith='sir')
# your function
"""
key = 'text_startswith'
async def check(self, message, text):
"""
:meta private:
"""
return message.text.startswith(text)
@ -194,13 +266,21 @@ class ChatFilter(AdvancedCustomFilter):
"""
Check whether chat_id corresponds to given chat_id.
Example:
@bot.message_handler(chat_id=[99999])
.. code-block:: python3
:caption: Example on using this filter:
@bot.message_handler(chat_id=[99999])
# your function
"""
key = 'chat_id'
async def check(self, message, text):
"""
:meta private:
"""
if isinstance(message, types.CallbackQuery):
return message.message.chat.id in text
return message.chat.id in text
@ -208,29 +288,41 @@ class ForwardFilter(SimpleCustomFilter):
"""
Check whether message was forwarded from channel or group.
Example:
.. code-block:: python3
:caption: Example on using this filter:
@bot.message_handler(is_forwarded=True)
@bot.message_handler(is_forwarded=True)
# your function
"""
key = 'is_forwarded'
async def check(self, message):
return message.forward_from_chat is not None
"""
:meta private:
"""
return message.forward_date is not None
class IsReplyFilter(SimpleCustomFilter):
"""
Check whether message is a reply.
Example:
.. code-block:: python3
:caption: Example on using this filter:
@bot.message_handler(is_reply=True)
@bot.message_handler(is_reply=True)
# your function
"""
key = 'is_reply'
async def check(self, message):
"""
:meta private:
"""
if isinstance(message, types.CallbackQuery):
return message.message.reply_to_message is not None
return message.reply_to_message is not None
@ -238,14 +330,19 @@ class LanguageFilter(AdvancedCustomFilter):
"""
Check users language_code.
Example:
.. code-block:: python3
:caption: Example on using this filter:
@bot.message_handler(language_code=['ru'])
@bot.message_handler(language_code=['ru'])
# your function
"""
key = 'language_code'
async def check(self, message, text):
"""
:meta private:
"""
if type(text) is list:
return message.from_user.language_code in text
else:
@ -256,8 +353,11 @@ class IsAdminFilter(SimpleCustomFilter):
"""
Check whether the user is administrator / owner of the chat.
Example:
@bot.message_handler(chat_types=['supergroup'], is_chat_admin=True)
.. code-block:: python3
:caption: Example on using this filter:
@bot.message_handler(chat_types=['supergroup'], is_chat_admin=True)
# your function
"""
key = 'is_chat_admin'
@ -266,6 +366,12 @@ class IsAdminFilter(SimpleCustomFilter):
self._bot = bot
async def check(self, message):
"""
:meta private:
"""
if isinstance(message, types.CallbackQuery):
result = await self._bot.get_chat_member(message.message.chat.id, message.from_user.id)
return result.status ('creator', 'administrator')
result = await self._bot.get_chat_member(message.chat.id, message.from_user.id)
return result.status in ['creator', 'administrator']
@ -274,8 +380,11 @@ class StateFilter(AdvancedCustomFilter):
"""
Filter to check state.
Example:
@bot.message_handler(state=1)
.. code-block:: python3
:caption: Example on using this filter:
@bot.message_handler(state=1)
# your function
"""
def __init__(self, bot):
@ -284,6 +393,9 @@ class StateFilter(AdvancedCustomFilter):
key = 'state'
async def check(self, message, text):
"""
:meta private:
"""
if text == '*': return True
# needs to work with callbackquery
@ -307,8 +419,8 @@ class StateFilter(AdvancedCustomFilter):
elif isinstance(text, State):
text = text.name
if message.chat.type == 'group':
group_state = await self.bot.current_states.get_state(user_id, chat_id)
if message.chat.type in ['group', 'supergroup']:
group_state = await self.bot.current_states.get_state(chat_id, user_id)
if group_state == text:
return True
elif type(text) is list and group_state in text:
@ -316,7 +428,7 @@ class StateFilter(AdvancedCustomFilter):
else:
user_state = await self.bot.current_states.get_state(user_id, chat_id)
user_state = await self.bot.current_states.get_state(chat_id, user_id)
if user_state == text:
return True
elif type(text) is list and user_state in text:
@ -327,10 +439,16 @@ class IsDigitFilter(SimpleCustomFilter):
"""
Filter to check whether the string is made up of only digits.
Example:
@bot.message_handler(is_digit=True)
.. code-block:: python3
:caption: Example on using this filter:
@bot.message_handler(is_digit=True)
# your function
"""
key = 'is_digit'
async def check(self, message):
"""
:meta private:
"""
return message.text.isdigit()

View File

@ -1,9 +1,43 @@
"""
File with all middleware classes, states.
"""
class BaseMiddleware:
"""
Base class for middleware.
Your middlewares should be inherited from this class.
Set update_sensitive=True if you want to get different updates on
different functions. For example, if you want to handle pre_process for
message update, then you will have to create pre_process_message function, and
so on. Same applies to post_process.
.. code-block:: python
:caption: Example of class-based middlewares
class MyMiddleware(BaseMiddleware):
def __init__(self):
self.update_sensitive = True
self.update_types = ['message', 'edited_message']
async def pre_process_message(self, message, data):
# only message update here
pass
async def post_process_message(self, message, data, exception):
pass # only message update here for post_process
async def pre_process_edited_message(self, message, data):
# only edited_message update here
pass
async def post_process_edited_message(self, message, data, exception):
pass # only edited_message update here for post_process
"""
update_sensitive: bool = False
def __init__(self):
pass
@ -15,6 +49,14 @@ class BaseMiddleware:
class State:
"""
Class representing a state.
.. code-block:: python3
class MyStates(StatesGroup):
my_state = State() # returns my_state:State string.
"""
def __init__(self) -> None:
self.name = None
@ -23,12 +65,27 @@ class State:
class StatesGroup:
def __init_subclass__(cls) -> None:
"""
Class representing common states.
.. code-block:: python3
class MyStates(StatesGroup):
my_state = State() # returns my_state:State string.
"""
def __init_subclass__(cls) -> None:
state_list = []
for name, value in cls.__dict__.items():
if not name.startswith('__') and not callable(value) and isinstance(value, State):
# change value of that variable
value.name = ':'.join((cls.__name__, name))
value.group = cls
state_list.append(value)
cls._state_list = state_list
@property
def state_list(self):
return self._state_list
class SkipHandler:
@ -43,6 +100,7 @@ class SkipHandler:
def __init__(self) -> None:
pass
class CancelUpdate:
"""
Class for canceling updates.
@ -53,4 +111,27 @@ class CancelUpdate:
"""
def __init__(self) -> None:
pass
pass
class ContinueHandling:
"""
Class for continue updates in handlers.
Just return instance of this class
in handlers to continue process.
.. code-block:: python3
:caption: Example of using ContinueHandling
@bot.message_handler(commands=['start'])
async def start(message):
await bot.send_message(message.chat.id, 'Hello World!')
return ContinueHandling()
@bot.message_handler(commands=['start'])
async def start2(message):
await bot.send_message(message.chat.id, 'Hello World2!')
"""
def __init__(self) -> None:
pass

File diff suppressed because it is too large Load Diff

View File

@ -28,7 +28,7 @@ class StatePickleStorage(StateStorageBase):
"""
Create directory .save-handlers.
"""
dirs = self.file_path.rsplit('/', maxsplit=1)[0]
dirs, filename = os.path.split(self.file_path)
os.makedirs(dirs, exist_ok=True)
if not os.path.isfile(self.file_path):
with open(self.file_path,'wb') as file:

View File

@ -1,12 +1,16 @@
from telebot.asyncio_storage.base_storage import StateStorageBase, StateContext
import json
redis_installed = True
is_actual_aioredis = False
try:
import aioredis
except:
redis_installed = False
is_actual_aioredis = True
except ImportError:
try:
from redis import asyncio as aioredis
except ImportError:
redis_installed = False
class StateRedisStorage(StateStorageBase):
@ -20,10 +24,10 @@ class StateRedisStorage(StateStorageBase):
if not redis_installed:
raise ImportError('AioRedis is not installed. Install it via "pip install aioredis"')
aioredis_version = tuple(map(int, aioredis.__version__.split(".")[0]))
if aioredis_version < (2,):
raise ImportError('Invalid aioredis version. Aioredis version should be >= 2.0.0')
if is_actual_aioredis:
aioredis_version = tuple(map(int, aioredis.__version__.split(".")[0]))
if aioredis_version < (2,):
raise ImportError('Invalid aioredis version. Aioredis version should be >= 2.0.0')
self.redis = aioredis.Redis(host=host, port=port, db=db, password=password)
self.prefix = prefix
@ -167,6 +171,6 @@ class StateRedisStorage(StateStorageBase):
user_id = str(user_id)
if response:
if user_id in response:
response[user_id]['data'] = dict(data, **response[user_id]['data'])
response[user_id]['data'] = data
await self.set_record(chat_id, response)
return True

View File

@ -1,18 +1,55 @@
"""
Callback data factory's file.
"""
"""
Copyright (c) 2017-2018 Alex Root Junior
Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included in all copies
or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
OR OTHER DEALINGS IN THE SOFTWARE.
This file was added during the pull request. The maintainers overlooked that it was copied
"as is" from another project and they do not consider it as a right way to develop a project.
However, due to backward compatibility we had to leave this file in the project with the above
copyright added, as it is required by the original project license.
"""
import typing
class CallbackDataFilter:
"""
Filter for CallbackData.
"""
def __init__(self, factory, config: typing.Dict[str, str]):
self.config = config
self.factory = factory
def check(self, query):
def check(self, query) -> bool:
"""
Checks if query.data appropriates to specified config
:param query: telebot.types.CallbackQuery
:return: bool
:type query: telebot.types.CallbackQuery
:return: True if query.data appropriates to specified config
:rtype: bool
"""
try:
@ -108,7 +145,7 @@ class CallbackData:
"""
Generate filter
:param config: specified named parameters will be checked with CallbackQury.data
:param config: specified named parameters will be checked with CallbackQuery.data
:return: CallbackDataFilter class
"""

View File

@ -14,6 +14,17 @@ class SimpleCustomFilter(ABC):
Accepts only message, returns bool value, that is compared with given in handler.
Child classes should have .key property.
.. code-block:: python3
:caption: Example on creating a simple custom filter.
class ForwardFilter(SimpleCustomFilter):
# Check whether message was forwarded from channel or group.
key = 'is_forwarded'
def check(self, message):
return message.forward_date is not None
"""
key: str = None
@ -27,13 +38,23 @@ class SimpleCustomFilter(ABC):
class AdvancedCustomFilter(ABC):
"""
Simple Custom Filter base class.
Advanced Custom Filter base class.
Create child class with check() method.
Accepts two parameters, returns bool: True - filter passed, False - filter failed.
message: Message class
text: Filter value given in handler
Child classes should have .key property.
.. code-block:: python3
:caption: Example on creating an advanced custom filter.
class TextStartsFilter(AdvancedCustomFilter):
# Filter to check whether message starts with some text.
key = 'text_startswith'
def check(self, message, text):
return message.text.startswith(text)
"""
key: str = None
@ -50,6 +71,25 @@ class TextFilter:
Advanced text filter to check (types.Message, types.CallbackQuery, types.InlineQuery, types.Poll)
example of usage is in examples/custom_filters/advanced_text_filter.py
:param equals: string, True if object's text is equal to passed string
:type equals: :obj:`str`
:param contains: list[str] or tuple[str], True if any string element of iterable is in text
:type contains: list[str] or tuple[str]
:param starts_with: string, True if object's text starts with passed string
:type starts_with: :obj:`str`
:param ends_with: string, True if object's text starts with passed string
:type ends_with: :obj:`str`
:param ignore_case: bool (default False), case insensitive
:type ignore_case: :obj:`bool`
:raises ValueError: if incorrect value for a parameter was supplied
:return: None
"""
def __init__(self,
@ -58,15 +98,27 @@ class TextFilter:
starts_with: Optional[Union[str, list, tuple]] = None,
ends_with: Optional[Union[str, list, tuple]] = None,
ignore_case: bool = False):
"""
:param equals: string, True if object's text is equal to passed string
:param contains: list[str] or tuple[str], True if any string element of iterable is in text
:param starts_with: string, True if object's text starts with passed string
:param ends_with: string, True if object's text starts with passed string
:param ignore_case: bool (default False), case insensitive
"""
:type equals: :obj:`str`
:param contains: list[str] or tuple[str], True if any string element of iterable is in text
:type contains: list[str] or tuple[str]
:param starts_with: string, True if object's text starts with passed string
:type starts_with: :obj:`str`
:param ends_with: string, True if object's text starts with passed string
:type ends_with: :obj:`str`
:param ignore_case: bool (default False), case insensitive
:type ignore_case: :obj:`bool`
:raises ValueError: if incorrect value for a parameter was supplied
:return: None
"""
to_check = sum((pattern is not None for pattern in (equals, contains, starts_with, ends_with)))
if to_check == 0:
raise ValueError('None of the check modes was specified')
@ -89,6 +141,9 @@ class TextFilter:
return iterable
def check(self, obj: Union[types.Message, types.CallbackQuery, types.InlineQuery, types.Poll]):
"""
:meta private:
"""
if isinstance(obj, types.Poll):
text = obj.question
@ -142,15 +197,20 @@ class TextFilter:
class TextMatchFilter(AdvancedCustomFilter):
"""
Filter to check Text message.
key: text
Example:
@bot.message_handler(text=['account'])
.. code-block:: python3
:caption: Example on using this filter:
@bot.message_handler(text=['account'])
# your function
"""
key = 'text'
def check(self, message, text):
"""
:meta private:
"""
if isinstance(text, TextFilter):
return text.check(message)
elif type(text) is list:
@ -164,14 +224,21 @@ class TextContainsFilter(AdvancedCustomFilter):
Filter to check Text message.
key: text
Example:
# Will respond if any message.text contains word 'account'
@bot.message_handler(text_contains=['account'])
.. code-block:: python3
:caption: Example on using this filter:
# Will respond if any message.text contains word 'account'
@bot.message_handler(text_contains=['account'])
# your function
"""
key = 'text_contains'
def check(self, message, text):
"""
:meta private:
"""
if not isinstance(text, str) and not isinstance(text, list) and not isinstance(text, tuple):
raise ValueError("Incorrect text_contains value")
elif isinstance(text, str):
@ -186,14 +253,20 @@ class TextStartsFilter(AdvancedCustomFilter):
"""
Filter to check whether message starts with some text.
Example:
# Will work if message.text starts with 'Sir'.
@bot.message_handler(text_startswith='Sir')
.. code-block:: python3
:caption: Example on using this filter:
# Will work if message.text starts with 'sir'.
@bot.message_handler(text_startswith='sir')
# your function
"""
key = 'text_startswith'
def check(self, message, text):
"""
:meta private:
"""
return message.text.startswith(text)
@ -201,13 +274,21 @@ class ChatFilter(AdvancedCustomFilter):
"""
Check whether chat_id corresponds to given chat_id.
Example:
@bot.message_handler(chat_id=[99999])
.. code-block:: python3
:caption: Example on using this filter:
@bot.message_handler(chat_id=[99999])
# your function
"""
key = 'chat_id'
def check(self, message, text):
"""
:meta private:
"""
if isinstance(message, types.CallbackQuery):
return message.message.chat.id in text
return message.chat.id in text
@ -215,29 +296,41 @@ class ForwardFilter(SimpleCustomFilter):
"""
Check whether message was forwarded from channel or group.
Example:
.. code-block:: python3
:caption: Example on using this filter:
@bot.message_handler(is_forwarded=True)
@bot.message_handler(is_forwarded=True)
# your function
"""
key = 'is_forwarded'
def check(self, message):
return message.forward_from_chat is not None
"""
:meta private:
"""
return message.forward_date is not None
class IsReplyFilter(SimpleCustomFilter):
"""
Check whether message is a reply.
Example:
.. code-block:: python3
:caption: Example on using this filter:
@bot.message_handler(is_reply=True)
@bot.message_handler(is_reply=True)
# your function
"""
key = 'is_reply'
def check(self, message):
"""
:meta private:
"""
if isinstance(message, types.CallbackQuery):
return message.message.reply_to_message is not None
return message.reply_to_message is not None
@ -245,14 +338,19 @@ class LanguageFilter(AdvancedCustomFilter):
"""
Check users language_code.
Example:
.. code-block:: python3
:caption: Example on using this filter:
@bot.message_handler(language_code=['ru'])
@bot.message_handler(language_code=['ru'])
# your function
"""
key = 'language_code'
def check(self, message, text):
"""
:meta private:
"""
if type(text) is list:
return message.from_user.language_code in text
else:
@ -263,8 +361,11 @@ class IsAdminFilter(SimpleCustomFilter):
"""
Check whether the user is administrator / owner of the chat.
Example:
@bot.message_handler(chat_types=['supergroup'], is_chat_admin=True)
.. code-block:: python3
:caption: Example on using this filter:
@bot.message_handler(chat_types=['supergroup'], is_chat_admin=True)
# your function
"""
key = 'is_chat_admin'
@ -273,6 +374,11 @@ class IsAdminFilter(SimpleCustomFilter):
self._bot = bot
def check(self, message):
"""
:meta private:
"""
if isinstance(message, types.CallbackQuery):
return self._bot.get_chat_member(message.message.chat.id, message.from_user.id).status in ['creator', 'administrator']
return self._bot.get_chat_member(message.chat.id, message.from_user.id).status in ['creator', 'administrator']
@ -280,8 +386,11 @@ class StateFilter(AdvancedCustomFilter):
"""
Filter to check state.
Example:
@bot.message_handler(state=1)
.. code-block:: python3
:caption: Example on using this filter:
@bot.message_handler(state=1)
# your function
"""
def __init__(self, bot):
@ -290,6 +399,9 @@ class StateFilter(AdvancedCustomFilter):
key = 'state'
def check(self, message, text):
"""
:meta private:
"""
if text == '*': return True
# needs to work with callbackquery
@ -315,8 +427,8 @@ class StateFilter(AdvancedCustomFilter):
elif isinstance(text, State):
text = text.name
if message.chat.type == 'group':
group_state = self.bot.current_states.get_state(user_id, chat_id)
if message.chat.type in ['group', 'supergroup']:
group_state = self.bot.current_states.get_state(chat_id, user_id)
if group_state == text:
return True
elif type(text) is list and group_state in text:
@ -324,7 +436,7 @@ class StateFilter(AdvancedCustomFilter):
else:
user_state = self.bot.current_states.get_state(user_id, chat_id)
user_state = self.bot.current_states.get_state(chat_id, user_id)
if user_state == text:
return True
elif type(text) is list and user_state in text:
@ -335,10 +447,16 @@ class IsDigitFilter(SimpleCustomFilter):
"""
Filter to check whether the string is made up of only digits.
Example:
@bot.message_handler(is_digit=True)
.. code-block:: python3
:caption: Example on using this filter:
@bot.message_handler(is_digit=True)
# your function
"""
key = 'is_digit'
def check(self, message):
"""
:meta private:
"""
return message.text.isdigit()

3
telebot/ext/__init__.py Normal file
View File

@ -0,0 +1,3 @@
"""
A folder with asynchronous and synchronous extensions.
"""

View File

@ -0,0 +1,10 @@
"""
A folder with all the async extensions.
"""
from .webhooks import AsyncWebhookListener
__all__ = [
"AsyncWebhookListener"
]

123
telebot/ext/aio/webhooks.py Normal file
View File

@ -0,0 +1,123 @@
"""
This file is used by AsyncTeleBot.run_webhooks() function.
Fastapi and starlette(0.20.2+) libraries are required to run this script.
"""
# modules required for running this script
fastapi_installed = True
try:
import fastapi
from fastapi.responses import JSONResponse
from fastapi.requests import Request
from uvicorn import Server, Config
except ImportError:
fastapi_installed = False
import asyncio
from telebot.types import Update
from typing import Optional
class AsyncWebhookListener:
def __init__(self, bot,
secret_token: str,
host: Optional[str]="127.0.0.1",
port: Optional[int]=443,
ssl_context: Optional[tuple]=None,
url_path: Optional[str]=None,
) -> None:
"""
Aynchronous implementation of webhook listener
for asynchronous version of telebot.
Not supposed to be used manually by user.
Use AsyncTeleBot.run_webhooks() instead.
:param bot: AsyncTeleBot instance.
:type bot: telebot.async_telebot.AsyncTeleBot
:param secret_token: Telegram secret token
:type secret_token: str
:param host: Webhook host
:type host: str
:param port: Webhook port
:type port: int
:param ssl_context: SSL context
:type ssl_context: tuple
:param url_path: Webhook url path
:type url_path: str
:raises ImportError: If FastAPI or uvicorn is not installed.
:raises ImportError: If Starlette version is too old.
:return: None
"""
self._check_dependencies()
self.app = fastapi.FastAPI()
self._secret_token = secret_token
self._bot = bot
self._port = port
self._host = host
self._ssl_context = ssl_context
self._url_path = url_path
self._prepare_endpoint_urls()
def _check_dependencies(self):
if not fastapi_installed:
raise ImportError('Fastapi or uvicorn is not installed. Please install it via pip.')
import starlette
if starlette.__version__ < '0.20.2':
raise ImportError('Starlette version is too old. Please upgrade it: `pip3 install starlette -U`')
return
def _prepare_endpoint_urls(self):
self.app.add_api_route(endpoint=self.process_update,path= self._url_path, methods=["POST"])
async def process_update(self, request: Request, update: dict):
"""
Processes updates.
:meta private:
"""
# header containsX-Telegram-Bot-Api-Secret-Token
if request.headers.get('X-Telegram-Bot-Api-Secret-Token') != self._secret_token:
# secret token didn't match
return JSONResponse(status_code=403, content={"error": "Forbidden"})
if request.headers.get('content-type') == 'application/json':
json_string = update
asyncio.create_task(self._bot.process_new_updates([Update.de_json(json_string)]))
return JSONResponse('', status_code=200)
return JSONResponse(status_code=403, content={"error": "Forbidden"})
async def run_app(self):
"""
Run app with the given parameters to init.
Not supposed to be used manually by user.
:return: None
"""
config = Config(app=self.app,
host=self._host,
port=self._port,
ssl_certfile=self._ssl_context[0],
ssl_keyfile=self._ssl_context[1]
)
server = Server(config)
await server.serve()
await self._bot.close_session()

31
telebot/ext/reloader.py Normal file
View File

@ -0,0 +1,31 @@
from watchdog.events import FileSystemEventHandler
from watchdog.events import FileSystemEvent
import psutil
import os
import sys
import logging
logger = logging.getLogger('TeleBot')
class EventHandler(FileSystemEventHandler):
def on_any_event(self, event: FileSystemEvent):
logger.info('* Detected changes in: %s, reloading', (event.src_path))
restart_file()
def restart_file():
try:
p = psutil.Process(os.getpid())
for handler in p.open_files() + p.connections():
os.close(handler.fd)
except OSError:
pass
except Exception as e:
logger.error(e)
python = sys.executable
if os.name == 'nt':
os.execv(sys.executable, ['python'] + sys.argv)
else:
os.execl(python, python, *sys.argv)

View File

@ -0,0 +1,10 @@
"""
A folder with all the sync extensions.
"""
from .webhooks import SyncWebhookListener
__all__ = [
"SyncWebhookListener"
]

View File

@ -0,0 +1,116 @@
"""
This file is used by TeleBot.run_webhooks() function.
Fastapi is required to run this script.
"""
# modules required for running this script
fastapi_installed = True
try:
import fastapi
from fastapi.responses import JSONResponse
from fastapi.requests import Request
import uvicorn
except ImportError:
fastapi_installed = False
from telebot.types import Update
from typing import Optional
class SyncWebhookListener:
def __init__(self, bot,
secret_token: str,
host: Optional[str]="127.0.0.1",
port: Optional[int]=443,
ssl_context: Optional[tuple]=None,
url_path: Optional[str]=None,
) -> None:
"""
Synchronous implementation of webhook listener
for synchronous version of telebot.
Not supposed to be used manually by user.
Use TeleBot.run_webhooks() instead.
:param bot: TeleBot instance.
:type bot: telebot.TeleBot
:param secret_token: Telegram secret token
:type secret_token: str
:param host: Webhook host
:type host: str
:param port: Webhook port
:type port: int
:param ssl_context: SSL context
:type ssl_context: tuple
:param url_path: Webhook url path
:type url_path: str
:raises ImportError: If FastAPI or uvicorn is not installed.
:raises ImportError: If Starlette version is too old.
:return: None
"""
self._check_dependencies()
self.app = fastapi.FastAPI()
self._secret_token = secret_token
self._bot = bot
self._port = port
self._host = host
self._ssl_context = ssl_context
self._url_path = url_path
self._prepare_endpoint_urls()
@staticmethod
def _check_dependencies():
if not fastapi_installed:
raise ImportError('Fastapi or uvicorn is not installed. Please install it via pip.')
import starlette
if starlette.__version__ < '0.20.2':
raise ImportError('Starlette version is too old. Please upgrade it: `pip3 install starlette -U`')
return
def _prepare_endpoint_urls(self):
self.app.add_api_route(endpoint=self.process_update,path= self._url_path, methods=["POST"])
def process_update(self, request: Request, update: dict):
"""
Processes updates.
:meta private:
"""
# header containsX-Telegram-Bot-Api-Secret-Token
if request.headers.get('X-Telegram-Bot-Api-Secret-Token') != self._secret_token:
# secret token didn't match
return JSONResponse(status_code=403, content={"error": "Forbidden"})
if request.headers.get('content-type') == 'application/json':
self._bot.process_new_updates([Update.de_json(update)])
return JSONResponse('', status_code=200)
return JSONResponse(status_code=403, content={"error": "Forbidden"})
def run_app(self):
"""
Run app with the given parameters to init.
Not supposed to be used manually by user.
:return: None
"""
uvicorn.run(app=self.app,
host=self._host,
port=self._port,
ssl_certfile=self._ssl_context[0],
ssl_keyfile=self._ssl_context[1]
)

View File

@ -5,14 +5,17 @@ Markdown & HTML formatting functions.
"""
import html
import re
from typing import Optional
def format_text(*args, separator="\n"):
"""
Formats a list of strings into a single string.
.. code:: python
.. code:: python3
format_text( # just an example
mbold('Hello'),
@ -20,7 +23,13 @@ def format_text(*args, separator="\n"):
)
:param args: Strings to format.
:type args: :obj:`str`
:param separator: The separator to use between each string.
:type separator: :obj:`str`
:return: The formatted string.
:rtype: :obj:`str`
"""
return separator.join(args)
@ -31,6 +40,10 @@ def escape_html(content: str) -> str:
Escapes HTML characters in a string of HTML.
:param content: The string of HTML to escape.
:type content: :obj:`str`
:return: The escaped string.
:rtype: :obj:`str`
"""
return html.escape(content)
@ -39,164 +52,263 @@ def escape_markdown(content: str) -> str:
"""
Escapes Markdown characters in a string of Markdown.
Credits: simonsmh
Credits to: simonsmh
:param content: The string of Markdown to escape.
:type content: :obj:`str`
:return: The escaped string.
:rtype: :obj:`str`
"""
parse = re.sub(r"([_*\[\]()~`>\#\+\-=|\.!])", r"\\\1", content)
reparse = re.sub(r"\\\\([_*\[\]()~`>\#\+\-=|\.!])", r"\1", parse)
parse = re.sub(r"([_*\[\]()~`>\#\+\-=|\.!\{\}\\])", r"\\\1", content)
reparse = re.sub(r"\\\\([_*\[\]()~`>\#\+\-=|\.!\{\}\\])", r"\1", parse)
return reparse
def mbold(content: str, escape: bool=True) -> str:
def mbold(content: str, escape: Optional[bool]=True) -> str:
"""
Returns a Markdown-formatted bold string.
:param content: The string to bold.
:param escape: True if you need to escape special characters.
:type content: :obj:`str`
:param escape: True if you need to escape special characters. Defaults to True.
:type escape: :obj:`bool`
:return: The formatted string.
:rtype: :obj:`str`
"""
return '*{}*'.format(escape_markdown(content) if escape else content)
def hbold(content: str, escape: bool=True) -> str:
def hbold(content: str, escape: Optional[bool]=True) -> str:
"""
Returns an HTML-formatted bold string.
:param content: The string to bold.
:param escape: True if you need to escape special characters.
:type content: :obj:`str`
:param escape: True if you need to escape special characters. Defaults to True.
:type escape: :obj:`bool`
:return: The formatted string.
:rtype: :obj:`str`
"""
return '<b>{}</b>'.format(escape_html(content) if escape else content)
def mitalic(content: str, escape: bool=True) -> str:
def mitalic(content: str, escape: Optional[bool]=True) -> str:
"""
Returns a Markdown-formatted italic string.
:param content: The string to italicize.
:param escape: True if you need to escape special characters.
:type content: :obj:`str`
:param escape: True if you need to escape special characters. Defaults to True.
:type escape: :obj:`bool`
:return: The formatted string.
:rtype: :obj:`str`
"""
return '_{}_\r'.format(escape_markdown(content) if escape else content)
def hitalic(content: str, escape: bool=True) -> str:
def hitalic(content: str, escape: Optional[bool]=True) -> str:
"""
Returns an HTML-formatted italic string.
:param content: The string to italicize.
:param escape: True if you need to escape special characters.
:type content: :obj:`str`
:param escape: True if you need to escape special characters. Defaults to True.
:type escape: :obj:`bool`
:return: The formatted string.
:rtype: :obj:`str`
"""
return '<i>{}</i>'.format(escape_html(content) if escape else content)
def munderline(content: str, escape: bool=True) -> str:
def munderline(content: str, escape: Optional[bool]=True) -> str:
"""
Returns a Markdown-formatted underline string.
:param content: The string to underline.
:param escape: True if you need to escape special characters.
:type content: :obj:`str`
:param escape: True if you need to escape special characters. Defaults to True.
:type escape: :obj:`bool`
:return: The formatted string.
:rtype: :obj:`str`
"""
return '__{}__'.format(escape_markdown(content) if escape else content)
def hunderline(content: str, escape: bool=True) -> str:
def hunderline(content: str, escape: Optional[bool]=True) -> str:
"""
Returns an HTML-formatted underline string.
:param content: The string to underline.
:param escape: True if you need to escape special characters.
:type content: :obj:`str`
:param escape: True if you need to escape special characters. Defaults to True.
:type escape: :obj:`bool`
:return: The formatted string.
:rtype: :obj:`str`
"""
return '<u>{}</u>'.format(escape_html(content) if escape else content)
def mstrikethrough(content: str, escape: bool=True) -> str:
def mstrikethrough(content: str, escape: Optional[bool]=True) -> str:
"""
Returns a Markdown-formatted strikethrough string.
:param content: The string to strikethrough.
:param escape: True if you need to escape special characters.
:type content: :obj:`str`
:param escape: True if you need to escape special characters. Defaults to True.
:type escape: :obj:`bool`
:return: The formatted string.
:rtype: :obj:`str`
"""
return '~{}~'.format(escape_markdown(content) if escape else content)
def hstrikethrough(content: str, escape: bool=True) -> str:
def hstrikethrough(content: str, escape: Optional[bool]=True) -> str:
"""
Returns an HTML-formatted strikethrough string.
:param content: The string to strikethrough.
:param escape: True if you need to escape special characters.
:type content: :obj:`str`
:param escape: True if you need to escape special characters. Defaults to True.
:type escape: :obj:`bool`
:return: The formatted string.
:rtype: :obj:`str`
"""
return '<s>{}</s>'.format(escape_html(content) if escape else content)
def mspoiler(content: str, escape: bool=True) -> str:
def mspoiler(content: str, escape: Optional[bool]=True) -> str:
"""
Returns a Markdown-formatted spoiler string.
:param content: The string to spoiler.
:param escape: True if you need to escape special characters.
:type content: :obj:`str`
:param escape: True if you need to escape special characters. Defaults to True.
:type escape: :obj:`bool`
:return: The formatted string.
:rtype: :obj:`str`
"""
return '||{}||'.format(escape_markdown(content) if escape else content)
def hspoiler(content: str, escape: bool=True) -> str:
def hspoiler(content: str, escape: Optional[bool]=True) -> str:
"""
Returns an HTML-formatted spoiler string.
:param content: The string to spoiler.
:param escape: True if you need to escape special characters.
:type content: :obj:`str`
:param escape: True if you need to escape special characters. Defaults to True.
:type escape: :obj:`bool`
:return: The formatted string.
:rtype: :obj:`str`
"""
return '<tg-spoiler>{}</tg-spoiler>'.format(escape_html(content) if escape else content)
def mlink(content: str, url: str, escape: bool=True) -> str:
def mlink(content: str, url: str, escape: Optional[bool]=True) -> str:
"""
Returns a Markdown-formatted link string.
:param content: The string to link.
:type content: :obj:`str`
:param url: The URL to link to.
:param escape: True if you need to escape special characters.
:type url: str
:param escape: True if you need to escape special characters. Defaults to True.
:type escape: :obj:`bool`
:return: The formatted string.
:rtype: :obj:`str`
"""
return '[{}]({})'.format(escape_markdown(content), escape_markdown(url) if escape else content)
def hlink(content: str, url: str, escape: bool=True) -> str:
def hlink(content: str, url: str, escape: Optional[bool]=True) -> str:
"""
Returns an HTML-formatted link string.
:param content: The string to link.
:type content: :obj:`str`
:param url: The URL to link to.
:param escape: True if you need to escape special characters.
:type url: :obj:`str`
:param escape: True if you need to escape special characters. Defaults to True.
:type escape: :obj:`bool`
:return: The formatted string.
:rtype: :obj:`str`
"""
return '<a href="{}">{}</a>'.format(escape_html(url), escape_html(content) if escape else content)
def mcode(content: str, language: str="", escape: bool=True) -> str:
def mcode(content: str, language: str="", escape: Optional[bool]=True) -> str:
"""
Returns a Markdown-formatted code string.
:param content: The string to code.
:param escape: True if you need to escape special characters.
:type content: :obj:`str`
:param escape: True if you need to escape special characters. Defaults to True.
:type escape: :obj:`bool`
:return: The formatted string.
:rtype: :obj:`str`
"""
return '```{}\n{}```'.format(language, escape_markdown(content) if escape else content)
def hcode(content: str, escape: bool=True) -> str:
def hcode(content: str, escape: Optional[bool]=True) -> str:
"""
Returns an HTML-formatted code string.
:param content: The string to code.
:param escape: True if you need to escape special characters.
:type content: :obj:`str`
:param escape: True if you need to escape special characters. Defaults to True.
:type escape: :obj:`bool`
:return: The formatted string.
:rtype: :obj:`str`
"""
return '<code>{}</code>'.format(escape_html(content) if escape else content)
def hpre(content: str, escape: bool=True, language: str="") -> str:
def hpre(content: str, escape: Optional[bool]=True, language: str="") -> str:
"""
Returns an HTML-formatted preformatted string.
:param content: The string to preformatted.
:param escape: True if you need to escape special characters.
:type content: :obj:`str`
:param escape: True if you need to escape special characters. Defaults to True.
:type escape: :obj:`bool`
:return: The formatted string.
:rtype: :obj:`str`
"""
return '<pre><code class="{}">{}</code></pre>'.format(language, escape_html(content) if escape else content)
@ -205,7 +317,10 @@ def hide_link(url: str) -> str:
"""
Hide url of an image.
:param url:
:return: str
:param url: The url of the image.
:type url: :obj:`str`
:return: The hidden url.
:rtype: :obj:`str`
"""
return f'<a href="{url}">&#8288;</a>'
return f'<a href="{url}">&#8288;</a>'

View File

@ -12,7 +12,9 @@ except:
class HandlerBackend(object):
"""
Class for saving (next step|reply) handlers
Class for saving (next step|reply) handlers.
:meta private:
"""
def __init__(self, handlers=None):
if handlers is None:
@ -30,6 +32,9 @@ class HandlerBackend(object):
class MemoryHandlerBackend(HandlerBackend):
"""
:meta private:
"""
def register_handler(self, handler_group_id, handler):
if handler_group_id in self.handlers:
self.handlers[handler_group_id].append(handler)
@ -47,6 +52,9 @@ class MemoryHandlerBackend(HandlerBackend):
class FileHandlerBackend(HandlerBackend):
"""
:meta private:
"""
def __init__(self, handlers=None, filename='./.handler-saves/handlers.save', delay=120):
super(FileHandlerBackend, self).__init__(handlers)
self.filename = filename
@ -119,6 +127,9 @@ class FileHandlerBackend(HandlerBackend):
class RedisHandlerBackend(HandlerBackend):
"""
:meta private:
"""
def __init__(self, handlers=None, host='localhost', port=6379, db=0, prefix='telebot', password=None):
super(RedisHandlerBackend, self).__init__(handlers)
if not redis_installed:
@ -150,27 +161,83 @@ class RedisHandlerBackend(HandlerBackend):
class State:
"""
Class representing a state.
.. code-block:: python3
class MyStates(StatesGroup):
my_state = State() # returns my_state:State string.
"""
def __init__(self) -> None:
self.name = None
def __str__(self) -> str:
return self.name
class StatesGroup:
"""
Class representing common states.
.. code-block:: python3
class MyStates(StatesGroup):
my_state = State() # returns my_state:State string.
"""
def __init_subclass__(cls) -> None:
state_list = []
for name, value in cls.__dict__.items():
if not name.startswith('__') and not callable(value) and isinstance(value, State):
# change value of that variable
value.name = ':'.join((cls.__name__, name))
value.group = cls
state_list.append(value)
cls._state_list = state_list
@property
def state_list(self):
return self._state_list
class BaseMiddleware:
"""
Base class for middleware.
Your middlewares should be inherited from this class.
Set update_sensitive=True if you want to get different updates on
different functions. For example, if you want to handle pre_process for
message update, then you will have to create pre_process_message function, and
so on. Same applies to post_process.
.. note::
If you want to use middleware, you have to set use_class_middlewares=True in your
TeleBot instance.
.. code-block:: python3
:caption: Example of class-based middlewares.
class MyMiddleware(BaseMiddleware):
def __init__(self):
self.update_sensitive = True
self.update_types = ['message', 'edited_message']
def pre_process_message(self, message, data):
# only message update here
pass
def post_process_message(self, message, data, exception):
pass # only message update here for post_process
def pre_process_edited_message(self, message, data):
# only edited_message update here
pass
def post_process_edited_message(self, message, data, exception):
pass # only edited_message update here for post_process
"""
update_sensitive: bool = False
def __init__(self):
pass
@ -189,10 +256,10 @@ class SkipHandler:
Update will go to post_process,
but will skip execution of handler.
"""
def __init__(self) -> None:
pass
class CancelUpdate:
"""
Class for canceling updates.
@ -201,6 +268,28 @@ class CancelUpdate:
Update will skip handler and execution
of post_process in middlewares.
"""
def __init__(self) -> None:
pass
pass
class ContinueHandling:
"""
Class for continue updates in handlers.
Just return instance of this class
in handlers to continue process.
.. code-block:: python3
:caption: Example of using ContinueHandling
@bot.message_handler(commands=['start'])
def start(message):
bot.send_message(message.chat.id, 'Hello World!')
return ContinueHandling()
@bot.message_handler(commands=['start'])
def start2(message):
bot.send_message(message.chat.id, 'Hello World2!')
"""
def __init__(self) -> None:
pass

84
telebot/service_utils.py Normal file
View File

@ -0,0 +1,84 @@
import random
import string
from io import BytesIO
try:
# noinspection PyPackageRequirements
from PIL import Image
pil_imported = True
except ImportError:
pil_imported = False
def is_string(var) -> bool:
"""
Returns True if the given object is a string.
"""
return isinstance(var, str)
def is_dict(var) -> bool:
"""
Returns True if the given object is a dictionary.
:param var: object to be checked
:type var: :obj:`object`
:return: True if the given object is a dictionary.
:rtype: :obj:`bool`
"""
return isinstance(var, dict)
def is_bytes(var) -> bool:
"""
Returns True if the given object is a bytes object.
:param var: object to be checked
:type var: :obj:`object`
:return: True if the given object is a bytes object.
:rtype: :obj:`bool`
"""
return isinstance(var, bytes)
def is_pil_image(var) -> bool:
"""
Returns True if the given object is a PIL.Image.Image object.
:param var: object to be checked
:type var: :obj:`object`
:return: True if the given object is a PIL.Image.Image object.
:rtype: :obj:`bool`
"""
return pil_imported and isinstance(var, Image.Image)
def pil_image_to_file(image, extension='JPEG', quality='web_low'):
if pil_imported:
photoBuffer = BytesIO()
image.convert('RGB').save(photoBuffer, extension, quality=quality)
photoBuffer.seek(0)
return photoBuffer
else:
raise RuntimeError('PIL module is not imported')
def chunks(lst, n):
"""Yield successive n-sized chunks from lst."""
# https://stackoverflow.com/a/312464/9935473
for i in range(0, len(lst), n):
yield lst[i:i + n]
def generate_random_token() -> str:
"""
Generates a random token consisting of letters and digits, 16 characters long.
:return: a random token
:rtype: :obj:`str`
"""
return ''.join(random.sample(string.ascii_letters, 16))

View File

@ -41,7 +41,10 @@ class StateStorageBase:
def get_state(self, chat_id, user_id):
raise NotImplementedError
def get_interactive_data(self, chat_id, user_id):
raise NotImplementedError
def save(self, chat_id, user_id, data):
raise NotImplementedError

View File

@ -3,6 +3,7 @@ from telebot.storage.base_storage import StateStorageBase, StateContext
class StateMemoryStorage(StateStorageBase):
def __init__(self) -> None:
super().__init__()
self.data = {}
#
# {chat_id: {user_id: {'state': None, 'data': {}}, ...}, ...}

View File

@ -5,8 +5,8 @@ import pickle
class StatePickleStorage(StateStorageBase):
# noinspection PyMissingConstructor
def __init__(self, file_path="./.state-save/states.pkl") -> None:
super().__init__()
self.file_path = file_path
self.create_dir()
self.data = self.read()
@ -34,7 +34,7 @@ class StatePickleStorage(StateStorageBase):
"""
Create directory .save-handlers.
"""
dirs = self.file_path.rsplit('/', maxsplit=1)[0]
dirs, filename = os.path.split(self.file_path)
os.makedirs(dirs, exist_ok=True)
if not os.path.isfile(self.file_path):
with open(self.file_path,'wb') as file:

View File

@ -16,6 +16,7 @@ class StateRedisStorage(StateStorageBase):
TeleBot(storage=StateRedisStorage())
"""
def __init__(self, host='localhost', port=6379, db=0, password=None, prefix='telebot_'):
super().__init__()
self.redis = ConnectionPool(host=host, port=port, db=db, password=password)
#self.con = Redis(connection_pool=self.redis) -> use this when necessary
#
@ -173,7 +174,7 @@ class StateRedisStorage(StateStorageBase):
user_id = str(user_id)
if response:
if user_id in response:
response[user_id]['data'] = dict(data, **response[user_id]['data'])
response[user_id]['data'] = data
self.set_record(chat_id, response)
return True

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,9 @@
# -*- coding: utf-8 -*-
import random
import re
import string
import threading
import traceback
from typing import Any, Callable, List, Dict, Optional, Union
import hmac
import json
from hashlib import sha256
from urllib.parse import parse_qsl
@ -15,47 +12,47 @@ import queue as Queue
import logging
from telebot import types
from telebot.service_utils import is_pil_image, is_dict, is_string, is_bytes, chunks, generate_random_token, pil_image_to_file
try:
import ujson as json
except ImportError:
import json
try:
# noinspection PyPackageRequirements
from PIL import Image
from io import BytesIO
pil_imported = True
except:
pil_imported = False
MAX_MESSAGE_LENGTH = 4096
logger = logging.getLogger('TeleBot')
thread_local = threading.local()
#: Contains all media content types.
content_type_media = [
'text', 'audio', 'animation', 'document', 'photo', 'sticker', 'video', 'video_note', 'voice', 'contact', 'dice', 'poll',
'venue', 'location'
'text', 'audio', 'document', 'animation', 'game', 'photo', 'sticker', 'video', 'video_note', 'voice', 'contact',
'location', 'venue', 'dice', 'invoice', 'successful_payment', 'connected_website', 'poll', 'passport_data',
'web_app_data',
]
#: Contains all service content types such as `User joined the group`.
content_type_service = [
'new_chat_members', 'left_chat_member', 'new_chat_title', 'new_chat_photo', 'delete_chat_photo', 'group_chat_created',
'supergroup_chat_created', 'channel_chat_created', 'migrate_to_chat_id', 'migrate_from_chat_id', 'pinned_message',
'proximity_alert_triggered', 'video_chat_scheduled', 'video_chat_started', 'video_chat_ended',
'video_chat_participants_invited', 'message_auto_delete_timer_changed'
'new_chat_members', 'left_chat_member', 'new_chat_title', 'new_chat_photo', 'delete_chat_photo',
'group_chat_created', 'supergroup_chat_created', 'channel_chat_created', 'migrate_to_chat_id',
'migrate_from_chat_id', 'pinned_message', 'proximity_alert_triggered', 'video_chat_scheduled', 'video_chat_started',
'video_chat_ended', 'video_chat_participants_invited', 'message_auto_delete_timer_changed', 'forum_topic_created',
'forum_topic_closed', 'forum_topic_reopened', 'user_shared', 'chat_shared',
]
#: All update types, should be used for allowed_updates parameter in polling.
update_types = [
"update_id", "message", "edited_message", "channel_post", "edited_channel_post", "inline_query",
"chosen_inline_result", "callback_query", "shipping_query", "pre_checkout_query", "poll", "poll_answer",
"my_chat_member", "chat_member", "chat_join_request"
"message", "edited_message", "channel_post", "edited_channel_post", "inline_query", "chosen_inline_result",
"callback_query", "shipping_query", "pre_checkout_query", "poll", "poll_answer", "my_chat_member", "chat_member",
"chat_join_request",
]
class WorkerThread(threading.Thread):
"""
:meta private:
"""
count = 0
def __init__(self, exception_callback=None, queue=None, name=None):
@ -119,6 +116,9 @@ class WorkerThread(threading.Thread):
class ThreadPool:
"""
:meta private:
"""
def __init__(self, telebot, num_threads=2):
self.telebot = telebot
@ -153,10 +153,15 @@ class ThreadPool:
for worker in self.workers:
worker.stop()
for worker in self.workers:
worker.join()
if worker != threading.current_thread():
worker.join()
class AsyncTask:
"""
:meta private:
"""
def __init__(self, target, *args, **kwargs):
self.target = target
self.args = args
@ -183,7 +188,11 @@ class AsyncTask:
class CustomRequestResponse():
def __init__(self, json_text, status_code = 200, reason = ""):
"""
:meta private:
"""
def __init__(self, json_text, status_code=200, reason=""):
self.status_code = status_code
self.text = json_text
self.reason = reason
@ -193,6 +202,10 @@ class CustomRequestResponse():
def async_dec():
"""
:meta private:
"""
def decorator(fn):
def wrapper(*args, **kwargs):
return AsyncTask(fn, *args, **kwargs)
@ -202,39 +215,15 @@ def async_dec():
return decorator
def is_string(var):
return isinstance(var, str)
def is_dict(var):
return isinstance(var, dict)
def is_bytes(var):
return isinstance(var, bytes)
def is_pil_image(var):
return pil_imported and isinstance(var, Image.Image)
def pil_image_to_file(image, extension='JPEG', quality='web_low'):
if pil_imported:
photoBuffer = BytesIO()
image.convert('RGB').save(photoBuffer, extension, quality=quality)
photoBuffer.seek(0)
return photoBuffer
else:
raise RuntimeError('PIL module is not imported')
def is_command(text: str) -> bool:
r"""
Checks if `text` is a command. Telegram chat commands start with the '/' character.
:param text: Text to check.
:type text: :obj:`str`
:return: True if `text` is a command, else False.
:rtype: :obj:`bool`
"""
if text is None: return False
return text.startswith('/')
@ -245,35 +234,78 @@ def extract_command(text: str) -> Union[str, None]:
Extracts the command from `text` (minus the '/') if `text` is a command (see is_command).
If `text` is not a command, this function returns None.
Examples:
extract_command('/help'): 'help'
extract_command('/help@BotName'): 'help'
extract_command('/search black eyed peas'): 'search'
extract_command('Good day to you'): None
.. code-block:: python3
:caption: Examples:
extract_command('/help'): 'help'
extract_command('/help@BotName'): 'help'
extract_command('/search black eyed peas'): 'search'
extract_command('Good day to you'): None
:param text: String to extract the command from
:type text: :obj:`str`
:return: the command if `text` is a command (according to is_command), else None.
:rtype: :obj:`str` or :obj:`None`
"""
if text is None: return None
return text.split()[0].split('@')[0][1:] if is_command(text) else None
def extract_arguments(text: str) -> str:
def extract_arguments(text: str) -> str or None:
"""
Returns the argument after the command.
Examples:
extract_arguments("/get name"): 'name'
extract_arguments("/get"): ''
extract_arguments("/get@botName name"): 'name'
.. code-block:: python3
:caption: Examples:
extract_arguments("/get name"): 'name'
extract_arguments("/get"): ''
extract_arguments("/get@botName name"): 'name'
:param text: String to extract the arguments from a command
:type text: :obj:`str`
:return: the arguments if `text` is a command (according to is_command), else None.
:rtype: :obj:`str` or :obj:`None`
"""
regexp = re.compile(r"/\w*(@\w*)*\s*([\s\S]*)", re.IGNORECASE)
result = regexp.match(text)
return result.group(2) if is_command(text) else None
def extract_entity(text: str, e: types.MessageEntity) -> str:
"""
Returns the content of the entity.
:param text: The text of the message the entity belongs to
:type text: :obj:`str`
:param e: The entity to extract
:type e: :obj:`MessageEntity`
:return: The content of the entity
:rtype: :obj:`str`
"""
offset = 0
start = 0
encoded_text = text.encode()
end = len(encoded_text)
i = 0
for byte in encoded_text:
if (byte & 0xc0) != 0x80:
if offset == e.offset:
start = i
elif offset - e.offset == e.length:
end = i
break
if byte >= 0xf0:
offset += 2
else:
offset += 1
i += 1
return encoded_text[start:end].decode()
def split_string(text: str, chars_per_string: int) -> List[str]:
"""
@ -281,13 +313,18 @@ def split_string(text: str, chars_per_string: int) -> List[str]:
This is very useful for splitting one giant message into multiples.
:param text: The text to split
:type text: :obj:`str`
:param chars_per_string: The number of characters per line the text is split into.
:type chars_per_string: :obj:`int`
:return: The splitted text as a list of strings.
:rtype: :obj:`list` of :obj:`str`
"""
return [text[i:i + chars_per_string] for i in range(0, len(text), chars_per_string)]
def smart_split(text: str, chars_per_string: int=MAX_MESSAGE_LENGTH) -> List[str]:
def smart_split(text: str, chars_per_string: int = MAX_MESSAGE_LENGTH) -> List[str]:
r"""
Splits one string into multiple strings, with a maximum amount of `chars_per_string` characters per string.
This is very useful for splitting one giant message into multiples.
@ -295,8 +332,13 @@ def smart_split(text: str, chars_per_string: int=MAX_MESSAGE_LENGTH) -> List[str
Splits by '\n', '. ' or ' ' in exactly this priority.
:param text: The text to split
:type text: :obj:`str`
:param chars_per_string: The number of maximum characters per part the text is split to.
:type chars_per_string: :obj:`int`
:return: The splitted text as a list of strings.
:rtype: :obj:`list` of :obj:`str`
"""
def _text_before_last(substr: str) -> str:
@ -312,9 +354,12 @@ def smart_split(text: str, chars_per_string: int=MAX_MESSAGE_LENGTH) -> List[str
part = text[:chars_per_string]
if "\n" in part: part = _text_before_last("\n")
elif ". " in part: part = _text_before_last(". ")
elif " " in part: part = _text_before_last(" ")
if "\n" in part:
part = _text_before_last("\n")
elif ". " in part:
part = _text_before_last(". ")
elif " " in part:
part = _text_before_last(" ")
parts.append(part)
text = text[len(part):]
@ -328,43 +373,62 @@ def escape(text: str) -> str:
:return: the escaped text
"""
chars = {"&": "&amp;", "<": "&lt;", ">": "&gt;"}
for old, new in chars.items(): text = text.replace(old, new)
if text is None:
return None
for old, new in chars.items():
text = text.replace(old, new)
return text
def user_link(user: types.User, include_id: bool=False) -> str:
def user_link(user: types.User, include_id: bool = False) -> str:
"""
Returns an HTML user link. This is useful for reports.
Attention: Don't forget to set parse_mode to 'HTML'!
Example:
bot.send_message(your_user_id, user_link(message.from_user) + ' started the bot!', parse_mode='HTML')
.. code-block:: python3
:caption: Example:
bot.send_message(your_user_id, user_link(message.from_user) + ' started the bot!', parse_mode='HTML')
.. note::
You can use formatting.* for all other formatting options(bold, italic, links, and etc.)
This method is kept for backward compatibility, and it is recommended to use formatting.* for
more options.
:param user: the user (not the user_id)
:type user: :obj:`telebot.types.User`
:param include_id: include the user_id
:type include_id: :obj:`bool`
:return: HTML user link
:rtype: :obj:`str`
"""
name = escape(user.first_name)
return (f"<a href='tg://user?id={user.id}'>{name}</a>"
+ (f" (<pre>{user.id}</pre>)" if include_id else ""))
+ (f" (<pre>{user.id}</pre>)" if include_id else ""))
def quick_markup(values: Dict[str, Dict[str, Any]], row_width: int=2) -> types.InlineKeyboardMarkup:
def quick_markup(values: Dict[str, Dict[str, Any]], row_width: int = 2) -> types.InlineKeyboardMarkup:
"""
Returns a reply markup from a dict in this format: {'text': kwargs}
This is useful to avoid always typing 'btn1 = InlineKeyboardButton(...)' 'btn2 = InlineKeyboardButton(...)'
Example:
.. code-block:: python
.. code-block:: python3
:caption: Using quick_markup:
quick_markup({
from telebot.util import quick_markup
markup = quick_markup({
'Twitter': {'url': 'https://twitter.com'},
'Facebook': {'url': 'https://facebook.com'},
'Back': {'callback_data': 'whatever'}
}, row_width=2):
# returns an InlineKeyboardMarkup with two buttons in a row, one leading to Twitter, the other to facebook
# and a back button below
}, row_width=2)
# returns an InlineKeyboardMarkup with two buttons in a row, one leading to Twitter, the other to facebook
# and a back button below
# kwargs can be:
{
@ -379,8 +443,13 @@ def quick_markup(values: Dict[str, Dict[str, Any]], row_width: int=2) -> types.I
}
:param values: a dict containing all buttons to create in this format: {text: kwargs} {str:}
:param row_width: int row width
:type values: :obj:`dict`
:param row_width: number of :class:`telebot.types.InlineKeyboardButton` objects on each row
:type row_width: :obj:`int`
:return: InlineKeyboardMarkup
:rtype: :obj:`types.InlineKeyboardMarkup`
"""
markup = types.InlineKeyboardMarkup(row_width=row_width)
buttons = [
@ -393,16 +462,25 @@ def quick_markup(values: Dict[str, Dict[str, Any]], row_width: int=2) -> types.I
# CREDITS TO http://stackoverflow.com/questions/12317940#answer-12320352
def or_set(self):
"""
:meta private:
"""
self._set()
self.changed()
def or_clear(self):
"""
:meta private:
"""
self._clear()
self.changed()
def orify(e, changed_callback):
"""
:meta private:
"""
if not hasattr(e, "_set"):
e._set = e.set
if not hasattr(e, "_clear"):
@ -413,6 +491,9 @@ def orify(e, changed_callback):
def OrEvent(*events):
"""
:meta private:
"""
or_event = threading.Event()
def changed():
@ -436,6 +517,9 @@ def OrEvent(*events):
def per_thread(key, construct_value, reset=False):
"""
:meta private:
"""
if reset or not hasattr(thread_local, key):
value = construct_value()
setattr(thread_local, key, value)
@ -443,26 +527,25 @@ def per_thread(key, construct_value, reset=False):
return getattr(thread_local, key)
def chunks(lst, n):
"""Yield successive n-sized chunks from lst."""
# https://stackoverflow.com/a/312464/9935473
for i in range(0, len(lst), n):
yield lst[i:i + n]
def generate_random_token():
return ''.join(random.sample(string.ascii_letters, 16))
def deprecated(warn: bool=True, alternative: Optional[Callable]=None, deprecation_text=None):
def deprecated(warn: bool = True, alternative: Optional[Callable] = None, deprecation_text=None):
"""
Use this decorator to mark functions as deprecated.
When the function is used, an info (or warning if `warn` is True) is logged.
:meta private:
:param warn: If True a warning is logged else an info
:type warn: :obj:`bool`
:param alternative: The new function to use instead
:type alternative: :obj:`Callable`
:param deprecation_text: Custom deprecation text
:type deprecation_text: :obj:`str`
:return: The decorated function
"""
def decorator(function):
def wrapper(*args, **kwargs):
info = f"`{function.__name__}` is deprecated."
@ -475,13 +558,25 @@ def deprecated(warn: bool=True, alternative: Optional[Callable]=None, deprecatio
else:
logger.warning(info)
return function(*args, **kwargs)
return wrapper
return decorator
# Cloud helpers
def webhook_google_functions(bot, request):
"""A webhook endpoint for Google Cloud Functions FaaS."""
"""
A webhook endpoint for Google Cloud Functions FaaS.
:param bot: The bot instance
:type bot: :obj:`telebot.TeleBot` or :obj:`telebot.async_telebot.AsyncTeleBot`
:param request: The request object
:type request: :obj:`flask.Request`
:return: The response object
"""
if request.is_json:
try:
request_json = request.get_json()
@ -495,7 +590,7 @@ def webhook_google_functions(bot, request):
return 'Bot ON'
def antiflood(function, *args, **kwargs):
def antiflood(function: Callable, *args, number_retries=5, **kwargs):
"""
Use this function inside loops in order to avoid getting TooManyRequests error.
Example:
@ -506,26 +601,48 @@ def antiflood(function, *args, **kwargs):
for chat_id in chat_id_list:
msg = antiflood(bot.send_message, chat_id, text)
:param function:
:param args:
:param kwargs:
:param function: The function to call
:type function: :obj:`Callable`
:param number_retries: Number of retries to send
:type function: :obj:int
:param args: The arguments to pass to the function
:type args: :obj:`tuple`
:param kwargs: The keyword arguments to pass to the function
:type kwargs: :obj:`dict`
:return: None
"""
from telebot.apihelper import ApiTelegramException
from time import sleep
msg = None
try:
msg = function(*args, **kwargs)
except ApiTelegramException as ex:
if ex.error_code == 429:
sleep(ex.result_json['parameters']['retry_after'])
msg = function(*args, **kwargs)
finally:
return msg
for _ in range(number_retries - 1):
try:
return function(*args, **kwargs)
except ApiTelegramException as ex:
if ex.error_code == 429:
sleep(ex.result_json['parameters']['retry_after'])
else:
raise
else:
return function(*args, **kwargs)
def parse_web_app_data(token: str, raw_init_data: str):
is_valid = validate_WebApp_data(token, raw_init_data)
"""
Parses web app data.
:param token: The bot token
:type token: :obj:`str`
:param raw_init_data: The raw init data
:type raw_init_data: :obj:`str`
:return: The parsed init data
"""
is_valid = validate_web_app_data(token, raw_init_data)
if not is_valid:
return False
@ -540,7 +657,18 @@ def parse_web_app_data(token: str, raw_init_data: str):
return result
def validate_web_app_data(token, raw_init_data):
def validate_web_app_data(token: str, raw_init_data: str):
"""
Validates web app data.
:param token: The bot token
:type token: :obj:`str`
:param raw_init_data: The raw init data
:type raw_init_data: :obj:`str`
:return: The parsed init data
"""
try:
parsed_data = dict(parse_qsl(raw_init_data))
except ValueError:
@ -554,4 +682,16 @@ def validate_web_app_data(token, raw_init_data):
return hmac.new(secret_key.digest(), data_check_string.encode(), sha256).hexdigest() == init_data_hash
__all__ = (
"content_type_media", "content_type_service", "update_types",
"WorkerThread", "AsyncTask", "CustomRequestResponse",
"async_dec", "deprecated",
"is_bytes", "is_string", "is_dict", "is_pil_image",
"chunks", "generate_random_token", "pil_image_to_file",
"is_command", "extract_command", "extract_arguments",
"split_string", "smart_split", "escape", "user_link", "quick_markup",
"antiflood", "parse_web_app_data", "validate_web_app_data",
"or_set", "or_clear", "orify", "OrEvent", "per_thread",
"webhook_google_functions"
)

View File

@ -1,3 +1,3 @@
# Versions should comply with PEP440.
# This line is parsed in setup.py:
__version__ = '4.6.0'
__version__ = '4.12.0'

View File

@ -470,6 +470,53 @@ class TestTeleBot:
for i in range(0,200):
util.antiflood(tb.send_message, CHAT_ID, text)
assert i == 199
def test_extract_entity(self):
entities_map = {"https://core.telegram.org/api/entities": "https://core.telegram.org/api/entities",
"https://github.com/eternnoir/pyTelegramBotAPI": "https://github.com/eternnoir/pyTelegramBotAPI",
"*粗 bold text体*": "粗 bold text体",
"_斜体 italic text_": "斜体 italic text",
"[谷歌](http://www.google.com/)": "谷歌",
'`std::cout<<"test"<<std::endl;`': 'std::cout<<"test"<<std::endl;',
'''```rust
let number = loop {
println!("Pick a pattern from 0-2:");
stdin.read_line(&mut option).unwrap();
match option.lines().next().unwrap().parse::<usize>() {
Ok(number @ 0..=2) => break number,
_ => {
println!("invalid input!");
option = String::new();
continue;
}
};
};```''': '''let number = loop {
println!("Pick a pattern from 0-2:");
stdin.read_line(&mut option).unwrap();
match option.lines().next().unwrap().parse::<usize>() {
Ok(number @ 0..=2) => break number,
_ => {
println!("invalid input!");
option = String::new();
continue;
}
};
};''',
"@username": "@username",
"#hashtag索引标签": "#hashtag索引标签",
"do-not-reply@telegram.org": "do-not-reply@telegram.org",
"+12125550123": "+12125550123"}
entites = list(entities_map.keys())
contents = list(entities_map.values())
contents.sort()
text = '\n'.join(entites)
bot = telebot.TeleBot(TOKEN)
message = bot.send_message(CHAT_ID, text, parse_mode="Markdown")
extracted_contents = [util.extract_entity(
message.text, e) for e in message.entities]
extracted_contents.sort()
assert contents == extracted_contents
@staticmethod
def create_text_message(text):

View File

@ -67,9 +67,9 @@ def test_json_GroupChat():
def test_json_Document():
json_string = r'{"file_name":"Text File","thumb":{},"file_id":"BQADBQADMwIAAsYifgZ_CEh0u682xwI","file_unique_id": "AgADJQEAAqfhOEY","file_size":446}'
json_string = r'{"file_name":"Text File","thumbnail":{},"file_id":"BQADBQADMwIAAsYifgZ_CEh0u682xwI","file_unique_id": "AgADJQEAAqfhOEY","file_size":446}'
doc = types.Document.de_json(json_string)
assert doc.thumb is None
assert doc.thumbnail is None
assert doc.file_name == 'Text File'
@ -83,23 +83,23 @@ def test_json_Message_Audio():
def test_json_Message_Sticker():
json_string = r'{"message_id": 21552, "from": {"id": 590740002, "is_bot": false, "first_name": "⚜️ Ƥυrуα ⚜️", "username": "Purya", "language_code": "en"}, "chat": {"id": -1001309982000, "title": "123", "type": "supergroup"}, "date": 1594068909, "sticker": {"width": 368, "height": 368, "emoji": "🤖", "set_name": "ipuryapack", "is_animated": false, "is_video": true, "thumb": {"file_id": "AAMCBAADHQJOFL7mAAJUMF8Dj62hpmDhpRAYvkc8CtIqipolAAJ8AAPA-8cF9yxjgjkLS97A0D4iXQARtQAHbQADHy4AAhoE", "file_unique_id": "AQADwNA-Il0AAx8uAAI", "file_size": 7776, "width": 60, "height": 60}, "file_id": "CAACAgQAAx0CThS-5gACVDBfA4-toaZg4aUQGL5HWerSKoqaJQACArADwPvHBfcsY4I5C3feGgQ", "file_unique_id": "AgADfAADsPvHWQ", "file_size": 14602}}'
json_string = r'{"message_id": 21552, "from": {"id": 590740002, "is_bot": false, "first_name": "⚜️ Ƥυrуα ⚜️", "username": "Purya", "language_code": "en"}, "chat": {"id": -1001309982000, "title": "123", "type": "supergroup"}, "date": 1594068909, "sticker": {"type": "regular", "width": 368, "height": 368, "emoji": "🤖", "set_name": "ipuryapack", "is_animated": false, "is_video": true, "thumbnail": {"file_id": "AAMCBAADHQJOFL7mAAJUMF8Dj62hpmDhpRAYvkc8CtIqipolAAJ8AAPA-8cF9yxjgjkLS97A0D4iXQARtQAHbQADHy4AAhoE", "file_unique_id": "AQADwNA-Il0AAx8uAAI", "file_size": 7776, "width": 60, "height": 60}, "file_id": "CAACAgQAAx0CThS-5gACVDBfA4-toaZg4aUQGL5HWerSKoqaJQACArADwPvHBfcsY4I5C3feGgQ", "file_unique_id": "AgADfAADsPvHWQ", "file_size": 14602}}'
msg = types.Message.de_json(json_string)
assert msg.sticker.height == 368
assert msg.sticker.thumb.height == 60
assert msg.sticker.thumbnail.height == 60
assert msg.content_type == 'sticker'
def test_json_Message_Sticker_without_thumb():
json_string = r'{"message_id": 21552, "from": {"id": 590740002, "is_bot": false, "first_name": "⚜️ Ƥυrуα ⚜️", "username": "Purya", "language_code": "en"}, "chat": {"id": -1001309982000, "title": "123", "type": "supergroup"}, "date": 1594068909, "sticker": {"width": 368, "height": 368, "emoji": "🤖", "set_name": "ipuryapack", "is_animated": false, "is_video": true, "file_id": "CAACAgQAAx0CThS-5gACVDBfA4-toaZg4aUQGL5HWerSKoqaJQACArADwPvHBfcsY4I5C3feGgQ", "file_unique_id": "AgADfAADsPvHWQ", "file_size": 14602}}'
def test_json_Message_Sticker_without_thumbnail():
json_string = r'{"message_id": 21552, "from": {"id": 590740002, "is_bot": false, "first_name": "⚜️ Ƥυrуα ⚜️", "username": "Purya", "language_code": "en"}, "chat": {"id": -1001309982000, "title": "123", "type": "supergroup"}, "date": 1594068909, "sticker": {"type": "regular", "width": 368, "height": 368, "emoji": "🤖", "set_name": "ipuryapack", "is_animated": false, "is_video": true, "file_id": "CAACAgQAAx0CThS-5gACVDBfA4-toaZg4aUQGL5HWerSKoqaJQACArADwPvHBfcsY4I5C3feGgQ", "file_unique_id": "AgADfAADsPvHWQ", "file_size": 14602}}'
msg = types.Message.de_json(json_string)
assert msg.sticker.height == 368
assert msg.sticker.thumb is None
assert msg.sticker.thumbnail is None
assert msg.content_type == 'sticker'
def test_json_Message_Document():
json_string = r'{"message_id":97,"from":{"id":10734,"first_name":"Fd","last_name":"Wd","username":"dd","is_bot":true },"chat":{"id":10,"first_name":"Fd","type":"private","last_name":"Wd","username":"dd"},"date":1435478744,"document":{"file_name":"Text File","thumb":{},"file_id":"BQADBQADMwIAAsYifgZ_CEh0u682xwI","file_unique_id": "AQAD_QIfa3QAAyA4BgAB","file_size":446}}'
json_string = r'{"message_id":97,"from":{"id":10734,"first_name":"Fd","last_name":"Wd","username":"dd","is_bot":true },"chat":{"id":10,"first_name":"Fd","type":"private","last_name":"Wd","username":"dd"},"date":1435478744,"document":{"file_name":"Text File","thumbnail":{},"file_id":"BQADBQADMwIAAsYifgZ_CEh0u682xwI","file_unique_id": "AQAD_QIfa3QAAyA4BgAB","file_size":446}}'
msg = types.Message.de_json(json_string)
assert msg.document.file_name == 'Text File'
assert msg.content_type == 'document'
@ -113,11 +113,11 @@ def test_json_Message_Photo():
def test_json_Message_Video():
json_string = r'{"message_id":101,"from":{"id":109734,"first_name":"dd","last_name":"dd","username":"dd","is_bot":true },"chat":{"id":109734,"first_name":"dd","type":"private","last_name":"dd","username":"dd"},"date":1435481960,"video":{"duration":3,"caption":"","width":360,"height":640,"thumb":{"file_id":"AAQFABPiYnBjkDwMAAIC","file_unique_id": "AQADTeisa3QAAz1nAAI","file_size":1597,"width":50,"height":90},"file_id":"BAADBQADNifgb_TOPEKErGoQI","file_unique_id": "AgADbgEAAn8VSFY","file_size":260699}}'
json_string = r'{"message_id":101,"from":{"id":109734,"first_name":"dd","last_name":"dd","username":"dd","is_bot":true },"chat":{"id":109734,"first_name":"dd","type":"private","last_name":"dd","username":"dd"},"date":1435481960,"video":{"duration":3,"caption":"","width":360,"height":640,"thumbnail":{"file_id":"AAQFABPiYnBjkDwMAAIC","file_unique_id": "AQADTeisa3QAAz1nAAI","file_size":1597,"width":50,"height":90},"file_id":"BAADBQADNifgb_TOPEKErGoQI","file_unique_id": "AgADbgEAAn8VSFY","file_size":260699}}'
msg = types.Message.de_json(json_string)
assert msg.video
assert msg.video.duration == 3
assert msg.video.thumb.width == 50
assert msg.video.thumbnail.width == 50
assert msg.content_type == 'video'
@ -271,5 +271,33 @@ def test_sent_web_app_message():
assert sent_web_app_message.inline_message_id == '29430'
def test_message_entity():
# TODO: Add support for nesting entities
sample_string_1 = r'{"update_id":934522126,"message":{"message_id":1374510,"from":{"id":927266710,"is_bot":false,"first_name":">_run","username":"coder2020","language_code":"en","is_premium":true},"chat":{"id":927266710,"first_name":">_run","username":"coder2020","type":"private"},"date":1682177590,"text":"b b b","entities":[{"offset":0,"length":2,"type":"bold"},{"offset":0,"length":1,"type":"italic"},{"offset":2,"length":2,"type":"bold"},{"offset":2,"length":1,"type":"italic"},{"offset":4,"length":1,"type":"bold"},{"offset":4,"length":1,"type":"italic"}]}}'
update = types.Update.de_json(sample_string_1)
message: types.Message = update.message
assert message.html_text == "<i><b>b </b></i><i><b>b </b></i><i><b>b</b></i>"
sample_string_2 = r'{"update_id":934522166,"message":{"message_id":1374526,"from":{"id":927266710,"is_bot":false,"first_name":">_run","username":"coder2020","language_code":"en","is_premium":true},"chat":{"id":927266710,"first_name":">_run","username":"coder2020","type":"private"},"date":1682179716,"text":"b b b","entities":[{"offset":0,"length":1,"type":"bold"},{"offset":2,"length":1,"type":"bold"},{"offset":4,"length":1,"type":"italic"}]}}'
message_2 = types.Update.de_json(sample_string_2).message
assert message_2.html_text == "<b>b</b> <b>b</b> <i>b</i>"
sample_string_3 = r'{"update_id":934522172,"message":{"message_id":1374530,"from":{"id":927266710,"is_bot":false,"first_name":">_run","username":"coder2020","language_code":"en","is_premium":true},"chat":{"id":927266710,"first_name":">_run","username":"coder2020","type":"private"},"date":1682179968,"text":"This is a bold text with a nested italic and bold text.","entities":[{"offset":10,"length":4,"type":"bold"},{"offset":27,"length":7,"type":"italic"},{"offset":34,"length":15,"type":"bold"},{"offset":34,"length":15,"type":"italic"}]}}'
message_3 = types.Update.de_json(sample_string_3).message
assert message_3.html_text == "This is a <b>bold</b> text with a <i>nested </i><i><b>italic and bold</b></i> text."
sample_string_4 = r'{"update_id":934522437,"message":{"message_id":1374619,"from":{"id":927266710,"is_bot":false,"first_name":">_run","username":"coder2020","language_code":"en","is_premium":true},"chat":{"id":927266710,"first_name":">_run","username":"coder2020","type":"private"},"date":1682189507,"forward_from":{"id":927266710,"is_bot":false,"first_name":">_run","username":"coder2020","language_code":"en","is_premium":true},"forward_date":1682189124,"text":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa😋😋","entities":[{"offset":0,"length":76,"type":"bold"},{"offset":0,"length":76,"type":"italic"},{"offset":0,"length":76,"type":"underline"},{"offset":0,"length":76,"type":"strikethrough"},{"offset":76,"length":2,"type":"custom_emoji","custom_emoji_id":"5456188142006575553"},{"offset":78,"length":2,"type":"custom_emoji","custom_emoji_id":"5456188142006575553"}]}}'
message_4 = types.Update.de_json(sample_string_4).message
assert message_4.html_text == '<s><u><i><b>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</b></i></u></s><tg-emoji emoji-id="5456188142006575553">😋</tg-emoji><tg-emoji emoji-id="5456188142006575553">😋</tg-emoji>'