Compare commits

..

38 Commits

Author SHA1 Message Date
Hinrich Mahler e9c01c7772 Bump version to v13.3 2021-02-19 19:55:49 +01:00
Bibo-Joshi 552298595c Doc Fixes (#2359)
* Improve some badges for PTB-Raw

* doc fix for add_error_handler

* Some rendering

* Doc fixes for filters.py

* render '@' as code

Co-authored-by: Harshil <ilovebhagwan@gmail.com>
2021-02-19 19:27:17 +01:00
Bibo-Joshi 2a4a0d0ccd Refactor Defaults Integration (#2363)
* Change default handling, update signatures, get existing tests to pass.

* Try running tests on ubuntu 18.04

* Roll back

* Rework check_shortcut_call tests

* Further improve check_shortcut_call tests

* Start on defaults-checks for shortcuts, get it working for test_message

* Add check_shortcut_defaults to all other shortcut tests

* Some fine tuning

* Add defaults checking for bot methods

* Missing tests for TestCallbackQuery

* Test edit_message_media with defaults & some comments

* Fix cryptography requirement

* drop debug prints

* Remove debug prints

* Another try

* Try to fix coverage & logs

* Rearrange test order

* increase coverage

* Try to fix coverage reports

* address review

* Adapt tests like in #2386

* fix CI

* fix CI
2021-02-19 19:07:48 +01:00
Harshil eb993db473 Add Missing telegram.SecureValue to init and Docs (#2398) 2021-02-19 17:46:52 +01:00
Bibo-Joshi c77ef7eef3 Deprecate MessageQueue (#2393) 2021-02-19 17:29:50 +01:00
Bibo-Joshi a34f0b9bee Make cryptography Dependency Optional & Refactor Some Tests (#2386)
* Make cryptography optional

* Try fixing CI

* Try some more

* Update pytest, mypy & pyupgrade, refactor test_meta, hope that things start to work

* Fix filterwarnings

* Mama mia! Here we go again!

* Add stupid debug prints

* A new hope
2021-02-13 22:07:37 +01:00
Bibo-Joshi eee8921598 Update cryptography Dependency (#2370) 2021-02-08 19:28:54 +01:00
Hinrich Mahler 1902c0ac36 Bump version to v13.2 2021-02-02 20:57:14 +01:00
Bibo-Joshi 544a3fbf48 ConversationHandler: Docs & edited_channel_post behavior (#2339)
* Update docs & ignore edited channel posts

* typo

* Apply suggestions from code review

Co-authored-by: Poolitzer <25934244+Poolitzer@users.noreply.github.com>

* Update telegram/ext/conversationhandler.py

* fix pre-commit

Co-authored-by: Poolitzer <25934244+Poolitzer@users.noreply.github.com>
2021-02-01 19:26:03 +01:00
Bibo-Joshi 36d49ea9cd Doc Fixes (#2253)
* Render-fixes for BP

* docs: fix simple typo, submition -> submission (#2260)

There is a small typo in tests/test_bot.py.

Should read `submission` rather than `submition`.

* Type on rawapibot.py docstring

* typo

* Typo: Filters.document(s)

* Typo fix

* Doc fix for messageentity (#2311)

* Add New Shortcuts to Chat (#2291)

* Add shortcuts

* Add a note

* Add run_async Parameter to ConversationHandler (#2292)

* Add run_async parameter

* Update docstring

* Update test to explicitly specify parameter

* Fix test job queue

* Add version added tag to docs

* Update docstring

Co-authored-by: Poolitzer <25934244+Poolitzer@users.noreply.github.com>

* Doc nitpicking

Co-authored-by: Poolitzer <25934244+Poolitzer@users.noreply.github.com>
Co-authored-by: Hinrich Mahler <hinrich.mahler@freenet.de>

* Fix rendering in messageentity

Co-authored-by: Bibo-Joshi <hinrich.mahler@freenet.de>
Co-authored-by: zeshuaro <joshuaystang@gmail.com>
Co-authored-by: Poolitzer <25934244+Poolitzer@users.noreply.github.com>

* fix: type hints for TelegramError

changed :class:`telegram.TelegramError` to :class:`telegram.error.TelegramError`

* fix: the error can be more then just a Telegram error

* Doc fix for inlinekeyboardbutton.py

added missing colon which broke rendering

* fix: remove context argument and doc remark

look at us already being in post 12

* use rtd badge

* filters doc fixes

* fix some rendering

* Doc & Rendering fixes for helpers.py

Co-authored-by: Tim Gates <tim.gates@iress.com>
Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com>
Co-authored-by: zeshuaro <joshuaystang@gmail.com>
Co-authored-by: Poolitzer <25934244+Poolitzer@users.noreply.github.com>
Co-authored-by: Harshil <ilovebhagwan@gmail.com>
2021-02-01 17:59:39 +01:00
Bibo-Joshi 25506f131d python-telegram-bot-raw (#2324)
* POC

* Remove decorator dependency

* Rework setup.py & build, add separate readme

* Move utils -> ext.utils

* Move pytz dep to ext

* Try fixing timing stuff

* Add 'Typed' classifier

* Update README_RAW.rst

Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com>

* Some wording

* Deprecation warnings for moved tg.utils

* Tests for Promise

* Test time-helpers without pytz

* Try fixing time-helper tests

* Merge master

Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com>
2021-01-30 14:15:39 +01:00
Bibo-Joshi 70aba136e4 Reduce Usage of typing.Any (#2321)
* Use object instead of Any where possible

* Revert a lof of noise from the PR
2021-01-30 11:38:54 +01:00
Stɑrry Shivɑm 40995b19fe Extend Deeplinking Example (#2335)
* extend deeplinking example

Signed-off-by: starry69 <starry369126@outlook.com>

* use username property instead of get_me calls

Signed-off-by: starry69 <starry369126@outlook.com>
2021-01-28 17:12:13 +01:00
zeshuaro 32da6d6fce Add Missing Shortcuts to Message (#2330)
* Add shortcuts for Message

* Fix docs in Chat

* Update docs in Message

* Fix tests in request.py

* Rollback changes made to fix mypy errors
2021-01-23 13:40:19 +01:00
Bibo-Joshi f31787a8ef Add pyupgrade to pre-commit Hooks (#2301)
* Add pyupgrade to pre-commit

* update test_chat
2021-01-17 23:24:20 +01:00
Stɑrry Shivɑm b43a599e53 Rich Comparison for Bot (#2320)
* Make telegram.Bot comparable

Signed-off-by: starry69 <starry369126@outlook.com>

* Address review

Signed-off-by: starry69 <starry369126@outlook.com>

* Enhance tests & add docstring about comparison

Signed-off-by: starry69 <starry369126@outlook.com>

* Minor doc fix

* Extend tests

Co-authored-by: Hinrich Mahler <hinrich.mahler@freenet.de>
2021-01-17 09:23:36 +01:00
Bibo-Joshi 7a3fd83570 Add PR Template (#2299)
* Add PR template

* Apply suggestions from code review

Co-authored-by: Poolitzer <25934244+Poolitzer@users.noreply.github.com>

* Some more

* reformulate

* Apply suggestions from code review

Co-authored-by: Poolitzer <25934244+Poolitzer@users.noreply.github.com>

Co-authored-by: Poolitzer <25934244+Poolitzer@users.noreply.github.com>
2021-01-16 13:57:25 +01:00
Bibo-Joshi 9ada2a7cca Drop Nightly Tests & Update Badges (#2323) 2021-01-16 11:27:06 +01:00
Eana Hufwe be54cf4ece Fix Escaping in Nested Entities in Message Properties (#2312)
* fix: overly escape and offset error markdown v2 symbols when nested

Signed-off-by: Eana Hufwe <ilove@1a23.com>

* fix: nested entity escape for HTML parsers and tests

Signed-off-by: Eana Hufwe <ilove@1a23.com>
2021-01-12 19:33:26 +01:00
zeshuaro 0c9915243d Add run_async Parameter to ConversationHandler (#2292)
* Add run_async parameter

* Update docstring

* Update test to explicitly specify parameter

* Fix test job queue

* Add version added tag to docs

* Update docstring

Co-authored-by: Poolitzer <25934244+Poolitzer@users.noreply.github.com>

* Doc nitpicking

Co-authored-by: Poolitzer <25934244+Poolitzer@users.noreply.github.com>
Co-authored-by: Hinrich Mahler <hinrich.mahler@freenet.de>
2021-01-09 20:05:58 +01:00
Bibo-Joshi 9930725e2a Add New Shortcuts to Chat (#2291)
* Add shortcuts

* Add a note
2021-01-09 17:48:56 +01:00
Bibo-Joshi ffd675daec Adjust Calling of Dispatcher.update_persistence (#2285)
* Adjust calling of update_persistence

(cherry picked from commit 89c522d883)

* Fix tests and stuff
2021-01-07 21:31:00 +01:00
Bibo-Joshi 6a831f926b Add New Constant MAX_ANSWER_CALLBACK_QUERY_TEXT_LENGTH (#2282) 2021-01-07 21:27:51 +01:00
Bibo-Joshi 6903d58142 Update Copyright (#2289)
* Update coypright headers

* typos
2021-01-04 17:24:14 +01:00
Bibo-Joshi 07b6ee69d2 Update Copyright (#2287)
Signed-off-by: starry69 <starry369126@outlook.com>
2021-01-03 10:30:02 +01:00
starry69 c8a3c31dcc Update copyright of docs config
Signed-off-by: starry69 <starry369126@outlook.com>
2021-01-03 14:42:51 +05:30
starry69 91e0271e4c Update copyright headers
Signed-off-by: starry69 <starry369126@outlook.com>
2021-01-03 10:40:24 +05:30
Hinrich Mahler 9ddb361f76 Revert "Adjust calling of update_persistence"
This reverts commit 89c522d883.
2021-01-01 21:44:23 +01:00
Hinrich Mahler 89c522d883 Adjust calling of update_persistence 2021-01-01 21:40:42 +01:00
Bibo-Joshi 2effff8254 Change Order of Class DocStrings (#2256) 2020-12-30 15:59:50 +01:00
Bibo-Joshi 2788191657 Add macOS to Test Matrix (#2266)
* Try testing on macos

* Skip JobQueue tests on macos

* Try stabilizing tests

* Try harder
2020-12-30 15:39:38 +01:00
Bibo-Joshi aec6d3bada Explicit Signatures for Shortcuts (#2240)
* First POC

* Actually get it to work

* locals-less POC

* pre-commit

* Work on Message shortcuts, update some annotations in Bot methods

* Tippity Tappity, coding stuff

* CallbackQuery

* InlineQuery & Some other stuff

* Media Classes and PassportFile

* Fix tests

* PreCheckout- & ShippingQuery

* User

* Fix tests

* Chat

* Update rawapibot

* Update annotations for answer_inline_query
2020-12-30 13:41:07 +01:00
Bibo-Joshi 80b34811ab Handle Bytes as File Input (#2233)
* Handle bytes file input

* fix tests

* Docs, Tests & Rearrangements

* Use versioning directives

* fixing type hinting of send_photo

Co-authored-by: Poolitzer <25934244+Poolitzer@users.noreply.github.com>
2020-12-18 11:20:03 +01:00
Poolitzer 2d7a974b8f Start Using Versioning Directives in Docs (#2252)
* adding versioning in sphinx, closing #2250

* adding version requirement to contributors doc
2020-12-17 19:05:12 +01:00
Bibo-Joshi ef703d19e9 Doc Fixes (#2225)
* Fix dscr for soccer ball values

* Update docs of BasePersistence regarding abc

* elaborate run_daily docs

* Make docstring of send_document.filename more precise

* increase bot API and add Discussion link

Co-authored-by: Poolitzer <25934244+Poolitzer@users.noreply.github.com>
2020-12-17 09:29:17 +01:00
Bibo-Joshi 77a8c64f6c Improve Annotations & Docs of Handlers (#2243)
* Improve typing & docs of handlers

* Apply suggestions from code review

Co-authored-by: Poolitzer <25934244+Poolitzer@users.noreply.github.com>

Co-authored-by: Poolitzer <25934244+Poolitzer@users.noreply.github.com>
2020-12-16 17:34:57 +01:00
Bibo-Joshi 786762bb73 Allow Passing Custom Filename For All Media (#2249)
* Add filename arg to send_media methods and InputMedia*

* Tests
2020-12-16 14:28:53 +01:00
Bibo-Joshi e0dbb99b08 Add quote kwarg to Message.reply_copy (#2232)
* add quote kwrag to Message.reply_copy

* Add docs & update tests
2020-12-03 20:51:47 +01:00
290 changed files with 10125 additions and 4497 deletions
+2
View File
@@ -91,6 +91,8 @@ Here's how to make a one-off code change.
Once the process terminates, you can view the built documentation by opening ``docs/build/html/index.html`` with a browser.
- Add ``.. versionadded:: version``, ``.. versionchanged:: version`` or ``.. deprecated:: version`` to the associated documentation of your changes, depending on what kind of change you made. This only applies if the change you made is visible to an end user. The directives should be added to class/method descriptions if their general behaviour changed and to the description of all arguments & attributes that changed.
- For consistency, please conform to `Google Python Style Guide`_ and `Google Python Style Docstrings`_.
- The following exceptions to the above (Google's) style guides applies:
+30
View File
@@ -0,0 +1,30 @@
<!--
Hey! You're PRing? Cool! Please have a look at the below checklist. It's here to help both you and the maintainers to remember some aspects. Make sure to check out our contribution guide (https://github.com/python-telegram-bot/python-telegram-bot/blob/master/.github/CONTRIBUTING.rst).
-->
### Checklist for PRs
- [ ] Added `.. versionadded:: version`, `.. versionchanged:: version` or `.. deprecated:: version` to the docstrings for user facing changes (for methods/class descriptions, arguments and attributes)
- [ ] Created new or adapted existing unit tests
- [ ] Added myself alphabetically to `AUTHORS.rst` (optional)
### If the PR contains API changes (otherwise, you can delete this passage)
* New classes:
- [ ] Added `self._id_attrs` and corresponding documentation
- [ ] `__init__` accepts `**_kwargs`
* Added new shortcuts:
- [ ] In `Chat` & `User` for all methods that accept `chat/user_id`
- [ ] In `Message` for all methods that accept `chat_id` and `message_id`
- [ ] For new `Message` shortcuts: Added `quote` argument if methods accepts `reply_to_message_id`
- [ ] In `CallbackQuery` for all methods that accept either `chat_id` and `message_id` or `inline_message_id`
* If relevant:
- [ ] Added new constants at `telegram.constants` and shortcuts to them as class variables
- [ ] Added new handlers for new update types
- [ ] Added new filters for new message (sub)types
- [ ] Added or updated documentation for the changed class(es) and/or method(s)
- [ ] Updated the Bot API version number in all places in `README.rst` and `README_RAW.rst`, including the badge
+16
View File
@@ -0,0 +1,16 @@
name: Warning maintainers
on:
pull_request:
paths:
- README.rst
- README_RAW.rst
jobs:
job:
runs-on: ubuntu-latest
name: about readme change
steps:
- name: running the check
uses: Poolitzer/notifier-action@master
with:
notify-message: Hey! Looks like you edited README.rst or README_RAW.rst. I'm just a friendly reminder to apply relevant changes to both of those files :)
repo-token: ${{ secrets.GITHUB_TOKEN }}
+20 -17
View File
@@ -3,8 +3,6 @@ on:
pull_request:
branches:
- master
schedule:
- cron: 7 3 * * *
push:
branches:
- master
@@ -16,14 +14,7 @@ jobs:
strategy:
matrix:
python-version: [3.6, 3.7, 3.8, 3.9]
os: [ubuntu-latest, windows-latest]
include:
- os: ubuntu-latest
python-version: 3.7
test-build: True
- os: windows-latest
python-version: 3.7
test-build: True
os: [ubuntu-latest, windows-latest, macos-latest]
fail-fast: False
steps:
- uses: actions/checkout@v2
@@ -42,18 +33,30 @@ jobs:
python -W ignore -m pip install -r requirements-dev.txt
- name: Test with pytest
# We run 3 different suites here
# 1. Test just utils.helpers.py without pytz being installed
# 2. Test just test_no_passport.py without passport dependencies being installed
# 3. Test everything else
# The first & second one are achieved by mocking the corresponding import
# See test_helpers.py & test_no_passport.py for details
run: |
pytest -v -m nocoverage
nocov_exit=$?
pytest -v -m "not nocoverage" --cov
cov_exit=$?
global_exit=$(( nocov_exit > cov_exit ? nocov_exit : cov_exit ))
pytest -v --cov -k test_no_passport.py
no_passport_exit=$?
export TEST_NO_PASSPORT='false'
pytest -v --cov --cov-append -k test_helpers.py
no_pytz_exit=$?
export TEST_NO_PYTZ='false'
pytest -v --cov --cov-append
full_exit=$?
special_exit=$(( no_pytz_exit > no_passport_exit ? no_pytz_exit : no_passport_exit ))
global_exit=$(( special_exit > full_exit ? special_exit : full_exit ))
exit ${global_exit}
env:
JOB_INDEX: ${{ strategy.job-index }}
BOTS: W3sidG9rZW4iOiAiNjk2MTg4NzMyOkFBR1Z3RUtmSEhsTmpzY3hFRE5LQXdraEdzdFpfa28xbUMwIiwgInBheW1lbnRfcHJvdmlkZXJfdG9rZW4iOiAiMjg0Njg1MDYzOlRFU1Q6WldGaU1UUmxNbVF5TnpNeSIsICJib3RfbmFtZSI6ICJQVEIgdGVzdHMgb24gVHJhdmlzIHVzaW5nIENQeXRob24gMi43IiwgInN1cGVyX2dyb3VwX2lkIjogIi0xMDAxMzkwOTgzOTk3IiwgImJvdF91c2VybmFtZSI6ICJAcHRiX3RyYXZpc19jcHl0aG9uXzI3X2JvdCJ9LCB7InRva2VuIjogIjY3MTQ2ODg4NjpBQUdQR2ZjaVJJQlVORmU4MjR1SVZkcTdKZTNfWW5BVE5HdyIsICJwYXltZW50X3Byb3ZpZGVyX3Rva2VuIjogIjI4NDY4NTA2MzpURVNUOlpHWXdPVGxrTXpNeE4yWTIiLCAiYm90X25hbWUiOiAiUFRCIHRlc3RzIG9uIFRyYXZpcyB1c2luZyBDUHl0aG9uIDMuNCIsICJzdXBlcl9ncm91cF9pZCI6ICItMTAwMTQ0NjAyMjUyMiIsICJib3RfdXNlcm5hbWUiOiAiQHB0Yl90cmF2aXNfY3B5dGhvbl8zNF9ib3QifSwgeyJ0b2tlbiI6ICI2MjkzMjY1Mzg6QUFGUnJaSnJCN29CM211ekdzR0pYVXZHRTVDUXpNNUNVNG8iLCAicGF5bWVudF9wcm92aWRlcl90b2tlbiI6ICIyODQ2ODUwNjM6VEVTVDpNbU01WVdKaFl6a3hNMlUxIiwgImJvdF9uYW1lIjogIlBUQiB0ZXN0cyBvbiBUcmF2aXMgdXNpbmcgQ1B5dGhvbiAzLjUiLCAic3VwZXJfZ3JvdXBfaWQiOiAiLTEwMDE0OTY5MTc3NTAiLCAiYm90X3VzZXJuYW1lIjogIkBwdGJfdHJhdmlzX2NweXRob25fMzVfYm90In0sIHsidG9rZW4iOiAiNjQwMjA4OTQzOkFBRmhCalFwOXFtM1JUeFN6VXBZekJRakNsZS1Kano1aGNrIiwgInBheW1lbnRfcHJvdmlkZXJfdG9rZW4iOiAiMjg0Njg1MDYzOlRFU1Q6WXpoa1pUZzFOamMxWXpWbCIsICJib3RfbmFtZSI6ICJQVEIgdGVzdHMgb24gVHJhdmlzIHVzaW5nIENQeXRob24gMy42IiwgInN1cGVyX2dyb3VwX2lkIjogIi0xMDAxMzMzODcxNDYxIiwgImJvdF91c2VybmFtZSI6ICJAcHRiX3RyYXZpc19jcHl0aG9uXzM2X2JvdCJ9LCB7InRva2VuIjogIjY5NTEwNDA4ODpBQUhmenlsSU9qU0lJUy1lT25JMjB5MkUyMEhvZEhzZnotMCIsICJwYXltZW50X3Byb3ZpZGVyX3Rva2VuIjogIjI4NDY4NTA2MzpURVNUOk9HUTFNRGd3WmpJd1pqRmwiLCAiYm90X25hbWUiOiAiUFRCIHRlc3RzIG9uIFRyYXZpcyB1c2luZyBDUHl0aG9uIDMuNyIsICJzdXBlcl9ncm91cF9pZCI6ICItMTAwMTQ3ODI5MzcxNCIsICJib3RfdXNlcm5hbWUiOiAiQHB0Yl90cmF2aXNfY3B5dGhvbl8zN19ib3QifSwgeyJ0b2tlbiI6ICI2OTE0MjM1NTQ6QUFGOFdrakNaYm5IcVBfaTZHaFRZaXJGRWxackdhWU9oWDAiLCAicGF5bWVudF9wcm92aWRlcl90b2tlbiI6ICIyODQ2ODUwNjM6VEVTVDpZamM1TlRoaU1tUXlNV1ZoIiwgImJvdF9uYW1lIjogIlBUQiB0ZXN0cyBvbiBUcmF2aXMgdXNpbmcgUHlQeSAyLjciLCAic3VwZXJfZ3JvdXBfaWQiOiAiLTEwMDEzNjM5MzI1NzMiLCAiYm90X3VzZXJuYW1lIjogIkBwdGJfdHJhdmlzX3B5cHlfMjdfYm90In0sIHsidG9rZW4iOiAiNjg0MzM5OTg0OkFBRk1nRUVqcDAxcjVyQjAwN3lDZFZOc2c4QWxOc2FVLWNjIiwgInBheW1lbnRfcHJvdmlkZXJfdG9rZW4iOiAiMjg0Njg1MDYzOlRFU1Q6TVRBek1UWTNNR1V5TmpnMCIsICJib3RfbmFtZSI6ICJQVEIgdGVzdHMgb24gVHJhdmlzIHVzaW5nIFB5UHkgMy41IiwgInN1cGVyX2dyb3VwX2lkIjogIi0xMDAxNDA3ODM2NjA1IiwgImJvdF91c2VybmFtZSI6ICJAcHRiX3RyYXZpc19weXB5XzM1X2JvdCJ9LCB7InRva2VuIjogIjY5MDA5MTM0NzpBQUZMbVI1cEFCNVljcGVfbU9oN3pNNEpGQk9oMHozVDBUbyIsICJwYXltZW50X3Byb3ZpZGVyX3Rva2VuIjogIjI4NDY4NTA2MzpURVNUOlpEaGxOekU1TURrd1lXSmkiLCAiYm90X25hbWUiOiAiUFRCIHRlc3RzIG9uIEFwcFZleW9yIHVzaW5nIENQeXRob24gMy40IiwgInN1cGVyX2dyb3VwX2lkIjogIi0xMDAxMjc5NjAwMDI2IiwgImJvdF91c2VybmFtZSI6ICJAcHRiX2FwcHZleW9yX2NweXRob25fMzRfYm90In0sIHsidG9rZW4iOiAiNjk0MzA4MDUyOkFBRUIyX3NvbkNrNTVMWTlCRzlBTy1IOGp4aVBTNTVvb0JBIiwgInBheW1lbnRfcHJvdmlkZXJfdG9rZW4iOiAiMjg0Njg1MDYzOlRFU1Q6WW1aaVlXWm1NakpoWkdNeSIsICJib3RfbmFtZSI6ICJQVEIgdGVzdHMgb24gQXBwVmV5b3IgdXNpbmcgQ1B5dGhvbiAyLjciLCAic3VwZXJfZ3JvdXBfaWQiOiAiLTEwMDEyOTMwNzkxNjUiLCAiYm90X3VzZXJuYW1lIjogIkBwdGJfYXBwdmV5b3JfY3B5dGhvbl8yN19ib3QifSwgeyJ0b2tlbiI6ICIxMDU1Mzk3NDcxOkFBRzE4bkJfUzJXQXd1SjNnN29oS0JWZ1hYY2VNbklPeVNjIiwgInBheW1lbnRfcHJvdmlkZXJfdG9rZW4iOiAiMjg0Njg1MDYzOlRFU1Q6TmpBd056QXpZalZpTkdOayIsICJuYW1lIjogIlBUQiB0ZXN0cyBbMF0iLCAic3VwZXJfZ3JvdXBfaWQiOiAiLTEwMDExODU1MDk2MzYiLCAidXNlcm5hbWUiOiAicHRiXzBfYm90In0sIHsidG9rZW4iOiAiMTA0NzMyNjc3MTpBQUY4bk90ODFGcFg4bGJidno4VWV3UVF2UmZUYkZmQnZ1SSIsICJwYXltZW50X3Byb3ZpZGVyX3Rva2VuIjogIjI4NDY4NTA2MzpURVNUOllUVTFOVEk0WkdSallqbGkiLCAibmFtZSI6ICJQVEIgdGVzdHMgWzFdIiwgInN1cGVyX2dyb3VwX2lkIjogIi0xMDAxNDg0Nzk3NjEyIiwgInVzZXJuYW1lIjogInB0Yl8xX2JvdCJ9LCB7InRva2VuIjogIjk3MTk5Mjc0NTpBQUdPa09hVzBOSGpnSXY1LTlqUWJPajR2R3FkaFNGLVV1cyIsICJwYXltZW50X3Byb3ZpZGVyX3Rva2VuIjogIjI4NDY4NTA2MzpURVNUOk5XWmtNV1ZoWWpsallqVTUiLCAibmFtZSI6ICJQVEIgdGVzdHMgWzJdIiwgInN1cGVyX2dyb3VwX2lkIjogIi0xMDAxNDAyMjU1MDcwIiwgInVzZXJuYW1lIjogInB0Yl8yX2JvdCJ9XQ==
TEST_BUILD: ${{ matrix.test-build }}
TEST_PRE_COMMIT: ${{ matrix.test-pre-commit }}
TEST_NO_PYTZ : "true"
TEST_NO_PASSPORT: "true"
TEST_BUILD: "true"
shell: bash --noprofile --norc {0}
- name: Submit coverage
+3
View File
@@ -84,3 +84,6 @@ telegram.jpg
# Exclude .exrc file for Vim
.exrc
# virtual env
venv*
+8 -1
View File
@@ -21,7 +21,14 @@ repos:
args:
- --rcfile=setup.cfg
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.790
rev: v0.800
hooks:
- id: mypy
files: ^(telegram|examples)/.*\.py$
- repo: https://github.com/asottile/pyupgrade
rev: v2.10.0
hooks:
- id: pyupgrade
files: ^(telegram|examples|tests)/.*\.py$
args:
- --py36-plus
+92
View File
@@ -2,6 +2,98 @@
Changelog
=========
Version 13.3
============
*Released 2021-02-19*
**Major Changes:**
- Make ``cryptography`` Dependency Optional & Refactor Some Tests (`#2386`_, `#2370`_)
- Deprecate ``MessageQueue`` (`#2393`_)
**Bug Fixes:**
- Refactor ``Defaults`` Integration (`#2363`_)
- Add Missing ``telegram.SecureValue`` to init and Docs (`#2398`_)
**Minor changes:**
- Doc Fixes (`#2359`_)
.. _`#2386`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2386
.. _`#2370`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2370
.. _`#2393`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2393
.. _`#2363`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2363
.. _`#2398`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2398
.. _`#2359`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2359
Version 13.2
============
*Released 2021-02-02*
**Major Changes:**
- Introduce ``python-telegram-bot-raw`` (`#2324`_)
- Explicit Signatures for Shortcuts (`#2240`_)
**New Features:**
- Add Missing Shortcuts to ``Message`` (`#2330`_)
- Rich Comparison for ``Bot`` (`#2320`_)
- Add ``run_async`` Parameter to ``ConversationHandler`` (`#2292`_)
- Add New Shortcuts to ``Chat`` (`#2291`_)
- Add New Constant ``MAX_ANSWER_CALLBACK_QUERY_TEXT_LENGTH`` (`#2282`_)
- Allow Passing Custom Filename For All Media (`#2249`_)
- Handle Bytes as File Input (`#2233`_)
**Bug Fixes:**
- Fix Escaping in Nested Entities in ``Message`` Properties (`#2312`_)
- Adjust Calling of ``Dispatcher.update_persistence`` (`#2285`_)
- Add ``quote`` kwarg to ``Message.reply_copy`` (`#2232`_)
- ``ConversationHandler``: Docs & ``edited_channel_post`` behavior (`#2339`_)
**Minor changes, CI improvements, doc fixes and type hinting:**
- Doc Fixes (`#2253`_, `#2225`_)
- Reduce Usage of ``typing.Any`` (`#2321`_)
- Extend Deeplinking Example (`#2335`_)
- Add pyupgrade to pre-commit Hooks (`#2301`_)
- Add PR Template (`#2299`_)
- Drop Nightly Tests & Update Badges (`#2323`_)
- Update Copyright (`#2289`_, `#2287`_)
- Change Order of Class DocStrings (`#2256`_)
- Add macOS to Test Matrix (`#2266`_)
- Start Using Versioning Directives in Docs (`#2252`_)
- Improve Annotations & Docs of Handlers (`#2243`_)
.. _`#2324`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2324
.. _`#2240`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2240
.. _`#2330`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2330
.. _`#2320`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2320
.. _`#2292`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2292
.. _`#2291`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2291
.. _`#2282`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2282
.. _`#2249`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2249
.. _`#2233`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2233
.. _`#2312`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2312
.. _`#2285`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2285
.. _`#2232`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2232
.. _`#2339`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2339
.. _`#2253`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2253
.. _`#2225`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2225
.. _`#2321`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2321
.. _`#2335`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2335
.. _`#2301`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2301
.. _`#2299`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2299
.. _`#2323`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2323
.. _`#2289`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2289
.. _`#2287`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2287
.. _`#2256`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2256
.. _`#2266`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2266
.. _`#2252`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2252
.. _`#2243`: https://github.com/python-telegram-bot/python-telegram-bot/pull/2243
Version 13.1
============
*Released 2020-11-29*
+1 -1
View File
@@ -1 +1 @@
include LICENSE LICENSE.lesser Makefile requirements.txt py.typed
include LICENSE LICENSE.lesser Makefile requirements.txt README_RAW.rst telegram/py.typed
+34 -10
View File
@@ -1,3 +1,6 @@
..
Make user to apply any changes to this file to README_RAW.rst as well!
.. image:: https://github.com/python-telegram-bot/logos/blob/master/logo-text/png/ptb-logo-text_768.png?raw=true
:align: center
:target: https://python-telegram-bot.org
@@ -17,26 +20,30 @@ We have a vibrant community of developers helping each other in our `Telegram gr
:target: https://pypi.org/project/python-telegram-bot/
:alt: Supported Python versions
.. image:: https://cpu.re/static/python-telegram-bot/downloads.svg
:target: https://www.cpu.re/static/python-telegram-bot/downloads-by-python-version.txt
.. image:: https://img.shields.io/badge/Bot%20API-5.0-blue?logo=telegram
:target: https://core.telegram.org/bots/api-changelog
:alt: Supported Bot API versions
.. image:: https://img.shields.io/pypi/dm/python-telegram-bot
:target: https://pypistats.org/packages/python-telegram-bot
:alt: PyPi Package Monthly Download
.. image:: https://img.shields.io/badge/docs-latest-af1a97.svg
:target: https://python-telegram-bot.readthedocs.io/
.. image:: https://readthedocs.org/projects/python-telegram-bot/badge/?version=stable
:target: https://python-telegram-bot.readthedocs.io/en/stable/?badge=stable
:alt: Documentation Status
.. image:: https://img.shields.io/pypi/l/python-telegram-bot.svg
:target: https://www.gnu.org/licenses/lgpl-3.0.html
:alt: LGPLv3 License
.. image:: https://github.com/python-telegram-bot/python-telegram-bot/workflows/GitHub%20Actions/badge.svg?event=schedule
.. image:: https://github.com/python-telegram-bot/python-telegram-bot/workflows/GitHub%20Actions/badge.svg
:target: https://github.com/python-telegram-bot/python-telegram-bot/
:alt: Github Actions workflow
.. image:: https://codecov.io/gh/python-telegram-bot/python-telegram-bot/branch/master/graph/badge.svg
:target: https://codecov.io/gh/python-telegram-bot/python-telegram-bot
:alt: Code coverage
.. image:: http://isitmaintained.com/badge/resolution/python-telegram-bot/python-telegram-bot.svg
:target: http://isitmaintained.com/project/python-telegram-bot/python-telegram-bot
:alt: Median time to resolve an issue
@@ -48,7 +55,7 @@ We have a vibrant community of developers helping each other in our `Telegram gr
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/psf/black
.. image:: https://img.shields.io/badge/Telegram-Group-blue.svg
.. image:: https://img.shields.io/badge/Telegram-Group-blue.svg?logo=telegram
:target: https://telegram.me/pythontelegrambotgroup
:alt: Telegram Group
@@ -92,11 +99,19 @@ In addition to the pure API implementation, this library features a number of hi
make the development of bots easy and straightforward. These classes are contained in the
``telegram.ext`` submodule.
A pure API implementation *without* ``telegram.ext`` is available as the standalone package ``python-telegram-bot-raw``. `See here for details. <https://github.com/python-telegram-bot/python-telegram-bot/blob/master/README_RAW.rst>`_
----
Note
----
Installing both ``python-telegram-bot`` and ``python-telegram-bot-raw`` in conjunction will result in undesired side-effects, so only install *one* of both.
====================
Telegram API support
====================
All types and methods of the Telegram Bot API **4.8** are supported.
All types and methods of the Telegram Bot API **5.0** are supported.
==========
Installing
@@ -122,6 +137,16 @@ In case you have a previously cloned local repository already, you should initia
$ git submodule update --init --recursive
---------------------
Optional Dependencies
---------------------
PTB can be installed with optional dependencies:
* ``pip install python-telegram-bot[passport]`` installs the `cryptography <https://cryptography.io>`_ library. Use this, if you want to use Telegram Passport related functionality.
* ``pip install python-telegram-bot[ujson]`` installs the `ujson <https://pypi.org/project/ujson/>`_ library. It will then be used for JSON de- & encoding, which can bring speed up compared to the standard `json <https://docs.python.org/3/library/json.html>`_ library.
* ``pip install python-telegram-bot[socks]`` installs the `PySocks <https://pypi.org/project/PySocks/>`_ library. Use this, if you want to work behind a Socks5 server.
===============
Getting started
===============
@@ -192,14 +217,13 @@ You can get help in several ways:
2. In case you are unable to join our group due to Telegram restrictions, you can use our `IRC channel <https://webchat.freenode.net/?channels=##python-telegram-bot>`_.
3. Report bugs, request new features or ask questions by `creating an issue <https://github.com/python-telegram-bot/python-telegram-bot/issues/new/choose>`_.
3. Report bugs, request new features or ask questions by `creating an issue <https://github.com/python-telegram-bot/python-telegram-bot/issues/new/choose>`_ or `a discussion <https://github.com/python-telegram-bot/python-telegram-bot/discussions/new>`_.
4. Our `Wiki pages <https://github.com/python-telegram-bot/python-telegram-bot/wiki/>`_ offer a growing amount of resources.
5. You can even ask for help on Stack Overflow using the `python-telegram-bot tag <https://stackoverflow.com/questions/tagged/python-telegram-bot>`_.
============
Contributing
============
+219
View File
@@ -0,0 +1,219 @@
..
Make user to apply any changes to this file to README.rst as well!
.. image:: https://github.com/python-telegram-bot/logos/blob/master/logo-text/png/ptb-raw-logo-text_768.png?raw=true
:align: center
:target: https://python-telegram-bot.org
:alt: python-telegram-bot-raw Logo
We have made you a wrapper you can't refuse
We have a vibrant community of developers helping each other in our `Telegram group <https://telegram.me/pythontelegrambotgroup>`_. Join us!
*Stay tuned for library updates and new releases on our* `Telegram Channel <https://telegram.me/pythontelegrambotchannel>`_.
.. image:: https://img.shields.io/pypi/v/python-telegram-bot-raw.svg
:target: https://pypi.org/project/python-telegram-bot-raw/
:alt: PyPi Package Version
.. image:: https://img.shields.io/pypi/pyversions/python-telegram-bot-raw.svg
:target: https://pypi.org/project/python-telegram-bot-raw/
:alt: Supported Python versions
.. image:: https://img.shields.io/badge/Bot%20API-5.0-blue?logo=telegram
:target: https://core.telegram.org/bots/api-changelog
:alt: Supported Bot API versions
.. image:: https://img.shields.io/pypi/dm/python-telegram-bot-raw
:target: https://pypistats.org/packages/python-telegram-bot-raw
:alt: PyPi Package Monthly Download
.. image:: https://readthedocs.org/projects/python-telegram-bot/badge/?version=stable
:target: https://python-telegram-bot.readthedocs.io/
:alt: Documentation Status
.. image:: https://img.shields.io/pypi/l/python-telegram-bot-raw.svg
:target: https://www.gnu.org/licenses/lgpl-3.0.html
:alt: LGPLv3 License
.. image:: https://github.com/python-telegram-bot/python-telegram-bot/workflows/GitHub%20Actions/badge.svg
:target: https://github.com/python-telegram-bot/python-telegram-bot/
:alt: Github Actions workflow
.. image:: https://codecov.io/gh/python-telegram-bot/python-telegram-bot/branch/master/graph/badge.svg
:target: https://codecov.io/gh/python-telegram-bot/python-telegram-bot
:alt: Code coverage
.. image:: http://isitmaintained.com/badge/resolution/python-telegram-bot/python-telegram-bot.svg
:target: http://isitmaintained.com/project/python-telegram-bot/python-telegram-bot
:alt: Median time to resolve an issue
.. image:: https://api.codacy.com/project/badge/Grade/99d901eaa09b44b4819aec05c330c968
:target: https://www.codacy.com/app/python-telegram-bot/python-telegram-bot?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=python-telegram-bot/python-telegram-bot&amp;utm_campaign=Badge_Grade
:alt: Code quality
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/psf/black
.. image:: https://img.shields.io/badge/Telegram-Group-blue.svg?logo=telegram
:target: https://telegram.me/pythontelegrambotgroup
:alt: Telegram Group
.. image:: https://img.shields.io/badge/IRC-Channel-blue.svg
:target: https://webchat.freenode.net/?channels=##python-telegram-bot
:alt: IRC Bridge
=================
Table of contents
=================
- `Introduction`_
- `Telegram API support`_
- `Installing`_
- `Getting started`_
#. `Logging`_
#. `Documentation`_
- `Getting help`_
- `Contributing`_
- `License`_
============
Introduction
============
This library provides a pure Python, lightweight interface for the
`Telegram Bot API <https://core.telegram.org/bots/api>`_.
It's compatible with Python versions 3.6+. PTB-Raw might also work on `PyPy <http://pypy.org/>`_, though there have been a lot of issues before. Hence, PyPy is not officially supported.
``python-telegram-bot-raw`` is part of the `python-telegram-bot <https://python-telegram-bot.org>`_ ecosystem and provides the pure API functionality extracted from PTB. It therefore does *not* have independent release schedules, changelogs or documentation. Please consult the PTB resources.
----
Note
----
Installing both ``python-telegram-bot`` and ``python-telegram-bot-raw`` in conjunction will result in undesired side-effects, so only install *one* of both.
====================
Telegram API support
====================
All types and methods of the Telegram Bot API **5.0** are supported.
==========
Installing
==========
You can install or upgrade python-telegram-bot-raw with:
.. code:: shell
$ pip install python-telegram-bot-raw --upgrade
Or you can install from source with:
.. code:: shell
$ git clone https://github.com/python-telegram-bot/python-telegram-bot --recursive
$ cd python-telegram-bot
$ python setup-raw.py install
In case you have a previously cloned local repository already, you should initialize the added urllib3 submodule before installing with:
.. code:: shell
$ git submodule update --init --recursive
----
Note
----
Installing the `.tar.gz` archive available on PyPi directly via `pip` will *not* work as expected, as `pip` does not recognize that it should use `setup-raw.py` instead of `setup.py`.
---------------------
Optional Dependencies
---------------------
PTB can be installed with optional dependencies:
* ``pip install python-telegram-bot-raw[passport]`` installs the `cryptography <https://cryptography.io>`_ library. Use this, if you want to use Telegram Passport related functionality.
* ``pip install python-telegram-bot-raw[ujson]`` installs the `ujson <https://pypi.org/project/ujson/>`_ library. It will then be used for JSON de- & encoding, which can bring speed up compared to the standard `json <https://docs.python.org/3/library/json.html>`_ library.
===============
Getting started
===============
Our Wiki contains an `Introduction to the API <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Introduction-to-the-API>`_. Other references are:
- the `Telegram API documentation <https://core.telegram.org/bots/api>`_
- the `python-telegram-bot documentation <https://python-telegram-bot.readthedocs.io/>`_
-------
Logging
-------
This library uses the ``logging`` module. To set up logging to standard output, put:
.. code:: python
import logging
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
at the beginning of your script.
You can also use logs in your application by calling ``logging.getLogger()`` and setting the log level you want:
.. code:: python
logger = logging.getLogger()
logger.setLevel(logging.INFO)
If you want DEBUG logs instead:
.. code:: python
logger.setLevel(logging.DEBUG)
=============
Documentation
=============
``python-telegram-bot``'s documentation lives at `readthedocs.io <https://python-telegram-bot.readthedocs.io/>`_, which
includes the relevant documentation for ``python-telegram-bot-raw``.
============
Getting help
============
You can get help in several ways:
1. We have a vibrant community of developers helping each other in our `Telegram group <https://telegram.me/pythontelegrambotgroup>`_. Join us!
2. In case you are unable to join our group due to Telegram restrictions, you can use our `IRC channel <https://webchat.freenode.net/?channels=##python-telegram-bot>`_.
3. Report bugs, request new features or ask questions by `creating an issue <https://github.com/python-telegram-bot/python-telegram-bot/issues/new/choose>`_ or `a discussion <https://github.com/python-telegram-bot/python-telegram-bot/discussions/new>`_.
4. Our `Wiki pages <https://github.com/python-telegram-bot/python-telegram-bot/wiki/>`_ offer a growing amount of resources.
5. You can even ask for help on Stack Overflow using the `python-telegram-bot tag <https://stackoverflow.com/questions/tagged/python-telegram-bot>`_.
============
Contributing
============
Contributions of all sizes are welcome. Please review our `contribution guidelines <https://github.com/python-telegram-bot/python-telegram-bot/blob/master/.github/CONTRIBUTING.rst>`_ to get started. You can also help by `reporting bugs <https://github.com/python-telegram-bot/python-telegram-bot/issues/new>`_.
=======
License
=======
You may copy, distribute and modify the software provided that modifications are described and licensed for free under `LGPL-3 <https://www.gnu.org/licenses/lgpl-3.0.html>`_. Derivatives works (including modifications or anything statically linked to the library) can only be redistributed under LGPL-3, but applications that use the library don't have to be.
+6 -3
View File
@@ -33,6 +33,9 @@ extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.napoleon'
]
# Don't show type hints in the signature - that just makes it hardly readable
# and we document the types anyway
autodoc_typehints = 'description'
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
@@ -50,7 +53,7 @@ master_doc = 'index'
# General information about the project.
project = u'Python Telegram Bot'
copyright = u'2015-2020, Leandro Toledo'
copyright = u'2015-2021, Leandro Toledo'
author = u'Leandro Toledo'
# The version info for the project you're documenting, acts as replacement for
@@ -58,9 +61,9 @@ author = u'Leandro Toledo'
# built documents.
#
# The short X.Y version.
version = '13.1' # telegram.__version__[:3]
version = '13.3' # telegram.__version__[:3]
# The full version, including alpha/beta/rc tags.
release = '13.1' # telegram.__version__
release = '13.3' # telegram.__version__
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
+12 -5
View File
@@ -6,13 +6,12 @@ telegram.ext package
telegram.ext.updater
telegram.ext.dispatcher
telegram.ext.dispatcherhandlerstop
telegram.ext.filters
telegram.ext.callbackcontext
telegram.ext.defaults
telegram.ext.job
telegram.ext.jobqueue
telegram.ext.messagequeue
telegram.ext.delayqueue
telegram.ext.callbackcontext
telegram.ext.defaults
Handlers
--------
@@ -22,10 +21,11 @@ Handlers
telegram.ext.handler
telegram.ext.callbackqueryhandler
telegram.ext.choseninlineresulthandler
telegram.ext.conversationhandler
telegram.ext.commandhandler
telegram.ext.conversationhandler
telegram.ext.inlinequeryhandler
telegram.ext.messagehandler
telegram.ext.filters
telegram.ext.pollanswerhandler
telegram.ext.pollhandler
telegram.ext.precheckoutqueryhandler
@@ -43,4 +43,11 @@ Persistence
telegram.ext.basepersistence
telegram.ext.picklepersistence
telegram.ext.dictpersistence
telegram.ext.dictpersistence
utils
-----
.. toctree::
telegram.ext.utils.promise
@@ -0,0 +1,6 @@
telegram.ext.utils.promise.Promise
==================================
.. autoclass:: telegram.ext.utils.promise.Promise
:members:
:show-inheritance:
+1
View File
@@ -140,6 +140,7 @@ Passport
telegram.credentials
telegram.datacredentials
telegram.securedata
telegram.securevalue
telegram.filecredentials
telegram.iddocumentdata
telegram.personaldetails
+6
View File
@@ -0,0 +1,6 @@
telegram.SecureValue
====================
.. autoclass:: telegram.SecureValue
:members:
:show-inheritance:
+6 -3
View File
@@ -1,6 +1,9 @@
telegram.utils.promise.Promise
==============================
.. autoclass:: telegram.utils.promise.Promise
:members:
:show-inheritance:
.. py:class:: telegram.utils.promise.Promise
Shortcut for :class:`telegram.ext.utils.promise.Promise`.
.. deprecated:: 13.2
Use :class:`telegram.ext.utils.promise.Promise` instead.
+1 -4
View File
@@ -1,5 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# pylint: disable=W0613, C0116
# type: ignore[union-attr]
# This program is dedicated to the public domain under the CC0 license.
@@ -128,9 +127,7 @@ def cancel(update: Update, context: CallbackContext) -> int:
def main() -> None:
# Create the Updater and pass it your bot's token.
# Make sure to set use_context=True to use the new context based callbacks
# Post version 12 this will no longer be necessary
updater = Updater("TOKEN", use_context=True)
updater = Updater("TOKEN")
# Get the dispatcher to register handlers
dispatcher = updater.dispatcher
+1 -4
View File
@@ -1,5 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# pylint: disable=W0613, C0116
# type: ignore[union-attr]
# This program is dedicated to the public domain under the CC0 license.
@@ -113,9 +112,7 @@ def done(update: Update, context: CallbackContext) -> int:
def main() -> None:
# Create the Updater and pass it your bot's token.
# Make sure to set use_context=True to use the new context based callbacks
# Post version 12 this will no longer be necessary
updater = Updater("TOKEN", use_context=True)
updater = Updater("TOKEN")
# Get the dispatcher to register handlers
dispatcher = updater.dispatcher
+48 -12
View File
@@ -1,5 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# pylint: disable=W0613, C0116
# type: ignore[union-attr]
# This program is dedicated to the public domain under the CC0 license.
@@ -23,27 +22,37 @@ bot.
import logging
from telegram import ParseMode, InlineKeyboardMarkup, InlineKeyboardButton, Update
from telegram.ext import Updater, CommandHandler, Filters, CallbackContext
from telegram.ext import (
Updater,
CommandHandler,
CallbackQueryHandler,
Filters,
CallbackContext,
)
# Enable logging
from telegram.utils import helpers
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
)
logger = logging.getLogger(__name__)
# Define constants that will allow us to reuse the deep-linking parameters.
CHECK_THIS_OUT = 'check-this-out'
USING_ENTITIES = 'using-entities-here'
SO_COOL = 'so-cool'
CHECK_THIS_OUT = "check-this-out"
USING_ENTITIES = "using-entities-here"
USING_KEYBOARD = "using-keyboard-here"
SO_COOL = "so-cool"
# Callback data to pass in 3rd level deeplinking
KEYBOARD_CALLBACKDATA = "keyboard-callback-data"
def start(update: Update, context: CallbackContext) -> None:
"""Send a deep-linked URL when the command /start is issued."""
bot = context.bot
url = helpers.create_deep_linked_url(bot.get_me().username, CHECK_THIS_OUT, group=True)
url = helpers.create_deep_linked_url(bot.username, CHECK_THIS_OUT, group=True)
text = "Feel free to tell your friends about it:\n\n" + url
update.message.reply_text(text)
@@ -51,13 +60,13 @@ def start(update: Update, context: CallbackContext) -> None:
def deep_linked_level_1(update: Update, context: CallbackContext) -> None:
"""Reached through the CHECK_THIS_OUT payload"""
bot = context.bot
url = helpers.create_deep_linked_url(bot.get_me().username, SO_COOL)
url = helpers.create_deep_linked_url(bot.username, SO_COOL)
text = (
"Awesome, you just accessed hidden functionality! "
" Now let's get back to the private chat."
)
keyboard = InlineKeyboardMarkup.from_button(
InlineKeyboardButton(text='Continue here!', url=url)
InlineKeyboardButton(text="Continue here!", url=url)
)
update.message.reply_text(text, reply_markup=keyboard)
@@ -65,13 +74,30 @@ def deep_linked_level_1(update: Update, context: CallbackContext) -> None:
def deep_linked_level_2(update: Update, context: CallbackContext) -> None:
"""Reached through the SO_COOL payload"""
bot = context.bot
url = helpers.create_deep_linked_url(bot.get_me().username, USING_ENTITIES)
url = helpers.create_deep_linked_url(bot.username, USING_ENTITIES)
text = f"You can also mask the deep-linked URLs as links: [▶️ CLICK HERE]({url})."
update.message.reply_text(text, parse_mode=ParseMode.MARKDOWN, disable_web_page_preview=True)
def deep_linked_level_3(update: Update, context: CallbackContext) -> None:
"""Reached through the USING_ENTITIES payload"""
update.message.reply_text(
"It is also possible to make deep-linking using InlineKeyboardButtons.",
reply_markup=InlineKeyboardMarkup(
[[InlineKeyboardButton(text="Like this!", callback_data=KEYBOARD_CALLBACKDATA)]]
),
)
def deep_link_level_3_callback(update: Update, context: CallbackContext) -> None:
"""Answers CallbackQuery with deeplinking url."""
bot = context.bot
url = helpers.create_deep_linked_url(bot.username, USING_KEYBOARD)
update.callback_query.answer(url=url)
def deep_linked_level_4(update: Update, context: CallbackContext) -> None:
"""Reached through the USING_KEYBOARD payload"""
payload = context.args
update.message.reply_text(
f"Congratulations! This is as deep as it gets 👏🏻\n\nThe payload was: {payload}"
@@ -81,7 +107,7 @@ def deep_linked_level_3(update: Update, context: CallbackContext) -> None:
def main():
"""Start the bot."""
# Create the Updater and pass it your bot's token.
updater = Updater("TOKEN", use_context=True)
updater = Updater("TOKEN")
# Get the dispatcher to register handlers
dispatcher = updater.dispatcher
@@ -102,6 +128,16 @@ def main():
CommandHandler("start", deep_linked_level_3, Filters.regex(USING_ENTITIES), pass_args=True)
)
# Possible with inline keyboard buttons aswell
dispatcher.add_handler(
CommandHandler("start", deep_linked_level_4, Filters.regex(USING_KEYBOARD))
)
# register callback handler for inline keyboard button
dispatcher.add_handler(
CallbackQueryHandler(deep_link_level_3_callback, pattern=KEYBOARD_CALLBACKDATA)
)
# Make sure the deep-linking handlers occur *before* the normal /start handler.
dispatcher.add_handler(CommandHandler("start", start))
@@ -114,5 +150,5 @@ def main():
updater.idle()
if __name__ == '__main__':
if __name__ == "__main__":
main()
+1 -4
View File
@@ -1,5 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# pylint: disable=W0613, C0116
# type: ignore[union-attr]
# This program is dedicated to the public domain under the CC0 license.
@@ -50,9 +49,7 @@ def echo(update: Update, context: CallbackContext) -> None:
def main():
"""Start the bot."""
# Create the Updater and pass it your bot's token.
# Make sure to set use_context=True to use the new context based callbacks
# Post version 12 this will no longer be necessary
updater = Updater("TOKEN", use_context=True)
updater = Updater("TOKEN")
# Get the dispatcher to register handlers
dispatcher = updater.dispatcher
+1 -4
View File
@@ -1,5 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# pylint: disable=W0613, C0116
# type: ignore[union-attr]
# This program is dedicated to the public domain under the CC0 license.
@@ -68,9 +67,7 @@ def start(update: Update, context: CallbackContext) -> None:
def main():
# Create the Updater and pass it your bot's token.
# Make sure to set use_context=True to use the new context based callbacks
# Post version 12 this will no longer be necessary
updater = Updater(BOT_TOKEN, use_context=True)
updater = Updater(BOT_TOKEN)
# Get the dispatcher to register handlers
dispatcher = updater.dispatcher
+1 -4
View File
@@ -1,5 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# pylint: disable=W0613, C0116
# type: ignore[union-attr]
# This program is dedicated to the public domain under the CC0 license.
@@ -69,9 +68,7 @@ def inlinequery(update: Update, context: CallbackContext) -> None:
def main() -> None:
# Create the Updater and pass it your bot's token.
# Make sure to set use_context=True to use the new context based callbacks
# Post version 12 this will no longer be necessary
updater = Updater("TOKEN", use_context=True)
updater = Updater("TOKEN")
# Get the dispatcher to register handlers
dispatcher = updater.dispatcher
+1 -4
View File
@@ -1,5 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# pylint: disable=W0613, C0116
# type: ignore[union-attr]
# This program is dedicated to the public domain under the CC0 license.
@@ -48,9 +47,7 @@ def help_command(update: Update, context: CallbackContext) -> None:
def main():
# Create the Updater and pass it your bot's token.
# Make sure to set use_context=True to use the new context based callbacks
# Post version 12 this will no longer be necessary
updater = Updater("TOKEN", use_context=True)
updater = Updater("TOKEN")
updater.dispatcher.add_handler(CommandHandler('start', start))
updater.dispatcher.add_handler(CallbackQueryHandler(button))
+1 -2
View File
@@ -1,5 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# pylint: disable=W0613, C0116
# type: ignore[union-attr]
# This program is dedicated to the public domain under the CC0 license.
@@ -162,7 +161,7 @@ def end(update: Update, context: CallbackContext) -> None:
def main():
# Create the Updater and pass it your bot's token.
updater = Updater("TOKEN", use_context=True)
updater = Updater("TOKEN")
# Get the dispatcher to register handlers
dispatcher = updater.dispatcher
+1 -4
View File
@@ -1,5 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# pylint: disable=W0613, C0116
# type: ignore[union-attr]
# This program is dedicated to the public domain under the CC0 license.
@@ -302,9 +301,7 @@ def stop_nested(update: Update, context: CallbackContext) -> None:
def main():
# Create the Updater and pass it your bot's token.
# Make sure to set use_context=True to use the new context based callbacks
# Post version 12 this will no longer be necessary
updater = Updater("TOKEN", use_context=True)
updater = Updater("TOKEN")
# Get the dispatcher to register handlers
dispatcher = updater.dispatcher
-1
View File
@@ -1,5 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# pylint: disable=W0613, C0116
# type: ignore[union-attr]
# This program is dedicated to the public domain under the CC0 license.
+1 -4
View File
@@ -1,5 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# pylint: disable=W0613, C0116
# type: ignore[union-attr]
# This program is dedicated to the public domain under the CC0 license.
@@ -128,9 +127,7 @@ def successful_payment_callback(update: Update, context: CallbackContext) -> Non
def main():
# Create the Updater and pass it your bot's token.
# Make sure to set use_context=True to use the new context based callbacks
# Post version 12 this will no longer be necessary
updater = Updater("TOKEN", use_context=True)
updater = Updater("TOKEN")
# Get the dispatcher to register handlers
dispatcher = updater.dispatcher
+2 -3
View File
@@ -1,5 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# pylint: disable=W0613, C0116, C0103
# type: ignore[union-attr]
# This program is dedicated to the public domain under the CC0 license.
@@ -123,7 +122,7 @@ def done(update: Update, context: CallbackContext) -> None:
del context.user_data['choice']
update.message.reply_text(
"I learned these facts about you:" f"{facts_to_str(context.user_data)}" "Until next time!"
"I learned these facts about you:" f"{facts_to_str(context.user_data)} Until next time!"
)
return ConversationHandler.END
@@ -131,7 +130,7 @@ def done(update: Update, context: CallbackContext) -> None:
def main():
# Create the Updater and pass it your bot's token.
pp = PicklePersistence(filename='conversationbot')
updater = Updater("TOKEN", persistence=pp, use_context=True)
updater = Updater("TOKEN", persistence=pp)
# Get the dispatcher to register handlers
dp = updater.dispatcher
+2 -5
View File
@@ -1,5 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# pylint: disable=W0613, C0116
# type: ignore[union-attr]
# This program is dedicated to the public domain under the CC0 license.
@@ -149,14 +148,12 @@ def receive_poll(update: Update, context: CallbackContext) -> None:
def help_handler(update: Update, context: CallbackContext) -> None:
"""Display a help message"""
update.message.reply_text("Use /quiz, /poll or /preview to test this " "bot.")
update.message.reply_text("Use /quiz, /poll or /preview to test this bot.")
def main() -> None:
# Create the Updater and pass it your bot's token.
# Make sure to set use_context=True to use the new context based callbacks
# Post version 12 this will no longer be necessary
updater = Updater("TOKEN", use_context=True)
updater = Updater("TOKEN")
dispatcher = updater.dispatcher
dispatcher.add_handler(CommandHandler('start', start))
dispatcher.add_handler(CommandHandler('poll', poll))
+4 -4
View File
@@ -1,9 +1,8 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# pylint: disable=W0603
"""Simple Bot to reply to Telegram messages.
This is built on the API wrapper, see rawapibot.py to see the same example built
This is built on the API wrapper, see echobot.py to see the same example built
on the telegram.ext bot framework.
This program is dedicated to the public domain under the CC0 license.
"""
@@ -51,8 +50,9 @@ def echo(bot: telegram.Bot) -> None:
UPDATE_ID = update.update_id + 1
if update.message: # your bot can receive updates without messages
# Reply to the message
update.message.reply_text(update.message.text)
if update.message.text: # not all messages contain text
# Reply to the message
update.message.reply_text(update.message.text)
if __name__ == '__main__':
+1 -4
View File
@@ -1,5 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# pylint: disable=W0613, C0116
# type: ignore[union-attr]
# This program is dedicated to the public domain under the CC0 license.
@@ -88,9 +87,7 @@ def unset(update: Update, context: CallbackContext) -> None:
def main():
"""Run bot."""
# Create the Updater and pass it your bot's token.
# Make sure to set use_context=True to use the new context based callbacks
# Post version 12 this will no longer be necessary
updater = Updater("TOKEN", use_context=True)
updater = Updater("TOKEN")
# Get the dispatcher to register handlers
dispatcher = updater.dispatcher
+6 -4
View File
@@ -1,13 +1,15 @@
# cryptography is an optional dependency, but running the tests properly requires it
cryptography!=3.4,!=3.4.1,!=3.4.2,!=3.4.3
pre-commit
# Make sure that the versions specified here match the pre-commit settings
black==20.8b1
flake8==3.8.4
pylint==2.6.0
mypy==0.790
mypy==0.800
pyupgrade==2.10.0
pytest==4.2.0
# Need older attrs version for pytest 4.2.0
attrs==19.1.0
pytest==6.2.2
flaky
beautifulsoup4
+1 -2
View File
@@ -1,6 +1,5 @@
certifi
# only telegram.ext: # Keep this line here; used in setup(-raw).py
tornado>=5.1
cryptography
decorator>=4.4.0
APScheduler==3.6.3
pytz>=2018.6
+7
View File
@@ -0,0 +1,7 @@
#!/usr/bin/env python
"""The setup and build script for the python-telegram-bot-raw library."""
from setuptools import setup
from setup import get_setup_kwargs
setup(**get_setup_kwargs(raw=True))
+4 -2
View File
@@ -13,7 +13,7 @@ upload-dir = docs/build/html
max-line-length = 99
ignore = W503, W605
extend-ignore = E203
exclude = setup.py, docs/source/conf.py, telegram/vendor
exclude = setup.py, setup-raw.py docs/source/conf.py, telegram/vendor
[pylint]
ignore=vendor
@@ -27,7 +27,9 @@ addopts = --no-success-flaky-report -rsxX
filterwarnings =
error
ignore::DeprecationWarning
ignore::telegram.utils.deprecate.TelegramDeprecationWarning
; Unfortunately due to https://github.com/pytest-dev/pytest/issues/8343 we can't have this here
; and instead do a trick directly in tests/conftest.py
; ignore::telegram.utils.deprecate.TelegramDeprecationWarning
[coverage:run]
branch = True
+99 -44
View File
@@ -3,67 +3,122 @@
import codecs
import os
import subprocess
import sys
from setuptools import setup, find_packages
UPSTREAM_URLLIB3_FLAG = '--with-upstream-urllib3'
def requirements():
def get_requirements(raw=False):
"""Build the requirements list for this project"""
requirements_list = []
with open('requirements.txt') as requirements:
for install in requirements:
with open('requirements.txt') as reqs:
for install in reqs:
if install.startswith('# only telegram.ext:'):
if raw:
break
continue
requirements_list.append(install.strip())
return requirements_list
packages = find_packages(exclude=['tests*'])
requirements = requirements()
def get_packages_requirements(raw=False):
"""Build the package & requirements list for this project"""
reqs = get_requirements(raw=raw)
# Allow for a package install to not use the vendored urllib3
UPSTREAM_URLLIB3_FLAG = '--with-upstream-urllib3'
if UPSTREAM_URLLIB3_FLAG in sys.argv:
sys.argv.remove(UPSTREAM_URLLIB3_FLAG)
requirements.append('urllib3 >= 1.19.1')
packages = [x for x in packages if not x.startswith('telegram.vendor.ptb_urllib3')]
exclude = ['tests*']
if raw:
exclude.append('telegram.ext*')
packs = find_packages(exclude=exclude)
# Allow for a package install to not use the vendored urllib3
if UPSTREAM_URLLIB3_FLAG in sys.argv:
sys.argv.remove(UPSTREAM_URLLIB3_FLAG)
reqs.append('urllib3 >= 1.19.1')
packs = [x for x in packs if not x.startswith('telegram.vendor.ptb_urllib3')]
return packs, reqs
def get_setup_kwargs(raw=False):
"""Builds a dictionary of kwargs for the setup function"""
packages, requirements = get_packages_requirements(raw=raw)
raw_ext = "-raw" if raw else ""
readme = f'README{"_RAW" if raw else ""}.rst'
with codecs.open('README.rst', 'r', 'utf-8') as fd:
fn = os.path.join('telegram', 'version.py')
with open(fn) as fh:
code = compile(fh.read(), fn, 'exec')
exec(code)
setup(name='python-telegram-bot',
version=__version__,
author='Leandro Toledo',
author_email='devs@python-telegram-bot.org',
license='LGPLv3',
url='https://python-telegram-bot.org/',
keywords='python telegram bot api wrapper',
description="We have made you a wrapper you can't refuse",
long_description=fd.read(),
packages=packages,
package_data={'telegram': ['py.typed']},
install_requires=requirements,
extras_require={
'json': 'ujson',
'socks': 'PySocks'
},
include_package_data=True,
classifiers=[
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)',
'Operating System :: OS Independent',
'Topic :: Software Development :: Libraries :: Python Modules',
'Topic :: Communications :: Chat',
'Topic :: Internet',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
],)
with open(readme, 'r', encoding='utf-8') as fd:
kwargs = dict(
script_name=f'setup{raw_ext}.py',
name=f'python-telegram-bot{raw_ext}',
version=locals()['__version__'],
author='Leandro Toledo',
author_email='devs@python-telegram-bot.org',
license='LGPLv3',
url='https://python-telegram-bot.org/',
# Keywords supported by PyPI can be found at https://git.io/JtLIZ
project_urls={
"Documentation": "https://python-telegram-bot.readthedocs.io",
"Bug Tracker": "https://github.com/python-telegram-bot/python-telegram-bot/issues",
"Source Code": "https://github.com/python-telegram-bot/python-telegram-bot",
"News": "https://t.me/pythontelegrambotchannel",
"Changelog": "https://python-telegram-bot.readthedocs.io/en/stable/changelog.html",
},
download_url=f'https://pypi.org/project/python-telegram-bot{raw_ext}/',
keywords='python telegram bot api wrapper',
description="We have made you a wrapper you can't refuse",
long_description=fd.read(),
long_description_content_type='text/x-rst',
packages=packages,
install_requires=requirements,
extras_require={
'json': 'ujson',
'socks': 'PySocks',
# 3.4-3.4.3 contained some cyclical import bugs
'passport': 'cryptography!=3.4,!=3.4.1,!=3.4.2,!=3.4.3',
},
include_package_data=True,
classifiers=[
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)',
'Operating System :: OS Independent',
'Topic :: Software Development :: Libraries :: Python Modules',
'Topic :: Communications :: Chat',
'Topic :: Internet',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
],
python_requires='>=3.6'
)
return kwargs
def main():
# If we're building, build ptb-raw as well
if set(sys.argv[1:]) in [{'bdist_wheel'}, {'sdist'}, {'sdist', 'bdist_wheel'}]:
args = ['python', 'setup-raw.py']
args.extend(sys.argv[1:])
subprocess.run(args, check=True, capture_output=True)
setup(**get_setup_kwargs(raw=False))
if __name__ == '__main__':
main()
+73 -74
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -139,6 +139,7 @@ from .passport.credentials import (
Credentials,
DataCredentials,
SecureData,
SecureValue,
FileCredentials,
TelegramDecryptionError,
)
@@ -147,24 +148,37 @@ from .version import __version__ # noqa: F401
__author__ = 'devs@python-telegram-bot.org'
__all__ = [
__all__ = ( # Keep this alphabetically ordered
'Animation',
'Audio',
'Bot',
'BotCommand',
'CallbackGame',
'CallbackQuery',
'Chat',
'ChatAction',
'ChatLocation',
'ChatMember',
'ChatPermissions',
'ChatAction',
'ChatPhoto',
'ChosenInlineResult',
'CallbackQuery',
'Contact',
'Credentials',
'DataCredentials',
'Dice',
'Document',
'EncryptedCredentials',
'EncryptedPassportElement',
'File',
'FileCredentials',
'ForceReply',
'Game',
'GameHighScore',
'IdDocumentData',
'InlineKeyboardButton',
'InlineKeyboardMarkup',
'InlineQuery',
'InlineQueryResult',
'InlineQueryResult',
'InlineQueryResultArticle',
'InlineQueryResultAudio',
'InlineQueryResultCachedAudio',
@@ -177,6 +191,7 @@ __all__ = [
'InlineQueryResultCachedVoice',
'InlineQueryResultContact',
'InlineQueryResultDocument',
'InlineQueryResultGame',
'InlineQueryResultGif',
'InlineQueryResultLocation',
'InlineQueryResultMpeg4Gif',
@@ -184,28 +199,70 @@ __all__ = [
'InlineQueryResultVenue',
'InlineQueryResultVideo',
'InlineQueryResultVoice',
'InlineQueryResultGame',
'InputContactMessageContent',
'InputFile',
'InputLocationMessageContent',
'InputMedia',
'InputMediaAnimation',
'InputMediaAudio',
'InputMediaDocument',
'InputMediaPhoto',
'InputMediaVideo',
'InputMessageContent',
'InputTextMessageContent',
'InputVenueMessageContent',
'Invoice',
'KeyboardButton',
'KeyboardButtonPollType',
'LabeledPrice',
'Location',
'ChatLocation',
'ProximityAlertTriggered',
'EncryptedCredentials',
'PassportFile',
'EncryptedPassportElement',
'PassportData',
'LoginUrl',
'MAX_CAPTION_LENGTH',
'MAX_FILESIZE_DOWNLOAD',
'MAX_FILESIZE_UPLOAD',
'MAX_MESSAGES_PER_MINUTE_PER_GROUP',
'MAX_MESSAGES_PER_SECOND',
'MAX_MESSAGES_PER_SECOND_PER_CHAT',
'MAX_MESSAGE_LENGTH',
'MaskPosition',
'Message',
'MessageEntity',
'MessageId',
'OrderInfo',
'ParseMode',
'PassportData',
'PassportElementError',
'PassportElementErrorDataField',
'PassportElementErrorFile',
'PassportElementErrorFiles',
'PassportElementErrorFrontSide',
'PassportElementErrorReverseSide',
'PassportElementErrorSelfie',
'PassportElementErrorTranslationFile',
'PassportElementErrorTranslationFiles',
'PassportElementErrorUnspecified',
'PassportFile',
'PersonalDetails',
'PhotoSize',
'ReplyKeyboardRemove',
'Poll',
'PollAnswer',
'PollOption',
'PreCheckoutQuery',
'ProximityAlertTriggered',
'ReplyKeyboardMarkup',
'ReplyKeyboardRemove',
'ReplyMarkup',
'ResidentialAddress',
'SUPPORTED_WEBHOOK_PORTS',
'SecureData',
'SecureValue',
'ShippingAddress',
'ShippingOption',
'ShippingQuery',
'Sticker',
'StickerSet',
'SuccessfulPayment',
'TelegramDecryptionError',
'TelegramError',
'TelegramObject',
'Update',
@@ -213,65 +270,7 @@ __all__ = [
'UserProfilePhotos',
'Venue',
'Video',
'Voice',
'MAX_MESSAGE_LENGTH',
'MAX_CAPTION_LENGTH',
'SUPPORTED_WEBHOOK_PORTS',
'MAX_FILESIZE_DOWNLOAD',
'MAX_FILESIZE_UPLOAD',
'MAX_MESSAGES_PER_SECOND_PER_CHAT',
'MAX_MESSAGES_PER_SECOND',
'MAX_MESSAGES_PER_MINUTE_PER_GROUP',
'WebhookInfo',
'Animation',
'Game',
'GameHighScore',
'VideoNote',
'LabeledPrice',
'SuccessfulPayment',
'ShippingOption',
'ShippingAddress',
'PreCheckoutQuery',
'OrderInfo',
'Invoice',
'ShippingQuery',
'ChatPhoto',
'StickerSet',
'MaskPosition',
'CallbackGame',
'InputMedia',
'InputMediaPhoto',
'InputMediaVideo',
'PassportElementError',
'PassportElementErrorFile',
'PassportElementErrorReverseSide',
'PassportElementErrorFrontSide',
'PassportElementErrorFiles',
'PassportElementErrorDataField',
'PassportElementErrorFile',
'Credentials',
'DataCredentials',
'SecureData',
'FileCredentials',
'IdDocumentData',
'PersonalDetails',
'ResidentialAddress',
'InputMediaVideo',
'InputMediaAnimation',
'InputMediaAudio',
'InputMediaDocument',
'TelegramDecryptionError',
'PassportElementErrorSelfie',
'PassportElementErrorTranslationFile',
'PassportElementErrorTranslationFiles',
'PassportElementErrorUnspecified',
'Poll',
'PollOption',
'PollAnswer',
'LoginUrl',
'KeyboardButton',
'KeyboardButtonPollType',
'Dice',
'BotCommand',
'MessageId',
]
'Voice',
'WebhookInfo',
)
+1 -1
View File
@@ -1,7 +1,7 @@
# !/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
+4 -7
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -23,7 +23,7 @@ except ImportError:
import json # type: ignore[no-redef]
import warnings
from typing import TYPE_CHECKING, Any, List, Optional, Tuple, Type, TypeVar
from typing import TYPE_CHECKING, List, Optional, Tuple, Type, TypeVar
from telegram.utils.types import JSONDict
@@ -36,15 +36,12 @@ TO = TypeVar('TO', bound='TelegramObject', covariant=True)
class TelegramObject:
"""Base class for most telegram objects."""
# def __init__(self, *args: Any, **_kwargs: Any):
# pass
_id_attrs: Tuple[Any, ...] = ()
_id_attrs: Tuple[object, ...] = ()
def __str__(self) -> str:
return str(self.to_dict())
def __getitem__(self, item: str) -> Any:
def __getitem__(self, item: str) -> object:
return self.__dict__[item]
@staticmethod
+647 -475
View File
File diff suppressed because it is too large Load Diff
+6 -5
View File
@@ -2,7 +2,7 @@
# pylint: disable=R0903
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -30,14 +30,15 @@ class BotCommand(TelegramObject):
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`command` and :attr:`description` are equal.
Attributes:
command (:obj:`str`): Text of the command.
description (:obj:`str`): Description of the command.
Args:
command (:obj:`str`): Text of the command, 1-32 characters. Can contain only lowercase
English letters, digits and underscores.
description (:obj:`str`): Description of the command, 3-256 characters.
Attributes:
command (:obj:`str`): Text of the command.
description (:obj:`str`): Description of the command.
"""
def __init__(self, command: str, description: str, **_kwargs: Any):
+328 -58
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -18,13 +18,21 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
# pylint: disable=W0622
"""This module contains an object that represents a Telegram CallbackQuery"""
from typing import TYPE_CHECKING, Any, List, Optional, Union
from typing import TYPE_CHECKING, Any, List, Optional, Union, Tuple, ClassVar
from telegram import Message, TelegramObject, User
from telegram.utils.types import JSONDict
from telegram import Message, TelegramObject, User, Location, ReplyMarkup, constants
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import JSONDict, ODVInput, DVInput
if TYPE_CHECKING:
from telegram import Bot, GameHighScore, InlineKeyboardMarkup, MessageId
from telegram import (
Bot,
GameHighScore,
InlineKeyboardMarkup,
MessageId,
InputMedia,
MessageEntity,
)
class CallbackQuery(TelegramObject):
@@ -41,19 +49,10 @@ class CallbackQuery(TelegramObject):
Note:
* In Python `from` is a reserved word, use `from_user` instead.
* Exactly one of the fields :attr:`data` or :attr:`game_short_name` will be present.
Attributes:
id (:obj:`str`): Unique identifier for this query.
from_user (:class:`telegram.User`): Sender.
chat_instance (:obj:`str`): Global identifier, uniquely corresponding to the chat to which
the message with the callback button was sent.
message (:class:`telegram.Message`): Optional. Message with the callback button that
originated the query.
data (:obj:`str`): Optional. Data associated with the callback button.
inline_message_id (:obj:`str`): Optional. Identifier of the message sent via the bot in
inline mode, that originated the query.
game_short_name (:obj:`str`): Optional. Short name of a Game to be returned.
bot (:class:`telegram.Bot`, optional): The Bot to use for instance methods.
* After the user presses an inline button, Telegram clients will display a progress bar
until you call :attr:`answer`. It is, therefore, necessary to react
by calling :attr:`telegram.Bot.answer_callback_query` even if no notification to the user
is needed (e.g., without specifying any of the optional parameters).
Args:
id (:obj:`str`): Unique identifier for this query.
@@ -71,11 +70,18 @@ class CallbackQuery(TelegramObject):
the unique identifier for the game
bot (:class:`telegram.Bot`, optional): The Bot to use for instance methods.
Note:
After the user presses an inline button, Telegram clients will display a progress bar
until you call :attr:`answer`. It is, therefore, necessary to react
by calling :attr:`telegram.Bot.answer_callback_query` even if no notification to the user
is needed (e.g., without specifying any of the optional parameters).
Attributes:
id (:obj:`str`): Unique identifier for this query.
from_user (:class:`telegram.User`): Sender.
chat_instance (:obj:`str`): Global identifier, uniquely corresponding to the chat to which
the message with the callback button was sent.
message (:class:`telegram.Message`): Optional. Message with the callback button that
originated the query.
data (:obj:`str`): Optional. Data associated with the callback button.
inline_message_id (:obj:`str`): Optional. Identifier of the message sent via the bot in
inline mode, that originated the query.
game_short_name (:obj:`str`): Optional. Short name of a Game to be returned.
bot (:class:`telegram.Bot`, optional): The Bot to use for instance methods.
"""
@@ -117,18 +123,46 @@ class CallbackQuery(TelegramObject):
return cls(bot=bot, **data)
def answer(self, *args: Any, **kwargs: Any) -> bool:
def answer(
self,
text: str = None,
show_alert: bool = False,
url: str = None,
cache_time: int = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::
bot.answer_callback_query(update.callback_query.id, *args, **kwargs)
For the documentation of the arguments, please see
:meth:`telegram.Bot.answer_callback_query`.
Returns:
:obj:`bool`: On success, :obj:`True` is returned.
"""
return self.bot.answer_callback_query(self.id, *args, **kwargs)
return self.bot.answer_callback_query(
callback_query_id=self.id,
text=text,
show_alert=show_alert,
url=url,
cache_time=cache_time,
timeout=timeout,
api_kwargs=api_kwargs,
)
def edit_message_text(self, text: str, *args: Any, **kwargs: Any) -> Union[Message, bool]:
def edit_message_text(
self,
text: str,
parse_mode: ODVInput[str] = DEFAULT_NONE,
disable_web_page_preview: ODVInput[bool] = DEFAULT_NONE,
reply_markup: 'InlineKeyboardMarkup' = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
) -> Union[Message, bool]:
"""Shortcut for either::
update.callback_query.message.edit_text(text, *args, **kwargs)
@@ -138,6 +172,9 @@ class CallbackQuery(TelegramObject):
bot.edit_message_text(text, inline_message_id=update.callback_query.inline_message_id,
*args, **kwargs)
For the documentation of the arguments, please see
:meth:`telegram.Bot.edit_message_text`.
Returns:
:class:`telegram.Message`: On success, if edited message is sent by the bot, the
edited Message is returned, otherwise :obj:`True` is returned.
@@ -145,12 +182,35 @@ class CallbackQuery(TelegramObject):
"""
if self.inline_message_id:
return self.bot.edit_message_text(
text, inline_message_id=self.inline_message_id, *args, **kwargs
inline_message_id=self.inline_message_id,
text=text,
parse_mode=parse_mode,
disable_web_page_preview=disable_web_page_preview,
reply_markup=reply_markup,
timeout=timeout,
api_kwargs=api_kwargs,
entities=entities,
chat_id=None,
message_id=None,
)
return self.message.edit_text(text, *args, **kwargs)
return self.message.edit_text(
text=text,
parse_mode=parse_mode,
disable_web_page_preview=disable_web_page_preview,
reply_markup=reply_markup,
timeout=timeout,
api_kwargs=api_kwargs,
entities=entities,
)
def edit_message_caption(
self, caption: str, *args: Any, **kwargs: Any
self,
caption: str = None,
reply_markup: 'InlineKeyboardMarkup' = None,
timeout: ODVInput[float] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
caption_entities: Union[List['MessageEntity'], Tuple['MessageEntity', ...]] = None,
) -> Union[Message, bool]:
"""Shortcut for either::
@@ -162,6 +222,9 @@ class CallbackQuery(TelegramObject):
inline_message_id=update.callback_query.inline_message_id,
*args, **kwargs)
For the documentation of the arguments, please see
:meth:`telegram.Bot.edit_message_caption`.
Returns:
:class:`telegram.Message`: On success, if edited message is sent by the bot, the
edited Message is returned, otherwise :obj:`True` is returned.
@@ -169,12 +232,30 @@ class CallbackQuery(TelegramObject):
"""
if self.inline_message_id:
return self.bot.edit_message_caption(
caption=caption, inline_message_id=self.inline_message_id, *args, **kwargs
caption=caption,
inline_message_id=self.inline_message_id,
reply_markup=reply_markup,
timeout=timeout,
parse_mode=parse_mode,
api_kwargs=api_kwargs,
caption_entities=caption_entities,
chat_id=None,
message_id=None,
)
return self.message.edit_caption(caption=caption, *args, **kwargs)
return self.message.edit_caption(
caption=caption,
reply_markup=reply_markup,
timeout=timeout,
parse_mode=parse_mode,
api_kwargs=api_kwargs,
caption_entities=caption_entities,
)
def edit_message_reply_markup(
self, reply_markup: 'InlineKeyboardMarkup', *args: Any, **kwargs: Any
self,
reply_markup: Optional['InlineKeyboardMarkup'] = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> Union[Message, bool]:
"""Shortcut for either::
@@ -193,6 +274,9 @@ class CallbackQuery(TelegramObject):
**kwargs
)
For the documentation of the arguments, please see
:meth:`telegram.Bot.edit_message_reply_markup`.
Returns:
:class:`telegram.Message`: On success, if edited message is sent by the bot, the
edited Message is returned, otherwise :obj:`True` is returned.
@@ -202,12 +286,24 @@ class CallbackQuery(TelegramObject):
return self.bot.edit_message_reply_markup(
reply_markup=reply_markup,
inline_message_id=self.inline_message_id,
*args,
**kwargs,
timeout=timeout,
api_kwargs=api_kwargs,
chat_id=None,
message_id=None,
)
return self.message.edit_reply_markup(reply_markup=reply_markup, *args, **kwargs)
return self.message.edit_reply_markup(
reply_markup=reply_markup,
timeout=timeout,
api_kwargs=api_kwargs,
)
def edit_message_media(self, *args: Any, **kwargs: Any) -> Union[Message, bool]:
def edit_message_media(
self,
media: 'InputMedia' = None,
reply_markup: 'InlineKeyboardMarkup' = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> Union[Message, bool]:
"""Shortcut for either::
update.callback_query.message.edit_media(*args, **kwargs)
@@ -217,6 +313,9 @@ class CallbackQuery(TelegramObject):
bot.edit_message_media(inline_message_id=update.callback_query.inline_message_id,
*args, **kwargs)
For the documentation of the arguments, please see
:meth:`telegram.Bot.edit_message_media`.
Returns:
:class:`telegram.Message`: On success, if edited message is sent by the bot, the
edited Message is returned, otherwise :obj:`True` is returned.
@@ -224,11 +323,33 @@ class CallbackQuery(TelegramObject):
"""
if self.inline_message_id:
return self.bot.edit_message_media(
inline_message_id=self.inline_message_id, *args, **kwargs
inline_message_id=self.inline_message_id,
media=media,
reply_markup=reply_markup,
timeout=timeout,
api_kwargs=api_kwargs,
chat_id=None,
message_id=None,
)
return self.message.edit_media(*args, **kwargs)
return self.message.edit_media(
media=media,
reply_markup=reply_markup,
timeout=timeout,
api_kwargs=api_kwargs,
)
def edit_message_live_location(self, *args: Any, **kwargs: Any) -> Union[Message, bool]:
def edit_message_live_location(
self,
latitude: float = None,
longitude: float = None,
location: Location = None,
reply_markup: 'InlineKeyboardMarkup' = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
horizontal_accuracy: float = None,
heading: int = None,
proximity_alert_radius: int = None,
) -> Union[Message, bool]:
"""Shortcut for either::
update.callback_query.message.edit_live_location(*args, **kwargs)
@@ -240,6 +361,9 @@ class CallbackQuery(TelegramObject):
*args, **kwargs
)
For the documentation of the arguments, please see
:meth:`telegram.Bot.edit_message_live_location`.
Returns:
:class:`telegram.Message`: On success, if edited message is sent by the bot, the
edited Message is returned, otherwise :obj:`True` is returned.
@@ -247,11 +371,37 @@ class CallbackQuery(TelegramObject):
"""
if self.inline_message_id:
return self.bot.edit_message_live_location(
inline_message_id=self.inline_message_id, *args, **kwargs
inline_message_id=self.inline_message_id,
latitude=latitude,
longitude=longitude,
location=location,
reply_markup=reply_markup,
timeout=timeout,
api_kwargs=api_kwargs,
horizontal_accuracy=horizontal_accuracy,
heading=heading,
proximity_alert_radius=proximity_alert_radius,
chat_id=None,
message_id=None,
)
return self.message.edit_live_location(*args, **kwargs)
return self.message.edit_live_location(
latitude=latitude,
longitude=longitude,
location=location,
reply_markup=reply_markup,
timeout=timeout,
api_kwargs=api_kwargs,
horizontal_accuracy=horizontal_accuracy,
heading=heading,
proximity_alert_radius=proximity_alert_radius,
)
def stop_message_live_location(self, *args: Any, **kwargs: Any) -> Union[Message, bool]:
def stop_message_live_location(
self,
reply_markup: 'InlineKeyboardMarkup' = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> Union[Message, bool]:
"""Shortcut for either::
update.callback_query.message.stop_live_location(*args, **kwargs)
@@ -263,6 +413,9 @@ class CallbackQuery(TelegramObject):
*args, **kwargs
)
For the documentation of the arguments, please see
:meth:`telegram.Bot.stop_message_live_location`.
Returns:
:class:`telegram.Message`: On success, if edited message is sent by the bot, the
edited Message is returned, otherwise :obj:`True` is returned.
@@ -270,11 +423,28 @@ class CallbackQuery(TelegramObject):
"""
if self.inline_message_id:
return self.bot.stop_message_live_location(
inline_message_id=self.inline_message_id, *args, **kwargs
inline_message_id=self.inline_message_id,
reply_markup=reply_markup,
timeout=timeout,
api_kwargs=api_kwargs,
chat_id=None,
message_id=None,
)
return self.message.stop_live_location(*args, **kwargs)
return self.message.stop_live_location(
reply_markup=reply_markup,
timeout=timeout,
api_kwargs=api_kwargs,
)
def set_game_score(self, *args: Any, **kwargs: Any) -> Union[Message, bool]:
def set_game_score(
self,
user_id: Union[int, str],
score: int,
force: bool = None,
disable_edit_message: bool = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> Union[Message, bool]:
"""Shortcut for either::
update.callback_query.message.set_game_score(*args, **kwargs)
@@ -284,6 +454,9 @@ class CallbackQuery(TelegramObject):
bot.set_game_score(inline_message_id=update.callback_query.inline_message_id,
*args, **kwargs)
For the documentation of the arguments, please see
:meth:`telegram.Bot.set_game_score`.
Returns:
:class:`telegram.Message`: On success, if edited message is sent by the bot, the
edited Message is returned, otherwise :obj:`True` is returned.
@@ -291,11 +464,31 @@ class CallbackQuery(TelegramObject):
"""
if self.inline_message_id:
return self.bot.set_game_score(
inline_message_id=self.inline_message_id, *args, **kwargs
inline_message_id=self.inline_message_id,
user_id=user_id,
score=score,
force=force,
disable_edit_message=disable_edit_message,
timeout=timeout,
api_kwargs=api_kwargs,
chat_id=None,
message_id=None,
)
return self.message.set_game_score(*args, **kwargs)
return self.message.set_game_score(
user_id=user_id,
score=score,
force=force,
disable_edit_message=disable_edit_message,
timeout=timeout,
api_kwargs=api_kwargs,
)
def get_game_high_scores(self, *args: Any, **kwargs: Any) -> List['GameHighScore']:
def get_game_high_scores(
self,
user_id: Union[int, str],
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> List['GameHighScore']:
"""Shortcut for either::
update.callback_query.message.get_game_high_score(*args, **kwargs)
@@ -305,28 +498,55 @@ class CallbackQuery(TelegramObject):
bot.get_game_high_scores(inline_message_id=update.callback_query.inline_message_id,
*args, **kwargs)
For the documentation of the arguments, please see
:meth:`telegram.Bot.get_game_high_scores`.
Returns:
List[:class:`telegram.GameHighScore`]
"""
if self.inline_message_id:
return self.bot.get_game_high_scores(
inline_message_id=self.inline_message_id, *args, **kwargs
inline_message_id=self.inline_message_id,
user_id=user_id,
timeout=timeout,
api_kwargs=api_kwargs,
chat_id=None,
message_id=None,
)
return self.message.get_game_high_scores(*args, **kwargs)
return self.message.get_game_high_scores(
user_id=user_id,
timeout=timeout,
api_kwargs=api_kwargs,
)
def delete_message(self, *args: Any, **kwargs: Any) -> Union[Message, bool]:
def delete_message(
self,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::
update.callback_query.message.delete(*args, **kwargs)
For the documentation of the arguments, please see
:meth:`telegram.Bot.delete_message`.
Returns:
:obj:`bool`: On success, :obj:`True` is returned.
"""
return self.message.delete(*args, **kwargs)
return self.message.delete(
timeout=timeout,
api_kwargs=api_kwargs,
)
def pin_message(self, *args: Any, **kwargs: Any) -> bool:
def pin_message(
self,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::
bot.pin_chat_message(chat_id=message.chat_id,
@@ -334,13 +554,24 @@ class CallbackQuery(TelegramObject):
*args,
**kwargs)
For the documentation of the arguments, please see
:meth:`telegram.Bot.pin_chat_message`.
Returns:
:obj:`bool`: On success, :obj:`True` is returned.
"""
return self.message.pin(*args, **kwargs)
return self.message.pin(
disable_notification=disable_notification,
timeout=timeout,
api_kwargs=api_kwargs,
)
def unpin_message(self, *args: Any, **kwargs: Any) -> bool:
def unpin_message(
self,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> bool:
"""Shortcut for::
bot.unpin_chat_message(chat_id=message.chat_id,
@@ -348,13 +579,31 @@ class CallbackQuery(TelegramObject):
*args,
**kwargs)
For the documentation of the arguments, please see
:meth:`telegram.Bot.unpin_chat_message`.
Returns:
:obj:`bool`: On success, :obj:`True` is returned.
"""
return self.message.unpin(*args, **kwargs)
return self.message.unpin(
timeout=timeout,
api_kwargs=api_kwargs,
)
def copy_message(self, chat_id: int, *args: Any, **kwargs: Any) -> 'MessageId':
def copy_message(
self,
chat_id: Union[int, str],
caption: str = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Union[Tuple['MessageEntity', ...], List['MessageEntity']] = None,
disable_notification: DVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Union[int, str] = None,
allow_sending_without_reply: DVInput[bool] = DEFAULT_NONE,
reply_markup: ReplyMarkup = None,
timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: JSONDict = None,
) -> 'MessageId':
"""Shortcut for::
update.callback_query.message.copy(
@@ -364,8 +613,29 @@ class CallbackQuery(TelegramObject):
*args,
**kwargs)
For the documentation of the arguments, please see
:meth:`telegram.Bot.copy_message`.
Returns:
:class:`telegram.MessageId`: On success, returns the MessageId of the sent message.
"""
return self.message.copy(chat_id, *args, **kwargs)
return self.message.copy(
chat_id=chat_id,
caption=caption,
parse_mode=parse_mode,
caption_entities=caption_entities,
disable_notification=disable_notification,
reply_to_message_id=reply_to_message_id,
allow_sending_without_reply=allow_sending_without_reply,
reply_markup=reply_markup,
timeout=timeout,
api_kwargs=api_kwargs,
)
MAX_ANSWER_TEXT_LENGTH: ClassVar[int] = constants.MAX_ANSWER_CALLBACK_QUERY_TEXT_LENGTH
"""
:const:`telegram.constants.MAX_ANSWER_CALLBACK_QUERY_TEXT_LENGTH`
.. versionadded:: 13.2
"""
+946 -100
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -2,7 +2,7 @@
# pylint: disable=R0903
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
+5 -5
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -35,16 +35,16 @@ class ChatLocation(TelegramObject):
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`location` is equal.
Attributes:
location (:class:`telegram.Location`): The location to which the supergroup is connected.
address (:obj:`str`): Location address, as defined by the chat owner
Args:
location (:class:`telegram.Location`): The location to which the supergroup is connected.
Can't be a live location.
address (:obj:`str`): Location address; 1-64 characters, as defined by the chat owner
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
Attributes:
location (:class:`telegram.Location`): The location to which the supergroup is connected.
address (:obj:`str`): Location address, as defined by the chat owner
"""
def __init__(
+37 -37
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -34,42 +34,6 @@ class ChatMember(TelegramObject):
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`user` and :attr:`status` are equal.
Attributes:
user (:class:`telegram.User`): Information about the user.
status (:obj:`str`): The member's status in the chat.
custom_title (:obj:`str`): Optional. Custom title for owner and administrators.
is_anonymous (:obj:`bool`): Optional. :obj:`True`, if the user's presence in the chat is
hidden.
until_date (:class:`datetime.datetime`): Optional. Date when restrictions will be lifted
for this user.
can_be_edited (:obj:`bool`): Optional. If the bot is allowed to edit administrator
privileges of that user.
can_change_info (:obj:`bool`): Optional. If the user can change the chat title, photo and
other settings.
can_post_messages (:obj:`bool`): Optional. If the administrator can post in the channel.
can_edit_messages (:obj:`bool`): Optional. If the administrator can edit messages of other
users.
can_delete_messages (:obj:`bool`): Optional. If the administrator can delete messages of
other users.
can_invite_users (:obj:`bool`): Optional. If the user can invite new users to the chat.
can_restrict_members (:obj:`bool`): Optional. If the administrator can restrict, ban or
unban chat members.
can_pin_messages (:obj:`bool`): Optional. If the user can pin messages.
can_promote_members (:obj:`bool`): Optional. If the administrator can add new
administrators.
is_member (:obj:`bool`): Optional. Restricted only. :obj:`True`, if the user is a member of
the chat at the moment of the request.
can_send_messages (:obj:`bool`): Optional. If the user can send text messages, contacts,
locations and venues.
can_send_media_messages (:obj:`bool`): Optional. If the user can send media messages,
implies can_send_messages.
can_send_polls (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to
send polls.
can_send_other_messages (:obj:`bool`): Optional. If the user can send animations, games,
stickers and use inline bots, implies can_send_media_messages.
can_add_web_page_previews (:obj:`bool`): Optional. If user may add web page previews to his
messages, implies can_send_media_messages
Args:
user (:class:`telegram.User`): Information about the user.
status (:obj:`str`): The member's status in the chat. Can be 'creator', 'administrator',
@@ -113,6 +77,42 @@ class ChatMember(TelegramObject):
can_add_web_page_previews (:obj:`bool`, optional): Restricted only. :obj:`True`, if user
may add web page previews to his messages.
Attributes:
user (:class:`telegram.User`): Information about the user.
status (:obj:`str`): The member's status in the chat.
custom_title (:obj:`str`): Optional. Custom title for owner and administrators.
is_anonymous (:obj:`bool`): Optional. :obj:`True`, if the user's presence in the chat is
hidden.
until_date (:class:`datetime.datetime`): Optional. Date when restrictions will be lifted
for this user.
can_be_edited (:obj:`bool`): Optional. If the bot is allowed to edit administrator
privileges of that user.
can_change_info (:obj:`bool`): Optional. If the user can change the chat title, photo and
other settings.
can_post_messages (:obj:`bool`): Optional. If the administrator can post in the channel.
can_edit_messages (:obj:`bool`): Optional. If the administrator can edit messages of other
users.
can_delete_messages (:obj:`bool`): Optional. If the administrator can delete messages of
other users.
can_invite_users (:obj:`bool`): Optional. If the user can invite new users to the chat.
can_restrict_members (:obj:`bool`): Optional. If the administrator can restrict, ban or
unban chat members.
can_pin_messages (:obj:`bool`): Optional. If the user can pin messages.
can_promote_members (:obj:`bool`): Optional. If the administrator can add new
administrators.
is_member (:obj:`bool`): Optional. Restricted only. :obj:`True`, if the user is a member of
the chat at the moment of the request.
can_send_messages (:obj:`bool`): Optional. If the user can send text messages, contacts,
locations and venues.
can_send_media_messages (:obj:`bool`): Optional. If the user can send media messages,
implies can_send_messages.
can_send_polls (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to
send polls.
can_send_other_messages (:obj:`bool`): Optional. If the user can send animations, games,
stickers and use inline bots, implies can_send_media_messages.
can_add_web_page_previews (:obj:`bool`): Optional. If user may add web page previews to his
messages, implies can_send_media_messages
"""
ADMINISTRATOR: ClassVar[str] = constants.CHATMEMBER_ADMINISTRATOR
+21 -21
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -36,26 +36,6 @@ class ChatPermissions(TelegramObject):
permissions that are set, but also sets all the others to :obj:`False`. However, since not
documented, this behaviour may change unbeknown to PTB.
Attributes:
can_send_messages (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to send text
messages, contacts, locations and venues.
can_send_media_messages (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to
send audios, documents, photos, videos, video notes and voice notes, implies
:attr:`can_send_messages`.
can_send_polls (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to send polls,
implies :attr:`can_send_messages`.
can_send_other_messages (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to
send animations, games, stickers and use inline bots, implies
:attr:`can_send_media_messages`.
can_add_web_page_previews (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to
add web page previews to their messages, implies :attr:`can_send_media_messages`.
can_change_info (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to change the
chat title, photo and other settings. Ignored in public supergroups.
can_invite_users (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to invite
new users to the chat.
can_pin_messages (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to pin
messages. Ignored in public supergroups.
Args:
can_send_messages (:obj:`bool`, optional): :obj:`True`, if the user is allowed to send text
messages, contacts, locations and venues.
@@ -76,6 +56,26 @@ class ChatPermissions(TelegramObject):
can_pin_messages (:obj:`bool`, optional): :obj:`True`, if the user is allowed to pin
messages. Ignored in public supergroups.
Attributes:
can_send_messages (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to send text
messages, contacts, locations and venues.
can_send_media_messages (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to
send audios, documents, photos, videos, video notes and voice notes, implies
:attr:`can_send_messages`.
can_send_polls (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to send polls,
implies :attr:`can_send_messages`.
can_send_other_messages (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to
send animations, games, stickers and use inline bots, implies
:attr:`can_send_media_messages`.
can_add_web_page_previews (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to
add web page previews to their messages, implies :attr:`can_send_media_messages`.
can_change_info (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to change the
chat title, photo and other settings. Ignored in public supergroups.
can_invite_users (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to invite
new users to the chat.
can_pin_messages (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to pin
messages. Ignored in public supergroups.
"""
def __init__(
+10 -12
View File
@@ -2,7 +2,7 @@
# pylint: disable=R0902,R0913
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -37,14 +37,9 @@ class ChosenInlineResult(TelegramObject):
considered equal, if their :attr:`result_id` is equal.
Note:
In Python `from` is a reserved word, use `from_user` instead.
Attributes:
result_id (:obj:`str`): The unique identifier for the result that was chosen.
from_user (:class:`telegram.User`): The user that chose the result.
location (:class:`telegram.Location`): Optional. Sender location.
inline_message_id (:obj:`str`): Optional. Identifier of the sent inline message.
query (:obj:`str`): The query that was used to obtain the result.
* In Python `from` is a reserved word, use `from_user` instead.
* It is necessary to enable inline feedback via `@Botfather <https://t.me/BotFather>`_ in
order to receive these objects in updates.
Args:
result_id (:obj:`str`): The unique identifier for the result that was chosen.
@@ -57,9 +52,12 @@ class ChosenInlineResult(TelegramObject):
query (:obj:`str`): The query that was used to obtain the result.
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
Note:
It is necessary to enable inline feedback via `@Botfather <https://t.me/BotFather>`_ in
order to receive these objects in updates.
Attributes:
result_id (:obj:`str`): The unique identifier for the result that was chosen.
from_user (:class:`telegram.User`): The user that chose the result.
location (:class:`telegram.Location`): Optional. Sender location.
inline_message_id (:obj:`str`): Optional. Identifier of the sent inline message.
query (:obj:`str`): The query that was used to obtain the result.
"""
+5 -1
View File
@@ -1,5 +1,5 @@
# python-telegram-bot - a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# by the python-telegram-bot contributors <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -32,6 +32,9 @@ Attributes:
MAX_MESSAGES_PER_SECOND (:obj:`int`): 30
MAX_MESSAGES_PER_MINUTE_PER_GROUP (:obj:`int`): 20
MAX_INLINE_QUERY_RESULTS (:obj:`int`): 50
MAX_ANSWER_CALLBACK_QUERY_TEXT_LENGTH (:obj:`int`): 200
.. versionadded:: 13.2
The following constant have been found by experimentation:
@@ -149,6 +152,7 @@ MAX_MESSAGES_PER_SECOND: int = 30
MAX_MESSAGES_PER_MINUTE_PER_GROUP: int = 20
MAX_MESSAGE_ENTITIES: int = 100
MAX_INLINE_QUERY_RESULTS: int = 50
MAX_ANSWER_CALLBACK_QUERY_TEXT_LENGTH: int = 200
CHAT_PRIVATE: str = 'private'
CHAT_GROUP: str = 'group'
+7 -6
View File
@@ -2,7 +2,7 @@
# pylint: disable=R0903
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -41,7 +41,7 @@ class Dice(TelegramObject):
3 indicates that the basket was missed. However, this behaviour is undocumented and might
be changed by Telegram.
If :attr:`emoji` is "", a value of 3 to 5 currently scores a goal, while a value of 1 to
If :attr:`emoji` is "", a value of 4 to 5 currently scores a goal, while a value of 1 to
3 indicates that the goal was missed. However, this behaviour is undocumented and might
be changed by Telegram.
@@ -49,14 +49,15 @@ class Dice(TelegramObject):
can be found at our `wiki <https://git.io/JkeC6>`_. However, this behaviour is undocumented
and might be changed by Telegram.
Attributes:
value (:obj:`int`): Value of the dice.
emoji (:obj:`str`): Emoji on which the dice throw animation is based.
Args:
value (:obj:`int`): Value of the dice. 1-6 for dice and darts, 1-5 for basketball and
football/soccer ball, 1-64 for slot machine.
emoji (:obj:`str`): Emoji on which the dice throw animation is based.
Attributes:
value (:obj:`int`): Value of the dice.
emoji (:obj:`str`): Emoji on which the dice throw animation is based.
"""
def __init__(self, value: int, emoji: str, **_kwargs: Any):
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
+42 -38
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -20,7 +20,7 @@
import warnings
from abc import ABC, abstractmethod
from copy import copy
from typing import Any, DefaultDict, Dict, Optional, Tuple, cast, ClassVar
from typing import DefaultDict, Dict, Optional, Tuple, cast, ClassVar
from telegram import Bot
@@ -31,17 +31,20 @@ class BasePersistence(ABC):
"""Interface class for adding persistence to your bot.
Subclass this object for different implementations of a persistent bot.
All relevant methods must be overwritten. This means:
All relevant methods must be overwritten. This includes:
* If :attr:`store_bot_data` is :obj:`True` you must overwrite :meth:`get_bot_data` and
:meth:`update_bot_data`.
* If :attr:`store_chat_data` is :obj:`True` you must overwrite :meth:`get_chat_data` and
:meth:`update_chat_data`.
* If :attr:`store_user_data` is :obj:`True` you must overwrite :meth:`get_user_data` and
:meth:`update_user_data`.
* If you want to store conversation data with :class:`telegram.ext.ConversationHandler`, you
must overwrite :meth:`get_conversations` and :meth:`update_conversation`.
* :meth:`flush` will be called when the bot is shutdown.
* :meth:`get_bot_data`
* :meth:`update_bot_data`
* :meth:`get_chat_data`
* :meth:`update_chat_data`
* :meth:`get_user_data`
* :meth:`update_user_data`
* :meth:`get_conversations`
* :meth:`update_conversation`
* :meth:`flush`
If you don't actually need one of those methods, a simple ``pass`` is enough. For example, if
``store_bot_data=False``, you don't need :meth:`get_bot_data` and :meth:`update_bot_data`.
Warning:
Persistence will try to replace :class:`telegram.Bot` instances by :attr:`REPLACED_BOT` and
@@ -55,14 +58,6 @@ class BasePersistence(ABC):
of the :meth:`update/get_*` methods, i.e. you don't need to worry about it while
implementing a custom persistence subclass.
Attributes:
store_user_data (:obj:`bool`): Optional, Whether user_data should be saved by this
persistence class.
store_chat_data (:obj:`bool`): Optional. Whether chat_data should be saved by this
persistence class.
store_bot_data (:obj:`bool`): Optional. Whether bot_data should be saved by this
persistence class.
Args:
store_user_data (:obj:`bool`, optional): Whether user_data should be saved by this
persistence class. Default is :obj:`True`.
@@ -70,9 +65,19 @@ class BasePersistence(ABC):
persistence class. Default is :obj:`True` .
store_bot_data (:obj:`bool`, optional): Whether bot_data should be saved by this
persistence class. Default is :obj:`True` .
Attributes:
store_user_data (:obj:`bool`): Optional, Whether user_data should be saved by this
persistence class.
store_chat_data (:obj:`bool`): Optional. Whether chat_data should be saved by this
persistence class.
store_bot_data (:obj:`bool`): Optional. Whether bot_data should be saved by this
persistence class.
"""
def __new__(cls, *args: Any, **kwargs: Any) -> 'BasePersistence': # pylint: disable=W0613
def __new__(
cls, *args: object, **kwargs: object # pylint: disable=W0613
) -> 'BasePersistence':
instance = super().__new__(cls)
get_user_data = instance.get_user_data
get_chat_data = instance.get_chat_data
@@ -81,13 +86,13 @@ class BasePersistence(ABC):
update_chat_data = instance.update_chat_data
update_bot_data = instance.update_bot_data
def get_user_data_insert_bot() -> DefaultDict[int, Dict[Any, Any]]:
def get_user_data_insert_bot() -> DefaultDict[int, Dict[object, object]]:
return instance.insert_bot(get_user_data())
def get_chat_data_insert_bot() -> DefaultDict[int, Dict[Any, Any]]:
def get_chat_data_insert_bot() -> DefaultDict[int, Dict[object, object]]:
return instance.insert_bot(get_chat_data())
def get_bot_data_insert_bot() -> Dict[Any, Any]:
def get_bot_data_insert_bot() -> Dict[object, object]:
return instance.insert_bot(get_bot_data())
def update_user_data_replace_bot(user_id: int, data: Dict) -> None:
@@ -143,7 +148,7 @@ class BasePersistence(ABC):
return cls._replace_bot(obj, {})
@classmethod
def _replace_bot(cls, obj: object, memo: Dict[int, Any]) -> object: # pylint: disable=R0911
def _replace_bot(cls, obj: object, memo: Dict[int, object]) -> object: # pylint: disable=R0911
obj_id = id(obj)
if obj_id in memo:
return memo[obj_id]
@@ -220,7 +225,7 @@ class BasePersistence(ABC):
"""
return self._insert_bot(obj, {})
def _insert_bot(self, obj: object, memo: Dict[int, Any]) -> object: # pylint: disable=R0911
def _insert_bot(self, obj: object, memo: Dict[int, object]) -> object: # pylint: disable=R0911
obj_id = id(obj)
if obj_id in memo:
return memo[obj_id]
@@ -285,9 +290,9 @@ class BasePersistence(ABC):
return obj
@abstractmethod
def get_user_data(self) -> DefaultDict[int, Dict[Any, Any]]:
""" "Will be called by :class:`telegram.ext.Dispatcher` upon creation with a
persistence object. It should return the user_data if stored, or an empty
def get_user_data(self) -> DefaultDict[int, Dict[object, object]]:
"""Will be called by :class:`telegram.ext.Dispatcher` upon creation with a
persistence object. It should return the ``user_data`` if stored, or an empty
``defaultdict(dict)``.
Returns:
@@ -295,9 +300,9 @@ class BasePersistence(ABC):
"""
@abstractmethod
def get_chat_data(self) -> DefaultDict[int, Dict[Any, Any]]:
""" "Will be called by :class:`telegram.ext.Dispatcher` upon creation with a
persistence object. It should return the chat_data if stored, or an empty
def get_chat_data(self) -> DefaultDict[int, Dict[object, object]]:
"""Will be called by :class:`telegram.ext.Dispatcher` upon creation with a
persistence object. It should return the ``chat_data`` if stored, or an empty
``defaultdict(dict)``.
Returns:
@@ -305,9 +310,9 @@ class BasePersistence(ABC):
"""
@abstractmethod
def get_bot_data(self) -> Dict[Any, Any]:
""" "Will be called by :class:`telegram.ext.Dispatcher` upon creation with a
persistence object. It should return the bot_data if stored, or an empty
def get_bot_data(self) -> Dict[object, object]:
"""Will be called by :class:`telegram.ext.Dispatcher` upon creation with a
persistence object. It should return the ``bot_data`` if stored, or an empty
:obj:`dict`.
Returns:
@@ -316,7 +321,7 @@ class BasePersistence(ABC):
@abstractmethod
def get_conversations(self, name: str) -> ConversationDict:
""" "Will be called by :class:`telegram.ext.Dispatcher` when a
"""Will be called by :class:`telegram.ext.Dispatcher` when a
:class:`telegram.ext.ConversationHandler` is added if
:attr:`telegram.ext.ConversationHandler.persistent` is :obj:`True`.
It should return the conversations for the handler with `name` or an empty :obj:`dict`
@@ -372,8 +377,7 @@ class BasePersistence(ABC):
def flush(self) -> None:
"""Will be called by :class:`telegram.ext.Updater` upon receiving a stop signal. Gives the
persistence a chance to finish up saving or close a database connection gracefully. If this
is not of any importance just pass will be sufficient.
persistence a chance to finish up saving or close a database connection gracefully.
"""
REPLACED_BOT: ClassVar[str] = 'bot_instance_replaced_by_ptb_persistence'
+15 -16
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -19,7 +19,7 @@
# pylint: disable=R0201
"""This module contains the CallbackContext class."""
from queue import Queue
from typing import TYPE_CHECKING, Any, Dict, List, Match, NoReturn, Optional, Tuple, Union
from typing import TYPE_CHECKING, Dict, List, Match, NoReturn, Optional, Tuple, Union
from telegram import Update
@@ -73,9 +73,8 @@ class CallbackContext:
is handled by :class:`telegram.ext.CommandHandler`, :class:`telegram.ext.PrefixHandler`
or :class:`telegram.ext.StringCommandHandler`. It contains a list of the words in the
text after the command, using any whitespace string as a delimiter.
error (:class:`telegram.TelegramError`): Optional. The error that was raised.
Only present when passed to a error handler registered with
:attr:`telegram.ext.Dispatcher.add_error_handler`.
error (:obj:`Exception`): Optional. The error that was raised. Only present when passed
to a error handler registered with :attr:`telegram.ext.Dispatcher.add_error_handler`.
async_args (List[:obj:`object`]): Optional. Positional arguments of the function that
raised the error. Only present when the raising function was run asynchronously using
:meth:`telegram.ext.Dispatcher.run_async`.
@@ -98,14 +97,14 @@ class CallbackContext:
)
self._dispatcher = dispatcher
self._bot_data = dispatcher.bot_data
self._chat_data: Optional[Dict[Any, Any]] = None
self._user_data: Optional[Dict[Any, Any]] = None
self._chat_data: Optional[Dict[object, object]] = None
self._user_data: Optional[Dict[object, object]] = None
self.args: Optional[List[str]] = None
self.matches: Optional[List[Match]] = None
self.error: Optional[Exception] = None
self.job: Optional['Job'] = None
self.async_args: Optional[Union[List, Tuple]] = None
self.async_kwargs: Optional[Dict[str, Any]] = None
self.async_kwargs: Optional[Dict[str, object]] = None
@property
def dispatcher(self) -> 'Dispatcher':
@@ -117,9 +116,9 @@ class CallbackContext:
return self._bot_data
@bot_data.setter
def bot_data(self, value: Any) -> NoReturn:
def bot_data(self, value: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to bot_data, see " "https://git.io/fjxKe"
"You can not assign a new value to bot_data, see https://git.io/Jt6ic"
)
@property
@@ -127,9 +126,9 @@ class CallbackContext:
return self._chat_data
@chat_data.setter
def chat_data(self, value: Any) -> NoReturn:
def chat_data(self, value: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to chat_data, see " "https://git.io/fjxKe"
"You can not assign a new value to chat_data, see https://git.io/Jt6ic"
)
@property
@@ -137,9 +136,9 @@ class CallbackContext:
return self._user_data
@user_data.setter
def user_data(self, value: Any) -> NoReturn:
def user_data(self, value: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to user_data, see " "https://git.io/fjxKe"
"You can not assign a new value to user_data, see https://git.io/Jt6ic"
)
@classmethod
@@ -149,7 +148,7 @@ class CallbackContext:
error: Exception,
dispatcher: 'Dispatcher',
async_args: Union[List, Tuple] = None,
async_kwargs: Dict[str, Any] = None,
async_kwargs: Dict[str, object] = None,
) -> 'CallbackContext':
self = cls.from_update(update, dispatcher)
self.error = error
@@ -177,7 +176,7 @@ class CallbackContext:
self.job = job
return self
def update(self, data: Dict[str, Any]) -> None:
def update(self, data: Dict[str, object]) -> None:
self.__dict__.update(data)
@property
+26 -28
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -21,7 +21,6 @@
import re
from typing import (
TYPE_CHECKING,
Any,
Callable,
Dict,
Match,
@@ -33,7 +32,6 @@ from typing import (
)
from telegram import Update
from telegram.utils.types import HandlerArg
from telegram.utils.helpers import DefaultValue, DEFAULT_FALSE
from .handler import Handler
@@ -44,29 +42,11 @@ if TYPE_CHECKING:
RT = TypeVar('RT')
class CallbackQueryHandler(Handler):
class CallbackQueryHandler(Handler[Update]):
"""Handler class to handle Telegram callback queries. Optionally based on a regex.
Read the documentation of the ``re`` module for more information.
Attributes:
callback (:obj:`callable`): The callback function for this handler.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
pattern (:obj:`str` | `Pattern`): Optional. Regex pattern to test
:attr:`telegram.CallbackQuery.data` against.
pass_groups (:obj:`bool`): Determines whether ``groups`` will be passed to the
callback function.
pass_groupdict (:obj:`bool`): Determines whether ``groupdict``. will be passed to
the callback function.
pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to
the callback function.
pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
Note:
:attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you
can use to keep any data in will be sent to the :attr:`callback` function. Related to
@@ -119,11 +99,29 @@ class CallbackQueryHandler(Handler):
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
Defaults to :obj:`False`.
Attributes:
callback (:obj:`callable`): The callback function for this handler.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
pattern (:obj:`str` | `Pattern`): Optional. Regex pattern to test
:attr:`telegram.CallbackQuery.data` against.
pass_groups (:obj:`bool`): Determines whether ``groups`` will be passed to the
callback function.
pass_groupdict (:obj:`bool`): Determines whether ``groupdict``. will be passed to
the callback function.
pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to
the callback function.
pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
"""
def __init__(
self,
callback: Callable[[HandlerArg, 'CallbackContext'], RT],
callback: Callable[[Update, 'CallbackContext'], RT],
pass_update_queue: bool = False,
pass_job_queue: bool = False,
pattern: Union[str, Pattern] = None,
@@ -149,11 +147,11 @@ class CallbackQueryHandler(Handler):
self.pass_groups = pass_groups
self.pass_groupdict = pass_groupdict
def check_update(self, update: HandlerArg) -> Optional[Union[bool, object]]:
def check_update(self, update: object) -> Optional[Union[bool, object]]:
"""Determines whether an update should be passed to this handlers :attr:`callback`.
Args:
update (:class:`telegram.Update`): Incoming telegram update.
update (:class:`telegram.Update` | :obj:`object`): Incoming update.
Returns:
:obj:`bool`
@@ -172,9 +170,9 @@ class CallbackQueryHandler(Handler):
def collect_optional_args(
self,
dispatcher: 'Dispatcher',
update: HandlerArg = None,
update: Update = None,
check_result: Union[bool, Match] = None,
) -> Dict[str, Any]:
) -> Dict[str, object]:
optional_args = super().collect_optional_args(dispatcher, update, check_result)
if self.pattern:
check_result = cast(Match, check_result)
@@ -187,7 +185,7 @@ class CallbackQueryHandler(Handler):
def collect_additional_context(
self,
context: 'CallbackContext',
update: HandlerArg,
update: Update,
dispatcher: 'Dispatcher',
check_result: Union[bool, Match],
) -> None:
+16 -17
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -21,28 +21,15 @@
from typing import Optional, TypeVar, Union
from telegram import Update
from telegram.utils.types import HandlerArg
from .handler import Handler
RT = TypeVar('RT')
class ChosenInlineResultHandler(Handler):
class ChosenInlineResultHandler(Handler[Update]):
"""Handler class to handle Telegram updates that contain a chosen inline result.
Attributes:
callback (:obj:`callable`): The callback function for this handler.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to
the callback function.
pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
Note:
:attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you
can use to keep any data in will be sent to the :attr:`callback` function. Related to
@@ -84,13 +71,25 @@ class ChosenInlineResultHandler(Handler):
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
Defaults to :obj:`False`.
Attributes:
callback (:obj:`callable`): The callback function for this handler.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to
the callback function.
pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
"""
def check_update(self, update: HandlerArg) -> Optional[Union[bool, object]]:
def check_update(self, update: object) -> Optional[Union[bool, object]]:
"""Determines whether an update should be passed to this handlers :attr:`callback`.
Args:
update (:class:`telegram.Update`): Incoming telegram update.
update (:class:`telegram.Update` | :obj:`object`): Incoming update.
Returns:
:obj:`bool`
+35 -35
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -19,12 +19,12 @@
"""This module contains the CommandHandler and PrefixHandler classes."""
import re
import warnings
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, TypeVar, Union
from typing import TYPE_CHECKING, Callable, Dict, List, Optional, Tuple, TypeVar, Union
from telegram import MessageEntity, Update
from telegram.ext import BaseFilter, Filters
from telegram.utils.deprecate import TelegramDeprecationWarning
from telegram.utils.types import HandlerArg, SLT
from telegram.utils.types import SLT
from telegram.utils.helpers import DefaultValue, DEFAULT_FALSE
from .handler import Handler
@@ -35,7 +35,7 @@ if TYPE_CHECKING:
RT = TypeVar('RT')
class CommandHandler(Handler):
class CommandHandler(Handler[Update]):
"""Handler class to handle Telegram commands.
Commands are Telegram messages that start with ``/``, optionally followed by an ``@`` and the
@@ -49,27 +49,6 @@ class CommandHandler(Handler):
Note:
:class:`telegram.ext.CommandHandler` does *not* handle (edited) channel posts.
Attributes:
command (:class:`telegram.utils.types.SLT[str]`):
The command or list of commands this handler should listen for.
Limitations are the same as described here https://core.telegram.org/bots#commands
callback (:obj:`callable`): The callback function for this handler.
filters (:class:`telegram.ext.BaseFilter`): Optional. Only allow updates with these
Filters.
allow_edited (:obj:`bool`): Determines whether the handler should also accept
edited messages.
pass_args (:obj:`bool`): Determines whether the handler should be passed
``args``.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to
the callback function.
pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
Note:
:attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a :obj:`dict` you
can use to keep any data in will be sent to the :attr:`callback` function. Related to
@@ -129,12 +108,33 @@ class CommandHandler(Handler):
Raises:
ValueError - when command is too long or has illegal chars.
Attributes:
command (:class:`telegram.utils.types.SLT[str]`):
The command or list of commands this handler should listen for.
Limitations are the same as described here https://core.telegram.org/bots#commands
callback (:obj:`callable`): The callback function for this handler.
filters (:class:`telegram.ext.BaseFilter`): Optional. Only allow updates with these
Filters.
allow_edited (:obj:`bool`): Determines whether the handler should also accept
edited messages.
pass_args (:obj:`bool`): Determines whether the handler should be passed
``args``.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to
the callback function.
pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
"""
def __init__(
self,
command: SLT[str],
callback: Callable[[HandlerArg, 'CallbackContext'], RT],
callback: Callable[[Update, 'CallbackContext'], RT],
filters: BaseFilter = None,
allow_edited: bool = None,
pass_args: bool = False,
@@ -177,12 +177,12 @@ class CommandHandler(Handler):
self.pass_args = pass_args
def check_update(
self, update: HandlerArg
self, update: object
) -> Optional[Union[bool, Tuple[List[str], Optional[Union[bool, Dict]]]]]:
"""Determines whether an update should be passed to this handlers :attr:`callback`.
Args:
update (:class:`telegram.Update`): Incoming telegram update.
update (:class:`telegram.Update` | :obj:`object`): Incoming update.
Returns:
:obj:`list`: The list of args for the handler.
@@ -218,9 +218,9 @@ class CommandHandler(Handler):
def collect_optional_args(
self,
dispatcher: 'Dispatcher',
update: HandlerArg = None,
update: Update = None,
check_result: Optional[Union[bool, Tuple[List[str], Optional[bool]]]] = None,
) -> Dict[str, Any]:
) -> Dict[str, object]:
optional_args = super().collect_optional_args(dispatcher, update)
if self.pass_args and isinstance(check_result, tuple):
optional_args['args'] = check_result[0]
@@ -229,7 +229,7 @@ class CommandHandler(Handler):
def collect_additional_context(
self,
context: 'CallbackContext',
update: HandlerArg,
update: Update,
dispatcher: 'Dispatcher',
check_result: Optional[Union[bool, Tuple[List[str], Optional[bool]]]],
) -> None:
@@ -344,7 +344,7 @@ class PrefixHandler(CommandHandler):
self,
prefix: SLT[str],
command: SLT[str],
callback: Callable[[HandlerArg, 'CallbackContext'], RT],
callback: Callable[[Update, 'CallbackContext'], RT],
filters: BaseFilter = None,
pass_args: bool = False,
pass_update_queue: bool = False,
@@ -415,12 +415,12 @@ class PrefixHandler(CommandHandler):
self._commands = [x.lower() + y.lower() for x in self.prefix for y in self.command]
def check_update(
self, update: HandlerArg
self, update: object
) -> Optional[Union[bool, Tuple[List[str], Optional[Union[bool, Dict]]]]]:
"""Determines whether an update should be passed to this handlers :attr:`callback`.
Args:
update (:class:`telegram.Update`): Incoming telegram update.
update (:class:`telegram.Update` | :obj:`object`): Incoming update.
Returns:
:obj:`list`: The list of args for the handler.
@@ -442,7 +442,7 @@ class PrefixHandler(CommandHandler):
def collect_additional_context(
self,
context: 'CallbackContext',
update: HandlerArg,
update: Update,
dispatcher: 'Dispatcher',
check_result: Optional[Union[bool, Tuple[List[str], Optional[bool]]]],
) -> None:
+84 -52
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -22,7 +22,7 @@
import logging
import warnings
from threading import Lock
from typing import TYPE_CHECKING, Any, Dict, List, NoReturn, Optional, Tuple, cast, ClassVar
from typing import TYPE_CHECKING, Dict, List, NoReturn, Optional, Tuple, cast, ClassVar
from telegram import Update
from telegram.ext import (
@@ -34,8 +34,8 @@ from telegram.ext import (
Handler,
InlineQueryHandler,
)
from telegram.utils.promise import Promise
from telegram.utils.types import ConversationDict, HandlerArg
from telegram.ext.utils.promise import Promise
from telegram.utils.types import ConversationDict
if TYPE_CHECKING:
from telegram.ext import Dispatcher, Job
@@ -56,10 +56,24 @@ class _ConversationTimeoutContext:
self.callback_context = callback_context
class ConversationHandler(Handler):
class ConversationHandler(Handler[Update]):
"""
A handler to hold a conversation with a single user by managing four collections of other
handlers.
A handler to hold a conversation with a single or multiple users through Telegram updates by
managing four collections of other handlers.
Note:
``ConversationHandler`` will only accept updates that are (subclass-)instances of
:class:`telegram.Update`. This is, because depending on the :attr:`per_user` and
:attr:`per_chat` ``ConversationHandler`` relies on
:attr:`telegram.Update.effective_user` and/or :attr:`telegram.Update.effective_chat` in
order to determine which conversation an update should belong to. For ``per_message=True``,
``ConversationHandler`` uses ``update.callback_query.message.message_id`` when
``per_chat=True`` and ``update.callback_query.inline_message_id`` when ``per_chat=False``.
For a more detailed explanation, please see our `FAQ`_.
Finally, ``ConversationHandler``, does *not* handle (edited) channel posts.
.. _`FAQ`: https://git.io/JtcyU
The first collection, a ``list`` named :attr:`entry_points`, is used to initiate the
conversation, for example with a :class:`telegram.ext.CommandHandler` or
@@ -101,35 +115,6 @@ class ConversationHandler(Handler):
.. _`examples`: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples
Attributes:
entry_points (List[:class:`telegram.ext.Handler`]): A list of ``Handler`` objects that can
trigger the start of the conversation.
states (Dict[:obj:`object`, List[:class:`telegram.ext.Handler`]]): A :obj:`dict` that
defines the different states of conversation a user can be in and one or more
associated ``Handler`` objects that should be used in that state.
fallbacks (List[:class:`telegram.ext.Handler`]): A list of handlers that might be used if
the user is in a conversation, but every handler for their current state returned
:obj:`False` on :attr:`check_update`.
allow_reentry (:obj:`bool`): Determines if a user can restart a conversation with
an entry point.
per_chat (:obj:`bool`): If the conversationkey should contain the Chat's ID.
per_user (:obj:`bool`): If the conversationkey should contain the User's ID.
per_message (:obj:`bool`): If the conversationkey should contain the Message's
ID.
conversation_timeout (:obj:`float` | :obj:`datetime.timedelta`): Optional. When this
handler is inactive more than this timeout (in seconds), it will be automatically
ended. If this value is 0 (default), there will be no timeout. When it's triggered, the
last received update and the corresponding ``context`` will be handled by ALL the
handler's who's :attr:`check_update` method returns :obj:`True` that are in the state
:attr:`ConversationHandler.TIMEOUT`.
name (:obj:`str`): Optional. The name for this conversationhandler. Required for
persistence
persistent (:obj:`bool`): Optional. If the conversations dict for this handler should be
saved. Name is required and persistence has to be set in :class:`telegram.ext.Updater`
map_to_parent (Dict[:obj:`object`, :obj:`object`]): Optional. A :obj:`dict` that can be
used to instruct a nested conversationhandler to transition into a mapped state on
its parent conversationhandler in place of a specified nested state.
Args:
entry_points (List[:class:`telegram.ext.Handler`]): A list of ``Handler`` objects that can
trigger the start of the conversation. The first handler which :attr:`check_update`
@@ -165,10 +150,52 @@ class ConversationHandler(Handler):
map_to_parent (Dict[:obj:`object`, :obj:`object`], optional): A :obj:`dict` that can be
used to instruct a nested conversationhandler to transition into a mapped state on
its parent conversationhandler in place of a specified nested state.
run_async (:obj:`bool`, optional): Pass :obj:`True` to *override* the
:attr:`Handler.run_async` setting of all handlers (in :attr:`entry_points`,
:attr:`states` and :attr:`fallbacks`).
Note:
If set to :obj:`True`, you should not pass a handler instance, that needs to be
run synchronously in another context.
.. versionadded:: 13.2
Raises:
ValueError
Attributes:
entry_points (List[:class:`telegram.ext.Handler`]): A list of ``Handler`` objects that can
trigger the start of the conversation.
states (Dict[:obj:`object`, List[:class:`telegram.ext.Handler`]]): A :obj:`dict` that
defines the different states of conversation a user can be in and one or more
associated ``Handler`` objects that should be used in that state.
fallbacks (List[:class:`telegram.ext.Handler`]): A list of handlers that might be used if
the user is in a conversation, but every handler for their current state returned
:obj:`False` on :attr:`check_update`.
allow_reentry (:obj:`bool`): Determines if a user can restart a conversation with
an entry point.
per_chat (:obj:`bool`): If the conversationkey should contain the Chat's ID.
per_user (:obj:`bool`): If the conversationkey should contain the User's ID.
per_message (:obj:`bool`): If the conversationkey should contain the Message's
ID.
conversation_timeout (:obj:`float` | :obj:`datetime.timedelta`): Optional. When this
handler is inactive more than this timeout (in seconds), it will be automatically
ended. If this value is 0 (default), there will be no timeout. When it's triggered, the
last received update and the corresponding ``context`` will be handled by ALL the
handler's who's :attr:`check_update` method returns :obj:`True` that are in the state
:attr:`ConversationHandler.TIMEOUT`.
name (:obj:`str`): Optional. The name for this conversationhandler. Required for
persistence
persistent (:obj:`bool`): Optional. If the conversations dict for this handler should be
saved. Name is required and persistence has to be set in :class:`telegram.ext.Updater`
map_to_parent (Dict[:obj:`object`, :obj:`object`]): Optional. A :obj:`dict` that can be
used to instruct a nested conversationhandler to transition into a mapped state on
its parent conversationhandler in place of a specified nested state.
run_async (:obj:`bool`): If :obj:`True`, will override the
:attr:`Handler.run_async` setting of all internal handlers on initialization.
.. versionadded:: 13.2
"""
END: ClassVar[int] = -1
@@ -192,8 +219,9 @@ class ConversationHandler(Handler):
name: str = None,
persistent: bool = False,
map_to_parent: Dict[object, object] = None,
run_async: bool = False,
):
self.run_async = False
self.run_async = run_async
self._entry_points = entry_points
self._states = states
@@ -229,7 +257,7 @@ class ConversationHandler(Handler):
"since message IDs are not globally unique."
)
all_handlers = list()
all_handlers: List[Handler] = list()
all_handlers.extend(entry_points)
all_handlers.extend(fallbacks)
@@ -263,12 +291,16 @@ class ConversationHandler(Handler):
)
break
if self.run_async:
for handler in all_handlers:
handler.run_async = True
@property
def entry_points(self) -> List[Handler]:
return self._entry_points
@entry_points.setter
def entry_points(self, value: Any) -> NoReturn:
def entry_points(self, value: object) -> NoReturn:
raise ValueError('You can not assign a new value to entry_points after initialization.')
@property
@@ -276,7 +308,7 @@ class ConversationHandler(Handler):
return self._states
@states.setter
def states(self, value: Any) -> NoReturn:
def states(self, value: object) -> NoReturn:
raise ValueError('You can not assign a new value to states after initialization.')
@property
@@ -284,7 +316,7 @@ class ConversationHandler(Handler):
return self._fallbacks
@fallbacks.setter
def fallbacks(self, value: Any) -> NoReturn:
def fallbacks(self, value: object) -> NoReturn:
raise ValueError('You can not assign a new value to fallbacks after initialization.')
@property
@@ -292,7 +324,7 @@ class ConversationHandler(Handler):
return self._allow_reentry
@allow_reentry.setter
def allow_reentry(self, value: Any) -> NoReturn:
def allow_reentry(self, value: object) -> NoReturn:
raise ValueError('You can not assign a new value to allow_reentry after initialization.')
@property
@@ -300,7 +332,7 @@ class ConversationHandler(Handler):
return self._per_user
@per_user.setter
def per_user(self, value: Any) -> NoReturn:
def per_user(self, value: object) -> NoReturn:
raise ValueError('You can not assign a new value to per_user after initialization.')
@property
@@ -308,7 +340,7 @@ class ConversationHandler(Handler):
return self._per_chat
@per_chat.setter
def per_chat(self, value: Any) -> NoReturn:
def per_chat(self, value: object) -> NoReturn:
raise ValueError('You can not assign a new value to per_chat after initialization.')
@property
@@ -316,7 +348,7 @@ class ConversationHandler(Handler):
return self._per_message
@per_message.setter
def per_message(self, value: Any) -> NoReturn:
def per_message(self, value: object) -> NoReturn:
raise ValueError('You can not assign a new value to per_message after initialization.')
@property
@@ -324,7 +356,7 @@ class ConversationHandler(Handler):
return self._conversation_timeout
@conversation_timeout.setter
def conversation_timeout(self, value: Any) -> NoReturn:
def conversation_timeout(self, value: object) -> NoReturn:
raise ValueError(
'You can not assign a new value to conversation_timeout after ' 'initialization.'
)
@@ -334,7 +366,7 @@ class ConversationHandler(Handler):
return self._name
@name.setter
def name(self, value: Any) -> NoReturn:
def name(self, value: object) -> NoReturn:
raise ValueError('You can not assign a new value to name after initialization.')
@property
@@ -342,7 +374,7 @@ class ConversationHandler(Handler):
return self._map_to_parent
@map_to_parent.setter
def map_to_parent(self, value: Any) -> NoReturn:
def map_to_parent(self, value: object) -> NoReturn:
raise ValueError('You can not assign a new value to map_to_parent after initialization.')
@property
@@ -391,13 +423,13 @@ class ConversationHandler(Handler):
return tuple(key)
def check_update(self, update: HandlerArg) -> CheckUpdateType: # pylint: disable=R0911
def check_update(self, update: object) -> CheckUpdateType: # pylint: disable=R0911
"""
Determines whether an update should be handled by this conversationhandler, and if so in
which state the conversation currently is.
Args:
update (:class:`telegram.Update`): Incoming telegram update.
update (:class:`telegram.Update` | :obj:`object`): Incoming update.
Returns:
:obj:`bool`
@@ -406,7 +438,7 @@ class ConversationHandler(Handler):
if not isinstance(update, Update):
return None
# Ignore messages in channels
if update.channel_post:
if update.channel_post or update.edited_channel_post:
return None
if self.per_chat and not update.effective_chat:
return None
@@ -487,7 +519,7 @@ class ConversationHandler(Handler):
def handle_update( # type: ignore[override]
self,
update: HandlerArg,
update: Update,
dispatcher: 'Dispatcher',
check_result: CheckUpdateType,
context: CallbackContext = None,
+72 -35
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2020
# Copyright (C) 2020-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -18,37 +18,17 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
# pylint: disable=R0201, E0401
"""This module contains the class Defaults, which allows to pass default values to Updater."""
from typing import Any, NoReturn, Optional, Union
from typing import NoReturn, Optional, Dict, Any
import pytz
from telegram.utils.helpers import DEFAULT_NONE, DefaultValue
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import ODVInput
class Defaults:
"""Convenience Class to gather all parameters with a (user defined) default value
Attributes:
parse_mode (:obj:`str`): Optional. Send Markdown or HTML, if you want Telegram apps to show
bold, italic, fixed-width text or URLs in your bot's message.
disable_notification (:obj:`bool`): Optional. Sends the message silently. Users will
receive a notification with no sound.
disable_web_page_preview (:obj:`bool`): Optional. Disables link previews for links in this
message.
allow_sending_without_reply (:obj:`bool`): Optional. Pass :obj:`True`, if the message
should be sent even if the specified replied-to message is not found.
timeout (:obj:`int` | :obj:`float`): Optional. If this value is specified, use it as the
read timeout from the server (instead of the one specified during creation of the
connection pool).
quote (:obj:`bool`): Optional. If set to :obj:`True`, the reply is sent as an actual reply
to the message. If ``reply_to_message_id`` is passed in ``kwargs``, this parameter will
be ignored. Default: :obj:`True` in group chats and :obj:`False` in private chats.
tzinfo (:obj:`tzinfo`): A timezone to be used for all date(time) objects appearing
throughout PTB.
run_async (:obj:`bool`): Optional. Default setting for the ``run_async`` parameter of
handlers and error handlers registered through :meth:`Dispatcher.add_handler` and
:meth:`Dispatcher.add_error_handler`.
Parameters:
parse_mode (:obj:`str`, optional): Send Markdown or HTML, if you want Telegram apps to show
bold, italic, fixed-width text or URLs in your bot's message.
@@ -68,9 +48,35 @@ class Defaults:
appearing throughout PTB, i.e. if a timezone naive date(time) object is passed
somewhere, it will be assumed to be in ``tzinfo``. Must be a timezone provided by the
``pytz`` module. Defaults to UTC.
Note:
Will *not* be used for :meth:`telegram.Bot.get_updates`!
run_async (:obj:`bool`, optional): Default setting for the ``run_async`` parameter of
handlers and error handlers registered through :meth:`Dispatcher.add_handler` and
:meth:`Dispatcher.add_error_handler`. Defaults to :obj:`False`.
Attributes:
parse_mode (:obj:`str`): Optional. Send Markdown or HTML, if you want Telegram apps to show
bold, italic, fixed-width text or URLs in your bot's message.
explanation_parse_mode (:obj:`str`): Optional. Alias for :attr:`parse_mode`, used for
the corresponding parameter of :meth:`telegram.Bot.send_poll`.
disable_notification (:obj:`bool`): Optional. Sends the message silently. Users will
receive a notification with no sound.
disable_web_page_preview (:obj:`bool`): Optional. Disables link previews for links in this
message.
allow_sending_without_reply (:obj:`bool`): Optional. Pass :obj:`True`, if the message
should be sent even if the specified replied-to message is not found.
timeout (:obj:`int` | :obj:`float`): Optional. If this value is specified, use it as the
read timeout from the server (instead of the one specified during creation of the
connection pool).
quote (:obj:`bool`): Optional. If set to :obj:`True`, the reply is sent as an actual reply
to the message. If ``reply_to_message_id`` is passed in ``kwargs``, this parameter will
be ignored. Default: :obj:`True` in group chats and :obj:`False` in private chats.
tzinfo (:obj:`tzinfo`): A timezone to be used for all date(time) objects appearing
throughout PTB.
run_async (:obj:`bool`): Optional. Default setting for the ``run_async`` parameter of
handlers and error handlers registered through :meth:`Dispatcher.add_handler` and
:meth:`Dispatcher.add_error_handler`.
"""
def __init__(
@@ -80,7 +86,7 @@ class Defaults:
disable_web_page_preview: bool = None,
# Timeout needs special treatment, since the bot methods have two different
# default values for timeout (None and 20s)
timeout: Union[float, DefaultValue] = DEFAULT_NONE,
timeout: ODVInput[float] = DEFAULT_NONE,
quote: bool = None,
tzinfo: pytz.BaseTzInfo = pytz.utc,
run_async: bool = False,
@@ -95,12 +101,43 @@ class Defaults:
self._tzinfo = tzinfo
self._run_async = run_async
# Gather all defaults that actually have a default value
self._api_defaults = {}
for kwarg in (
'parse_mode',
'explanation_parse_mode',
'disable_notification',
'disable_web_page_preview',
'allow_sending_without_reply',
):
value = getattr(self, kwarg)
if value not in [None, DEFAULT_NONE]:
self._api_defaults[kwarg] = value
# Special casing, as None is a valid default value
if self.timeout != DEFAULT_NONE:
self._api_defaults['timeout'] = self.timeout
@property
def api_defaults(self) -> Dict[str, Any]:
return self._api_defaults
@property
def parse_mode(self) -> Optional[str]:
return self._parse_mode
@parse_mode.setter
def parse_mode(self, value: Any) -> NoReturn:
def parse_mode(self, value: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to defaults after because it would "
"not have any effect."
)
@property
def explanation_parse_mode(self) -> Optional[str]:
return self._parse_mode
@explanation_parse_mode.setter
def explanation_parse_mode(self, value: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to defaults after because it would "
"not have any effect."
@@ -111,7 +148,7 @@ class Defaults:
return self._disable_notification
@disable_notification.setter
def disable_notification(self, value: Any) -> NoReturn:
def disable_notification(self, value: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to defaults after because it would "
"not have any effect."
@@ -122,7 +159,7 @@ class Defaults:
return self._disable_web_page_preview
@disable_web_page_preview.setter
def disable_web_page_preview(self, value: Any) -> NoReturn:
def disable_web_page_preview(self, value: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to defaults after because it would "
"not have any effect."
@@ -133,18 +170,18 @@ class Defaults:
return self._allow_sending_without_reply
@allow_sending_without_reply.setter
def allow_sending_without_reply(self, value: Any) -> NoReturn:
def allow_sending_without_reply(self, value: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to defaults after because it would "
"not have any effect."
)
@property
def timeout(self) -> Union[float, DefaultValue]:
def timeout(self) -> ODVInput[float]:
return self._timeout
@timeout.setter
def timeout(self, value: Any) -> NoReturn:
def timeout(self, value: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to defaults after because it would "
"not have any effect."
@@ -155,7 +192,7 @@ class Defaults:
return self._quote
@quote.setter
def quote(self, value: Any) -> NoReturn:
def quote(self, value: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to defaults after because it would "
"not have any effect."
@@ -166,18 +203,18 @@ class Defaults:
return self._tzinfo
@tzinfo.setter
def tzinfo(self, value: Any) -> NoReturn:
def tzinfo(self, value: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to defaults after because it would "
"not have any effect."
)
@property
def run_async(self) -> Optional[bool]:
def run_async(self) -> bool:
return self._run_async
@run_async.setter
def run_async(self, value: Any) -> NoReturn:
def run_async(self, value: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to defaults after because it would "
"not have any effect."
+14 -14
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -19,7 +19,7 @@
"""This module contains the DictPersistence class."""
from copy import deepcopy
from typing import Any, DefaultDict, Dict, Optional, Tuple
from typing import DefaultDict, Dict, Optional, Tuple
from collections import defaultdict
from telegram.utils.helpers import (
@@ -54,14 +54,6 @@ class DictPersistence(BasePersistence):
:meth:`telegram.ext.BasePersistence.replace_bot` and
:meth:`telegram.ext.BasePersistence.insert_bot`.
Attributes:
store_user_data (:obj:`bool`): Whether user_data should be saved by this
persistence class.
store_chat_data (:obj:`bool`): Whether chat_data should be saved by this
persistence class.
store_bot_data (:obj:`bool`): Whether bot_data should be saved by this
persistence class.
Args:
store_user_data (:obj:`bool`, optional): Whether user_data should be saved by this
persistence class. Default is :obj:`True`.
@@ -77,6 +69,14 @@ class DictPersistence(BasePersistence):
bot_data on creating this persistence. Default is ``""``.
conversations_json (:obj:`str`, optional): Json string that will be used to reconstruct
conversation on creating this persistence. Default is ``""``.
Attributes:
store_user_data (:obj:`bool`): Whether user_data should be saved by this
persistence class.
store_chat_data (:obj:`bool`): Whether chat_data should be saved by this
persistence class.
store_bot_data (:obj:`bool`): Whether bot_data should be saved by this
persistence class.
"""
def __init__(
@@ -169,7 +169,7 @@ class DictPersistence(BasePersistence):
return json.dumps(self.bot_data)
@property
def conversations(self) -> Optional[Dict[str, Dict[Tuple, Any]]]:
def conversations(self) -> Optional[Dict[str, Dict[Tuple, object]]]:
""":obj:`dict`: The conversations as a dict."""
return self._conversations
@@ -180,7 +180,7 @@ class DictPersistence(BasePersistence):
return self._conversations_json
return encode_conversations_to_json(self.conversations) # type: ignore[arg-type]
def get_user_data(self) -> DefaultDict[int, Dict[Any, Any]]:
def get_user_data(self) -> DefaultDict[int, Dict[object, object]]:
"""Returns the user_data created from the ``user_data_json`` or an empty
:obj:`defaultdict`.
@@ -193,7 +193,7 @@ class DictPersistence(BasePersistence):
self._user_data = defaultdict(dict)
return deepcopy(self.user_data) # type: ignore[arg-type]
def get_chat_data(self) -> DefaultDict[int, Dict[Any, Any]]:
def get_chat_data(self) -> DefaultDict[int, Dict[object, object]]:
"""Returns the chat_data created from the ``chat_data_json`` or an empty
:obj:`defaultdict`.
@@ -206,7 +206,7 @@ class DictPersistence(BasePersistence):
self._chat_data = defaultdict(dict)
return deepcopy(self.chat_data) # type: ignore[arg-type]
def get_bot_data(self) -> Dict[Any, Any]:
def get_bot_data(self) -> Dict[object, object]:
"""Returns the bot_data created from the ``bot_data_json`` or an empty :obj:`dict`.
Returns:
+61 -45
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -26,7 +26,7 @@ from functools import wraps
from queue import Empty, Queue
from threading import BoundedSemaphore, Event, Lock, Thread, current_thread
from time import sleep
from typing import TYPE_CHECKING, Any, Callable, DefaultDict, Dict, List, Optional, Set, Union
from typing import TYPE_CHECKING, Callable, DefaultDict, Dict, List, Optional, Set, Union
from uuid import uuid4
from telegram import TelegramError, Update
@@ -34,8 +34,7 @@ from telegram.ext import BasePersistence
from telegram.ext.callbackcontext import CallbackContext
from telegram.ext.handler import Handler
from telegram.utils.deprecate import TelegramDeprecationWarning
from telegram.utils.promise import Promise
from telegram.utils.types import HandlerArg
from telegram.ext.utils.promise import Promise
from telegram.utils.helpers import DefaultValue, DEFAULT_FALSE
if TYPE_CHECKING:
@@ -46,8 +45,8 @@ DEFAULT_GROUP: int = 0
def run_async(
func: Callable[[Update, CallbackContext], Any]
) -> Callable[[Update, CallbackContext], Any]:
func: Callable[[Update, CallbackContext], object]
) -> Callable[[Update, CallbackContext], object]:
"""
Function decorator that will run the function in a new thread.
@@ -65,7 +64,7 @@ def run_async(
"""
@wraps(func)
def async_func(*args: Any, **kwargs: Any) -> Any:
def async_func(*args: object, **kwargs: object) -> object:
warnings.warn(
'The @run_async decorator is deprecated. Use the `run_async` parameter of '
'your Handler or `Dispatcher.run_async` instead.',
@@ -81,7 +80,7 @@ def run_async(
class DispatcherHandlerStop(Exception):
"""
Raise this in handler to prevent execution any other handler (even in different group).
Raise this in handler to prevent execution of any other handler (even in different group).
In order to use this exception in a :class:`telegram.ext.ConversationHandler`, pass the
optional ``state`` parameter instead of returning the next state:
@@ -107,19 +106,6 @@ class DispatcherHandlerStop(Exception):
class Dispatcher:
"""This class dispatches all kinds of updates to its registered handlers.
Attributes:
bot (:class:`telegram.Bot`): The bot object that should be passed to the handlers.
update_queue (:obj:`Queue`): The synchronized queue that will contain the updates.
job_queue (:class:`telegram.ext.JobQueue`): Optional. The :class:`telegram.ext.JobQueue`
instance to pass onto handler callbacks.
workers (:obj:`int`, optional): Number of maximum concurrent worker threads for the
``@run_async`` decorator and :meth:`run_async`.
user_data (:obj:`defaultdict`): A dictionary handlers can use to store data for the user.
chat_data (:obj:`defaultdict`): A dictionary handlers can use to store data for the chat.
bot_data (:obj:`dict`): A dictionary handlers can use to store data for the bot.
persistence (:class:`telegram.ext.BasePersistence`): Optional. The persistence class to
store data that should be persistent over restarts.
Args:
bot (:class:`telegram.Bot`): The bot object that should be passed to the handlers.
update_queue (:obj:`Queue`): The synchronized queue that will contain the updates.
@@ -133,6 +119,19 @@ class Dispatcher:
API (ignored if `dispatcher` argument is used). Defaults to :obj:`True`.
**New users**: set this to :obj:`True`.
Attributes:
bot (:class:`telegram.Bot`): The bot object that should be passed to the handlers.
update_queue (:obj:`Queue`): The synchronized queue that will contain the updates.
job_queue (:class:`telegram.ext.JobQueue`): Optional. The :class:`telegram.ext.JobQueue`
instance to pass onto handler callbacks.
workers (:obj:`int`, optional): Number of maximum concurrent worker threads for the
``@run_async`` decorator and :meth:`run_async`.
user_data (:obj:`defaultdict`): A dictionary handlers can use to store data for the user.
chat_data (:obj:`defaultdict`): A dictionary handlers can use to store data for the chat.
bot_data (:obj:`dict`): A dictionary handlers can use to store data for the bot.
persistence (:class:`telegram.ext.BasePersistence`): Optional. The persistence class to
store data that should be persistent over restarts.
"""
__singleton_lock = Lock()
@@ -163,8 +162,8 @@ class Dispatcher:
stacklevel=3,
)
self.user_data: DefaultDict[int, Dict[Any, Any]] = defaultdict(dict)
self.chat_data: DefaultDict[int, Dict[Any, Any]] = defaultdict(dict)
self.user_data: DefaultDict[int, Dict[object, object]] = defaultdict(dict)
self.chat_data: DefaultDict[int, Dict[object, object]] = defaultdict(dict)
self.bot_data = {}
self.persistence: Optional[BasePersistence] = None
self._update_persistence_lock = Lock()
@@ -288,7 +287,7 @@ class Dispatcher:
self.logger.exception('An uncaught error was raised while handling the error.')
def run_async(
self, func: Callable[..., Any], *args: Any, update: HandlerArg = None, **kwargs: Any
self, func: Callable[..., object], *args: object, update: object = None, **kwargs: object
) -> Promise:
"""
Queue a function (with given args/kwargs) to be run asynchronously. Exceptions raised
@@ -304,9 +303,9 @@ class Dispatcher:
Args:
func (:obj:`callable`): The function to run in the thread.
*args (:obj:`tuple`, optional): Arguments to ``func``.
update (:class:`telegram.Update`, optional): The update associated with the functions
call. If passed, it will be available in the error handlers, in case an exception
is raised by :attr:`func`.
update (:class:`telegram.Update` | :obj:`object`, optional): The update associated with
the functions call. If passed, it will be available in the error handlers, in case
an exception is raised by :attr:`func`.
**kwargs (:obj:`dict`, optional): Keyword arguments to ``func``.
Returns:
@@ -317,11 +316,11 @@ class Dispatcher:
def _run_async(
self,
func: Callable[..., Any],
*args: Any,
update: HandlerArg = None,
func: Callable[..., object],
*args: object,
update: object = None,
error_handling: bool = True,
**kwargs: Any,
**kwargs: object,
) -> Promise:
# TODO: Remove error_handling parameter once we drop the @run_async decorator
promise = Promise(func, args, kwargs, update=update, error_handling=error_handling)
@@ -403,11 +402,18 @@ class Dispatcher:
def has_running_threads(self) -> bool:
return self.running or bool(self.__async_threads)
def process_update(self, update: Union[str, Update, TelegramError]) -> None:
"""Processes a single update.
def process_update(self, update: object) -> None:
"""Processes a single update and updates the persistence.
Note:
If the update is handled by least one synchronously running handlers (i.e.
``run_async=False``), :meth:`update_persistence` is called *once* after all handlers
synchronous handlers are done. Each asynchronously running handler will trigger
:meth:`update_persistence` on its own.
Args:
update (:obj:`str` | :class:`telegram.Update` | :class:`telegram.TelegramError`):
update (:class:`telegram.Update` | :obj:`object` | \
:class:`telegram.error.TelegramError`):
The update to process.
"""
@@ -421,6 +427,8 @@ class Dispatcher:
return
context = None
handled = False
sync_modes = []
for group in self.groups:
try:
@@ -429,11 +437,9 @@ class Dispatcher:
if check is not None and check is not False:
if not context and self.use_context:
context = CallbackContext.from_update(update, self)
handled = True
sync_modes.append(handler.run_async)
handler.handle_update(update, self, check, context)
# If handler runs async updating immediately doesn't make sense
if not handler.run_async:
self.update_persistence(update=update)
break
# Stop processing with any other handler.
@@ -453,6 +459,16 @@ class Dispatcher:
except Exception:
self.logger.exception('An uncaught error was raised while handling the error.')
# Update persistence, if handled
handled_only_async = all(sync_modes)
if handled:
# Respect default settings
if all(mode is DEFAULT_FALSE for mode in sync_modes) and self.bot.defaults:
handled_only_async = self.bot.defaults.run_async
# If update was only handled by async handlers, we don't need to update here
if not handled_only_async:
self.update_persistence(update=update)
def add_handler(self, handler: Handler, group: int = DEFAULT_GROUP) -> None:
"""Register a handler.
@@ -515,7 +531,7 @@ class Dispatcher:
del self.handlers[group]
self.groups.remove(group)
def update_persistence(self, update: HandlerArg = None) -> None:
def update_persistence(self, update: object = None) -> None:
"""Update :attr:`user_data`, :attr:`chat_data` and :attr:`bot_data` in :attr:`persistence`.
Args:
@@ -525,7 +541,7 @@ class Dispatcher:
with self._update_persistence_lock:
self.__update_persistence(update)
def __update_persistence(self, update: HandlerArg = None) -> None:
def __update_persistence(self, update: object = None) -> None:
if self.persistence:
# We use list() here in order to decouple chat_ids from self.chat_data, as dict view
# objects will change, when the dict does and we want to loop over chat_ids
@@ -586,7 +602,7 @@ class Dispatcher:
def add_error_handler(
self,
callback: Callable[[Any, CallbackContext], None],
callback: Callable[[object, CallbackContext], None],
run_async: Union[bool, DefaultValue] = DEFAULT_FALSE, # pylint: disable=W0621
) -> None:
"""Registers an error handler in the Dispatcher. This handler will receive every error
@@ -603,7 +619,7 @@ class Dispatcher:
callback (:obj:`callable`): The callback function for this error handler. Will be
called when an error is raised. Callback signature for context based API:
``def callback(update: Update, context: CallbackContext)``
``def callback(update: object, context: CallbackContext)``
The error that happened will be present in context.error.
run_async (:obj:`bool`, optional): Whether this handlers callback should be run
@@ -622,7 +638,7 @@ class Dispatcher:
self.error_handlers[callback] = run_async
def remove_error_handler(self, callback: Callable[[Any, CallbackContext], None]) -> None:
def remove_error_handler(self, callback: Callable[[object, CallbackContext], None]) -> None:
"""Removes an error handler.
Args:
@@ -632,12 +648,12 @@ class Dispatcher:
self.error_handlers.pop(callback, None)
def dispatch_error(
self, update: Optional[HandlerArg], error: Exception, promise: Promise = None
self, update: Optional[object], error: Exception, promise: Promise = None
) -> None:
"""Dispatches an error.
Args:
update (:obj:`str` | :class:`telegram.Update` | None): The update that caused the error
update (:obj:`object` | :class:`telegram.Update`): The update that caused the error.
error (:obj:`Exception`): The error that was raised.
promise (:class:`telegram.utils.Promise`, optional): The promise whose pooled function
raised the error.
+80 -75
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -91,7 +91,7 @@ class BaseFilter(ABC):
If you want to create your own filters create a class inheriting from either
:class:`MessageFilter` or :class:`UpdateFilter` and implement a :meth:``filter`` method that
:class:`MessageFilter` or :class:`UpdateFilter` and implement a :meth:`filter` method that
returns a boolean: :obj:`True` if the message should be
handled, :obj:`False` otherwise.
Note that the filters work only as class instances, not
@@ -148,7 +148,8 @@ class MessageFilter(BaseFilter, ABC):
"""Base class for all Message Filters. In contrast to :class:`UpdateFilter`, the object passed
to :meth:`filter` is ``update.effective_message``.
Please see :class:`telegram.ext.BaseFilter` for details on how to create custom filters.
Please see :class:`telegram.ext.filters.BaseFilter` for details on how to create custom
filters.
Attributes:
name (:obj:`str`): Name for this filter. Defaults to the type of filter.
@@ -176,11 +177,12 @@ class MessageFilter(BaseFilter, ABC):
class UpdateFilter(BaseFilter, ABC):
"""Base class for all Update Filters. In contrast to :class:`UpdateFilter`, the object
"""Base class for all Update Filters. In contrast to :class:`MessageFilter`, the object
passed to :meth:`filter` is ``update``, which allows to create filters like
:attr:`Filters.update.edited_message`.
Please see :class:`telegram.ext.BaseFilter` for details on how to create custom filters.
Please see :class:`telegram.ext.filters.BaseFilter` for details on how to create custom
filters.
Attributes:
name (:obj:`str`): Name for this filter. Defaults to the type of filter.
@@ -316,7 +318,7 @@ class MergedFilter(UpdateFilter):
class XORFilter(UpdateFilter):
"""Convenience filter acting as wrapper for :class:`MergedFilter` representing the an XOR gate
for two filters
for two filters.
Args:
base_filter: Filter 1 of the merged filter.
@@ -643,7 +645,7 @@ class Filters:
send media with wrong types that don't fit to this handler.
Example:
Filters.documents.category('audio/') returns :obj:`True` for all types
Filters.document.category('audio/') returns :obj:`True` for all types
of audio sent as file, for example 'audio/mpeg' or 'audio/x-wav'.
"""
@@ -677,7 +679,7 @@ class Filters:
send media with wrong types that don't fit to this handler.
Example:
``Filters.documents.mime_type('audio/mpeg')`` filters all audio in mp3 format.
``Filters.document.mime_type('audio/mpeg')`` filters all audio in mp3 format.
"""
def __init__(self, mimetype: Optional[str]):
@@ -794,7 +796,7 @@ class Filters:
send media with wrong types that don't fit to this handler.
Example:
``Filters.documents.category('audio/')`` filters all types
``Filters.document.category('audio/')`` filters all types
of audio sent as file, for example 'audio/mpeg' or 'audio/x-wav'.
application: Same as ``Filters.document.category("application")``.
audio: Same as ``Filters.document.category("audio")``.
@@ -811,23 +813,23 @@ class Filters:
send media with wrong types that don't fit to this handler.
Example:
``Filters.documents.mime_type('audio/mpeg')`` filters all audio in mp3 format.
apk: Same as ``Filters.document.mime_type("application/vnd.android.package-archive")``-
doc: Same as ``Filters.document.mime_type("application/msword")``-
``Filters.document.mime_type('audio/mpeg')`` filters all audio in mp3 format.
apk: Same as ``Filters.document.mime_type("application/vnd.android.package-archive")``.
doc: Same as ``Filters.document.mime_type("application/msword")``.
docx: Same as ``Filters.document.mime_type("application/vnd.openxmlformats-\
officedocument.wordprocessingml.document")``-
exe: Same as ``Filters.document.mime_type("application/x-ms-dos-executable")``-
gif: Same as ``Filters.document.mime_type("video/mp4")``-
jpg: Same as ``Filters.document.mime_type("image/jpeg")``-
mp3: Same as ``Filters.document.mime_type("audio/mpeg")``-
pdf: Same as ``Filters.document.mime_type("application/pdf")``-
py: Same as ``Filters.document.mime_type("text/x-python")``-
svg: Same as ``Filters.document.mime_type("image/svg+xml")``-
txt: Same as ``Filters.document.mime_type("text/plain")``-
targz: Same as ``Filters.document.mime_type("application/x-compressed-tar")``-
wav: Same as ``Filters.document.mime_type("audio/x-wav")``-
xml: Same as ``Filters.document.mime_type("application/xml")``-
zip: Same as ``Filters.document.mime_type("application/zip")``-
officedocument.wordprocessingml.document")``.
exe: Same as ``Filters.document.mime_type("application/x-ms-dos-executable")``.
gif: Same as ``Filters.document.mime_type("video/mp4")``.
jpg: Same as ``Filters.document.mime_type("image/jpeg")``.
mp3: Same as ``Filters.document.mime_type("audio/mpeg")``.
pdf: Same as ``Filters.document.mime_type("application/pdf")``.
py: Same as ``Filters.document.mime_type("text/x-python")``.
svg: Same as ``Filters.document.mime_type("image/svg+xml")``.
txt: Same as ``Filters.document.mime_type("text/plain")``.
targz: Same as ``Filters.document.mime_type("application/x-compressed-tar")``.
wav: Same as ``Filters.document.mime_type("audio/x-wav")``.
xml: Same as ``Filters.document.mime_type("application/xml")``.
zip: Same as ``Filters.document.mime_type("application/zip")``.
file_extension: This filter filters documents by their file ending/extension.
Note:
@@ -1409,24 +1411,25 @@ officedocument.wordprocessingml.document")``-
that it is not causing race conditions, as this will complete replace the current set
of allowed users.
Attributes:
user_ids(set(:obj:`int`), optional): Which user ID(s) to allow through.
usernames(set(:obj:`str`), optional): Which username(s) (without leading '@') to allow
through.
allow_empty(:obj:`bool`, optional): Whether updates should be processed, if no user
is specified in :attr:`user_ids` and :attr:`usernames`.
Args:
user_id(:class:`telegram.utils.types.SLT[int]`, optional):
Which user ID(s) to allow through.
username(:class:`telegram.utils.types.SLT[str]`, optional):
Which username(s) to allow through. Leading '@'s in usernames will be discarded.
Which username(s) to allow through. Leading ``'@'`` s in usernames will be
discarded.
allow_empty(:obj:`bool`, optional): Whether updates should be processed, if no user
is specified in :attr:`user_ids` and :attr:`usernames`. Defaults to :obj:`False`
Raises:
RuntimeError: If user_id and username are both present.
Attributes:
user_ids(set(:obj:`int`), optional): Which user ID(s) to allow through.
usernames(set(:obj:`str`), optional): Which username(s) (without leading ``'@'``) to
allow through.
allow_empty(:obj:`bool`, optional): Whether updates should be processed, if no user
is specified in :attr:`user_ids` and :attr:`usernames`.
"""
def __init__(
@@ -1456,7 +1459,7 @@ officedocument.wordprocessingml.document")``-
Args:
username(:class:`telegram.utils.types.SLT[str]`, optional):
Which username(s) to allow through.
Leading '@'s in usernames will be discarded.
Leading ``'@'`` s in usernames will be discarded.
"""
return super().add_usernames(username)
@@ -1477,7 +1480,7 @@ officedocument.wordprocessingml.document")``-
Args:
username(:class:`telegram.utils.types.SLT[str]`, optional):
Which username(s) to disallow through.
Leading '@'s in usernames will be discarded.
Leading ``'@'`` s in usernames will be discarded.
"""
return super().remove_usernames(username)
@@ -1507,23 +1510,25 @@ officedocument.wordprocessingml.document")``-
that it is not causing race conditions, as this will complete replace the current set
of allowed bots.
Attributes:
bot_ids(set(:obj:`int`), optional): Which bot ID(s) to allow through.
usernames(set(:obj:`str`), optional): Which username(s) (without leading '@') to allow
through.
allow_empty(:obj:`bool`, optional): Whether updates should be processed, if no bot
is specified in :attr:`bot_ids` and :attr:`usernames`.
Args:
bot_id(:class:`telegram.utils.types.SLT[int]`, optional):
Which bot ID(s) to allow through.
username(:class:`telegram.utils.types.SLT[str]`, optional):
Which username(s) to allow through. Leading '@'s in usernames will be discarded.
Which username(s) to allow through. Leading ``'@'`` s in usernames will be
discarded.
allow_empty(:obj:`bool`, optional): Whether updates should be processed, if no user
is specified in :attr:`bot_ids` and :attr:`usernames`. Defaults to :obj:`False`
Raises:
RuntimeError: If bot_id and username are both present.
Attributes:
bot_ids(set(:obj:`int`), optional): Which bot ID(s) to allow through.
usernames(set(:obj:`str`), optional): Which username(s) (without leading ``'@'``) to
allow through.
allow_empty(:obj:`bool`, optional): Whether updates should be processed, if no bot
is specified in :attr:`bot_ids` and :attr:`usernames`.
"""
def __init__(
@@ -1553,7 +1558,7 @@ officedocument.wordprocessingml.document")``-
Args:
username(:class:`telegram.utils.types.SLT[str]`, optional):
Which username(s) to allow through.
Leading '@'s in usernames will be discarded.
Leading ``'@'`` s in usernames will be discarded.
"""
return super().add_usernames(username)
@@ -1575,7 +1580,7 @@ officedocument.wordprocessingml.document")``-
Args:
username(:class:`telegram.utils.types.SLT[str]`, optional):
Which username(s) to disallow through.
Leading '@'s in usernames will be discarded.
Leading ``'@'`` s in usernames will be discarded.
"""
return super().remove_usernames(username)
@@ -1604,25 +1609,25 @@ officedocument.wordprocessingml.document")``-
that it is not causing race conditions, as this will complete replace the current set
of allowed chats.
Attributes:
chat_ids(set(:obj:`int`), optional): Which chat ID(s) to allow through.
usernames(set(:obj:`str`), optional): Which username(s) (without leading '@') to allow
through.
allow_empty(:obj:`bool`, optional): Whether updates should be processed, if no chat
is specified in :attr:`chat_ids` and :attr:`usernames`.
Args:
chat_id(:class:`telegram.utils.types.SLT[int]`, optional):
Which chat ID(s) to allow through.
username(:class:`telegram.utils.types.SLT[str]`, optional):
Which username(s) to allow through.
Leading `'@'` s in usernames will be discarded.
Leading ``'@'`` s in usernames will be discarded.
allow_empty(:obj:`bool`, optional): Whether updates should be processed, if no chat
is specified in :attr:`chat_ids` and :attr:`usernames`. Defaults to :obj:`False`
Raises:
RuntimeError: If chat_id and username are both present.
Attributes:
chat_ids(set(:obj:`int`), optional): Which chat ID(s) to allow through.
usernames(set(:obj:`str`), optional): Which username(s) (without leading ``'@'``) to
allow through.
allow_empty(:obj:`bool`, optional): Whether updates should be processed, if no chat
is specified in :attr:`chat_ids` and :attr:`usernames`.
"""
def get_chat_or_user(self, message: Message) -> Optional[Chat]:
@@ -1635,7 +1640,7 @@ officedocument.wordprocessingml.document")``-
Args:
username(:class:`telegram.utils.types.SLT[str]`, optional):
Which username(s) to allow through.
Leading `'@'` s in usernames will be discarded.
Leading ``'@'`` s in usernames will be discarded.
"""
return super().add_usernames(username)
@@ -1656,7 +1661,7 @@ officedocument.wordprocessingml.document")``-
Args:
username(:class:`telegram.utils.types.SLT[str]`, optional):
Which username(s) to disallow through.
Leading '@'s in usernames will be discarded.
Leading ``'@'`` s in usernames will be discarded.
"""
return super().remove_usernames(username)
@@ -1694,10 +1699,23 @@ officedocument.wordprocessingml.document")``-
that it is not causing race conditions, as this will complete replace the current set
of allowed chats.
Args:
chat_id(:class:`telegram.utils.types.SLT[int]`, optional):
Which sender chat chat ID(s) to allow through.
username(:class:`telegram.utils.types.SLT[str]`, optional):
Which sender chat username(s) to allow through.
Leading ``'@'`` s in usernames will be discarded.
allow_empty(:obj:`bool`, optional): Whether updates should be processed, if no sender
chat is specified in :attr:`chat_ids` and :attr:`usernames`. Defaults to
:obj:`False`
Raises:
RuntimeError: If both chat_id and username are present.
Attributes:
chat_ids(set(:obj:`int`), optional): Which sender chat chat ID(s) to allow through.
usernames(set(:obj:`str`), optional): Which sender chat username(s) (without leading
'@') to allow through.
``'@'``) to allow through.
allow_empty(:obj:`bool`, optional): Whether updates should be processed, if no sender
chat is specified in :attr:`chat_ids` and :attr:`usernames`.
super_group: Messages whose sender chat is a super group.
@@ -1709,19 +1727,6 @@ officedocument.wordprocessingml.document")``-
Examples:
``Filters.sender_chat.channel``
Args:
chat_id(:class:`telegram.utils.types.SLT[int]`, optional):
Which sender chat chat ID(s) to allow through.
username(:class:`telegram.utils.types.SLT[str]`, optional):
Which sender chat sername(s) to allow through.
Leading `'@'` s in usernames will be discarded.
allow_empty(:obj:`bool`, optional): Whether updates should be processed, if no sender
chat is specified in :attr:`chat_ids` and :attr:`usernames`. Defaults to
:obj:`False`
Raises:
RuntimeError: If chat_id and username are both present.
"""
def get_chat_or_user(self, message: Message) -> Optional[Chat]:
@@ -1734,7 +1739,7 @@ officedocument.wordprocessingml.document")``-
Args:
username(:class:`telegram.utils.types.SLT[str]`, optional):
Which sender chat username(s) to allow through.
Leading `'@'` s in usernames will be discarded.
Leading ``'@'`` s in usernames will be discarded.
"""
return super().add_usernames(username)
@@ -1755,7 +1760,7 @@ officedocument.wordprocessingml.document")``-
Args:
username(:class:`telegram.utils.types.SLT[str]`, optional):
Which sender chat username(s) to disallow through.
Leading '@'s in usernames will be discarded.
Leading ``'@'`` s in usernames will be discarded.
"""
return super().remove_usernames(username)
@@ -1839,14 +1844,14 @@ officedocument.wordprocessingml.document")``-
To allow only dice with value 5 `or` 6, use
``MessageHandler(Filters.dice([5, 6]), callback_method)``.
Args:
update (:class:`telegram.utils.types.SLT[int]`, optional):
Which values to allow. If not specified, will allow any dice message.
Note:
Dice messages don't have text. If you want to filter either text or dice messages, use
``Filters.text | Filters.dice``.
Args:
update (:class:`telegram.utils.types.SLT[int]`, optional):
Which values to allow. If not specified, will allow any dice message.
Attributes:
dice: Dice messages with the emoji 🎲. Passing a list of integers is supported just as for
:attr:`Filters.dice`.
+29 -25
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -19,34 +19,22 @@
"""This module contains the base class for handlers as used by the Dispatcher."""
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, TypeVar, Union
from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, TypeVar, Union, Generic
from telegram import Update
from telegram.utils.promise import Promise
from telegram.utils.types import HandlerArg
from telegram.ext.utils.promise import Promise
from telegram.utils.helpers import DefaultValue, DEFAULT_FALSE
if TYPE_CHECKING:
from telegram.ext import CallbackContext, Dispatcher
RT = TypeVar('RT')
UT = TypeVar('UT')
class Handler(ABC):
class Handler(Generic[UT], ABC):
"""The base class for all update handlers. Create custom handlers by inheriting from it.
Attributes:
callback (:obj:`callable`): The callback function for this handler.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to
the callback function.
pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
Note:
:attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you
can use to keep any data in will be sent to the :attr:`callback` function. Related to
@@ -88,18 +76,30 @@ class Handler(ABC):
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
Defaults to :obj:`False`.
Attributes:
callback (:obj:`callable`): The callback function for this handler.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to
the callback function.
pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
"""
def __init__(
self,
callback: Callable[[HandlerArg, 'CallbackContext'], RT],
callback: Callable[[UT, 'CallbackContext'], RT],
pass_update_queue: bool = False,
pass_job_queue: bool = False,
pass_user_data: bool = False,
pass_chat_data: bool = False,
run_async: Union[bool, DefaultValue] = DEFAULT_FALSE,
):
self.callback: Callable[[HandlerArg, 'CallbackContext'], RT] = callback
self.callback = callback
self.pass_update_queue = pass_update_queue
self.pass_job_queue = pass_job_queue
self.pass_user_data = pass_user_data
@@ -107,11 +107,15 @@ class Handler(ABC):
self.run_async = run_async
@abstractmethod
def check_update(self, update: HandlerArg) -> Optional[Union[bool, object]]:
def check_update(self, update: object) -> Optional[Union[bool, object]]:
"""
This method is called to determine if an update should be handled by
this handler instance. It should always be overridden.
Note:
Custom updates types can be handled by the dispatcher. Therefore, an implementation of
this method should always check the type of :attr:`update`.
Args:
update (:obj:`str` | :class:`telegram.Update`): The update to be tested.
@@ -124,7 +128,7 @@ class Handler(ABC):
def handle_update(
self,
update: HandlerArg,
update: UT,
dispatcher: 'Dispatcher',
check_result: object,
context: 'CallbackContext' = None,
@@ -165,7 +169,7 @@ class Handler(ABC):
def collect_additional_context(
self,
context: 'CallbackContext',
update: HandlerArg,
update: UT,
dispatcher: 'Dispatcher',
check_result: Any,
) -> None:
@@ -182,9 +186,9 @@ class Handler(ABC):
def collect_optional_args(
self,
dispatcher: 'Dispatcher',
update: HandlerArg = None,
update: UT = None,
check_result: Any = None, # pylint: disable=W0613
) -> Dict[str, Any]:
) -> Dict[str, object]:
"""
Prepares the optional arguments. If the handler has additional optional args,
it should subclass this method, but remember to call this super method.
@@ -198,7 +202,7 @@ class Handler(ABC):
check_result: The result from check_update
"""
optional_args: Dict[str, Any] = dict()
optional_args: Dict[str, object] = dict()
if self.pass_update_queue:
optional_args['update_queue'] = dispatcher.update_queue
+26 -28
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -20,7 +20,6 @@
import re
from typing import (
TYPE_CHECKING,
Any,
Callable,
Dict,
Match,
@@ -32,7 +31,6 @@ from typing import (
)
from telegram import Update
from telegram.utils.types import HandlerArg
from telegram.utils.helpers import DefaultValue, DEFAULT_FALSE
from .handler import Handler
@@ -43,29 +41,11 @@ if TYPE_CHECKING:
RT = TypeVar('RT')
class InlineQueryHandler(Handler):
class InlineQueryHandler(Handler[Update]):
"""
Handler class to handle Telegram inline queries. Optionally based on a regex. Read the
documentation of the ``re`` module for more information.
Attributes:
callback (:obj:`callable`): The callback function for this handler.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
pattern (:obj:`str` | :obj:`Pattern`): Optional. Regex pattern to test
:attr:`telegram.InlineQuery.query` against.
pass_groups (:obj:`bool`): Determines whether ``groups`` will be passed to the
callback function.
pass_groupdict (:obj:`bool`): Determines whether ``groupdict``. will be passed to
the callback function.
pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to
the callback function.
pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
Note:
:attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you
can use to keep any data in will be sent to the :attr:`callback` function. Related to
@@ -118,11 +98,29 @@ class InlineQueryHandler(Handler):
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
Defaults to :obj:`False`.
Attributes:
callback (:obj:`callable`): The callback function for this handler.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
pattern (:obj:`str` | :obj:`Pattern`): Optional. Regex pattern to test
:attr:`telegram.InlineQuery.query` against.
pass_groups (:obj:`bool`): Determines whether ``groups`` will be passed to the
callback function.
pass_groupdict (:obj:`bool`): Determines whether ``groupdict``. will be passed to
the callback function.
pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to
the callback function.
pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
"""
def __init__(
self,
callback: Callable[[HandlerArg, 'CallbackContext'], RT],
callback: Callable[[Update, 'CallbackContext'], RT],
pass_update_queue: bool = False,
pass_job_queue: bool = False,
pattern: Union[str, Pattern] = None,
@@ -148,12 +146,12 @@ class InlineQueryHandler(Handler):
self.pass_groups = pass_groups
self.pass_groupdict = pass_groupdict
def check_update(self, update: HandlerArg) -> Optional[Union[bool, Match]]:
def check_update(self, update: object) -> Optional[Union[bool, Match]]:
"""
Determines whether an update should be passed to this handlers :attr:`callback`.
Args:
update (:class:`telegram.Update`): Incoming telegram update.
update (:class:`telegram.Update` | :obj:`object`): Incoming update.
Returns:
:obj:`bool`
@@ -173,9 +171,9 @@ class InlineQueryHandler(Handler):
def collect_optional_args(
self,
dispatcher: 'Dispatcher',
update: HandlerArg = None,
update: Update = None,
check_result: Optional[Union[bool, Match]] = None,
) -> Dict[str, Any]:
) -> Dict[str, object]:
optional_args = super().collect_optional_args(dispatcher, update, check_result)
if self.pattern:
check_result = cast(Match, check_result)
@@ -188,7 +186,7 @@ class InlineQueryHandler(Handler):
def collect_additional_context(
self,
context: 'CallbackContext',
update: HandlerArg,
update: Update,
dispatcher: 'Dispatcher',
check_result: Optional[Union[bool, Match]],
) -> None:
+16 -14
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -21,13 +21,14 @@
import datetime
import logging
from typing import TYPE_CHECKING, Any, Callable, List, Optional, Tuple, Union, cast, overload
from typing import TYPE_CHECKING, Callable, List, Optional, Tuple, Union, cast, overload
import pytz
from apscheduler.events import EVENT_JOB_ERROR, EVENT_JOB_EXECUTED, JobEvent
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.triggers.combining import OrTrigger
from apscheduler.triggers.cron import CronTrigger
from apscheduler.job import Job as APSJob
from telegram.ext.callbackcontext import CallbackContext
from telegram.utils.types import JSONDict
@@ -35,6 +36,7 @@ from telegram.utils.types import JSONDict
if TYPE_CHECKING:
from telegram import Bot
from telegram.ext import Dispatcher
import apscheduler.job # noqa: F401
class Days:
@@ -409,7 +411,7 @@ class JobQueue:
time (:obj:`datetime.time`): Time of day at which the job should run. If the timezone
(``time.tzinfo``) is :obj:`None`, the default timezone of the bot will be used.
days (Tuple[:obj:`int`], optional): Defines on which days of the week the job should
run. Defaults to ``EVERY_DAY``
run (where ``0-6`` correspond to monday - sunday). Defaults to ``EVERY_DAY``
context (:obj:`object`, optional): Additional data needed for the callback function.
Can be accessed through ``job.context`` in the callback. Defaults to :obj:`None`.
name (:obj:`str`, optional): The name of the new job. Defaults to
@@ -522,13 +524,6 @@ class Job:
* If :attr:`job` isn't passed on initialization, it must be set manually afterwards for
this :class:`telegram.ext.Job` to be useful.
Attributes:
callback (:obj:`callable`): The callback function that should be executed by the new job.
context (:obj:`object`): Optional. Additional data needed for the callback function.
name (:obj:`str`): Optional. The name of the new job.
job_queue (:class:`telegram.ext.JobQueue`): Optional. The ``JobQueue`` this job belongs to.
job (:class:`apscheduler.job.Job`): Optional. The APS Job this job is a wrapper for.
Args:
callback (:obj:`callable`): The callback function that should be executed by the new job.
Callback signature for context based API:
@@ -543,6 +538,13 @@ class Job:
job_queue (:class:`telegram.ext.JobQueue`, optional): The ``JobQueue`` this job belongs to.
Only optional for backward compatibility with ``JobQueue.put()``.
job (:class:`apscheduler.job.Job`, optional): The APS Job this job is a wrapper for.
Attributes:
callback (:obj:`callable`): The callback function that should be executed by the new job.
context (:obj:`object`): Optional. Additional data needed for the callback function.
name (:obj:`str`): Optional. The name of the new job.
job_queue (:class:`telegram.ext.JobQueue`): Optional. The ``JobQueue`` this job belongs to.
job (:class:`apscheduler.job.Job`): Optional. The APS Job this job is a wrapper for.
"""
def __init__(
@@ -551,7 +553,7 @@ class Job:
context: object = None,
name: str = None,
job_queue: JobQueue = None,
job: 'Job' = None,
job: APSJob = None,
):
self.callback = callback
@@ -562,7 +564,7 @@ class Job:
self._removed = False
self._enabled = False
self.job = cast('Job', job)
self.job = cast(APSJob, job)
def run(self, dispatcher: 'Dispatcher') -> None:
"""Executes the callback function independently of the jobs schedule."""
@@ -618,7 +620,7 @@ class Job:
return self.job.next_run_time
@classmethod
def from_aps_job(cls, job: 'Job', job_queue: JobQueue) -> 'Job':
def from_aps_job(cls, job: APSJob, job_queue: JobQueue) -> 'Job':
# context based callbacks
if len(job.args) == 1:
context = job.args[0].job.context
@@ -626,7 +628,7 @@ class Job:
context = job.args[1].context
return cls(job.func, context=context, name=job.name, job_queue=job_queue, job=job)
def __getattr__(self, item: str) -> Any:
def __getattr__(self, item: str) -> object:
return getattr(self.job, item)
def __lt__(self, other: object) -> bool:
+28 -29
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -19,12 +19,11 @@
# TODO: Remove allow_edited
"""This module contains the MessageHandler class."""
import warnings
from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, TypeVar, Union
from typing import TYPE_CHECKING, Callable, Dict, Optional, TypeVar, Union
from telegram import Update
from telegram.ext import BaseFilter, Filters
from telegram.utils.deprecate import TelegramDeprecationWarning
from telegram.utils.types import HandlerArg
from telegram.utils.helpers import DefaultValue, DEFAULT_FALSE
from .handler import Handler
@@ -35,29 +34,9 @@ if TYPE_CHECKING:
RT = TypeVar('RT')
class MessageHandler(Handler):
class MessageHandler(Handler[Update]):
"""Handler class to handle telegram messages. They might contain text, media or status updates.
Attributes:
filters (:obj:`Filter`): Only allow updates with these Filters. See
:mod:`telegram.ext.filters` for a full list of all available filters.
callback (:obj:`callable`): The callback function for this handler.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to
the callback function.
pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to
the callback function.
message_updates (:obj:`bool`): Should "normal" message updates be handled?
Default is :obj:`None`.
channel_post_updates (:obj:`bool`): Should channel posts updates be handled?
Default is :obj:`None`.
edited_updates (:obj:`bool`): Should "edited" message updates be handled?
Default is :obj:`None`.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
Note:
:attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you
can use to keep any data in will be sent to the :attr:`callback` function. Related to
@@ -119,12 +98,32 @@ class MessageHandler(Handler):
Raises:
ValueError
Attributes:
filters (:obj:`Filter`): Only allow updates with these Filters. See
:mod:`telegram.ext.filters` for a full list of all available filters.
callback (:obj:`callable`): The callback function for this handler.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to
the callback function.
pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to
the callback function.
message_updates (:obj:`bool`): Should "normal" message updates be handled?
Default is :obj:`None`.
channel_post_updates (:obj:`bool`): Should channel posts updates be handled?
Default is :obj:`None`.
edited_updates (:obj:`bool`): Should "edited" message updates be handled?
Default is :obj:`None`.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
"""
def __init__(
self,
filters: BaseFilter,
callback: Callable[[HandlerArg, 'CallbackContext'], RT],
callback: Callable[[Update, 'CallbackContext'], RT],
pass_update_queue: bool = False,
pass_job_queue: bool = False,
pass_user_data: bool = False,
@@ -180,11 +179,11 @@ class MessageHandler(Handler):
Filters.update.edited_message | Filters.update.edited_channel_post
)
def check_update(self, update: HandlerArg) -> Optional[Union[bool, Dict[str, Any]]]:
def check_update(self, update: object) -> Optional[Union[bool, Dict[str, object]]]:
"""Determines whether an update should be passed to this handlers :attr:`callback`.
Args:
update (:class:`telegram.Update`): Incoming telegram update.
update (:class:`telegram.Update` | :obj:`object`): Incoming update.
Returns:
:obj:`bool`
@@ -197,9 +196,9 @@ class MessageHandler(Handler):
def collect_additional_context(
self,
context: 'CallbackContext',
update: HandlerArg,
update: Update,
dispatcher: 'Dispatcher',
check_result: Optional[Union[bool, Dict[str, Any]]],
check_result: Optional[Union[bool, Dict[str, object]]],
) -> None:
if isinstance(check_result, dict):
context.update(check_result)
+34 -12
View File
@@ -4,7 +4,7 @@
# Tymofii A. Khodniev (thodnev) <thodnev@mail.ru>
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -24,9 +24,11 @@ import functools
import queue as q
import threading
import time
from typing import TYPE_CHECKING, Any, Callable, List, NoReturn
import warnings
from typing import TYPE_CHECKING, Callable, List, NoReturn
from telegram.utils.promise import Promise
from telegram.ext.utils.promise import Promise
from telegram.utils.deprecate import TelegramDeprecationWarning
if TYPE_CHECKING:
from telegram import Bot
@@ -44,13 +46,9 @@ class DelayQueue(threading.Thread):
Processes callbacks from queue with specified throughput limits. Creates a separate thread to
process callbacks with delays.
Attributes:
burst_limit (:obj:`int`): Number of maximum callbacks to process per time-window.
time_limit (:obj:`int`): Defines width of time-window used when each processing limit is
calculated.
exc_route (:obj:`callable`): A callable, accepting 1 positional argument; used to route
exceptions from processor thread to main thread;
name (:obj:`str`): Thread's name.
.. deprecated:: 13.3
:class:`telegram.ext.DelayQueue` in its current form is deprecated and will be reinvented
in a future release. See `this thread <https://git.io/JtDbF>`_ for a list of known bugs.
Args:
queue (:obj:`Queue`, optional): Used to pass callbacks to thread. Creates ``Queue``
@@ -69,6 +67,14 @@ class DelayQueue(threading.Thread):
name (:obj:`str`, optional): Thread's name. Defaults to ``'DelayQueue-N'``, where N is
sequential number of object created.
Attributes:
burst_limit (:obj:`int`): Number of maximum callbacks to process per time-window.
time_limit (:obj:`int`): Defines width of time-window used when each processing limit is
calculated.
exc_route (:obj:`callable`): A callable, accepting 1 positional argument; used to route
exceptions from processor thread to main thread;
name (:obj:`str`): Thread's name.
"""
_instcnt = 0 # instance counter
@@ -82,6 +88,12 @@ class DelayQueue(threading.Thread):
autostart: bool = True,
name: str = None,
):
warnings.warn(
'DelayQueue in its current form is deprecated and will be reinvented in a future '
'release. See https://git.io/JtDbF for a list of known bugs.',
category=TelegramDeprecationWarning,
)
self._queue = queue if queue is not None else q.Queue()
self.burst_limit = burst_limit
self.time_limit = time_limit_ms / 1000
@@ -153,7 +165,7 @@ class DelayQueue(threading.Thread):
raise exc
def __call__(self, func: Callable, *args: Any, **kwargs: Any) -> None:
def __call__(self, func: Callable, *args: object, **kwargs: object) -> None:
"""Used to process callbacks in throughput-limiting thread through queue.
Args:
@@ -182,6 +194,10 @@ class MessageQueue:
Callables are processed through *group* ``DelayQueue``, then through *all* ``DelayQueue`` for
group-type messages. For non-group messages, only the *all* ``DelayQueue`` is used.
.. deprecated:: 13.3
:class:`telegram.ext.MessageQueue` in its current form is deprecated and will be reinvented
in a future release. See `this thread <https://git.io/JtDbF>`_ for a list of known bugs.
Args:
all_burst_limit (:obj:`int`, optional): Number of maximum *all-type* callbacks to process
per time-window defined by :attr:`all_time_limit_ms`. Defaults to 30.
@@ -210,6 +226,12 @@ class MessageQueue:
exc_route: Callable[[Exception], None] = None,
autostart: bool = True,
):
warnings.warn(
'MessageQueue in its current form is deprecated and will be reinvented in a future '
'release. See https://git.io/JtDbF for a list of known bugs.',
category=TelegramDeprecationWarning,
)
# create according delay queues, use composition
self._all_delayq = DelayQueue(
burst_limit=all_burst_limit,
@@ -300,7 +322,7 @@ def queuedmessage(method: Callable) -> Callable:
"""
@functools.wraps(method)
def wrapped(self: 'Bot', *args: Any, **kwargs: Any) -> Any:
def wrapped(self: 'Bot', *args: object, **kwargs: object) -> object:
# pylint: disable=W0212
queued = kwargs.pop(
'queued', self._is_messages_queued_default # type: ignore[attr-defined]
+25 -25
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -38,23 +38,6 @@ class PicklePersistence(BasePersistence):
:meth:`telegram.ext.BasePersistence.replace_bot` and
:meth:`telegram.ext.BasePersistence.insert_bot`.
Attributes:
filename (:obj:`str`): The filename for storing the pickle files. When :attr:`single_file`
is :obj:`False` this will be used as a prefix.
store_user_data (:obj:`bool`): Optional. Whether user_data should be saved by this
persistence class.
store_chat_data (:obj:`bool`): Optional. Whether user_data should be saved by this
persistence class.
store_bot_data (:obj:`bool`): Optional. Whether bot_data should be saved by this
persistence class.
single_file (:obj:`bool`): Optional. When :obj:`False` will store 3 separate files of
`filename_user_data`, `filename_chat_data` and `filename_conversations`. Default is
:obj:`True`.
on_flush (:obj:`bool`, optional): When :obj:`True` will only save to file when
:meth:`flush` is called and keep data in memory until that happens. When
:obj:`False` will store data on any transaction *and* on call to :meth:`flush`.
Default is :obj:`False`.
Args:
filename (:obj:`str`): The filename for storing the pickle files. When :attr:`single_file`
is :obj:`False` this will be used as a prefix.
@@ -71,6 +54,23 @@ class PicklePersistence(BasePersistence):
:meth:`flush` is called and keep data in memory until that happens. When
:obj:`False` will store data on any transaction *and* on call to :meth:`flush`.
Default is :obj:`False`.
Attributes:
filename (:obj:`str`): The filename for storing the pickle files. When :attr:`single_file`
is :obj:`False` this will be used as a prefix.
store_user_data (:obj:`bool`): Optional. Whether user_data should be saved by this
persistence class.
store_chat_data (:obj:`bool`): Optional. Whether user_data should be saved by this
persistence class.
store_bot_data (:obj:`bool`): Optional. Whether bot_data should be saved by this
persistence class.
single_file (:obj:`bool`): Optional. When :obj:`False` will store 3 separate files of
`filename_user_data`, `filename_chat_data` and `filename_conversations`. Default is
:obj:`True`.
on_flush (:obj:`bool`, optional): When :obj:`True` will only save to file when
:meth:`flush` is called and keep data in memory until that happens. When
:obj:`False` will store data on any transaction *and* on call to :meth:`flush`.
Default is :obj:`False`.
"""
def __init__(
@@ -93,7 +93,7 @@ class PicklePersistence(BasePersistence):
self.user_data: Optional[DefaultDict[int, Dict]] = None
self.chat_data: Optional[DefaultDict[int, Dict]] = None
self.bot_data: Optional[Dict] = None
self.conversations: Optional[Dict[str, Dict[Tuple, Any]]] = None
self.conversations: Optional[Dict[str, Dict[Tuple, object]]] = None
def load_singlefile(self) -> None:
try:
@@ -105,7 +105,7 @@ class PicklePersistence(BasePersistence):
# For backwards compatibility with files not containing bot data
self.bot_data = data.get('bot_data', {})
self.conversations = data['conversations']
except IOError:
except OSError:
self.conversations = dict()
self.user_data = defaultdict(dict)
self.chat_data = defaultdict(dict)
@@ -120,7 +120,7 @@ class PicklePersistence(BasePersistence):
try:
with open(filename, "rb") as file:
return pickle.load(file)
except IOError:
except OSError:
return None
except pickle.UnpicklingError as exc:
raise TypeError(f"File {filename} does not contain valid pickle data") from exc
@@ -138,11 +138,11 @@ class PicklePersistence(BasePersistence):
pickle.dump(data, file)
@staticmethod
def dump_file(filename: str, data: Any) -> None:
def dump_file(filename: str, data: object) -> None:
with open(filename, "wb") as file:
pickle.dump(data, file)
def get_user_data(self) -> DefaultDict[int, Dict[Any, Any]]:
def get_user_data(self) -> DefaultDict[int, Dict[object, object]]:
"""Returns the user_data from the pickle file if it exists or an empty :obj:`defaultdict`.
Returns:
@@ -162,7 +162,7 @@ class PicklePersistence(BasePersistence):
self.load_singlefile()
return deepcopy(self.user_data) # type: ignore[arg-type]
def get_chat_data(self) -> DefaultDict[int, Dict[Any, Any]]:
def get_chat_data(self) -> DefaultDict[int, Dict[object, object]]:
"""Returns the chat_data from the pickle file if it exists or an empty :obj:`defaultdict`.
Returns:
@@ -182,7 +182,7 @@ class PicklePersistence(BasePersistence):
self.load_singlefile()
return deepcopy(self.chat_data) # type: ignore[arg-type]
def get_bot_data(self) -> Dict[Any, Any]:
def get_bot_data(self) -> Dict[object, object]:
"""Returns the bot_data from the pickle file if it exists or an empty :obj:`dict`.
Returns:
+17 -17
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2019
# Copyright (C) 2019-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -18,27 +18,15 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the PollAnswerHandler class."""
from telegram import Update
from telegram.utils.types import HandlerArg
from .handler import Handler
class PollAnswerHandler(Handler):
class PollAnswerHandler(Handler[Update]):
"""Handler class to handle Telegram updates that contain a poll answer.
Attributes:
callback (:obj:`callable`): The callback function for this handler.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to
the callback function.
pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
Note:
:attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you
can use to keep any data in will be sent to the :attr:`callback` function. Related to
@@ -80,13 +68,25 @@ class PollAnswerHandler(Handler):
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
Defaults to :obj:`False`.
Attributes:
callback (:obj:`callable`): The callback function for this handler.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to
the callback function.
pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
"""
def check_update(self, update: HandlerArg) -> bool:
def check_update(self, update: object) -> bool:
"""Determines whether an update should be passed to this handlers :attr:`callback`.
Args:
update (:class:`telegram.Update`): Incoming telegram update.
update (:class:`telegram.Update` | :obj:`object`): Incoming update.
Returns:
:obj:`bool`
+17 -17
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2019
# Copyright (C) 2019-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -18,27 +18,15 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the PollHandler classes."""
from telegram import Update
from telegram.utils.types import HandlerArg
from .handler import Handler
class PollHandler(Handler):
class PollHandler(Handler[Update]):
"""Handler class to handle Telegram updates that contain a poll.
Attributes:
callback (:obj:`callable`): The callback function for this handler.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to
the callback function.
pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
Note:
:attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you
can use to keep any data in will be sent to the :attr:`callback` function. Related to
@@ -80,13 +68,25 @@ class PollHandler(Handler):
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
Defaults to :obj:`False`.
Attributes:
callback (:obj:`callable`): The callback function for this handler.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to
the callback function.
pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
"""
def check_update(self, update: HandlerArg) -> bool:
def check_update(self, update: object) -> bool:
"""Determines whether an update should be passed to this handlers :attr:`callback`.
Args:
update (:class:`telegram.Update`): Incoming telegram update.
update (:class:`telegram.Update` | :obj:`object`): Incoming update.
Returns:
:obj:`bool`
+17 -17
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -18,27 +18,15 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the PreCheckoutQueryHandler class."""
from telegram import Update
from telegram.utils.types import HandlerArg
from .handler import Handler
class PreCheckoutQueryHandler(Handler):
class PreCheckoutQueryHandler(Handler[Update]):
"""Handler class to handle Telegram PreCheckout callback queries.
Attributes:
callback (:obj:`callable`): The callback function for this handler.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to
the callback function.
pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
Note:
:attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you
can use to keep any data in will be sent to the :attr:`callback` function. Related to
@@ -80,13 +68,25 @@ class PreCheckoutQueryHandler(Handler):
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
Defaults to :obj:`False`.
Attributes:
callback (:obj:`callable`): The callback function for this handler.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to
the callback function.
pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
"""
def check_update(self, update: HandlerArg) -> bool:
def check_update(self, update: object) -> bool:
"""Determines whether an update should be passed to this handlers :attr:`callback`.
Args:
update (:class:`telegram.Update`): Incoming telegram update.
update (:class:`telegram.Update` | :obj:`object`): Incoming update.
Returns:
:obj:`bool`
+23 -23
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -20,11 +20,11 @@
"""This module contains the RegexHandler class."""
import warnings
from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Pattern, TypeVar, Union
from typing import TYPE_CHECKING, Callable, Dict, Optional, Pattern, TypeVar, Union, Any
from telegram import Update
from telegram.ext import Filters, MessageHandler
from telegram.utils.deprecate import TelegramDeprecationWarning
from telegram.utils.types import HandlerArg
from telegram.utils.helpers import DefaultValue, DEFAULT_FALSE
if TYPE_CHECKING:
@@ -40,23 +40,6 @@ class RegexHandler(MessageHandler):
module for more information. The ``re.match`` function is used to determine if an update should
be handled by this handler.
Attributes:
pattern (:obj:`str` | :obj:`Pattern`): The regex pattern.
callback (:obj:`callable`): The callback function for this handler.
pass_groups (:obj:`bool`): Determines whether ``groups`` will be passed to the
callback function.
pass_groupdict (:obj:`bool`): Determines whether ``groupdict``. will be passed to
the callback function.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to
the callback function.
pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
Note:
This handler is being deprecated. For the same use case use:
``MessageHandler(Filters.regex(r'pattern'), callback)``
@@ -106,12 +89,29 @@ class RegexHandler(MessageHandler):
Raises:
ValueError
Attributes:
pattern (:obj:`str` | :obj:`Pattern`): The regex pattern.
callback (:obj:`callable`): The callback function for this handler.
pass_groups (:obj:`bool`): Determines whether ``groups`` will be passed to the
callback function.
pass_groupdict (:obj:`bool`): Determines whether ``groupdict``. will be passed to
the callback function.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to
the callback function.
pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
"""
def __init__(
self,
pattern: Union[str, Pattern],
callback: Callable[[HandlerArg, 'CallbackContext'], RT],
callback: Callable[[Update, 'CallbackContext'], RT],
pass_groups: bool = False,
pass_groupdict: bool = False,
pass_update_queue: bool = False,
@@ -147,9 +147,9 @@ class RegexHandler(MessageHandler):
def collect_optional_args(
self,
dispatcher: 'Dispatcher',
update: HandlerArg = None,
update: Update = None,
check_result: Optional[Union[bool, Dict[str, Any]]] = None,
) -> Dict[str, Any]:
) -> Dict[str, object]:
optional_args = super().collect_optional_args(dispatcher, update, check_result)
if isinstance(check_result, dict):
if self.pass_groups:
+17 -18
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -18,27 +18,14 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the ShippingQueryHandler class."""
from telegram import Update
from telegram.utils.types import HandlerArg
from telegram import Update
from .handler import Handler
class ShippingQueryHandler(Handler):
class ShippingQueryHandler(Handler[Update]):
"""Handler class to handle Telegram shipping callback queries.
Attributes:
callback (:obj:`callable`): The callback function for this handler.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to
the callback function.
pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
Note:
:attr:`pass_user_data` and :attr:`pass_chat_data` determine whether a ``dict`` you
can use to keep any data in will be sent to the :attr:`callback` function. Related to
@@ -80,13 +67,25 @@ class ShippingQueryHandler(Handler):
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
Defaults to :obj:`False`.
Attributes:
callback (:obj:`callable`): The callback function for this handler.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
pass_user_data (:obj:`bool`): Determines whether ``user_data`` will be passed to
the callback function.
pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
"""
def check_update(self, update: HandlerArg) -> bool:
def check_update(self, update: object) -> bool:
"""Determines whether an update should be passed to this handlers :attr:`callback`.
Args:
update (:class:`telegram.Update`): Incoming telegram update.
update (:class:`telegram.Update` | :obj:`object`): Incoming update.
Returns:
:obj:`bool`
+20 -21
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -18,9 +18,8 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the StringCommandHandler class."""
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, TypeVar, Union
from typing import TYPE_CHECKING, Callable, Dict, List, Optional, TypeVar, Union
from telegram.utils.types import HandlerArg
from telegram.utils.helpers import DefaultValue, DEFAULT_FALSE
from .handler import Handler
@@ -31,7 +30,7 @@ if TYPE_CHECKING:
RT = TypeVar('RT')
class StringCommandHandler(Handler):
class StringCommandHandler(Handler[str]):
"""Handler class to handle string commands. Commands are string updates that start with ``/``.
Note:
@@ -42,17 +41,6 @@ class StringCommandHandler(Handler):
When setting ``run_async`` to :obj:`True`, you cannot rely on adding custom
attributes to :class:`telegram.ext.CallbackContext`. See its docs for more info.
Attributes:
command (:obj:`str`): The command this handler should listen for.
callback (:obj:`callable`): The callback function for this handler.
pass_args (:obj:`bool`): Determines whether the handler should be passed
``args``.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
Args:
command (:obj:`str`): The command this handler should listen for.
callback (:obj:`callable`): The callback function for this handler. Will be called when
@@ -81,12 +69,23 @@ class StringCommandHandler(Handler):
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
Defaults to :obj:`False`.
Attributes:
command (:obj:`str`): The command this handler should listen for.
callback (:obj:`callable`): The callback function for this handler.
pass_args (:obj:`bool`): Determines whether the handler should be passed
``args``.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
"""
def __init__(
self,
command: str,
callback: Callable[[HandlerArg, 'CallbackContext'], RT],
callback: Callable[[str, 'CallbackContext'], RT],
pass_args: bool = False,
pass_update_queue: bool = False,
pass_job_queue: bool = False,
@@ -101,11 +100,11 @@ class StringCommandHandler(Handler):
self.command = command
self.pass_args = pass_args
def check_update(self, update: HandlerArg) -> Optional[List[str]]:
def check_update(self, update: object) -> Optional[List[str]]:
"""Determines whether an update should be passed to this handlers :attr:`callback`.
Args:
update (:obj:`str`): An incoming command.
update (:obj:`object`): The incoming update.
Returns:
:obj:`bool`
@@ -120,9 +119,9 @@ class StringCommandHandler(Handler):
def collect_optional_args(
self,
dispatcher: 'Dispatcher',
update: HandlerArg = None,
update: str = None,
check_result: Optional[List[str]] = None,
) -> Dict[str, Any]:
) -> Dict[str, object]:
optional_args = super().collect_optional_args(dispatcher, update, check_result)
if self.pass_args:
optional_args['args'] = check_result
@@ -131,7 +130,7 @@ class StringCommandHandler(Handler):
def collect_additional_context(
self,
context: 'CallbackContext',
update: HandlerArg,
update: str,
dispatcher: 'Dispatcher',
check_result: Optional[List[str]],
) -> None:
+22 -23
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -19,9 +19,8 @@
"""This module contains the StringRegexHandler class."""
import re
from typing import TYPE_CHECKING, Any, Callable, Dict, Match, Optional, Pattern, TypeVar, Union
from typing import TYPE_CHECKING, Callable, Dict, Match, Optional, Pattern, TypeVar, Union
from telegram.utils.types import HandlerArg
from telegram.utils.helpers import DefaultValue, DEFAULT_FALSE
from .handler import Handler
@@ -32,7 +31,7 @@ if TYPE_CHECKING:
RT = TypeVar('RT')
class StringRegexHandler(Handler):
class StringRegexHandler(Handler[str]):
"""Handler class to handle string updates based on a regex which checks the update content.
Read the documentation of the ``re`` module for more information. The ``re.match`` function is
@@ -46,19 +45,6 @@ class StringRegexHandler(Handler):
When setting ``run_async`` to :obj:`True`, you cannot rely on adding custom
attributes to :class:`telegram.ext.CallbackContext`. See its docs for more info.
Attributes:
pattern (:obj:`str` | :obj:`Pattern`): The regex pattern.
callback (:obj:`callable`): The callback function for this handler.
pass_groups (:obj:`bool`): Determines whether ``groups`` will be passed to the
callback function.
pass_groupdict (:obj:`bool`): Determines whether ``groupdict``. will be passed to
the callback function.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
Args:
pattern (:obj:`str` | :obj:`Pattern`): The regex pattern.
callback (:obj:`callable`): The callback function for this handler. Will be called when
@@ -90,12 +76,25 @@ class StringRegexHandler(Handler):
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
Defaults to :obj:`False`.
Attributes:
pattern (:obj:`str` | :obj:`Pattern`): The regex pattern.
callback (:obj:`callable`): The callback function for this handler.
pass_groups (:obj:`bool`): Determines whether ``groups`` will be passed to the
callback function.
pass_groupdict (:obj:`bool`): Determines whether ``groupdict``. will be passed to
the callback function.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
"""
def __init__(
self,
pattern: Union[str, Pattern],
callback: Callable[[HandlerArg, 'CallbackContext'], RT],
callback: Callable[[str, 'CallbackContext'], RT],
pass_groups: bool = False,
pass_groupdict: bool = False,
pass_update_queue: bool = False,
@@ -116,11 +115,11 @@ class StringRegexHandler(Handler):
self.pass_groups = pass_groups
self.pass_groupdict = pass_groupdict
def check_update(self, update: HandlerArg) -> Optional[Match]:
def check_update(self, update: object) -> Optional[Match]:
"""Determines whether an update should be passed to this handlers :attr:`callback`.
Args:
update (:obj:`str`): An incoming command.
update (:obj:`object`): The incoming update.
Returns:
:obj:`bool`
@@ -135,9 +134,9 @@ class StringRegexHandler(Handler):
def collect_optional_args(
self,
dispatcher: 'Dispatcher',
update: HandlerArg = None,
update: str = None,
check_result: Optional[Match] = None,
) -> Dict[str, Any]:
) -> Dict[str, object]:
optional_args = super().collect_optional_args(dispatcher, update, check_result)
if self.pattern:
if self.pass_groups and check_result:
@@ -149,7 +148,7 @@ class StringRegexHandler(Handler):
def collect_additional_context(
self,
context: 'CallbackContext',
update: HandlerArg,
update: str,
dispatcher: 'Dispatcher',
check_result: Optional[Match],
) -> None:
+18 -17
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -18,7 +18,7 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the TypeHandler class."""
from typing import TYPE_CHECKING, Any, Callable, Type, TypeVar, Union
from typing import TYPE_CHECKING, Callable, Type, TypeVar, Union
from telegram.utils.helpers import DefaultValue, DEFAULT_FALSE
from .handler import Handler
@@ -27,21 +27,12 @@ if TYPE_CHECKING:
from telegram.ext import CallbackContext
RT = TypeVar('RT')
UT = TypeVar('UT')
class TypeHandler(Handler):
class TypeHandler(Handler[UT]):
"""Handler class to handle updates of custom types.
Attributes:
type (:obj:`type`): The ``type`` of updates this handler should process.
callback (:obj:`callable`): The callback function for this handler.
strict (:obj:`bool`): Use ``type`` instead of ``isinstance``. Default is :obj:`False`.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
Warning:
When setting ``run_async`` to :obj:`True`, you cannot rely on adding custom
attributes to :class:`telegram.ext.CallbackContext`. See its docs for more info.
@@ -72,12 +63,22 @@ class TypeHandler(Handler):
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
Defaults to :obj:`False`.
Attributes:
type (:obj:`type`): The ``type`` of updates this handler should process.
callback (:obj:`callable`): The callback function for this handler.
strict (:obj:`bool`): Use ``type`` instead of ``isinstance``. Default is :obj:`False`.
pass_update_queue (:obj:`bool`): Determines whether ``update_queue`` will be
passed to the callback function.
pass_job_queue (:obj:`bool`): Determines whether ``job_queue`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
"""
def __init__(
self,
type: Type, # pylint: disable=W0622
callback: Callable[[Any, 'CallbackContext'], RT],
type: Type[UT], # pylint: disable=W0622
callback: Callable[[UT, 'CallbackContext'], RT],
strict: bool = False,
pass_update_queue: bool = False,
pass_job_queue: bool = False,
@@ -92,11 +93,11 @@ class TypeHandler(Handler):
self.type = type
self.strict = strict
def check_update(self, update: Any) -> bool:
def check_update(self, update: object) -> bool:
"""Determines whether an update should be passed to this handlers :attr:`callback`.
Args:
update (:class:`telegram.Update`): Incoming telegram update.
update (:obj:`object`): Incoming update.
Returns:
:obj:`bool`
+22 -22
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -33,7 +33,7 @@ from telegram.ext import Dispatcher, JobQueue
from telegram.utils.deprecate import TelegramDeprecationWarning
from telegram.utils.helpers import get_signal_name
from telegram.utils.request import Request
from telegram.utils.webhookhandler import WebhookAppClass, WebhookServer
from telegram.ext.utils.webhookhandler import WebhookAppClass, WebhookServer
if TYPE_CHECKING:
from telegram.ext import BasePersistence, Defaults
@@ -50,19 +50,10 @@ class Updater:
production, use a webhook to receive updates. This is achieved using the WebhookServer and
WebhookHandler classes.
Attributes:
bot (:class:`telegram.Bot`): The bot used with this Updater.
user_sig_handler (:obj:`function`): Optional. Function to be called when a signal is
received.
update_queue (:obj:`Queue`): Queue for the updates.
job_queue (:class:`telegram.ext.JobQueue`): Jobqueue for the updater.
dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that handles the updates and
dispatches them to the handlers.
running (:obj:`bool`): Indicates if the updater is running.
persistence (:class:`telegram.ext.BasePersistence`): Optional. The persistence class to
store data that should be persistent over restarts.
use_context (:obj:`bool`): Optional. :obj:`True` if using context based callbacks.
Note:
* You must supply either a :attr:`bot` or a :attr:`token` argument.
* If you supply a :attr:`bot`, you will need to pass :attr:`defaults` to *both* the bot and
the :class:`telegram.ext.Updater`.
Args:
token (:obj:`str`, optional): The bot's token given by the @BotFather.
@@ -95,14 +86,23 @@ class Updater:
defaults (:class:`telegram.ext.Defaults`, optional): An object containing default values to
be used if not set explicitly in the bot methods.
Note:
* You must supply either a :attr:`bot` or a :attr:`token` argument.
* If you supply a :attr:`bot`, you will need to pass :attr:`defaults` to *both* the bot and
the :class:`telegram.ext.Updater`.
Raises:
ValueError: If both :attr:`token` and :attr:`bot` are passed or none of them.
Attributes:
bot (:class:`telegram.Bot`): The bot used with this Updater.
user_sig_handler (:obj:`function`): Optional. Function to be called when a signal is
received.
update_queue (:obj:`Queue`): Queue for the updates.
job_queue (:class:`telegram.ext.JobQueue`): Jobqueue for the updater.
dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that handles the updates and
dispatches them to the handlers.
running (:obj:`bool`): Indicates if the updater is running.
persistence (:class:`telegram.ext.BasePersistence`): Optional. The persistence class to
store data that should be persistent over restarts.
use_context (:obj:`bool`): Optional. :obj:`True` if using context based callbacks.
"""
_request = None
@@ -219,7 +219,7 @@ class Updater:
self.__lock = Lock()
self.__threads: List[Thread] = []
def _init_thread(self, target: Callable, name: str, *args: Any, **kwargs: Any) -> None:
def _init_thread(self, target: Callable, name: str, *args: object, **kwargs: object) -> None:
thr = Thread(
target=self._thread_wrapper,
name=f"Bot:{self.bot.id}:{name}",
@@ -229,7 +229,7 @@ class Updater:
thr.start()
self.__threads.append(thr)
def _thread_wrapper(self, target: Callable, *args: Any, **kwargs: Any) -> None:
def _thread_wrapper(self, target: Callable, *args: object, **kwargs: object) -> None:
thr_name = current_thread().name
self.logger.debug('%s - started', thr_name)
try:
+17
View File
@@ -0,0 +1,17 @@
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser Public License for more details.
#
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
+113
View File
@@ -0,0 +1,113 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser Public License for more details.
#
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the Promise class."""
import logging
from threading import Event
from typing import Callable, List, Optional, Tuple, TypeVar, Union
from telegram.utils.types import JSONDict
RT = TypeVar('RT')
logger = logging.getLogger(__name__)
class Promise:
"""A simple Promise implementation for use with the run_async decorator, DelayQueue etc.
Args:
pooled_function (:obj:`callable`): The callable that will be called concurrently.
args (:obj:`list` | :obj:`tuple`): Positional arguments for :attr:`pooled_function`.
kwargs (:obj:`dict`): Keyword arguments for :attr:`pooled_function`.
update (:class:`telegram.Update` | :obj:`object`, optional): The update this promise is
associated with.
error_handling (:obj:`bool`, optional): Whether exceptions raised by :attr:`func`
may be handled by error handlers. Defaults to :obj:`True`.
Attributes:
pooled_function (:obj:`callable`): The callable that will be called concurrently.
args (:obj:`list` | :obj:`tuple`): Positional arguments for :attr:`pooled_function`.
kwargs (:obj:`dict`): Keyword arguments for :attr:`pooled_function`.
done (:obj:`threading.Event`): Is set when the result is available.
update (:class:`telegram.Update` | :obj:`object`): Optional. The update this promise is
associated with.
error_handling (:obj:`bool`): Optional. Whether exceptions raised by :attr:`func`
may be handled by error handlers. Defaults to :obj:`True`.
"""
# TODO: Remove error_handling parameter once we drop the @run_async decorator
def __init__(
self,
pooled_function: Callable[..., RT],
args: Union[List, Tuple],
kwargs: JSONDict,
update: object = None,
error_handling: bool = True,
):
self.pooled_function = pooled_function
self.args = args
self.kwargs = kwargs
self.update = update
self.error_handling = error_handling
self.done = Event()
self._result: Optional[RT] = None
self._exception: Optional[Exception] = None
def run(self) -> None:
"""Calls the :attr:`pooled_function` callable."""
try:
self._result = self.pooled_function(*self.args, **self.kwargs)
except Exception as exc:
self._exception = exc
finally:
self.done.set()
def __call__(self) -> None:
self.run()
def result(self, timeout: float = None) -> Optional[RT]:
"""Return the result of the ``Promise``.
Args:
timeout (:obj:`float`, optional): Maximum time in seconds to wait for the result to be
calculated. ``None`` means indefinite. Default is ``None``.
Returns:
Returns the return value of :attr:`pooled_function` or ``None`` if the ``timeout``
expires.
Raises:
object exception raised by :attr:`pooled_function`.
"""
self.done.wait(timeout=timeout)
if self._exception is not None:
raise self._exception # pylint: disable=raising-bad-type
return self._result
@property
def exception(self) -> Optional[Exception]:
"""The exception raised by :attr:`pooled_function` or ``None`` if no exception has been
raised (yet)."""
return self._exception
+208
View File
@@ -0,0 +1,208 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser Public License for more details.
#
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
# pylint: disable=E0401, C0114
import asyncio
import logging
import os
import sys
from queue import Queue
from ssl import SSLContext
from threading import Event, Lock
from typing import TYPE_CHECKING, Any, Optional
import tornado.web
from tornado import httputil
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from telegram import Update
from telegram.utils.types import JSONDict
if TYPE_CHECKING:
from telegram import Bot
try:
import ujson as json
except ImportError:
import json # type: ignore[no-redef]
class WebhookServer:
def __init__(
self, listen: str, port: int, webhook_app: 'WebhookAppClass', ssl_ctx: SSLContext
):
self.http_server = HTTPServer(webhook_app, ssl_options=ssl_ctx)
self.listen = listen
self.port = port
self.loop: Optional[IOLoop] = None
self.logger = logging.getLogger(__name__)
self.is_running = False
self.server_lock = Lock()
self.shutdown_lock = Lock()
def serve_forever(self, force_event_loop: bool = False, ready: Event = None) -> None:
with self.server_lock:
self.is_running = True
self.logger.debug('Webhook Server started.')
self._ensure_event_loop(force_event_loop=force_event_loop)
self.loop = IOLoop.current()
self.http_server.listen(self.port, address=self.listen)
if ready is not None:
ready.set()
self.loop.start()
self.logger.debug('Webhook Server stopped.')
self.is_running = False
def shutdown(self) -> None:
with self.shutdown_lock:
if not self.is_running:
self.logger.warning('Webhook Server already stopped.')
return
self.loop.add_callback(self.loop.stop) # type: ignore
def handle_error(self, request: object, client_address: str) -> None: # pylint: disable=W0613
"""Handle an error gracefully."""
self.logger.debug(
'Exception happened during processing of request from %s',
client_address,
exc_info=True,
)
def _ensure_event_loop(self, force_event_loop: bool = False) -> None:
"""If there's no asyncio event loop set for the current thread - create one."""
try:
loop = asyncio.get_event_loop()
if (
not force_event_loop
and os.name == 'nt'
and sys.version_info >= (3, 8)
and isinstance(loop, asyncio.ProactorEventLoop)
):
raise TypeError(
'`ProactorEventLoop` is incompatible with '
'Tornado. Please switch to `SelectorEventLoop`.'
)
except RuntimeError:
# Python 3.8 changed default asyncio event loop implementation on windows
# from SelectorEventLoop to ProactorEventLoop. At the time of this writing
# Tornado doesn't support ProactorEventLoop and suggests that end users
# change asyncio event loop policy to WindowsSelectorEventLoopPolicy.
# https://github.com/tornadoweb/tornado/issues/2608
# To avoid changing the global event loop policy, we manually construct
# a SelectorEventLoop instance instead of using asyncio.new_event_loop().
# Note that the fix is not applied in the main thread, as that can break
# user code in even more ways than changing the global event loop policy can,
# and because Updater always starts its webhook server in a separate thread.
# Ideally, we would want to check that Tornado actually raises the expected
# NotImplementedError, but it's not possible to cleanly recover from that
# exception in current Tornado version.
if (
os.name == 'nt'
and sys.version_info >= (3, 8)
# OS+version check makes hasattr check redundant, but just to be sure
and hasattr(asyncio, 'WindowsProactorEventLoopPolicy')
and (
isinstance(
asyncio.get_event_loop_policy(),
asyncio.WindowsProactorEventLoopPolicy, # pylint: disable=E1101
)
)
): # pylint: disable=E1101
self.logger.debug(
'Applying Tornado asyncio event loop fix for Python 3.8+ on Windows'
)
loop = asyncio.SelectorEventLoop()
else:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
class WebhookAppClass(tornado.web.Application):
def __init__(self, webhook_path: str, bot: 'Bot', update_queue: Queue):
self.shared_objects = {"bot": bot, "update_queue": update_queue}
handlers = [(rf"{webhook_path}/?", WebhookHandler, self.shared_objects)] # noqa
tornado.web.Application.__init__(self, handlers)
def log_request(self, handler: tornado.web.RequestHandler) -> None:
pass
# WebhookHandler, process webhook calls
# pylint: disable=W0223
class WebhookHandler(tornado.web.RequestHandler):
SUPPORTED_METHODS = ["POST"]
def __init__(
self,
application: tornado.web.Application,
request: httputil.HTTPServerRequest,
**kwargs: JSONDict,
):
super().__init__(application, request, **kwargs)
self.logger = logging.getLogger(__name__)
def initialize(self, bot: 'Bot', update_queue: Queue) -> None:
# pylint: disable=W0201
self.bot = bot
self.update_queue = update_queue
def set_default_headers(self) -> None:
self.set_header("Content-Type", 'application/json; charset="utf-8"')
def post(self) -> None:
self.logger.debug('Webhook triggered')
self._validate_post()
json_string = self.request.body.decode()
data = json.loads(json_string)
self.set_status(200)
self.logger.debug('Webhook received data: %s', json_string)
update = Update.de_json(data, self.bot)
if update:
self.logger.debug('Received Update with ID %d on Webhook', update.update_id)
self.update_queue.put(update)
def _validate_post(self) -> None:
ct_header = self.request.headers.get("Content-Type", None)
if ct_header != 'application/json':
raise tornado.web.HTTPError(403)
def write_error(self, status_code: int, **kwargs: Any) -> None:
"""Log an arbitrary message.
This is used by all other logging functions.
It overrides ``BaseHTTPRequestHandler.log_message``, which logs to ``sys.stderr``.
The first argument, FORMAT, is a format string for the message to be logged. If the format
string contains any % escapes requiring parameters, they should be specified as subsequent
arguments (it's just like printf!).
The client ip is prefixed to every message.
"""
super().write_error(status_code, **kwargs)
self.logger.debug(
"%s - - %s",
self.request.remote_ip,
"Exception in WebhookHandler",
exc_info=kwargs['exc_info'],
)
+23 -25
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -20,7 +20,8 @@
from typing import TYPE_CHECKING, Any, Optional
from telegram import PhotoSize, TelegramObject
from telegram.utils.types import JSONDict
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import Bot, File
@@ -32,20 +33,6 @@ class Animation(TelegramObject):
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`file_unique_id` is equal.
Attributes:
file_id (:obj:`str`): File identifier.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
width (:obj:`int`): Video width as defined by sender.
height (:obj:`int`): Video height as defined by sender.
duration (:obj:`int`): Duration of the video in seconds as defined by sender.
thumb (:class:`telegram.PhotoSize`): Optional. Animation thumbnail as defined by sender.
file_name (:obj:`str`): Optional. Original animation filename as defined by sender.
mime_type (:obj:`str`): Optional. MIME type of the file as defined by sender.
file_size (:obj:`int`): Optional. File size.
bot (:class:`telegram.Bot`): Optional. The Bot to use for instance methods.
Args:
file_id (:obj:`str`): Identifier for this file, which can be used to download
or reuse the file.
@@ -62,6 +49,20 @@ class Animation(TelegramObject):
bot (:class:`telegram.Bot`, optional): The Bot to use for instance methods.
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
Attributes:
file_id (:obj:`str`): File identifier.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
width (:obj:`int`): Video width as defined by sender.
height (:obj:`int`): Video height as defined by sender.
duration (:obj:`int`): Duration of the video in seconds as defined by sender.
thumb (:class:`telegram.PhotoSize`): Optional. Animation thumbnail as defined by sender.
file_name (:obj:`str`): Optional. Original animation filename as defined by sender.
mime_type (:obj:`str`): Optional. MIME type of the file as defined by sender.
file_size (:obj:`int`): Optional. File size.
bot (:class:`telegram.Bot`): Optional. The Bot to use for instance methods.
"""
def __init__(
@@ -104,21 +105,18 @@ class Animation(TelegramObject):
return cls(bot=bot, **data)
def get_file(self, timeout: int = None, api_kwargs: JSONDict = None) -> 'File':
def get_file(
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
) -> 'File':
"""Convenience wrapper over :attr:`telegram.Bot.get_file`
Args:
timeout (:obj:`int` | :obj:`float`, optional): If this value is specified, use it as
the read timeout from the server (instead of the one specified during creation of
the connection pool).
api_kwargs (:obj:`dict`, optional): Arbitrary keyword arguments to be passed to the
Telegram API.
For the documentation of the arguments, please see :meth:`telegram.Bot.get_file`.
Returns:
:class:`telegram.File`
Raises:
:class:`telegram.TelegramError`
:class:`telegram.error.TelegramError`
"""
return self.bot.get_file(self.file_id, timeout=timeout, api_kwargs=api_kwargs)
return self.bot.get_file(file_id=self.file_id, timeout=timeout, api_kwargs=api_kwargs)
+25 -27
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any, Optional
from telegram import PhotoSize, TelegramObject
from telegram.utils.types import JSONDict
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import Bot, File
@@ -33,22 +34,6 @@ class Audio(TelegramObject):
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`file_unique_id` is equal.
Attributes:
file_id (:obj:`str`): Identifier for this file.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
duration (:obj:`int`): Duration of the audio in seconds.
performer (:obj:`str`): Optional. Performer of the audio as defined by sender or by audio
tags.
title (:obj:`str`): Optional. Title of the audio as defined by sender or by audio tags.
file_name (:obj:`str`): Optional. Original filename as defined by sender.
mime_type (:obj:`str`): Optional. MIME type of the file as defined by sender.
file_size (:obj:`int`): Optional. File size.
thumb (:class:`telegram.PhotoSize`): Optional. Thumbnail of the album cover to
which the music file belongs.
bot (:class:`telegram.Bot`): Optional. The Bot to use for instance methods.
Args:
file_id (:obj:`str`): Identifier for this file, which can be used to download
or reuse the file.
@@ -66,6 +51,22 @@ class Audio(TelegramObject):
bot (:class:`telegram.Bot`, optional): The Bot to use for instance methods.
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
Attributes:
file_id (:obj:`str`): Identifier for this file.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
duration (:obj:`int`): Duration of the audio in seconds.
performer (:obj:`str`): Optional. Performer of the audio as defined by sender or by audio
tags.
title (:obj:`str`): Optional. Title of the audio as defined by sender or by audio tags.
file_name (:obj:`str`): Optional. Original filename as defined by sender.
mime_type (:obj:`str`): Optional. MIME type of the file as defined by sender.
file_size (:obj:`int`): Optional. File size.
thumb (:class:`telegram.PhotoSize`): Optional. Thumbnail of the album cover to
which the music file belongs.
bot (:class:`telegram.Bot`): Optional. The Bot to use for instance methods.
"""
def __init__(
@@ -108,21 +109,18 @@ class Audio(TelegramObject):
return cls(bot=bot, **data)
def get_file(self, timeout: int = None, api_kwargs: JSONDict = None) -> 'File':
def get_file(
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
) -> 'File':
"""Convenience wrapper over :attr:`telegram.Bot.get_file`
Args:
timeout (:obj:`int` | :obj:`float`, optional): If this value is specified, use it as
the read timeout from the server (instead of the one specified during creation of
the connection pool).
api_kwargs (:obj:`dict`, optional): Arbitrary keyword arguments to be passed to the
Telegram API.
For the documentation of the arguments, please see :meth:`telegram.Bot.get_file`.
Returns:
:class:`telegram.File`
Raises:
:class:`telegram.TelegramError`
:class:`telegram.error.TelegramError`
"""
return self.bot.get_file(self.file_id, timeout=timeout, api_kwargs=api_kwargs)
return self.bot.get_file(file_id=self.file_id, timeout=timeout, api_kwargs=api_kwargs)
+31 -32
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -20,6 +20,8 @@
from typing import TYPE_CHECKING, Any
from telegram import TelegramObject
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import Bot, File
@@ -32,19 +34,6 @@ class ChatPhoto(TelegramObject):
considered equal, if their :attr:`small_file_unique_id` and :attr:`big_file_unique_id` are
equal.
Attributes:
small_file_id (:obj:`str`): File identifier of small (160x160) chat photo.
This file_id can be used only for photo download and only for as long
as the photo is not changed.
small_file_unique_id (:obj:`str`): Unique file identifier of small (160x160) chat photo,
which is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
big_file_id (:obj:`str`): File identifier of big (640x640) chat photo.
This file_id can be used only for photo download and only for as long as
the photo is not changed.
big_file_unique_id (:obj:`str`): Unique file identifier of big (640x640) chat photo,
which is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
Args:
small_file_id (:obj:`str`): Unique file identifier of small (160x160) chat photo. This
file_id can be used only for photo download and only for as long
@@ -60,6 +49,20 @@ class ChatPhoto(TelegramObject):
bot (:class:`telegram.Bot`, optional): The Bot to use for instance methods
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
Attributes:
small_file_id (:obj:`str`): File identifier of small (160x160) chat photo.
This file_id can be used only for photo download and only for as long
as the photo is not changed.
small_file_unique_id (:obj:`str`): Unique file identifier of small (160x160) chat photo,
which is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
big_file_id (:obj:`str`): File identifier of big (640x640) chat photo.
This file_id can be used only for photo download and only for as long as
the photo is not changed.
big_file_unique_id (:obj:`str`): Unique file identifier of big (640x640) chat photo,
which is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
"""
def __init__(
@@ -83,42 +86,38 @@ class ChatPhoto(TelegramObject):
self.big_file_unique_id,
)
def get_small_file(self, timeout: int = None, **kwargs: Any) -> 'File':
def get_small_file(
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
) -> 'File':
"""Convenience wrapper over :attr:`telegram.Bot.get_file` for getting the
small (160x160) chat photo
Args:
timeout (:obj:`int` | :obj:`float`, optional): If this value is specified, use it as
the read timeout from the server (instead of the one specified during creation of
the connection pool).
api_kwargs (:obj:`dict`, optional): Arbitrary keyword arguments to be passed to the
Telegram API.
For the documentation of the arguments, please see :meth:`telegram.Bot.get_file`.
Returns:
:class:`telegram.File`
Raises:
:class:`telegram.TelegramError`
:class:`telegram.error.TelegramError`
"""
return self.bot.get_file(self.small_file_id, timeout=timeout, **kwargs)
return self.bot.get_file(
file_id=self.small_file_id, timeout=timeout, api_kwargs=api_kwargs
)
def get_big_file(self, timeout: int = None, **kwargs: Any) -> 'File':
def get_big_file(
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
) -> 'File':
"""Convenience wrapper over :attr:`telegram.Bot.get_file` for getting the
big (640x640) chat photo
Args:
timeout (:obj:`int` | :obj:`float`, optional): If this value is specified, use it as
the read timeout from the server (instead of the one specified during creation of
the connection pool).
api_kwargs (:obj:`dict`, optional): Arbitrary keyword arguments to be passed to the
Telegram API.
For the documentation of the arguments, please see :meth:`telegram.Bot.get_file`.
Returns:
:class:`telegram.File`
Raises:
:class:`telegram.TelegramError`
:class:`telegram.error.TelegramError`
"""
return self.bot.get_file(self.big_file_id, timeout=timeout, **kwargs)
return self.bot.get_file(file_id=self.big_file_id, timeout=timeout, api_kwargs=api_kwargs)
+8 -8
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -29,13 +29,6 @@ class Contact(TelegramObject):
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`phone_number` is equal.
Attributes:
phone_number (:obj:`str`): Contact's phone number.
first_name (:obj:`str`): Contact's first name.
last_name (:obj:`str`): Optional. Contact's last name.
user_id (:obj:`int`): Optional. Contact's user identifier in Telegram.
vcard (:obj:`str`): Optional. Additional data about the contact in the form of a vCard.
Args:
phone_number (:obj:`str`): Contact's phone number.
first_name (:obj:`str`): Contact's first name.
@@ -44,6 +37,13 @@ class Contact(TelegramObject):
vcard (:obj:`str`, optional): Additional data about the contact in the form of a vCard.
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
Attributes:
phone_number (:obj:`str`): Contact's phone number.
first_name (:obj:`str`): Contact's first name.
last_name (:obj:`str`): Optional. Contact's last name.
user_id (:obj:`int`): Optional. Contact's user identifier in Telegram.
vcard (:obj:`str`): Optional. Additional data about the contact in the form of a vCard.
"""
def __init__(
+20 -22
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any, Optional
from telegram import PhotoSize, TelegramObject
from telegram.utils.types import JSONDict
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import Bot, File
@@ -34,17 +35,6 @@ class Document(TelegramObject):
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`file_unique_id` is equal.
Attributes:
file_id (:obj:`str`): File identifier.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
thumb (:class:`telegram.PhotoSize`): Optional. Document thumbnail.
file_name (:obj:`str`): Original filename.
mime_type (:obj:`str`): Optional. MIME type of the file.
file_size (:obj:`int`): Optional. File size.
bot (:class:`telegram.Bot`): Optional. The Bot to use for instance methods.
Args:
file_id (:obj:`str`): Identifier for this file, which can be used to download
or reuse the file.
@@ -57,6 +47,17 @@ class Document(TelegramObject):
bot (:class:`telegram.Bot`, optional): The Bot to use for instance methods.
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
Attributes:
file_id (:obj:`str`): File identifier.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
thumb (:class:`telegram.PhotoSize`): Optional. Document thumbnail.
file_name (:obj:`str`): Original filename.
mime_type (:obj:`str`): Optional. MIME type of the file.
file_size (:obj:`int`): Optional. File size.
bot (:class:`telegram.Bot`): Optional. The Bot to use for instance methods.
"""
_id_keys = ('file_id',)
@@ -95,21 +96,18 @@ class Document(TelegramObject):
return cls(bot=bot, **data)
def get_file(self, timeout: int = None, api_kwargs: JSONDict = None) -> 'File':
def get_file(
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
) -> 'File':
"""Convenience wrapper over :attr:`telegram.Bot.get_file`
Args:
timeout (:obj:`int` | :obj:`float`, optional): If this value is specified, use it as
the read timeout from the server (instead of the one specified during creation of
the connection pool).
api_kwargs (:obj:`dict`, optional): Arbitrary keyword arguments to be passed to the
Telegram API.
For the documentation of the arguments, please see :meth:`telegram.Bot.get_file`.
Returns:
:class:`telegram.File`
Raises:
:class:`telegram.TelegramError`
:class:`telegram.error.TelegramError`
"""
return self.bot.get_file(self.file_id, timeout=timeout, api_kwargs=api_kwargs)
return self.bot.get_file(file_id=self.file_id, timeout=timeout, api_kwargs=api_kwargs)
+11 -13
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -42,15 +42,9 @@ class File(TelegramObject):
considered equal, if their :attr:`file_unique_id` is equal.
Note:
Maximum file size to download is 20 MB.
Attributes:
file_id (:obj:`str`): Identifier for this file.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
file_size (:obj:`str`): Optional. File size.
file_path (:obj:`str`): Optional. File path. Use :attr:`download` to get the file.
* Maximum file size to download is 20 MB.
* If you obtain an instance of this class from :attr:`telegram.PassportFile.get_file`,
then it will automatically be decrypted as it downloads when you call :attr:`download()`.
Args:
file_id (:obj:`str`): Identifier for this file, which can be used to download
@@ -63,9 +57,13 @@ class File(TelegramObject):
bot (:obj:`telegram.Bot`, optional): Bot to use with shortcut method.
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
Note:
If you obtain an instance of this class from :attr:`telegram.PassportFile.get_file`,
then it will automatically be decrypted as it downloads when you call :attr:`download()`.
Attributes:
file_id (:obj:`str`): Identifier for this file.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
file_size (:obj:`str`): Optional. File size.
file_path (:obj:`str`): Optional. File path. Use :attr:`download` to get the file.
"""
+16 -12
View File
@@ -2,7 +2,7 @@
# pylint: disable=W0622,E0611
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -23,7 +23,7 @@ import imghdr
import logging
import mimetypes
import os
from typing import IO, Optional, Tuple
from typing import IO, Optional, Tuple, Union
from uuid import uuid4
DEFAULT_MIME_TYPE = 'application/octet-stream'
@@ -33,13 +33,9 @@ logger = logging.getLogger(__name__)
class InputFile:
"""This object represents a Telegram InputFile.
Attributes:
input_file_content (:obj:`bytes`): The binary content of the file to send.
filename (:obj:`str`): Optional. Filename for the file to be sent.
attach (:obj:`str`): Optional. Attach id for sending multiple files.
Args:
obj (:obj:`File handler`): An open file descriptor.
obj (:obj:`File handler` | :obj:`bytes`): An open file descriptor or the files content as
bytes.
filename (:obj:`str`, optional): Filename for this InputFile.
attach (:obj:`bool`, optional): Whether this should be send as one file or is part of a
collection of files.
@@ -47,17 +43,25 @@ class InputFile:
Raises:
TelegramError
Attributes:
input_file_content (:obj:`bytes`): The binary content of the file to send.
filename (:obj:`str`): Optional. Filename for the file to be sent.
attach (:obj:`str`): Optional. Attach id for sending multiple files.
"""
def __init__(self, obj: IO, filename: str = None, attach: bool = None):
def __init__(self, obj: Union[IO, bytes], filename: str = None, attach: bool = None):
self.filename = None
self.input_file_content = obj.read()
if isinstance(obj, bytes):
self.input_file_content = obj
else:
self.input_file_content = obj.read()
self.attach = 'attached' + uuid4().hex if attach else None
if filename:
self.filename = filename
elif hasattr(obj, 'name') and not isinstance(obj.name, int):
self.filename = os.path.basename(obj.name)
elif hasattr(obj, 'name') and not isinstance(obj.name, int): # type: ignore[union-attr]
self.filename = os.path.basename(obj.name) # type: ignore[union-attr]
image_mime_type = self.is_image(self.input_file_content)
if image_mime_type:
+198 -136
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -30,8 +30,8 @@ from telegram import (
Video,
MessageEntity,
)
from telegram.utils.helpers import DEFAULT_NONE, DefaultValue, parse_file_input
from telegram.utils.types import FileInput, JSONDict
from telegram.utils.helpers import DEFAULT_NONE, parse_file_input
from telegram.utils.types import FileInput, JSONDict, ODVInput
class InputMedia(TelegramObject):
@@ -59,6 +59,45 @@ class InputMedia(TelegramObject):
class InputMediaAnimation(InputMedia):
"""Represents an animation file (GIF or H.264/MPEG-4 AVC video without sound) to be sent.
Note:
When using a :class:`telegram.Animation` for the :attr:`media` attribute. It will take the
width, height and duration from that video, unless otherwise specified with the optional
arguments.
Args:
media (:obj:`str` | `filelike object` | :obj:`bytes` | :class:`pathlib.Path` | \
:class:`telegram.Animation`): File to send. Pass a
file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP
URL for Telegram to get a file from the Internet. Lastly you can pass an existing
:class:`telegram.Animation` object to send.
.. versionchanged:: 13.2
Accept :obj:`bytes` as input.
filename (:obj:`str`, optional): Custom file name for the animation, when uploading a
new file. Convenience parameter, useful e.g. when sending files generated by the
:obj:`tempfile` module.
.. versionadded:: 13.1
thumb (`filelike object` | :obj:`bytes` | :class:`pathlib.Path`, optional): Thumbnail of
the file sent; can be ignored if
thumbnail generation for the file is supported server-side. The thumbnail should be
in JPEG format and less than 200 kB in size. A thumbnail's width and height should
not exceed 320. Ignored if the file is not uploaded using multipart/form-data.
Thumbnails can't be reused and can be only uploaded as a new file.
.. versionchanged:: 13.2
Accept :obj:`bytes` as input.
caption (:obj:`str`, optional): Caption of the animation to be sent, 0-1024 characters
after entities parsing.
parse_mode (:obj:`str`, optional): Send Markdown or HTML, if you want Telegram apps to show
bold, italic, fixed-width text or inline URLs in the media caption. See the constants
in :class:`telegram.ParseMode` for the available modes.
caption_entities (List[:class:`telegram.MessageEntity`], optional): List of special
entities that appear in the caption, which can be specified instead of parse_mode.
width (:obj:`int`, optional): Animation width.
height (:obj:`int`, optional): Animation height.
duration (:obj:`int`, optional): Animation duration.
Attributes:
type (:obj:`str`): ``animation``.
media (:obj:`str` | :class:`telegram.InputFile`): Animation to send.
@@ -71,34 +110,6 @@ class InputMediaAnimation(InputMedia):
height (:obj:`int`): Optional. Animation height.
duration (:obj:`int`): Optional. Animation duration.
Args:
media (:obj:`str` | `filelike object` | :class:`pathlib.Path` | \
:class:`telegram.Animation`): File to send. Pass a
file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP
URL for Telegram to get a file from the Internet. Lastly you can pass an existing
:class:`telegram.Animation` object to send.
thumb (`filelike object` | :class:`pathlib.Path`, optional): Thumbnail of the file sent;
can be ignored if
thumbnail generation for the file is supported server-side. The thumbnail should be
in JPEG format and less than 200 kB in size. A thumbnail's width and height should
not exceed 320. Ignored if the file is not uploaded using multipart/form-data.
Thumbnails can't be reused and can be only uploaded as a new file.
caption (:obj:`str`, optional): Caption of the animation to be sent, 0-1024 characters
after entities parsing.
parse_mode (:obj:`str`, optional): Send Markdown or HTML, if you want Telegram apps to show
bold, italic, fixed-width text or inline URLs in the media caption. See the constants
in :class:`telegram.ParseMode` for the available modes.
caption_entities (List[:class:`telegram.MessageEntity`], optional): List of special
entities that appear in the caption, which can be specified instead of parse_mode.
width (:obj:`int`, optional): Animation width.
height (:obj:`int`, optional): Animation height.
duration (:obj:`int`, optional): Animation duration.
Note:
When using a :class:`telegram.Animation` for the :attr:`media` attribute. It will take the
width, height and duration from that video, unless otherwise specified with the optional
arguments.
"""
def __init__(
@@ -106,11 +117,12 @@ class InputMediaAnimation(InputMedia):
media: Union[FileInput, Animation],
thumb: FileInput = None,
caption: str = None,
parse_mode: Union[str, DefaultValue] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
width: int = None,
height: int = None,
duration: int = None,
caption_entities: Union[List[MessageEntity], Tuple[MessageEntity, ...]] = None,
filename: str = None,
):
self.type = 'animation'
@@ -120,7 +132,7 @@ class InputMediaAnimation(InputMedia):
self.height = media.height
self.duration = media.duration
else:
self.media = parse_file_input(media, attach=True)
self.media = parse_file_input(media, attach=True, filename=filename)
if thumb:
self.thumb = parse_file_input(thumb, attach=True)
@@ -140,6 +152,28 @@ class InputMediaAnimation(InputMedia):
class InputMediaPhoto(InputMedia):
"""Represents a photo to be sent.
Args:
media (:obj:`str` | `filelike object` | :obj:`bytes` | :class:`pathlib.Path` | \
:class:`telegram.PhotoSize`): File to send. Pass a
file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP
URL for Telegram to get a file from the Internet. Lastly you can pass an existing
:class:`telegram.PhotoSize` object to send.
.. versionchanged:: 13.2
Accept :obj:`bytes` as input.
filename (:obj:`str`, optional): Custom file name for the photo, when uploading a
new file. Convenience parameter, useful e.g. when sending files generated by the
:obj:`tempfile` module.
.. versionadded:: 13.1
caption (:obj:`str`, optional ): Caption of the photo to be sent, 0-1024 characters after
entities parsing.
parse_mode (:obj:`str`, optional): Send Markdown or HTML, if you want Telegram apps to show
bold, italic, fixed-width text or inline URLs in the media caption. See the constants
in :class:`telegram.ParseMode` for the available modes.
caption_entities (List[:class:`telegram.MessageEntity`], optional): List of special
entities that appear in the caption, which can be specified instead of parse_mode.
Attributes:
type (:obj:`str`): ``photo``.
media (:obj:`str` | :class:`telegram.InputFile`): Photo to send.
@@ -148,30 +182,18 @@ class InputMediaPhoto(InputMedia):
caption_entities (List[:class:`telegram.MessageEntity`]): Optional. List of special
entities that appear in the caption.
Args:
media (:obj:`str` | `filelike object` | :class:`pathlib.Path` | \
:class:`telegram.PhotoSize`): File to send. Pass a
file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP
URL for Telegram to get a file from the Internet. Lastly you can pass an existing
:class:`telegram.PhotoSize` object to send.
caption (:obj:`str`, optional ): Caption of the photo to be sent, 0-1024 characters after
entities parsing.
parse_mode (:obj:`str`, optional): Send Markdown or HTML, if you want Telegram apps to show
bold, italic, fixed-width text or inline URLs in the media caption. See the constants
in :class:`telegram.ParseMode` for the available modes.
caption_entities (List[:class:`telegram.MessageEntity`], optional): List of special
entities that appear in the caption, which can be specified instead of parse_mode.
"""
def __init__(
self,
media: Union[FileInput, PhotoSize],
caption: str = None,
parse_mode: Union[str, DefaultValue] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Union[List[MessageEntity], Tuple[MessageEntity, ...]] = None,
filename: str = None,
):
self.type = 'photo'
self.media = parse_file_input(media, PhotoSize, attach=True)
self.media = parse_file_input(media, PhotoSize, attach=True, filename=filename)
if caption:
self.caption = caption
@@ -182,6 +204,50 @@ class InputMediaPhoto(InputMedia):
class InputMediaVideo(InputMedia):
"""Represents a video to be sent.
Note:
* When using a :class:`telegram.Video` for the :attr:`media` attribute. It will take the
width, height and duration from that video, unless otherwise specified with the optional
arguments.
* ``thumb`` will be ignored for small video files, for which Telegram can easily
generate thumb nails. However, this behaviour is undocumented and might be changed
by Telegram.
Args:
media (:obj:`str` | `filelike object` | :obj:`bytes` | :class:`pathlib.Path` | \
:class:`telegram.Video`): File to send. Pass a
file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP
URL for Telegram to get a file from the Internet. Lastly you can pass an existing
:class:`telegram.Video` object to send.
.. versionchanged:: 13.2
Accept :obj:`bytes` as input.
filename (:obj:`str`, optional): Custom file name for the video, when uploading a
new file. Convenience parameter, useful e.g. when sending files generated by the
:obj:`tempfile` module.
.. versionadded:: 13.1
caption (:obj:`str`, optional): Caption of the video to be sent, 0-1024 characters after
entities parsing.
parse_mode (:obj:`str`, optional): Send Markdown or HTML, if you want Telegram apps to show
bold, italic, fixed-width text or inline URLs in the media caption. See the constants
in :class:`telegram.ParseMode` for the available modes.
caption_entities (List[:class:`telegram.MessageEntity`], optional): List of special
entities that appear in the caption, which can be specified instead of parse_mode.
width (:obj:`int`, optional): Video width.
height (:obj:`int`, optional): Video height.
duration (:obj:`int`, optional): Video duration.
supports_streaming (:obj:`bool`, optional): Pass :obj:`True`, if the uploaded video is
suitable for streaming.
thumb (`filelike object` | :obj:`bytes` | :class:`pathlib.Path`, optional): Thumbnail of
the file sent; can be ignored if
thumbnail generation for the file is supported server-side. The thumbnail should be
in JPEG format and less than 200 kB in size. A thumbnail's width and height should
not exceed 320. Ignored if the file is not uploaded using multipart/form-data.
Thumbnails can't be reused and can be only uploaded as a new file.
.. versionchanged:: 13.2
Accept :obj:`bytes` as input.
Attributes:
type (:obj:`str`): ``video``.
media (:obj:`str` | :class:`telegram.InputFile`): Video file to send.
@@ -196,38 +262,6 @@ class InputMediaVideo(InputMedia):
suitable for streaming.
thumb (:class:`telegram.InputFile`): Optional. Thumbnail of the file to send.
Args:
media (:obj:`str` | `filelike object` | :class:`pathlib.Path` | :class:`telegram.Video`):
File to send. Pass a
file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP
URL for Telegram to get a file from the Internet. Lastly you can pass an existing
:class:`telegram.Video` object to send.
caption (:obj:`str`, optional): Caption of the video to be sent, 0-1024 characters after
entities parsing.
parse_mode (:obj:`str`, optional): Send Markdown or HTML, if you want Telegram apps to show
bold, italic, fixed-width text or inline URLs in the media caption. See the constants
in :class:`telegram.ParseMode` for the available modes.
caption_entities (List[:class:`telegram.MessageEntity`], optional): List of special
entities that appear in the caption, which can be specified instead of parse_mode.
width (:obj:`int`, optional): Video width.
height (:obj:`int`, optional): Video height.
duration (:obj:`int`, optional): Video duration.
supports_streaming (:obj:`bool`, optional): Pass :obj:`True`, if the uploaded video is
suitable for streaming.
thumb (`filelike object` | :class:`pathlib.Path`, optional): Thumbnail of the file sent;
can be ignored if
thumbnail generation for the file is supported server-side. The thumbnail should be
in JPEG format and less than 200 kB in size. A thumbnail's width and height should
not exceed 320. Ignored if the file is not uploaded using multipart/form-data.
Thumbnails can't be reused and can be only uploaded as a new file.
Note:
* When using a :class:`telegram.Video` for the :attr:`media` attribute. It will take the
width, height and duration from that video, unless otherwise specified with the optional
arguments.
* ``thumb`` will be ignored for small video files, for which Telegram can easily
generate thumb nails. However, this behaviour is undocumented and might be changed
by Telegram.
"""
def __init__(
@@ -238,9 +272,10 @@ class InputMediaVideo(InputMedia):
height: int = None,
duration: int = None,
supports_streaming: bool = None,
parse_mode: Union[str, DefaultValue] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
thumb: FileInput = None,
caption_entities: Union[List[MessageEntity], Tuple[MessageEntity, ...]] = None,
filename: str = None,
):
self.type = 'video'
@@ -250,7 +285,7 @@ class InputMediaVideo(InputMedia):
self.height = media.height
self.duration = media.duration
else:
self.media = parse_file_input(media, attach=True)
self.media = parse_file_input(media, attach=True, filename=filename)
if thumb:
self.thumb = parse_file_input(thumb, attach=True)
@@ -272,6 +307,47 @@ class InputMediaVideo(InputMedia):
class InputMediaAudio(InputMedia):
"""Represents an audio file to be treated as music to be sent.
Note:
When using a :class:`telegram.Audio` for the :attr:`media` attribute. It will take the
duration, performer and title from that video, unless otherwise specified with the
optional arguments.
Args:
media (:obj:`str` | `filelike object` | :obj:`bytes` | :class:`pathlib.Path` | \
:class:`telegram.Audio`):
File to send. Pass a
file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP
URL for Telegram to get a file from the Internet. Lastly you can pass an existing
:class:`telegram.Audio` object to send.
.. versionchanged:: 13.2
Accept :obj:`bytes` as input.
filename (:obj:`str`, optional): Custom file name for the audio, when uploading a
new file. Convenience parameter, useful e.g. when sending files generated by the
:obj:`tempfile` module.
.. versionadded:: 13.1
caption (:obj:`str`, optional): Caption of the audio to be sent, 0-1024 characters after
entities parsing.
parse_mode (:obj:`str`, optional): Send Markdown or HTML, if you want Telegram apps to show
bold, italic, fixed-width text or inline URLs in the media caption. See the constants
in :class:`telegram.ParseMode` for the available modes.
caption_entities (List[:class:`telegram.MessageEntity`], optional): List of special
entities that appear in the caption, which can be specified instead of parse_mode.
duration (:obj:`int`): Duration of the audio in seconds as defined by sender.
performer (:obj:`str`, optional): Performer of the audio as defined by sender or by audio
tags.
title (:obj:`str`, optional): Title of the audio as defined by sender or by audio tags.
thumb (`filelike object` | :obj:`bytes` | :class:`pathlib.Path`, optional): Thumbnail of
the file sent; can be ignored if
thumbnail generation for the file is supported server-side. The thumbnail should be
in JPEG format and less than 200 kB in size. A thumbnail's width and height should
not exceed 320. Ignored if the file is not uploaded using multipart/form-data.
Thumbnails can't be reused and can be only uploaded as a new file.
.. versionchanged:: 13.2
Accept :obj:`bytes` as input.
Attributes:
type (:obj:`str`): ``audio``.
media (:obj:`str` | :class:`telegram.InputFile`): Audio file to send.
@@ -285,34 +361,6 @@ class InputMediaAudio(InputMedia):
title (:obj:`str`): Optional. Title of the audio as defined by sender or by audio tags.
thumb (:class:`telegram.InputFile`): Optional. Thumbnail of the file to send.
Args:
media (:obj:`str` | `filelike object` | :class:`pathlib.Path` | :class:`telegram.Audio`):
File to send. Pass a
file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP
URL for Telegram to get a file from the Internet. Lastly you can pass an existing
:class:`telegram.Audio` object to send.
caption (:obj:`str`, optional): Caption of the audio to be sent, 0-1024 characters after
entities parsing.
parse_mode (:obj:`str`, optional): Send Markdown or HTML, if you want Telegram apps to show
bold, italic, fixed-width text or inline URLs in the media caption. See the constants
in :class:`telegram.ParseMode` for the available modes.
caption_entities (List[:class:`telegram.MessageEntity`], optional): List of special
entities that appear in the caption, which can be specified instead of parse_mode.
duration (:obj:`int`): Duration of the audio in seconds as defined by sender.
performer (:obj:`str`, optional): Performer of the audio as defined by sender or by audio
tags.
title (:obj:`str`, optional): Title of the audio as defined by sender or by audio tags.
thumb (`filelike object` | :class:`pathlib.Path`, optional): Thumbnail of the file sent;
can be ignored if
thumbnail generation for the file is supported server-side. The thumbnail should be
in JPEG format and less than 200 kB in size. A thumbnail's width and height should
not exceed 320. Ignored if the file is not uploaded using multipart/form-data.
Thumbnails can't be reused and can be only uploaded as a new file.
Note:
When using a :class:`telegram.Audio` for the :attr:`media` attribute. It will take the
duration, performer and title from that video, unless otherwise specified with the
optional arguments.
"""
def __init__(
@@ -320,11 +368,12 @@ class InputMediaAudio(InputMedia):
media: Union[FileInput, Audio],
thumb: FileInput = None,
caption: str = None,
parse_mode: Union[str, DefaultValue] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
duration: int = None,
performer: str = None,
title: str = None,
caption_entities: Union[List[MessageEntity], Tuple[MessageEntity, ...]] = None,
filename: str = None,
):
self.type = 'audio'
@@ -334,7 +383,7 @@ class InputMediaAudio(InputMedia):
self.performer = media.performer
self.title = media.title
else:
self.media = parse_file_input(media, attach=True)
self.media = parse_file_input(media, attach=True, filename=filename)
if thumb:
self.thumb = parse_file_input(thumb, attach=True)
@@ -354,6 +403,40 @@ class InputMediaAudio(InputMedia):
class InputMediaDocument(InputMedia):
"""Represents a general file to be sent.
Args:
media (:obj:`str` | `filelike object` | :obj:`bytes` | :class:`pathlib.Path` | \
:class:`telegram.Document`): File to send. Pass a
file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP
URL for Telegram to get a file from the Internet. Lastly you can pass an existing
:class:`telegram.Document` object to send.
.. versionchanged:: 13.2
Accept :obj:`bytes` as input.
filename (:obj:`str`, optional): Custom file name for the document, when uploading a
new file. Convenience parameter, useful e.g. when sending files generated by the
:obj:`tempfile` module.
.. versionadded:: 13.1
caption (:obj:`str`, optional): Caption of the document to be sent, 0-1024 characters after
entities parsing.
parse_mode (:obj:`str`, optional): Send Markdown or HTML, if you want Telegram apps to show
bold, italic, fixed-width text or inline URLs in the media caption. See the constants
in :class:`telegram.ParseMode` for the available modes.
caption_entities (List[:class:`telegram.MessageEntity`], optional): List of special
entities that appear in the caption, which can be specified instead of parse_mode.
thumb (`filelike object` | :obj:`bytes` | :class:`pathlib.Path`, optional): Thumbnail of
the file sent; can be ignored if
thumbnail generation for the file is supported server-side. The thumbnail should be
in JPEG format and less than 200 kB in size. A thumbnail's width and height should
not exceed 320. Ignored if the file is not uploaded using multipart/form-data.
Thumbnails can't be reused and can be only uploaded as a new file.
.. versionchanged:: 13.2
Accept :obj:`bytes` as input.
disable_content_type_detection (:obj:`bool`, optional): Disables automatic server-side
content type detection for files uploaded using multipart/form-data. Always true, if
the document is sent as part of an album.
Attributes:
type (:obj:`str`): ``document``.
media (:obj:`str` | :class:`telegram.InputFile`): File to send.
@@ -366,28 +449,6 @@ class InputMediaDocument(InputMedia):
content type detection for files uploaded using multipart/form-data. Always true, if
the document is sent as part of an album.
Args:
media (:obj:`str` | `filelike object` | :class:`pathlib.Path` | \
:class:`telegram.Document`): File to send. Pass a
file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP
URL for Telegram to get a file from the Internet. Lastly you can pass an existing
:class:`telegram.Document` object to send.
caption (:obj:`str`, optional): Caption of the document to be sent, 0-1024 characters after
entities parsing.
parse_mode (:obj:`str`, optional): Send Markdown or HTML, if you want Telegram apps to show
bold, italic, fixed-width text or inline URLs in the media caption. See the constants
in :class:`telegram.ParseMode` for the available modes.
caption_entities (List[:class:`telegram.MessageEntity`], optional): List of special
entities that appear in the caption, which can be specified instead of parse_mode.
thumb (`filelike object` | :class:`pathlib.Path`, optional): Thumbnail of the file sent;
can be ignored if
thumbnail generation for the file is supported server-side. The thumbnail should be
in JPEG format and less than 200 kB in size. A thumbnail's width and height should
not exceed 320. Ignored if the file is not uploaded using multipart/form-data.
Thumbnails can't be reused and can be only uploaded as a new file.
disable_content_type_detection (:obj:`bool`, optional): Disables automatic server-side
content type detection for files uploaded using multipart/form-data. Always true, if
the document is sent as part of an album.
"""
def __init__(
@@ -395,12 +456,13 @@ class InputMediaDocument(InputMedia):
media: Union[FileInput, Document],
thumb: FileInput = None,
caption: str = None,
parse_mode: Union[str, DefaultValue] = DEFAULT_NONE,
parse_mode: ODVInput[str] = DEFAULT_NONE,
disable_content_type_detection: bool = None,
caption_entities: Union[List[MessageEntity], Tuple[MessageEntity, ...]] = None,
filename: str = None,
):
self.type = 'document'
self.media = parse_file_input(media, Document, attach=True)
self.media = parse_file_input(media, Document, attach=True, filename=filename)
if thumb:
self.thumb = parse_file_input(thumb, attach=True)
+13 -13
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -29,18 +29,6 @@ class Location(TelegramObject):
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`longitute` and :attr:`latitude` are equal.
Attributes:
longitude (:obj:`float`): Longitude as defined by sender.
latitude (:obj:`float`): Latitude as defined by sender.
horizontal_accuracy (:obj:`float`): Optional. The radius of uncertainty for the location,
measured in meters.
live_period (:obj:`int`): Optional. Time relative to the message sending date, during which
the location can be updated, in seconds. For active live locations only.
heading (:obj:`int`): Optional. The direction in which user is moving, in degrees.
For active live locations only.
proximity_alert_radius (:obj:`int`): Optional. Maximum distance for proximity alerts about
approaching another chat member, in meters. For sent live locations only.
Args:
longitude (:obj:`float`): Longitude as defined by sender.
latitude (:obj:`float`): Latitude as defined by sender.
@@ -54,6 +42,18 @@ class Location(TelegramObject):
approaching another chat member, in meters. For sent live locations only.
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
Attributes:
longitude (:obj:`float`): Longitude as defined by sender.
latitude (:obj:`float`): Latitude as defined by sender.
horizontal_accuracy (:obj:`float`): Optional. The radius of uncertainty for the location,
measured in meters.
live_period (:obj:`int`): Optional. Time relative to the message sending date, during which
the location can be updated, in seconds. For active live locations only.
heading (:obj:`int`): Optional. The direction in which user is moving, in degrees.
For active live locations only.
proximity_alert_radius (:obj:`int`): Optional. Maximum distance for proximity alerts about
approaching another chat member, in meters. For sent live locations only.
"""
def __init__(
+19 -21
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any
from telegram import TelegramObject
from telegram.utils.types import JSONDict
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import Bot, File
@@ -33,16 +34,6 @@ class PhotoSize(TelegramObject):
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`file_unique_id` is equal.
Attributes:
file_id (:obj:`str`): Identifier for this file.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
width (:obj:`int`): Photo width.
height (:obj:`int`): Photo height.
file_size (:obj:`int`): Optional. File size.
bot (:class:`telegram.Bot`): Optional. The Bot to use for instance methods.
Args:
file_id (:obj:`str`): Identifier for this file, which can be used to download
or reuse the file.
@@ -55,6 +46,16 @@ class PhotoSize(TelegramObject):
bot (:class:`telegram.Bot`, optional): The Bot to use for instance methods.
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
Attributes:
file_id (:obj:`str`): Identifier for this file.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
width (:obj:`int`): Photo width.
height (:obj:`int`): Photo height.
file_size (:obj:`int`): Optional. File size.
bot (:class:`telegram.Bot`): Optional. The Bot to use for instance methods.
"""
def __init__(
@@ -78,21 +79,18 @@ class PhotoSize(TelegramObject):
self._id_attrs = (self.file_unique_id,)
def get_file(self, timeout: int = None, api_kwargs: JSONDict = None) -> 'File':
def get_file(
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
) -> 'File':
"""Convenience wrapper over :attr:`telegram.Bot.get_file`
Args:
timeout (:obj:`int` | :obj:`float`, optional): If this value is specified, use it as
the read timeout from the server (instead of the one specified during creation of
the connection pool).
api_kwargs (:obj:`dict`, optional): Arbitrary keyword arguments to be passed to the
Telegram API.
For the documentation of the arguments, please see :meth:`telegram.Bot.get_file`.
Returns:
:class:`telegram.File`
Raises:
:class:`telegram.TelegramError`
:class:`telegram.error.TelegramError`
"""
return self.bot.get_file(self.file_id, timeout=timeout, api_kwargs=api_kwargs)
return self.bot.get_file(file_id=self.file_id, timeout=timeout, api_kwargs=api_kwargs)
+25 -28
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any, List, Optional, ClassVar
from telegram import PhotoSize, TelegramObject, constants
from telegram.utils.types import JSONDict
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import Bot, File
@@ -33,23 +34,6 @@ class Sticker(TelegramObject):
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`file_unique_id` is equal.
Attributes:
file_id (:obj:`str`): Identifier for this file.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
width (:obj:`int`): Sticker width.
height (:obj:`int`): Sticker height.
is_animated (:obj:`bool`): :obj:`True`, if the sticker is animated.
thumb (:class:`telegram.PhotoSize`): Optional. Sticker thumbnail in the .webp or .jpg
format.
emoji (:obj:`str`): Optional. Emoji associated with the sticker.
set_name (:obj:`str`): Optional. Name of the sticker set to which the sticker belongs.
mask_position (:class:`telegram.MaskPosition`): Optional. For mask stickers, the position
where the mask should be placed.
file_size (:obj:`int`): Optional. File size.
bot (:class:`telegram.Bot`): Optional. The Bot to use for instance methods.
Args:
file_id (:obj:`str`): Identifier for this file, which can be used to download
or reuse the file.
@@ -70,6 +54,22 @@ class Sticker(TelegramObject):
bot (:class:`telegram.Bot`, optional): The Bot to use for instance methods.
**kwargs (obj:`dict`): Arbitrary keyword arguments.
Attributes:
file_id (:obj:`str`): Identifier for this file.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
width (:obj:`int`): Sticker width.
height (:obj:`int`): Sticker height.
is_animated (:obj:`bool`): :obj:`True`, if the sticker is animated.
thumb (:class:`telegram.PhotoSize`): Optional. Sticker thumbnail in the .webp or .jpg
format.
emoji (:obj:`str`): Optional. Emoji associated with the sticker.
set_name (:obj:`str`): Optional. Name of the sticker set to which the sticker belongs.
mask_position (:class:`telegram.MaskPosition`): Optional. For mask stickers, the position
where the mask should be placed.
file_size (:obj:`int`): Optional. File size.
bot (:class:`telegram.Bot`): Optional. The Bot to use for instance methods.
"""
@@ -116,24 +116,21 @@ class Sticker(TelegramObject):
return cls(bot=bot, **data)
def get_file(self, timeout: str = None, api_kwargs: JSONDict = None) -> 'File':
def get_file(
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
) -> 'File':
"""Convenience wrapper over :attr:`telegram.Bot.get_file`
Args:
timeout (:obj:`int` | :obj:`float`, optional): If this value is specified, use it as
the read timeout from the server (instead of the one specified during creation of
the connection pool).
api_kwargs (:obj:`dict`, optional): Arbitrary keyword arguments to be passed to the
Telegram API.
For the documentation of the arguments, please see :meth:`telegram.Bot.get_file`.
Returns:
:class:`telegram.File`
Raises:
:class:`telegram.TelegramError`
:class:`telegram.error.TelegramError`
"""
return self.bot.get_file(self.file_id, timeout=timeout, api_kwargs=api_kwargs)
return self.bot.get_file(file_id=self.file_id, timeout=timeout, api_kwargs=api_kwargs)
class StickerSet(TelegramObject):
+10 -10
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -37,15 +37,6 @@ class Venue(TelegramObject):
Foursquare details and Google Pace details are mutually exclusive. However, this
behaviour is undocumented and might be changed by Telegram.
Attributes:
location (:class:`telegram.Location`): Venue location.
title (:obj:`str`): Name of the venue.
address (:obj:`str`): Address of the venue.
foursquare_id (:obj:`str`): Optional. Foursquare identifier of the venue.
foursquare_type (:obj:`str`): Optional. Foursquare type of the venue.
google_place_id (:obj:`str`): Optional. Google Places identifier of the venue.
google_place_type (:obj:`str`): Optional. Google Places type of the venue.
Args:
location (:class:`telegram.Location`): Venue location.
title (:obj:`str`): Name of the venue.
@@ -58,6 +49,15 @@ class Venue(TelegramObject):
`supported types <https://developers.google.com/places/web-service/supported_types>`_.)
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
Attributes:
location (:class:`telegram.Location`): Venue location.
title (:obj:`str`): Name of the venue.
address (:obj:`str`): Address of the venue.
foursquare_id (:obj:`str`): Optional. Foursquare identifier of the venue.
foursquare_type (:obj:`str`): Optional. Foursquare type of the venue.
google_place_id (:obj:`str`): Optional. Google Places identifier of the venue.
google_place_type (:obj:`str`): Optional. Google Places type of the venue.
"""
def __init__(
+23 -25
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any, Optional
from telegram import PhotoSize, TelegramObject
from telegram.utils.types import JSONDict
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import Bot, File
@@ -33,20 +34,6 @@ class Video(TelegramObject):
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`file_unique_id` is equal.
Attributes:
file_id (:obj:`str`): Identifier for this file.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
width (:obj:`int`): Video width as defined by sender.
height (:obj:`int`): Video height as defined by sender.
duration (:obj:`int`): Duration of the video in seconds as defined by sender.
thumb (:class:`telegram.PhotoSize`): Optional. Video thumbnail.
file_name (:obj:`str`): Optional. Original filename as defined by sender.
mime_type (:obj:`str`): Optional. Mime type of a file as defined by sender.
file_size (:obj:`int`): Optional. File size.
bot (:class:`telegram.Bot`): Optional. The Bot to use for instance methods.
Args:
file_id (:obj:`str`): Identifier for this file, which can be used to download
or reuse the file.
@@ -63,6 +50,20 @@ class Video(TelegramObject):
bot (:class:`telegram.Bot`, optional): The Bot to use for instance methods.
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
Attributes:
file_id (:obj:`str`): Identifier for this file.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
width (:obj:`int`): Video width as defined by sender.
height (:obj:`int`): Video height as defined by sender.
duration (:obj:`int`): Duration of the video in seconds as defined by sender.
thumb (:class:`telegram.PhotoSize`): Optional. Video thumbnail.
file_name (:obj:`str`): Optional. Original filename as defined by sender.
mime_type (:obj:`str`): Optional. Mime type of a file as defined by sender.
file_size (:obj:`int`): Optional. File size.
bot (:class:`telegram.Bot`): Optional. The Bot to use for instance methods.
"""
def __init__(
@@ -105,21 +106,18 @@ class Video(TelegramObject):
return cls(bot=bot, **data)
def get_file(self, timeout: int = None, api_kwargs: JSONDict = None) -> 'File':
def get_file(
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
) -> 'File':
"""Convenience wrapper over :attr:`telegram.Bot.get_file`
Args:
timeout (:obj:`int` | :obj:`float`, optional): If this value is specified, use it as
the read timeout from the server (instead of the one specified during creation of
the connection pool).
api_kwargs (:obj:`dict`, optional): Arbitrary keyword arguments to be passed to the
Telegram API.
For the documentation of the arguments, please see :meth:`telegram.Bot.get_file`.
Returns:
:class:`telegram.File`
Raises:
:class:`telegram.TelegramError`
:class:`telegram.error.TelegramError`
"""
return self.bot.get_file(self.file_id, timeout=timeout, api_kwargs=api_kwargs)
return self.bot.get_file(file_id=self.file_id, timeout=timeout, api_kwargs=api_kwargs)
+21 -23
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -18,10 +18,11 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram VideoNote."""
from typing import TYPE_CHECKING, Any, Optional
from typing import TYPE_CHECKING, Optional, Any
from telegram import PhotoSize, TelegramObject
from telegram.utils.types import JSONDict
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import Bot, File
@@ -33,17 +34,6 @@ class VideoNote(TelegramObject):
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`file_unique_id` is equal.
Attributes:
file_id (:obj:`str`): Identifier for this file.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
length (:obj:`int`): Video width and height as defined by sender.
duration (:obj:`int`): Duration of the video in seconds as defined by sender.
thumb (:class:`telegram.PhotoSize`): Optional. Video thumbnail.
file_size (:obj:`int`): Optional. File size.
bot (:class:`telegram.Bot`): Optional. The Bot to use for instance methods.
Args:
file_id (:obj:`str`): Identifier for this file, which can be used to download
or reuse the file.
@@ -58,6 +48,17 @@ class VideoNote(TelegramObject):
bot (:class:`telegram.Bot`, optional): The Bot to use for instance methods.
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
Attributes:
file_id (:obj:`str`): Identifier for this file.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
length (:obj:`int`): Video width and height as defined by sender.
duration (:obj:`int`): Duration of the video in seconds as defined by sender.
thumb (:class:`telegram.PhotoSize`): Optional. Video thumbnail.
file_size (:obj:`int`): Optional. File size.
bot (:class:`telegram.Bot`): Optional. The Bot to use for instance methods.
"""
def __init__(
@@ -94,21 +95,18 @@ class VideoNote(TelegramObject):
return cls(bot=bot, **data)
def get_file(self, timeout: int = None, api_kwargs: JSONDict = None) -> 'File':
def get_file(
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
) -> 'File':
"""Convenience wrapper over :attr:`telegram.Bot.get_file`
Args:
timeout (:obj:`int` | :obj:`float`, optional): If this value is specified, use it as
the read timeout from the server (instead of the one specified during creation of
the connection pool).
api_kwargs (:obj:`dict`, optional): Arbitrary keyword arguments to be passed to the
Telegram API.
For the documentation of the arguments, please see :meth:`telegram.Bot.get_file`.
Returns:
:class:`telegram.File`
Raises:
:class:`telegram.TelegramError`
:class:`telegram.error.TelegramError`
"""
return self.bot.get_file(self.file_id, timeout=timeout, api_kwargs=api_kwargs)
return self.bot.get_file(file_id=self.file_id, timeout=timeout, api_kwargs=api_kwargs)
+19 -21
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -21,7 +21,8 @@
from typing import TYPE_CHECKING, Any
from telegram import TelegramObject
from telegram.utils.types import JSONDict
from telegram.utils.helpers import DEFAULT_NONE
from telegram.utils.types import JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import Bot, File
@@ -33,16 +34,6 @@ class Voice(TelegramObject):
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`file_unique_id` is equal.
Attributes:
file_id (:obj:`str`): Identifier for this file.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
duration (:obj:`int`): Duration of the audio in seconds as defined by sender.
mime_type (:obj:`str`): Optional. MIME type of the file as defined by sender.
file_size (:obj:`int`): Optional. File size.
bot (:class:`telegram.Bot`): Optional. The Bot to use for instance methods.
Args:
file_id (:obj:`str`): Identifier for this file, which can be used to download
or reuse the file.
@@ -55,6 +46,16 @@ class Voice(TelegramObject):
bot (:class:`telegram.Bot`, optional): The Bot to use for instance methods.
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
Attributes:
file_id (:obj:`str`): Identifier for this file.
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
duration (:obj:`int`): Duration of the audio in seconds as defined by sender.
mime_type (:obj:`str`): Optional. MIME type of the file as defined by sender.
file_size (:obj:`int`): Optional. File size.
bot (:class:`telegram.Bot`): Optional. The Bot to use for instance methods.
"""
def __init__(
@@ -78,21 +79,18 @@ class Voice(TelegramObject):
self._id_attrs = (self.file_unique_id,)
def get_file(self, timeout: int = None, api_kwargs: JSONDict = None) -> 'File':
def get_file(
self, timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: JSONDict = None
) -> 'File':
"""Convenience wrapper over :attr:`telegram.Bot.get_file`
Args:
timeout (:obj:`int` | :obj:`float`, optional): If this value is specified, use it as
the read timeout from the server (instead of the one specified during creation of
the connection pool).
api_kwargs (:obj:`dict`, optional): Arbitrary keyword arguments to be passed to the
Telegram API.
For the documentation of the arguments, please see :meth:`telegram.Bot.get_file`.
Returns:
:class:`telegram.File`
Raises:
:class:`telegram.TelegramError`
:class:`telegram.error.TelegramError`
"""
return self.bot.get_file(self.file_id, timeout=timeout, api_kwargs=api_kwargs)
return self.bot.get_file(file_id=self.file_id, timeout=timeout, api_kwargs=api_kwargs)
+6 -6
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -33,11 +33,6 @@ class ForceReply(ReplyMarkup):
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`selective` is equal.
Attributes:
force_reply (:obj:`True`): Shows reply interface to the user, as if they manually selected
the bot's message and tapped 'Reply'.
selective (:obj:`bool`): Optional. Force reply from specific users only.
Args:
selective (:obj:`bool`, optional): Use this parameter if you want to force reply from
specific users only. Targets:
@@ -48,6 +43,11 @@ class ForceReply(ReplyMarkup):
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
Attributes:
force_reply (:obj:`True`): Shows reply interface to the user, as if they manually selected
the bots message and tapped 'Reply'.
selective (:obj:`bool`): Optional. Force reply from specific users only.
"""
def __init__(self, force_reply: bool = True, selective: bool = False, **_kwargs: Any):
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
+15 -15
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -36,20 +36,6 @@ class Game(TelegramObject):
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`title`, :attr:`description` and :attr:`photo` are equal.
Attributes:
title (:obj:`str`): Title of the game.
description (:obj:`str`): Description of the game.
photo (List[:class:`telegram.PhotoSize`]): Photo that will be displayed in the game message
in chats.
text (:obj:`str`): Optional. Brief description of the game or high scores included in the
game message. Can be automatically edited to include current high scores for the game
when the bot calls :meth:`telegram.Bot.set_game_score`, or manually edited
using :meth:`telegram.Bot.edit_message_text`.
text_entities (List[:class:`telegram.MessageEntity`]): Optional. Special entities that
appear in text, such as usernames, URLs, bot commands, etc.
animation (:class:`telegram.Animation`): Optional. Animation that will be displayed in the
game message in chats. Upload via `BotFather <https://t.me/BotFather>`_.
Args:
title (:obj:`str`): Title of the game.
description (:obj:`str`): Description of the game.
@@ -65,6 +51,20 @@ class Game(TelegramObject):
animation (:class:`telegram.Animation`, optional): Animation that will be displayed in the
game message in chats. Upload via `BotFather <https://t.me/BotFather>`_.
Attributes:
title (:obj:`str`): Title of the game.
description (:obj:`str`): Description of the game.
photo (List[:class:`telegram.PhotoSize`]): Photo that will be displayed in the game message
in chats.
text (:obj:`str`): Optional. Brief description of the game or high scores included in the
game message. Can be automatically edited to include current high scores for the game
when the bot calls :meth:`telegram.Bot.set_game_score`, or manually edited
using :meth:`telegram.Bot.edit_message_text`.
text_entities (List[:class:`telegram.MessageEntity`]): Optional. Special entities that
appear in text, such as usernames, URLs, bot commands, etc.
animation (:class:`telegram.Animation`): Optional. Animation that will be displayed in the
game message in chats. Upload via `BotFather <https://t.me/BotFather>`_.
"""
def __init__(
+3 -3
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -33,12 +33,12 @@ class GameHighScore(TelegramObject):
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`position`, :attr:`user` and :attr:`score` are equal.
Attributes:
Args:
position (:obj:`int`): Position in high score table for the game.
user (:class:`telegram.User`): User.
score (:obj:`int`): Score.
Args:
Attributes:
position (:obj:`int`): Position in high score table for the game.
user (:class:`telegram.User`): User.
score (:obj:`int`): Score.
+19 -19
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2020
# Copyright (C) 2015-2021
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
@@ -38,27 +38,10 @@ class InlineKeyboardButton(TelegramObject):
You must use exactly one of the optional fields. Mind that :attr:`callback_game` is not
working as expected. Putting a game short name in it might, but is not guaranteed to work.
Attributes:
text (:obj:`str`): Label text on the button.
url (:obj:`str`): Optional. HTTP or tg:// url to be opened when button is pressed.
login_url (:class:`telegram.LoginUrl`) Optional. An HTTP URL used to automatically
authorize the user. Can be used as a replacement for the Telegram Login Widget.
callback_data (:obj:`str`): Optional. Data to be sent in a callback query to the bot when
button is pressed, UTF-8 1-64 bytes.
switch_inline_query (:obj:`str`): Optional. Will prompt the user to select one of their
chats, open that chat and insert the bot's username and the specified inline query in
the input field. Can be empty, in which case just the bots username will be inserted.
switch_inline_query_current_chat (:obj:`str`): Optional. Will insert the bot's username and
the specified inline query in the current chat's input field. Can be empty, in which
case just the bots username will be inserted.
callback_game (:class:`telegram.CallbackGame`): Optional. Description of the game that will
be launched when the user presses the button.
pay (:obj:`bool`): Optional. Specify True, to send a Pay button.
Args:
text (:obj:`str`): Label text on the button.
url (:obj:`str`): HTTP or tg:// url to be opened when button is pressed.
login_url (:class:`telegram.LoginUrl`, optional) An HTTP URL used to automatically
login_url (:class:`telegram.LoginUrl`, optional): An HTTP URL used to automatically
authorize the user. Can be used as a replacement for the Telegram Login Widget.
callback_data (:obj:`str`, optional): Data to be sent in a callback query to the bot when
button is pressed, UTF-8 1-64 bytes.
@@ -81,6 +64,23 @@ class InlineKeyboardButton(TelegramObject):
must always be the ``first`` button in the first row.
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
Attributes:
text (:obj:`str`): Label text on the button.
url (:obj:`str`): Optional. HTTP or tg:// url to be opened when button is pressed.
login_url (:class:`telegram.LoginUrl`): Optional. An HTTP URL used to automatically
authorize the user. Can be used as a replacement for the Telegram Login Widget.
callback_data (:obj:`str`): Optional. Data to be sent in a callback query to the bot when
button is pressed, UTF-8 1-64 bytes.
switch_inline_query (:obj:`str`): Optional. Will prompt the user to select one of their
chats, open that chat and insert the bot's username and the specified inline query in
the input field. Can be empty, in which case just the bots username will be inserted.
switch_inline_query_current_chat (:obj:`str`): Optional. Will insert the bot's username and
the specified inline query in the current chat's input field. Can be empty, in which
case just the bots username will be inserted.
callback_game (:class:`telegram.CallbackGame`): Optional. Description of the game that will
be launched when the user presses the button.
pay (:obj:`bool`): Optional. Specify :obj:`True`, to send a Pay button.
"""
def __init__(

Some files were not shown because too many files have changed in this diff Show More