mirror of
https://github.com/python-telegram-bot/python-telegram-bot.git
synced 2026-06-19 15:45:13 +00:00
Compare commits
85 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 82c98b64a7 | |||
| f9ccf560f6 | |||
| 40ab8aadca | |||
| 644d76b592 | |||
| bd24da29cd | |||
| caffb9d66e | |||
| 1efd8e80ab | |||
| 8cc55c3381 | |||
| fbe9eeeaf5 | |||
| ebed8ec7d3 | |||
| 009785f028 | |||
| 7c858473ca | |||
| 58a109aae6 | |||
| 71eff4731c | |||
| c2c8c53d9c | |||
| 3b78934a77 | |||
| 5128748092 | |||
| 03f87750d4 | |||
| 4c4bf2185d | |||
| aaadc70fcc | |||
| ed3acd4b81 | |||
| a00ba52114 | |||
| 0ae991c141 | |||
| 7226aaea04 | |||
| 50a16edb41 | |||
| 59105b240f | |||
| db6030ea83 | |||
| 7d52ead228 | |||
| 589047ddbf | |||
| 5534ddfaa0 | |||
| 1d27a0fadb | |||
| 79cda7582e | |||
| dccf62eb1c | |||
| fb86bb3417 | |||
| 58b89cf0e9 | |||
| 4a6e0fd7a6 | |||
| 623d2f7f0b | |||
| 62a8cfc395 | |||
| b0cff31fc1 | |||
| 3c87e450fb | |||
| 8e91a6adba | |||
| 63fd846233 | |||
| 814c72052f | |||
| 1a7edd7a5d | |||
| f0e71216fe | |||
| ca37219a68 | |||
| c9636726f7 | |||
| 9c8d6efe7a | |||
| bf54599618 | |||
| 4c8d7332db | |||
| c185137c9e | |||
| 3c5a16be1c | |||
| cd25964419 | |||
| 5309cf6555 | |||
| bb8b508a22 | |||
| 4f15a7feee | |||
| 57c780c62f | |||
| 99fd4432db | |||
| e432c296a9 | |||
| 1fdccd7bf9 | |||
| bfbf6d3f94 | |||
| 0c4180c74b | |||
| 1c6ae435bf | |||
| 66b6d3c497 | |||
| 8c252c9822 | |||
| 450dc2115c | |||
| 87a6890900 | |||
| 83ab12c387 | |||
| 3f444dad8d | |||
| f23315d08b | |||
| 7b116be344 | |||
| 934e4c9bd4 | |||
| 1966fb25c5 | |||
| a333d8514a | |||
| b146c7131e | |||
| 53093ebceb | |||
| 401b2decce | |||
| 83a164e5ef | |||
| d91bc45cdc | |||
| 8967912f46 | |||
| 7ab2cafbee | |||
| 7e0ed2235e | |||
| 53abb7b4bd | |||
| 11f86b8813 | |||
| 9997a9f47e |
+52
-23
@@ -67,6 +67,7 @@ Here's how to make a one-off code change.
|
||||
$ git checkout -b your-branch-name
|
||||
|
||||
3. **Make a commit to your feature branch**. Each commit should be self-contained and have a descriptive commit message that helps other developers understand why the changes were made.
|
||||
We also have a check-list for PRs `below`_.
|
||||
|
||||
- You can refer to relevant issues in the commit message by writing, e.g., "#105".
|
||||
|
||||
@@ -80,7 +81,7 @@ Here's how to make a one-off code change.
|
||||
|
||||
- The following exceptions to the above (Google's) style guides applies:
|
||||
|
||||
- Documenting types of global variables and complex types of class members can be done using the Sphinx docstring convention.
|
||||
- Documenting types of global variables and complex types of class members can be done using the Sphinx docstring convention.
|
||||
|
||||
- In addition, PTB uses some formatting/styling and linting tools in the pre-commit setup. Some of those tools also have command line tools that can help to run these tools outside of the pre-commit step. If you'd like to leverage that, please have a look at the `pre-commit config file`_ for an overview of which tools (and which versions of them) are used. For example, we use `Black`_ for code formatting. Plugins for Black exist for some `popular editors`_. You can use those instead of manually formatting everything.
|
||||
|
||||
@@ -121,11 +122,11 @@ Here's how to make a one-off code change.
|
||||
|
||||
- When your reviewer has reviewed the code, you'll get a notification. You'll need to respond in two ways:
|
||||
|
||||
- Make a new commit addressing the comments you agree with, and push it to the same branch. Ideally, the commit message would explain what the commit does (e.g. "Fix lint error"), but if there are lots of disparate review comments, it's fine to refer to the original commit message and add something like "(address review comments)".
|
||||
- Make a new commit addressing the comments you agree with, and push it to the same branch. Ideally, the commit message would explain what the commit does (e.g. "Fix lint error"), but if there are lots of disparate review comments, it's fine to refer to the original commit message and add something like "(address review comments)".
|
||||
|
||||
- In order to keep the commit history intact, please avoid squashing or amending history and then force-pushing to the PR. Reviewers often want to look at individual commits.
|
||||
- In order to keep the commit history intact, please avoid squashing or amending history and then force-pushing to the PR. Reviewers often want to look at individual commits.
|
||||
|
||||
- In addition, please reply to each comment. Each reply should be either "Done" or a response explaining why the corresponding suggestion wasn't implemented. All comments must be resolved before LGTM can be given.
|
||||
- In addition, please reply to each comment. Each reply should be either "Done" or a response explaining why the corresponding suggestion wasn't implemented. All comments must be resolved before LGTM can be given.
|
||||
|
||||
- Resolve any merge conflicts that arise. To resolve conflicts between 'your-branch-name' (in your fork) and 'master' (in the ``python-telegram-bot`` repository), run:
|
||||
|
||||
@@ -150,6 +151,52 @@ Here's how to make a one-off code change.
|
||||
|
||||
7. **Celebrate.** Congratulations, you have contributed to ``python-telegram-bot``!
|
||||
|
||||
Check-list for PRs
|
||||
------------------
|
||||
|
||||
This checklist is a non-exhaustive reminder of things that should be done before a PR is merged, both for you as contributor and for the maintainers.
|
||||
Feel free to copy (parts of) the checklist to the PR description to remind you or the maintainers of open points or if you have questions on anything.
|
||||
|
||||
- Added ``.. versionadded:: NEXT.VERSION``, ``.. versionchanged:: NEXT.VERSION`` or ``.. deprecated:: NEXT.VERSION`` to the docstrings for user facing changes (for methods/class descriptions, arguments and attributes)
|
||||
- Created new or adapted existing unit tests
|
||||
- Documented code changes according to the `CSI standard <https://standards.mousepawmedia.com/en/stable/csi.html>`__
|
||||
- Added myself alphabetically to ``AUTHORS.rst`` (optional)
|
||||
- Added new classes & modules to the docs and all suitable ``__all__`` s
|
||||
- Checked the `Stability Policy <https://docs.python-telegram-bot.org/stability_policy.html>`_ in case of deprecations or changes to documented behavior
|
||||
|
||||
**If the PR contains API changes (otherwise, you can ignore this passage)**
|
||||
|
||||
- Checked the Bot API specific sections of the `Stability Policy <https://docs.python-telegram-bot.org/stability_policy.html>`_
|
||||
- Created a PR to remove functionality deprecated in the previous Bot API release (`see here <https://docs.python-telegram-bot.org/en/stable/stability_policy.html#case-2>`_)
|
||||
|
||||
- New classes:
|
||||
|
||||
- Added ``self._id_attrs`` and corresponding documentation
|
||||
- ``__init__`` accepts ``api_kwargs`` as kw-only
|
||||
|
||||
- Added new shortcuts:
|
||||
|
||||
- In :class:`~telegram.Chat` & :class:`~telegram.User` for all methods that accept ``chat/user_id``
|
||||
- In :class:`~telegram.Message` for all methods that accept ``chat_id`` and ``message_id``
|
||||
- For new :class:`~telegram.Message` shortcuts: Added ``quote`` argument if methods accepts ``reply_to_message_id``
|
||||
- In :class:`~telegram.CallbackQuery` for all methods that accept either ``chat_id`` and ``message_id`` or ``inline_message_id``
|
||||
|
||||
- If relevant:
|
||||
|
||||
- Added new constants at :mod:`telegram.constants` and shortcuts to them as class variables
|
||||
- Link new and existing constants in docstrings instead of hard-coded numbers and strings
|
||||
- Add new message types to :attr:`telegram.Message.effective_attachment`
|
||||
- Added new handlers for new update types
|
||||
|
||||
- Add the handlers to the warning loop in the :class:`~telegram.ext.ConversationHandler`
|
||||
|
||||
- Added new filters for new message (sub)types
|
||||
- Added or updated documentation for the changed class(es) and/or method(s)
|
||||
- Added the new method(s) to ``_extbot.py``
|
||||
- Added or updated ``bot_methods.rst``
|
||||
- Updated the Bot API version number in all places: ``README.rst`` and ``README_RAW.rst`` (including the badge), as well as ``telegram.constants.BOT_API_VERSION_INFO``
|
||||
- Added logic for arbitrary callback data in :class:`telegram.ext.ExtBot` for new methods that either accept a ``reply_markup`` in some form or have a return type that is/contains :class:`~telegram.Message`
|
||||
|
||||
Documenting
|
||||
===========
|
||||
|
||||
@@ -228,25 +275,6 @@ callable we prefer that the call also uses keyword arg syntax. For example:
|
||||
This gives us the flexibility to re-order arguments and more importantly
|
||||
to add new required arguments. It's also more explicit and easier to read.
|
||||
|
||||
Properly defining optional arguments
|
||||
------------------------------------
|
||||
|
||||
It's always good to not initialize optional arguments at class creation,
|
||||
instead use ``**kwargs`` to get them. It's well known Telegram API can
|
||||
change without notice, in that case if a new argument is added it won't
|
||||
break the API classes. For example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# GOOD
|
||||
def __init__(self, id, name, last_name=None, **kwargs):
|
||||
self.last_name = last_name
|
||||
|
||||
|
||||
# BAD
|
||||
def __init__(self, id, name, last_name=None):
|
||||
self.last_name = last_name
|
||||
|
||||
|
||||
.. _`Code of Conduct`: https://www.python.org/psf/conduct/
|
||||
.. _`issue tracker`: https://github.com/python-telegram-bot/python-telegram-bot/issues
|
||||
@@ -266,3 +294,4 @@ break the API classes. For example:
|
||||
.. _`CSI`: https://standards.mousepawmedia.com/en/stable/csi.html
|
||||
.. _`section`: #documenting
|
||||
.. _`testing page`: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/tests/README.rst
|
||||
.. _`below`: #check-list-for-prs
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
# Config file for workflows/labelling.yml
|
||||
|
||||
version: 1
|
||||
|
||||
labels:
|
||||
- label: "dependencies"
|
||||
authors: ["dependabot[bot]", "pre-commit-ci[bot]"]
|
||||
- label: "code quality ✨"
|
||||
authors: ["pre-commit-ci[bot]"]
|
||||
@@ -1,38 +1,6 @@
|
||||
<!--
|
||||
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).
|
||||
Hey! You're PRing? Cool!
|
||||
Please be sure to check out our contribution guide (https://github.com/python-telegram-bot/python-telegram-bot/blob/master/.github/CONTRIBUTING.rst).
|
||||
Especially, please have a look at the check list for PRs (https://github.com/python-telegram-bot/python-telegram-bot/blob/master/.github/CONTRIBUTING.rst#check-list-for-prs). Feel free to copy (parts of) the checklist to the PR description to remind you or the maintainers of open points or if you have questions on anything.
|
||||
-->
|
||||
|
||||
### 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
|
||||
- [ ] Documented code changes according to the [CSI standard](https://standards.mousepawmedia.com/en/stable/csi.html)
|
||||
- [ ] Added myself alphabetically to `AUTHORS.rst` (optional)
|
||||
- [ ] Added new classes & modules to the docs and all suitable `__all__` s
|
||||
|
||||
|
||||
### If the PR contains API changes (otherwise, you can delete this passage)
|
||||
|
||||
* New classes:
|
||||
- [ ] Added `self._id_attrs` and corresponding documentation
|
||||
- [ ] `__init__` accepts `api_kwargs` as kw-only
|
||||
|
||||
* 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
|
||||
- [ ] Link new and existing constants in docstrings instead of hard coded number and strings
|
||||
- [ ] Add new message types to `Message.effective_attachment`
|
||||
- [ ] Added new handlers for new update types
|
||||
- [ ] Add the handlers to the warning loop in the `ConversationHandler`
|
||||
- [ ] Added new filters for new message (sub)types
|
||||
- [ ] Added or updated documentation for the changed class(es) and/or method(s)
|
||||
- [ ] Added the new method(s) to `_extbot.py`
|
||||
- [ ] Added or updated `bot_methods.rst`
|
||||
- [ ] Updated the Bot API version number in all places: `README.rst` and `README_RAW.rst` (including the badge), as well as `telegram.constants.BOT_API_VERSION_INFO`
|
||||
- [ ] Added logic for arbitrary callback data in `tg.ext.Bot` for new methods that either accept a `reply_markup` in some form or have a return type that is/contains `telegram.Message`
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
name: Process Dependabot PRs
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, reopened]
|
||||
|
||||
jobs:
|
||||
process-dependabot-prs:
|
||||
permissions:
|
||||
pull-requests: read
|
||||
contents: write
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.pull_request.user.login == 'dependabot[bot]' }}
|
||||
steps:
|
||||
|
||||
- name: Fetch Dependabot metadata
|
||||
id: dependabot-metadata
|
||||
uses: dependabot/fetch-metadata@v1.6.1
|
||||
|
||||
- uses: actions/checkout@v3.5.2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.ref }}
|
||||
|
||||
- name: Update Version Number in Other Files
|
||||
uses: jacobtomlinson/gha-find-replace@v3
|
||||
with:
|
||||
find: ${{ steps.dependabot-metadata.outputs.previous-version }}
|
||||
replace: ${{ steps.dependabot-metadata.outputs.new-version }}
|
||||
regex: false
|
||||
exclude: CHANGES.rst
|
||||
|
||||
- name: Commit & Push Changes to PR
|
||||
uses: EndBug/add-and-commit@v9.1.3
|
||||
with:
|
||||
message: 'Update version number in other files'
|
||||
committer_name: GitHub Actions
|
||||
committer_email: 41898282+github-actions[bot]@users.noreply.github.com
|
||||
@@ -0,0 +1,17 @@
|
||||
name: PR Labeler
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
pre-commit-ci:
|
||||
permissions:
|
||||
contents: read # for srvaroa/labeler to read config file
|
||||
pull-requests: write # for srvaroa/labeler to add labels in PR
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: srvaroa/labeler@v1.6.1
|
||||
# Config file at .github/labeler.yml
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
@@ -8,7 +8,7 @@ jobs:
|
||||
lock:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/lock-threads@v4.0.0
|
||||
- uses: dessant/lock-threads@v4.0.1
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
issue-inactive-days: '7'
|
||||
|
||||
@@ -7,7 +7,7 @@ jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v7
|
||||
- uses: actions/stale@v8
|
||||
with:
|
||||
# PRs never get stale
|
||||
days-before-stale: 3
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -22,7 +22,7 @@ jobs:
|
||||
cache-dependency-path: '**/requirements*.txt'
|
||||
- name: Install Pyright
|
||||
run: |
|
||||
python -W ignore -m pip install pyright~=1.1.291
|
||||
python -W ignore -m pip install pyright~=1.1.316
|
||||
- name: Get PR Completeness
|
||||
# Must run before base completeness, as base completeness will checkout the base branch
|
||||
# And we can't go back to the PR branch after that in case the PR is coming from a fork
|
||||
@@ -49,21 +49,21 @@ jobs:
|
||||
pr = float(
|
||||
json.load(open("pr.json", "rb"))["typeCompleteness"]["completenessScore"]
|
||||
)
|
||||
base_text = f"After this PR, type completeness will be {round(pr, 3)}."
|
||||
if pr < (base - 0.1):
|
||||
text = f"This PR decreases type completeness by {round(base - pr, 3)}. ❌"
|
||||
base_text = f"This PR changes type completeness from {round(base, 3)} to {round(pr, 3)}."
|
||||
if pr < (base - 0.001):
|
||||
text = f"{base_text} ❌"
|
||||
set_summary(text)
|
||||
print(Path("pr.readable").read_text(encoding="utf-8"))
|
||||
error(f"{text}\n{base_text}")
|
||||
error(text)
|
||||
exit(1)
|
||||
elif pr > (base + 0.1):
|
||||
text = f"This PR increases type completeness by {round(pr - base, 3)}. ✨"
|
||||
elif pr > (base + 0.001):
|
||||
text = f"{base_text} ✨"
|
||||
set_summary(text)
|
||||
if pr < 1:
|
||||
print(Path("pr.readable").read_text(encoding="utf-8"))
|
||||
print(f"{text}\n{base_text}")
|
||||
print(text)
|
||||
else:
|
||||
text = f"This PR does not change type completeness by more than 0.1. ✅"
|
||||
text = f"{base_text} This is less than 0.1 percentage points. ✅"
|
||||
set_summary(text)
|
||||
print(Path("pr.readable").read_text(encoding="utf-8"))
|
||||
print(f"{text}\n{base_text}")
|
||||
print(text)
|
||||
|
||||
+23
-26
@@ -3,24 +3,21 @@
|
||||
ci:
|
||||
autofix_prs: false
|
||||
autoupdate_schedule: monthly
|
||||
# We currently only need this behavior on the v13.x branch were we have the vendored urllib
|
||||
# TODO: Remove once we discontinue v13
|
||||
submodules: true
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 23.1.0
|
||||
rev: 23.7.0
|
||||
hooks:
|
||||
- id: black
|
||||
args:
|
||||
- --diff
|
||||
- --check
|
||||
- repo: https://github.com/PyCQA/flake8
|
||||
rev: 6.0.0
|
||||
rev: 6.1.0
|
||||
hooks:
|
||||
- id: flake8
|
||||
- repo: https://github.com/PyCQA/pylint
|
||||
rev: v2.16.4
|
||||
rev: v3.0.0a6
|
||||
hooks:
|
||||
- id: pylint
|
||||
files: ^(telegram|examples)/.*\.py$
|
||||
@@ -31,14 +28,14 @@ repos:
|
||||
- --jobs=0
|
||||
|
||||
additional_dependencies:
|
||||
- httpx~=0.23.3
|
||||
- httpx~=0.24.1
|
||||
- tornado~=6.2
|
||||
- APScheduler~=3.10.1
|
||||
- cachetools~=5.3.0
|
||||
- aiolimiter~=1.0.0
|
||||
- APScheduler~=3.10.4
|
||||
- cachetools~=5.3.1
|
||||
- aiolimiter~=1.1.0
|
||||
- . # this basically does `pip install -e .`
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v1.0.1
|
||||
rev: v1.4.1
|
||||
hooks:
|
||||
- id: mypy
|
||||
name: mypy-ptb
|
||||
@@ -47,11 +44,11 @@ repos:
|
||||
- types-pytz
|
||||
- types-cryptography
|
||||
- types-cachetools
|
||||
- httpx~=0.23.3
|
||||
- httpx~=0.24.1
|
||||
- tornado~=6.2
|
||||
- APScheduler~=3.10.1
|
||||
- cachetools~=5.3.0
|
||||
- aiolimiter~=1.0.0
|
||||
- APScheduler~=3.10.4
|
||||
- cachetools~=5.3.1
|
||||
- aiolimiter~=1.1.0
|
||||
- . # this basically does `pip install -e .`
|
||||
- id: mypy
|
||||
name: mypy-examples
|
||||
@@ -61,16 +58,16 @@ repos:
|
||||
- --follow-imports=silent
|
||||
additional_dependencies:
|
||||
- tornado~=6.2
|
||||
- APScheduler~=3.10.1
|
||||
- cachetools~=5.3.0
|
||||
- APScheduler~=3.10.4
|
||||
- cachetools~=5.3.1
|
||||
- . # this basically does `pip install -e .`
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v3.3.1
|
||||
rev: v3.10.1
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
files: ^(telegram|examples|tests|docs)/.*\.py$
|
||||
args:
|
||||
- --py37-plus
|
||||
- --py38-plus
|
||||
- repo: https://github.com/pycqa/isort
|
||||
rev: 5.12.0
|
||||
hooks:
|
||||
@@ -79,15 +76,15 @@ repos:
|
||||
args:
|
||||
- --diff
|
||||
- --check
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
rev: 'v0.0.254'
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: 'v0.0.281'
|
||||
hooks:
|
||||
- id: ruff
|
||||
name: ruff
|
||||
files: ^(telegram|examples)/.*\.py$
|
||||
files: ^(telegram|examples|tests)/.*\.py$
|
||||
additional_dependencies:
|
||||
- httpx~=0.23.3
|
||||
- httpx~=0.24.1
|
||||
- tornado~=6.2
|
||||
- APScheduler~=3.10.1
|
||||
- cachetools~=5.3.0
|
||||
- aiolimiter~=1.0.0
|
||||
- APScheduler~=3.10.4
|
||||
- cachetools~=5.3.1
|
||||
- aiolimiter~=1.1.0
|
||||
|
||||
@@ -21,9 +21,11 @@ Contributors
|
||||
|
||||
The following wonderful people contributed directly or indirectly to this project:
|
||||
|
||||
- `Abdelrahman <https://github.com/aelkheir>`_
|
||||
- `Abshar <https://github.com/abxhr>`_
|
||||
- `Alateas <https://github.com/alateas>`_
|
||||
- `Ales Dokshanin <https://github.com/alesdokshanin>`_
|
||||
- `Alizia <https://github.com/thefunkycat>`_
|
||||
- `Ambro17 <https://github.com/Ambro17>`_
|
||||
- `Andrej Zhilenkov <https://github.com/Andrej730>`_
|
||||
- `Anton Tagunov <https://github.com/anton-tagunov>`_
|
||||
@@ -56,6 +58,7 @@ The following wonderful people contributed directly or indirectly to this projec
|
||||
- `Harshil <https://github.com/harshil21>`_
|
||||
- `Hugo Damer <https://github.com/HakimusGIT>`_
|
||||
- `ihoru <https://github.com/ihoru>`_
|
||||
- `Iulian Onofrei <https://github.com/revolter>`_
|
||||
- `Jasmin Bom <https://github.com/jsmnbom>`_
|
||||
- `JASON0916 <https://github.com/JASON0916>`_
|
||||
- `jeffffc <https://github.com/jeffffc>`_
|
||||
@@ -72,10 +75,12 @@ The following wonderful people contributed directly or indirectly to this projec
|
||||
- `Li-aung Yip <https://github.com/LiaungYip>`_
|
||||
- `Loo Zheng Yuan <https://github.com/loozhengyuan>`_
|
||||
- `LRezende <https://github.com/lrezende>`_
|
||||
- `Luca Bellanti <https://github.com/Trifase>`_
|
||||
- `macrojames <https://github.com/macrojames>`_
|
||||
- `Matheus Lemos <https://github.com/mlemosf>`_
|
||||
- `Michael Dix <https://github.com/Eisberge>`_
|
||||
- `Michael Elovskikh <https://github.com/wronglink>`_
|
||||
- `Miguel C. R. <https://github.com/MiguelX413>`_
|
||||
- `miles <https://github.com/miles170>`_
|
||||
- `Mischa Krüger <https://github.com/Makman2>`_
|
||||
- `naveenvhegde <https://github.com/naveenvhegde>`_
|
||||
@@ -116,6 +121,7 @@ The following wonderful people contributed directly or indirectly to this projec
|
||||
- `Wagner Macedo <https://github.com/wagnerluis1982>`_
|
||||
- `wjt <https://github.com/wjt>`_
|
||||
- `Yaw Danso <https://github.com/dglitxh>`_
|
||||
- `Yao Kuan <https://github.com/thatguylah>`_
|
||||
- `zeroone2numeral2 <https://github.com/zeroone2numeral2>`_
|
||||
- `zeshuaro <https://github.com/zeshuaro>`_
|
||||
- `zpavloudis <https://github.com/zpavloudis>`_
|
||||
|
||||
+796
-1380
File diff suppressed because it is too large
Load Diff
+19
-19
@@ -14,7 +14,7 @@
|
||||
:target: https://pypi.org/project/python-telegram-bot/
|
||||
:alt: Supported Python versions
|
||||
|
||||
.. image:: https://img.shields.io/badge/Bot%20API-6.6-blue?logo=telegram
|
||||
.. image:: https://img.shields.io/badge/Bot%20API-6.8-blue?logo=telegram
|
||||
:target: https://core.telegram.org/bots/api-changelog
|
||||
:alt: Supported Bot API versions
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
: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
|
||||
.. image:: https://github.com/python-telegram-bot/python-telegram-bot/workflows/Unit%20Tests/badge.svg
|
||||
:target: https://github.com/python-telegram-bot/python-telegram-bot/
|
||||
:alt: Github Actions workflow
|
||||
|
||||
@@ -46,8 +46,8 @@
|
||||
:target: https://app.codacy.com/gh/python-telegram-bot/python-telegram-bot/dashboard
|
||||
:alt: Code quality: Codacy
|
||||
|
||||
.. image:: https://deepsource.io/gh/python-telegram-bot/python-telegram-bot.svg/?label=active+issues
|
||||
:target: https://deepsource.io/gh/python-telegram-bot/python-telegram-bot/?ref=repository-badge
|
||||
.. image:: https://app.deepsource.com/gh/python-telegram-bot/python-telegram-bot.svg/?label=active+issues
|
||||
:target: https://app.deepsource.com/gh/python-telegram-bot/python-telegram-bot/?ref=repository-badge
|
||||
:alt: Code quality: DeepSource
|
||||
|
||||
.. image:: https://results.pre-commit.ci/badge/github/python-telegram-bot/python-telegram-bot/master.svg
|
||||
@@ -77,7 +77,7 @@ Introduction
|
||||
|
||||
This library provides a pure Python, asynchronous interface for the
|
||||
`Telegram Bot API <https://core.telegram.org/bots/api>`_.
|
||||
It's compatible with Python versions **3.7+**.
|
||||
It's compatible with Python versions **3.8+**.
|
||||
|
||||
In addition to the pure API implementation, this library features a number of high-level classes to
|
||||
make the development of bots easy and straightforward. These classes are contained in the
|
||||
@@ -93,7 +93,7 @@ Installing both ``python-telegram-bot`` and ``python-telegram-bot-raw`` in conju
|
||||
Telegram API support
|
||||
====================
|
||||
|
||||
All types and methods of the Telegram Bot API **6.6** are supported.
|
||||
All types and methods of the Telegram Bot API **6.8** are supported.
|
||||
|
||||
Installing
|
||||
==========
|
||||
@@ -135,7 +135,7 @@ As these features are *optional*, the corresponding 3rd party dependencies are n
|
||||
Instead, they are listed as optional dependencies.
|
||||
This allows to avoid unnecessary dependency conflicts for users who don't need the optional features.
|
||||
|
||||
The only required dependency is `httpx ~= 0.23.3 <https://www.python-httpx.org>`_ for
|
||||
The only required dependency is `httpx ~= 0.24.1 <https://www.python-httpx.org>`_ for
|
||||
``telegram.request.HTTPXRequest``, the default networking backend.
|
||||
|
||||
``python-telegram-bot`` is most useful when used along with additional libraries.
|
||||
@@ -148,26 +148,26 @@ Optional Dependencies
|
||||
|
||||
PTB can be installed with optional dependencies:
|
||||
|
||||
* ``pip install python-telegram-bot[passport]`` installs the `cryptography>=39.0.1 <https://cryptography.io/en/stable>`_ library. Use this, if you want to use Telegram Passport related functionality.
|
||||
* ``pip install python-telegram-bot[socks]`` installs `httpx[socks] <https://www.python-httpx.org/#dependencies>`_. Use this, if you want to work behind a Socks5 server.
|
||||
* ``pip install python-telegram-bot[http2]`` installs `httpx[http2] <https://www.python-httpx.org/#dependencies>`_. Use this, if you want to use HTTP/2.
|
||||
* ``pip install python-telegram-bot[rate-limiter]`` installs `aiolimiter~=1.0.0 <https://aiolimiter.readthedocs.io/en/stable/>`_. Use this, if you want to use ``telegram.ext.AIORateLimiter``.
|
||||
* ``pip install python-telegram-bot[webhooks]`` installs the `tornado~=6.2 <https://www.tornadoweb.org/en/stable/>`_ library. Use this, if you want to use ``telegram.ext.Updater.start_webhook``/``telegram.ext.Application.run_webhook``.
|
||||
* ``pip install python-telegram-bot[callback-data]`` installs the `cachetools~=5.3.0 <https://cachetools.readthedocs.io/en/latest/>`_ library. Use this, if you want to use `arbitrary callback_data <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Arbitrary-callback_data>`_.
|
||||
* ``pip install python-telegram-bot[job-queue]`` installs the `APScheduler~=3.10.1 <https://apscheduler.readthedocs.io/en/3.x/>`_ library and enforces `pytz>=2018.6 <https://pypi.org/project/pytz/>`_, where ``pytz`` is a dependency of ``APScheduler``. Use this, if you want to use the ``telegram.ext.JobQueue``.
|
||||
* ``pip install "python-telegram-bot[passport]"`` installs the `cryptography>=39.0.1 <https://cryptography.io/en/stable>`_ library. Use this, if you want to use Telegram Passport related functionality.
|
||||
* ``pip install "python-telegram-bot[socks]"`` installs `httpx[socks] <https://www.python-httpx.org/#dependencies>`_. Use this, if you want to work behind a Socks5 server.
|
||||
* ``pip install "python-telegram-bot[http2]"`` installs `httpx[http2] <https://www.python-httpx.org/#dependencies>`_. Use this, if you want to use HTTP/2.
|
||||
* ``pip install "python-telegram-bot[rate-limiter]"`` installs `aiolimiter~=1.1.0 <https://aiolimiter.readthedocs.io/en/stable/>`_. Use this, if you want to use ``telegram.ext.AIORateLimiter``.
|
||||
* ``pip install "python-telegram-bot[webhooks]"`` installs the `tornado~=6.2 <https://www.tornadoweb.org/en/stable/>`_ library. Use this, if you want to use ``telegram.ext.Updater.start_webhook``/``telegram.ext.Application.run_webhook``.
|
||||
* ``pip install "python-telegram-bot[callback-data]"`` installs the `cachetools~=5.3.1 <https://cachetools.readthedocs.io/en/latest/>`_ library. Use this, if you want to use `arbitrary callback_data <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Arbitrary-callback_data>`_.
|
||||
* ``pip install "python-telegram-bot[job-queue]"`` installs the `APScheduler~=3.10.4 <https://apscheduler.readthedocs.io/en/3.x/>`_ library and enforces `pytz>=2018.6 <https://pypi.org/project/pytz/>`_, where ``pytz`` is a dependency of ``APScheduler``. Use this, if you want to use the ``telegram.ext.JobQueue``.
|
||||
|
||||
To install multiple optional dependencies, separate them by commas, e.g. ``pip install python-telegram-bot[socks,webhooks]``.
|
||||
To install multiple optional dependencies, separate them by commas, e.g. ``pip install "python-telegram-bot[socks,webhooks]"``.
|
||||
|
||||
Additionally, two shortcuts are provided:
|
||||
|
||||
* ``pip install python-telegram-bot[all]`` installs all optional dependencies.
|
||||
* ``pip install python-telegram-bot[ext]`` installs all optional dependencies that are related to ``telegram.ext``, i.e. ``[rate-limiter, webhooks, callback-data, job-queue]``.
|
||||
* ``pip install "python-telegram-bot[all]"`` installs all optional dependencies.
|
||||
* ``pip install "python-telegram-bot[ext]"`` installs all optional dependencies that are related to ``telegram.ext``, i.e. ``[rate-limiter, webhooks, callback-data, job-queue]``.
|
||||
|
||||
Quick Start
|
||||
===========
|
||||
|
||||
Our Wiki contains an `Introduction to the API <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Introduction-to-the-API>`_ explaining how the pure Bot API can be accessed via ``python-telegram-bot``.
|
||||
Moreover, the `Tutorial: Your first Bot <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Extensions-%E2%80%93-Your-first-Bot>`_ gives an introduction on how chatbots can be easily programmed with the help of the ``telegram.ext`` module.
|
||||
Moreover, the `Tutorial: Your first Bot <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Extensions---Your-first-Bot>`_ gives an introduction on how chatbots can be easily programmed with the help of the ``telegram.ext`` module.
|
||||
|
||||
Resources
|
||||
=========
|
||||
@@ -209,7 +209,7 @@ 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 or feature requests <https://github.com/python-telegram-bot/python-telegram-bot/issues/new>`_.
|
||||
You can also help by `reporting bugs or feature requests <https://github.com/python-telegram-bot/python-telegram-bot/issues/new/choose>`_.
|
||||
|
||||
Donating
|
||||
========
|
||||
|
||||
+13
-13
@@ -14,7 +14,7 @@
|
||||
:target: https://pypi.org/project/python-telegram-bot-raw/
|
||||
:alt: Supported Python versions
|
||||
|
||||
.. image:: https://img.shields.io/badge/Bot%20API-6.6-blue?logo=telegram
|
||||
.. image:: https://img.shields.io/badge/Bot%20API-6.8-blue?logo=telegram
|
||||
:target: https://core.telegram.org/bots/api-changelog
|
||||
:alt: Supported Bot API versions
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
: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
|
||||
.. image:: https://github.com/python-telegram-bot/python-telegram-bot/workflows/Unit%20Tests/badge.svg
|
||||
:target: https://github.com/python-telegram-bot/python-telegram-bot/
|
||||
:alt: Github Actions workflow
|
||||
|
||||
@@ -46,8 +46,8 @@
|
||||
:target: https://app.codacy.com/gh/python-telegram-bot/python-telegram-bot/dashboard
|
||||
:alt: Code quality: Codacy
|
||||
|
||||
.. image:: https://deepsource.io/gh/python-telegram-bot/python-telegram-bot.svg/?label=active+issues
|
||||
:target: https://deepsource.io/gh/python-telegram-bot/python-telegram-bot/?ref=repository-badge
|
||||
.. image:: https://app.deepsource.com/gh/python-telegram-bot/python-telegram-bot.svg/?label=active+issues
|
||||
:target: https://app.deepsource.com/gh/python-telegram-bot/python-telegram-bot/?ref=repository-badge
|
||||
:alt: Code quality: DeepSource
|
||||
|
||||
.. image:: https://results.pre-commit.ci/badge/github/python-telegram-bot/python-telegram-bot/master.svg
|
||||
@@ -77,7 +77,7 @@ Introduction
|
||||
|
||||
This library provides a pure Python, asynchronous interface for the
|
||||
`Telegram Bot API <https://core.telegram.org/bots/api>`_.
|
||||
It's compatible with Python versions **3.7+**.
|
||||
It's compatible with Python versions **3.8+**.
|
||||
|
||||
``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.
|
||||
|
||||
@@ -89,7 +89,7 @@ Installing both ``python-telegram-bot`` and ``python-telegram-bot-raw`` in conju
|
||||
Telegram API support
|
||||
====================
|
||||
|
||||
All types and methods of the Telegram Bot API **6.6** are supported.
|
||||
All types and methods of the Telegram Bot API **6.8** are supported.
|
||||
|
||||
Installing
|
||||
==========
|
||||
@@ -136,7 +136,7 @@ As these features are *optional*, the corresponding 3rd party dependencies are n
|
||||
Instead, they are listed as optional dependencies.
|
||||
This allows to avoid unnecessary dependency conflicts for users who don't need the optional features.
|
||||
|
||||
The only required dependency is `httpx ~= 0.23.3 <https://www.python-httpx.org>`_ for
|
||||
The only required dependency is `httpx ~= 0.24.1 <https://www.python-httpx.org>`_ for
|
||||
``telegram.request.HTTPXRequest``, the default networking backend.
|
||||
|
||||
``python-telegram-bot`` is most useful when used along with additional libraries.
|
||||
@@ -149,13 +149,13 @@ Optional Dependencies
|
||||
|
||||
PTB can be installed with optional dependencies:
|
||||
|
||||
* ``pip install python-telegram-bot-raw[passport]`` installs the `cryptography>=39.0.1 <https://cryptography.io/en/stable>`_ library. Use this, if you want to use Telegram Passport related functionality.
|
||||
* ``pip install python-telegram-bot-raw[socks]`` installs `httpx[socks] <https://www.python-httpx.org/#dependencies>`_. Use this, if you want to work behind a Socks5 server.
|
||||
* ``pip install python-telegram-bot[http2]`` installs `httpx[http2] <https://www.python-httpx.org/#dependencies>`_. Use this, if you want to use HTTP/2.
|
||||
* ``pip install "python-telegram-bot-raw[passport]"`` installs the `cryptography>=39.0.1 <https://cryptography.io/en/stable>`_ library. Use this, if you want to use Telegram Passport related functionality.
|
||||
* ``pip install "python-telegram-bot-raw[socks]"`` installs `httpx[socks] <https://www.python-httpx.org/#dependencies>`_. Use this, if you want to work behind a Socks5 server.
|
||||
* ``pip install "python-telegram-bot-raw[http2]"`` installs `httpx[http2] <https://www.python-httpx.org/#dependencies>`_. Use this, if you want to use HTTP/2.
|
||||
|
||||
To install multiple optional dependencies, separate them by commas, e.g. ``pip install python-telegram-bot-raw[passport,socks]``.
|
||||
To install multiple optional dependencies, separate them by commas, e.g. ``pip install "python-telegram-bot-raw[passport,socks]"``.
|
||||
|
||||
Additionally, the shortcut ``pip install python-telegram-bot-raw[all]`` installs all optional dependencies.
|
||||
Additionally, the shortcut ``pip install "python-telegram-bot-raw[all]"`` installs all optional dependencies.
|
||||
|
||||
Quick Start
|
||||
===========
|
||||
@@ -195,7 +195,7 @@ 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 or feature requests <https://github.com/python-telegram-bot/python-telegram-bot/issues/new>`_.
|
||||
You can also help by `reporting bugs or feature requests <https://github.com/python-telegram-bot/python-telegram-bot/issues/new/choose>`_.
|
||||
|
||||
Donating
|
||||
========
|
||||
|
||||
@@ -174,8 +174,7 @@ class AdmonitionInserter:
|
||||
break
|
||||
|
||||
for line in lines_with_attrs:
|
||||
line_match = attr_docstr_pattern.match(line)
|
||||
if not line_match:
|
||||
if not (line_match := attr_docstr_pattern.match(line)):
|
||||
continue
|
||||
|
||||
target_attr = line_match.group("attr_name")
|
||||
@@ -529,7 +528,11 @@ class AdmonitionInserter:
|
||||
# For custom generics like telegram.ext._application.Application[~BT, ~CCT, ~UD...].
|
||||
# This must come before the check for isinstance(type) because GenericAlias can also be
|
||||
# recognized as type if it belongs to <class 'types.GenericAlias'>.
|
||||
elif str(type(arg)) in ("<class 'typing._GenericAlias'>", "<class 'types.GenericAlias'>"):
|
||||
elif str(type(arg)) in (
|
||||
"<class 'typing._GenericAlias'>",
|
||||
"<class 'types.GenericAlias'>",
|
||||
"<class 'typing._LiteralGenericAlias'>",
|
||||
):
|
||||
if "telegram" in str(arg):
|
||||
# get_origin() of telegram.ext._application.Application[~BT, ~CCT, ~UD...]
|
||||
# will produce <class 'telegram.ext._application.Application'>
|
||||
|
||||
@@ -42,7 +42,7 @@ keyword_args = [
|
||||
]
|
||||
write_timeout_sub = [":attr:`~telegram.request.BaseRequest.DEFAULT_NONE`", "``20``"]
|
||||
read_timeout_sub = [
|
||||
":attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.",
|
||||
":attr:`~telegram.request.BaseRequest.DEFAULT_NONE`",
|
||||
"``2``. :paramref:`timeout` will be added to this value",
|
||||
]
|
||||
read_timeout_type = [":obj:`float` | :obj:`None`", ":obj:`float`"]
|
||||
|
||||
@@ -189,8 +189,10 @@ def autodoc_process_bases(app, name, obj, option, bases: list):
|
||||
bases[idx] = f":class:`{base}`"
|
||||
|
||||
# Now convert `telegram._message.Message` to `telegram.Message` etc
|
||||
match = re.search(pattern=r"(telegram(\.ext|))\.[_\w\.]+", string=base)
|
||||
if not match or "_utils" in base:
|
||||
if (
|
||||
not (match := re.search(pattern=r"(telegram(\.ext|))\.[_\w\.]+", string=base))
|
||||
or "_utils" in base
|
||||
):
|
||||
continue
|
||||
|
||||
parts = match.group(0).split(".")
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
sphinx==6.1.3
|
||||
sphinx==7.2.5
|
||||
sphinx-pypi-upload
|
||||
furo==2023.3.23
|
||||
git+https://github.com/harshil21/furo-sphinx-search@01efc7be422d7dc02390aab9be68d6f5ce1a5618#egg=furo-sphinx-search
|
||||
sphinx-paramlinks==0.5.4
|
||||
sphinxcontrib-mermaid==0.8.1
|
||||
sphinx-copybutton==0.5.1
|
||||
furo==2023.8.19
|
||||
git+https://github.com/harshil21/furo-sphinx-search@v0.2.0.1
|
||||
sphinx-paramlinks==0.6.0
|
||||
sphinxcontrib-mermaid==0.9.2
|
||||
sphinx-copybutton==0.5.2
|
||||
sphinx-inline-tabs==2023.4.21
|
||||
|
||||
+8
-3
@@ -21,9 +21,9 @@ author = "Leandro Toledo"
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = "20.2" # telegram.__version__[:3]
|
||||
version = "20.5" # telegram.__version__[:3]
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = "20.2" # telegram.__version__
|
||||
release = "20.5" # telegram.__version__
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
needs_sphinx = "6.1.3"
|
||||
@@ -39,12 +39,17 @@ extensions = [
|
||||
"sphinx.ext.extlinks",
|
||||
"sphinx_paramlinks",
|
||||
"sphinx_copybutton",
|
||||
"sphinx_inline_tabs",
|
||||
"sphinxcontrib.mermaid",
|
||||
"sphinx_search.extension",
|
||||
]
|
||||
|
||||
# For shorter links to Wiki in docstrings
|
||||
extlinks = {"wiki": ("https://github.com/python-telegram-bot/python-telegram-bot/wiki/%s", "%s")}
|
||||
extlinks = {
|
||||
"wiki": ("https://github.com/python-telegram-bot/python-telegram-bot/wiki/%s", "%s"),
|
||||
"pr": ("https://github.com/python-telegram-bot/python-telegram-bot/pull/%s", "#%s"),
|
||||
"issue": ("https://github.com/python-telegram-bot/python-telegram-bot/issues/%s", "#%s"),
|
||||
}
|
||||
|
||||
# Use intersphinx to reference the python builtin library docs
|
||||
intersphinx_mapping = {
|
||||
|
||||
@@ -1,7 +1,43 @@
|
||||
``customwebhookbot.py``
|
||||
=======================
|
||||
|
||||
.. literalinclude:: ../../examples/customwebhookbot.py
|
||||
:language: python
|
||||
:linenos:
|
||||
This example is available for different web frameworks.
|
||||
You can select your preferred framework by opening one of the tabs above the code example.
|
||||
|
||||
.. hint::
|
||||
|
||||
The following examples show how different Python web frameworks can be used alongside PTB.
|
||||
This can be useful for two use cases:
|
||||
|
||||
1. For extending the functionality of your existing bot to handling updates of external services
|
||||
2. For extending the functionality of your exisiting web application to also include chat bot functionality
|
||||
|
||||
How the PTB and web framework components of the examples below are viewed surely depends on which use case one has in mind.
|
||||
We are fully aware that a combination of PTB with web frameworks will always mean finding a tradeoff between usability and best practices for both PTB and the web framework and these examples are certainly far from optimal solutions.
|
||||
Please understand them as starting points and use your expertise of the web framework of your choosing to build up on them.
|
||||
You are of course also very welcome to help improve these examples!
|
||||
|
||||
.. tab:: ``starlette``
|
||||
|
||||
.. literalinclude:: ../../examples/customwebhookbot/starlettebot.py
|
||||
:language: python
|
||||
:linenos:
|
||||
|
||||
.. tab:: ``flask``
|
||||
|
||||
.. literalinclude:: ../../examples/customwebhookbot/flaskbot.py
|
||||
:language: python
|
||||
:linenos:
|
||||
|
||||
.. tab:: ``quart``
|
||||
|
||||
.. literalinclude:: ../../examples/customwebhookbot/quartbot.py
|
||||
:language: python
|
||||
:linenos:
|
||||
|
||||
.. tab:: ``Django``
|
||||
|
||||
.. literalinclude:: ../../examples/customwebhookbot/djangobot.py
|
||||
:language: python
|
||||
:linenos:
|
||||
|
||||
@@ -8,7 +8,7 @@ aspect of the Telegram Bot API while others focus on one of the
|
||||
mechanics of this library. Except for the
|
||||
:any:`examples.rawapibot` example, they all use the high-level
|
||||
framework this library provides with the
|
||||
:any:`telegram.ext <telegram.ext>` submodule.
|
||||
:mod:`telegram.ext` submodule.
|
||||
|
||||
All examples are licensed under the `CC0
|
||||
License <https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/LICENSE.txt>`__
|
||||
@@ -38,9 +38,8 @@ class to send timed messages. The user sets a timer by using ``/set``
|
||||
command with a specific time, for example ``/set 30``. The bot then sets
|
||||
up a job to send a message to that user after 30 seconds. The user can
|
||||
also cancel the timer by sending ``/unset``. To learn more about the
|
||||
``JobQueue``, read `this wiki
|
||||
article <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Extensions-%E2%80%93-JobQueue>`__.
|
||||
Note: To use ``JobQueue``, you must install PTB via ``pip install python-telegram-bot[job-queue]``
|
||||
``JobQueue``, read `this wiki article <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Extensions---JobQueue>`__.
|
||||
Note: To use ``JobQueue``, you must install PTB via ``pip install "python-telegram-bot[job-queue]"``
|
||||
|
||||
:any:`examples.conversationbot`
|
||||
-------------------------------
|
||||
@@ -116,7 +115,7 @@ Don’t forget to enable and configure payments with
|
||||
`@BotFather <https://telegram.me/BotFather>`_. Check out this
|
||||
`guide <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Telegram-Passport>`__
|
||||
on Telegram passports in PTB.
|
||||
Note: To use Telegram Passport, you must install PTB via ``pip install python-telegram-bot[passport]``
|
||||
Note: To use Telegram Passport, you must install PTB via ``pip install "python-telegram-bot[passport]"``
|
||||
|
||||
:any:`examples.paymentbot`
|
||||
--------------------------
|
||||
@@ -164,7 +163,7 @@ combination with ``telegram.ext.Application``.
|
||||
|
||||
This example showcases how PTBs “arbitrary callback data” feature can be
|
||||
used.
|
||||
Note: To use arbitrary callback data, you must install PTB via ``pip install python-telegram-bot[callback-data]``
|
||||
Note: To use arbitrary callback data, you must install PTB via ``pip install "python-telegram-bot[callback-data]"``
|
||||
|
||||
Pure API
|
||||
--------
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
.. tip::
|
||||
When combining ``python-telegram-bot`` with other :mod:`asyncio` based frameworks, using this
|
||||
method is likely not the best choice, as it blocks the event loop until it receives a stop
|
||||
signal as described above.
|
||||
Instead, you can manually call the methods listed below to start and shut down the application
|
||||
and the :attr:`~telegram.ext.Application.updater`.
|
||||
Keeping the event loop running and listening for a stop signal is then up to you.
|
||||
* When combining ``python-telegram-bot`` with other :mod:`asyncio` based frameworks, using this
|
||||
method is likely not the best choice, as it blocks the event loop until it receives a stop
|
||||
signal as described above.
|
||||
Instead, you can manually call the methods listed below to start and shut down the application
|
||||
and the :attr:`~telegram.ext.Application.updater`.
|
||||
Keeping the event loop running and listening for a stop signal is then up to you.
|
||||
* To gracefully stop the execution of this method from within a handler, job or error callback,
|
||||
use :meth:`~telegram.ext.Application.stop_running`.
|
||||
@@ -196,6 +196,10 @@
|
||||
- Used for setting the short description of the bot
|
||||
* - :meth:`~telegram.Bot.get_my_short_description`
|
||||
- Used for obtaining the short description of the bot
|
||||
* - :meth:`~telegram.Bot.set_my_name`
|
||||
- Used for setting the name of the bot
|
||||
* - :meth:`~telegram.Bot.get_my_name`
|
||||
- Used for obtaining the name of the bot
|
||||
|
||||
.. raw:: html
|
||||
|
||||
@@ -233,7 +237,7 @@
|
||||
- Used for setting the keywords of a sticker
|
||||
* - :meth:`~telegram.Bot.set_sticker_mask_position`
|
||||
- Used for setting the mask position of a mask sticker
|
||||
* - :meth:`~telegram.Bot.set_sticker_set_thumb`
|
||||
* - :meth:`~telegram.Bot.set_sticker_set_thumbnail`
|
||||
- Used for setting the thumbnail of a sticker set
|
||||
* - :meth:`~telegram.Bot.set_custom_emoji_sticker_set_thumbnail`
|
||||
- Used for setting the thumbnail of a custom emoji sticker set
|
||||
@@ -324,6 +328,8 @@
|
||||
- Used to reopen the general topic
|
||||
* - :meth:`~telegram.Bot.unpin_all_forum_topic_messages`
|
||||
- Used to unpin all messages in a forum topic
|
||||
* - :meth:`~telegram.Bot.unpin_all_general_forum_topic_messages`
|
||||
- Used to unpin all messages in the general forum topic
|
||||
|
||||
.. raw:: html
|
||||
|
||||
|
||||
@@ -27,11 +27,12 @@
|
||||
:hidden:
|
||||
:caption: Project
|
||||
|
||||
stability_policy
|
||||
changelog
|
||||
coc
|
||||
contributing
|
||||
testing
|
||||
Website <https://python-telegram-bot.org>
|
||||
GitHub Repository <https://github.com/python-telegram-bot/python-telegram-bot/>
|
||||
Telegram Channel <https://t.me/pythontelegrambotchannel/>
|
||||
Telegram User Group <https://t.me/pythontelegrambotgroup/>
|
||||
coc
|
||||
contributing
|
||||
testing
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
Stability Policy
|
||||
================
|
||||
|
||||
.. important::
|
||||
|
||||
This stability policy is in place since version 20.3.
|
||||
While earlier versions of ``python-telegram-bot`` also had stable interfaces, they had no explicit stability policy and hence did not follow the rules outlined below in all detail.
|
||||
Please also refer to the :ref:`changelog <ptb-changelog>`.
|
||||
|
||||
.. caution::
|
||||
|
||||
Large parts of the :mod:`telegram` package are the Python representations of the Telegram Bot API, whose stability policy PTB can not influence.
|
||||
This policy hence includes some special cases for those parts.
|
||||
|
||||
What does this policy cover?
|
||||
----------------------------
|
||||
|
||||
This policy includes any API or behavior that is covered in this documentation.
|
||||
This covers both the :mod:`telegram` package and the :mod:`telegram.ext` package.
|
||||
|
||||
What doesn't this policy cover?
|
||||
-------------------------------
|
||||
|
||||
Introduction of new features or changes of flavors of comparable behavior (e.g. the default for the HTTP protocol version being used) are not covered by this policy.
|
||||
|
||||
The internal structure of classes in PTB, i.e. things like the result of ``dir(obj))`` or the contents of ``obj.__dict__``, is not covered by this policy.
|
||||
|
||||
Objects are in general not guaranteed to be pickleable (unless stated otherwise) and pickled objects from one version of PTB may not be loadable in future versions.
|
||||
We may provide a way to convert pickled objects from one version to another, but this is not guaranteed.
|
||||
|
||||
Functionality that is part of PTBs API but is explicitly documented as not being intended to be used directly by users (e.g. :meth:`telegram.request.BaseRequest.do_request`) may change.
|
||||
This also applies to functions or attributes marked as final in the sense of `PEP 591 <https://peps.python.org/pep-0591/>`__.
|
||||
|
||||
PTB has dependencies to third-party packages.
|
||||
The versions that PTB uses of these third-party packages may change if that does not affect PTBs public API.
|
||||
|
||||
PTB does not give guarantees about which Python versions are supported.
|
||||
In general, we will try to support all Python versions that have not yet reached their end of life, but we reserve ourselves the option to drop support for Python versions earlier if that benefits the advancement of the library.
|
||||
|
||||
PTB provides static type hints for all public attributes, parameters, return values and generic classes.
|
||||
These type hints are not covered by this policy and may change at any time under the condition that these changes have no impact on the runtime behavior of PTB.
|
||||
|
||||
.. _bot-api-functionality-1:
|
||||
|
||||
Bot API Functionality
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Comparison of equality of instances of the classes in the :mod:`telegram` package is subject to change and the PTB team will update the behavior to best reflect updates in the Bot API.
|
||||
Changes in this regard will be documented in the affected classes.
|
||||
Note that equality comparison with objects that where serialized by an older version of PTB may hence give unexpected results.
|
||||
|
||||
When the order of arguments of the Bot API methods changes or they become optional/mandatory due to changes in the Bot API, PTB will always try to reflect these changes.
|
||||
While we try to make such changes backward compatible, this is not always possible or only with significant effort.
|
||||
In such cases we will find a trade-off between backward compatibility and fully complying with the Bot API, which may result in breaking changes.
|
||||
We highly recommend using keyword arguments, which can help make such changes non-breaking on your end.
|
||||
|
||||
..
|
||||
We have documented a few common cases and possible backwards compatible solutions in the wiki as a reference for the dev team: https://github.com/python-telegram-bot/python-telegram-bot/wiki/Bot-API-Backward-Compatibility
|
||||
|
||||
When the Bot API changes attributes of classes, the method :meth:`telegram.TelegramObject.to_dict` will change as necessary to reflect these changes.
|
||||
In particular, attributes deprecated by Telegram will be removed from the returned dictionary.
|
||||
Deprecated attributes that are still passed by Telegram will be available in the :attr:`~telegram.TelegramObject.api_kwargs` dictionary as long as PTB can support that with feasible effort.
|
||||
Since attributes of the classes in the :mod:`telegram` package are not writable, we may change them to properties where appropriate.
|
||||
|
||||
Development Versions
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Pre-releases marked as alpha, beta or release candidate are not covered by this policy.
|
||||
Before a feature is in a stable release, i.e. the feature was merged into the ``master`` branch but not released yet (or only in a pre-release), it is not covered by this policy either and may change.
|
||||
|
||||
Security
|
||||
~~~~~~~~
|
||||
|
||||
We make exceptions from our stability policy for security.
|
||||
We will violate this policy as necessary in order to resolve a security issue or harden PTB against a possible attack.
|
||||
|
||||
Versioning
|
||||
----------
|
||||
|
||||
PTB uses a versioning scheme that roughly follows `https://semver.org/ <https://semver.org/>`_, although it may not be quite as strict.
|
||||
|
||||
Given a version of PTB X.Y.Z,
|
||||
|
||||
- X indicates the major version number.
|
||||
This is incremented when backward incompatible changes are introduced.
|
||||
- Y indicates the minor version number.
|
||||
This is incremented when new functionality or backward compatible changes are introduced by PTB.
|
||||
*This is also incremented when PTB adds support for a new Bot API version, which may include backward incompatible changes in some cases as outlined* :ref:`below <bot-api-versioning>`.
|
||||
- Z is the patch version.
|
||||
This is incremented if backward compatible bug fixes or smaller changes are introduced.
|
||||
If this number is 0, it can be omitted, i.e. we just write X.Y instead of X.Y.0.
|
||||
|
||||
Deprecation
|
||||
~~~~~~~~~~~
|
||||
|
||||
From time to time we will want to change the behavior of an API or remove it entirely, or we do so to comply with changes in the Telegram Bot API.
|
||||
In those cases, we follow a deprecation schedule as detailed below.
|
||||
|
||||
Functionality is marked as deprecated by a corresponding note in the release notes and the documentation.
|
||||
Where possible, a :class:`~telegram.warnings.PTBDeprecationWarning` is issued when deprecated functionality is used, but this is not mandatory.
|
||||
|
||||
From time to time, we may decide to deprecate an API that is particularly widely used.
|
||||
In these cases, we may decide to provide an extended deprecation period, at our discretion.
|
||||
|
||||
With version 20.0.0, PTB introduced major structural breaking changes without the above deprecation period.
|
||||
Should a similarly big change ever be deemed necessary again by the development team and should a deprecation period prove too much additional effort, this violation of the stability policy will be announced well ahead of the release in our channel, `as was done for v20 <https://t.me/pythontelegrambotchannel/94>`_.
|
||||
|
||||
Non-Bot API Functionality
|
||||
#########################
|
||||
|
||||
Starting with version 20.3, deprecated functionality will stay available for the current and the next major version.
|
||||
For example:
|
||||
|
||||
- In PTB v20.1.1 the feature exists
|
||||
- In PTB v20.1.2 or v20.2.0 the feature is marked as deprecated
|
||||
- In PTB v21.*.* the feature is marked as deprecated
|
||||
- In PTB v22.0 the feature is removed or changed
|
||||
|
||||
.. _bot-api-versioning:
|
||||
|
||||
Bot API Functionality
|
||||
#####################
|
||||
|
||||
As PTB has no control over deprecations introduced by Telegram and the schedule of these deprecations rarely coincides with PTBs deprecation schedule, we have a special policy for Bot API functionality.
|
||||
|
||||
Starting with 20.3, deprecated Bot API functionality will stay available for the current and the next major version of PTB *or* until the next version of the Bot API.
|
||||
More precisely, two cases are possible, for which we show examples below.
|
||||
|
||||
Case 1
|
||||
^^^^^^
|
||||
|
||||
- In PTB v20.1 the feature exists
|
||||
- Bot API version 6.6 is released and deprecates the feature
|
||||
- PTB v20.2 adds support for Bot API 6.6 and the feature is
|
||||
marked as deprecated
|
||||
- In PTB v21.0 the feature is removed or changed
|
||||
|
||||
Case 2
|
||||
^^^^^^
|
||||
|
||||
- In PTB v20.1 the feature exists
|
||||
- Bot API version 6.6 is released and deprecates the feature
|
||||
- PTB v20.2 adds support for Bot API version 6.6 and the feature is marked as deprecated
|
||||
- In PTB v20.2.* and v20.3.* the feature is marked as deprecated
|
||||
- Bot API version 6.7 is released
|
||||
- PTB v20.4 adds support for Bot API version 6.7 and the feature is removed or changed
|
||||
@@ -16,6 +16,7 @@ Available Types
|
||||
telegram.botcommandscopechatmember
|
||||
telegram.botcommandscopedefault
|
||||
telegram.botdescription
|
||||
telegram.botname
|
||||
telegram.botshortdescription
|
||||
telegram.callbackquery
|
||||
telegram.chat
|
||||
@@ -78,6 +79,8 @@ Available Types
|
||||
telegram.replykeyboardmarkup
|
||||
telegram.replykeyboardremove
|
||||
telegram.sentwebappmessage
|
||||
telegram.story
|
||||
telegram.switchinlinequerychosenchat
|
||||
telegram.telegramobject
|
||||
telegram.update
|
||||
telegram.user
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
BotName
|
||||
=======
|
||||
|
||||
.. autoclass:: telegram.BotName
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
BaseUpdateProcessor
|
||||
===================
|
||||
|
||||
.. autoclass:: telegram.ext.BaseUpdateProcessor
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -1,18 +1,22 @@
|
||||
telegram.ext package
|
||||
====================
|
||||
|
||||
.. automodule:: telegram.ext
|
||||
|
||||
.. toctree::
|
||||
:titlesonly:
|
||||
|
||||
telegram.ext.application
|
||||
telegram.ext.applicationbuilder
|
||||
telegram.ext.applicationhandlerstop
|
||||
telegram.ext.baseupdateprocessor
|
||||
telegram.ext.callbackcontext
|
||||
telegram.ext.contexttypes
|
||||
telegram.ext.defaults
|
||||
telegram.ext.extbot
|
||||
telegram.ext.job
|
||||
telegram.ext.jobqueue
|
||||
telegram.ext.simpleupdateprocessor
|
||||
telegram.ext.updater
|
||||
telegram.ext.handlers-tree.rst
|
||||
telegram.ext.persistence-tree.rst
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
SimpleUpdateProcessor
|
||||
=====================
|
||||
|
||||
.. autoclass:: telegram.ext.SimpleUpdateProcessor
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -24,6 +24,7 @@ Inline Mode
|
||||
telegram.inlinequeryresultlocation
|
||||
telegram.inlinequeryresultmpeg4gif
|
||||
telegram.inlinequeryresultphoto
|
||||
telegram.inlinequeryresultsbutton
|
||||
telegram.inlinequeryresultvenue
|
||||
telegram.inlinequeryresultvideo
|
||||
telegram.inlinequeryresultvoice
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
InlineQueryResultsButton
|
||||
========================
|
||||
|
||||
.. autoclass:: telegram.InlineQueryResultsButton
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
Story
|
||||
=====
|
||||
|
||||
.. autoclass:: telegram.Story
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
SwitchInlineQueryChosenChat
|
||||
===========================
|
||||
|
||||
.. autoclass:: telegram.SwitchInlineQueryChosenChat
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -14,10 +14,6 @@
|
||||
|
||||
.. |thumbdocstringnopath| replace:: |thumbdocstringbase| |uploadinputnopath|
|
||||
|
||||
.. |thumbargumentdeprecation| replace:: As of Bot API 6.6 this argument is deprecated in favor of
|
||||
|
||||
.. |thumbattributedeprecation| replace:: As of Bot API 6.6 this attribute is deprecated in favor of
|
||||
|
||||
.. |editreplymarkup| replace:: It is currently only possible to edit messages without :attr:`telegram.Message.reply_markup` or with inline keyboards.
|
||||
|
||||
.. |toapikwargsbase| replace:: These arguments are also considered by :meth:`~telegram.TelegramObject.to_dict` and :meth:`~telegram.TelegramObject.to_json`, i.e. when passing objects to Telegram. Passing them to Telegram is however not guaranteed to work for all kinds of objects, e.g. this will fail for objects that can not directly be JSON serialized.
|
||||
@@ -55,3 +51,13 @@
|
||||
.. |sequenceargs| replace:: Accepts any :class:`collections.abc.Sequence` as input instead of just a list.
|
||||
|
||||
.. |captionentitiesattr| replace:: Tuple of special entities that appear in the caption, which can be specified instead of ``parse_mode``.
|
||||
|
||||
.. |datetime_localization| replace:: The default timezone of the bot is used for localization, which is UTC unless :attr:`telegram.ext.Defaults.tzinfo` is used.
|
||||
|
||||
.. |post_methods_note| replace:: If you implement custom logic that implies that you will **not** be using :class:`~telegram.ext.Application`'s methods :meth:`~telegram.ext.Application.run_polling` or :meth:`~telegram.ext.Application.run_webhook` to run your application (like it's done in `Custom Webhook Bot Example <https://docs.python-telegram-bot.org/en/stable/examples.customwebhookbot.html>`__), the callback you set in this method **will not be called automatically**. So instead of setting a callback with this method, you have to explicitly ``await`` the function that you want to run at this stage of your application's life (in the `example mentioned above <https://docs.python-telegram-bot.org/en/stable/examples.customwebhookbot.html>`__, that would be in ``async with application`` context manager).
|
||||
|
||||
.. |removed_thumb_note| replace:: Removed the deprecated argument and attribute ``thumb``.
|
||||
|
||||
.. |removed_thumb_url_note| replace:: Removed the deprecated argument and attribute ``thumb_url``.
|
||||
|
||||
.. |removed_thumb_wildcard_note| replace:: Removed the deprecated arguments and attributes ``thumb_*``.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument, import-error
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""This example showcases how PTBs "arbitrary callback data" feature can be used.
|
||||
@@ -9,24 +9,11 @@ https://github.com/python-telegram-bot/python-telegram-bot/wiki/Arbitrary-callba
|
||||
|
||||
Note:
|
||||
To use arbitrary callback data, you must install PTB via
|
||||
`pip install python-telegram-bot[callback-data]`
|
||||
`pip install "python-telegram-bot[callback-data]"`
|
||||
"""
|
||||
import logging
|
||||
from typing import List, Tuple, cast
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
|
||||
from telegram.ext import (
|
||||
Application,
|
||||
@@ -41,6 +28,9 @@ from telegram.ext import (
|
||||
logging.basicConfig(
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
|
||||
)
|
||||
# set higher logging level for httpx to avoid all GET and POST requests being logged
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -122,7 +112,7 @@ def main() -> None:
|
||||
application.add_handler(CallbackQueryHandler(list_button))
|
||||
|
||||
# Run the bot until the user presses Ctrl-C
|
||||
application.run_polling()
|
||||
application.run_polling(allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
+10
-21
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument, import-error
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
@@ -14,19 +14,6 @@ bot.
|
||||
import logging
|
||||
from typing import Optional, Tuple
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import Chat, ChatMember, ChatMemberUpdated, Update
|
||||
from telegram.constants import ParseMode
|
||||
from telegram.ext import (
|
||||
@@ -44,6 +31,9 @@ logging.basicConfig(
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
|
||||
)
|
||||
|
||||
# set higher logging level for httpx to avoid all GET and POST requests being logged
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -103,13 +93,12 @@ async def track_chats(update: Update, context: ContextTypes.DEFAULT_TYPE) -> Non
|
||||
elif was_member and not is_member:
|
||||
logger.info("%s removed the bot from the group %s", cause_name, chat.title)
|
||||
context.bot_data.setdefault("group_ids", set()).discard(chat.id)
|
||||
else:
|
||||
if not was_member and is_member:
|
||||
logger.info("%s added the bot to the channel %s", cause_name, chat.title)
|
||||
context.bot_data.setdefault("channel_ids", set()).add(chat.id)
|
||||
elif was_member and not is_member:
|
||||
logger.info("%s removed the bot from the channel %s", cause_name, chat.title)
|
||||
context.bot_data.setdefault("channel_ids", set()).discard(chat.id)
|
||||
elif not was_member and is_member:
|
||||
logger.info("%s added the bot to the channel %s", cause_name, chat.title)
|
||||
context.bot_data.setdefault("channel_ids", set()).add(chat.id)
|
||||
elif was_member and not is_member:
|
||||
logger.info("%s removed the bot from the channel %s", cause_name, chat.title)
|
||||
context.bot_data.setdefault("channel_ids", set()).discard(chat.id)
|
||||
|
||||
|
||||
async def show_chats(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
|
||||
+11
-16
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument, import-error
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
@@ -14,19 +14,6 @@ import logging
|
||||
from collections import defaultdict
|
||||
from typing import DefaultDict, Optional, Set
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
|
||||
from telegram.constants import ParseMode
|
||||
from telegram.ext import (
|
||||
@@ -43,6 +30,9 @@ from telegram.ext import (
|
||||
logging.basicConfig(
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
|
||||
)
|
||||
# set higher logging level for httpx to avoid all GET and POST requests being logged
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -57,7 +47,12 @@ class ChatData:
|
||||
class CustomContext(CallbackContext[ExtBot, dict, ChatData, dict]):
|
||||
"""Custom class for context."""
|
||||
|
||||
def __init__(self, application: Application, chat_id: int = None, user_id: int = None):
|
||||
def __init__(
|
||||
self,
|
||||
application: Application,
|
||||
chat_id: Optional[int] = None,
|
||||
user_id: Optional[int] = None,
|
||||
):
|
||||
super().__init__(application=application, chat_id=chat_id, user_id=user_id)
|
||||
self._message_id: Optional[int] = None
|
||||
|
||||
@@ -142,7 +137,7 @@ def main() -> None:
|
||||
application.add_handler(CallbackQueryHandler(count_click))
|
||||
application.add_handler(CommandHandler("print_users", print_users))
|
||||
|
||||
application.run_polling()
|
||||
application.run_polling(allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument, import-error
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
@@ -16,19 +16,6 @@ bot.
|
||||
|
||||
import logging
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 5):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, Update
|
||||
from telegram.ext import (
|
||||
Application,
|
||||
@@ -43,6 +30,9 @@ from telegram.ext import (
|
||||
logging.basicConfig(
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
|
||||
)
|
||||
# set higher logging level for httpx to avoid all GET and POST requests being logged
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
GENDER, PHOTO, LOCATION, BIO = range(4)
|
||||
@@ -169,7 +159,7 @@ def main() -> None:
|
||||
application.add_handler(conv_handler)
|
||||
|
||||
# Run the bot until the user presses Ctrl-C
|
||||
application.run_polling()
|
||||
application.run_polling(allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument, import-error
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
@@ -17,19 +17,6 @@ bot.
|
||||
import logging
|
||||
from typing import Dict
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, Update
|
||||
from telegram.ext import (
|
||||
Application,
|
||||
@@ -44,6 +31,9 @@ from telegram.ext import (
|
||||
logging.basicConfig(
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
|
||||
)
|
||||
# set higher logging level for httpx to avoid all GET and POST requests being logged
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
CHOOSING, TYPING_REPLY, TYPING_CHOICE = range(3)
|
||||
@@ -157,7 +147,7 @@ def main() -> None:
|
||||
application.add_handler(conv_handler)
|
||||
|
||||
# Run the bot until the user presses Ctrl-C
|
||||
application.run_polling()
|
||||
application.run_polling(allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
#!/usr/bin/env python
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
# pylint: disable=import-error,unused-argument
|
||||
"""
|
||||
Simple example of a bot that uses a custom webhook setup and handles custom updates.
|
||||
For the custom webhook setup, the libraries `Django` and `uvicorn` are used. Please
|
||||
install them as `pip install Django~=4.2.4 uvicorn~=0.23.2`.
|
||||
Note that any other `asyncio` based web server framework can be used for a custom webhook setup
|
||||
just as well.
|
||||
|
||||
Usage:
|
||||
Set bot Token, URL, admin CHAT_ID and PORT after the imports.
|
||||
You may also need to change the `listen` value in the uvicorn configuration to match your setup.
|
||||
Press Ctrl-C on the command line or send a signal to the process to stop the bot.
|
||||
"""
|
||||
import asyncio
|
||||
import html
|
||||
import json
|
||||
import logging
|
||||
from dataclasses import dataclass
|
||||
from uuid import uuid4
|
||||
|
||||
import uvicorn
|
||||
from django.conf import settings
|
||||
from django.core.asgi import get_asgi_application
|
||||
from django.http import HttpRequest, HttpResponse, HttpResponseBadRequest
|
||||
from django.urls import path
|
||||
|
||||
from telegram import Update
|
||||
from telegram.constants import ParseMode
|
||||
from telegram.ext import (
|
||||
Application,
|
||||
CallbackContext,
|
||||
CommandHandler,
|
||||
ContextTypes,
|
||||
ExtBot,
|
||||
TypeHandler,
|
||||
)
|
||||
|
||||
# Enable logging
|
||||
logging.basicConfig(
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
|
||||
)
|
||||
# set higher logging level for httpx to avoid all GET and POST requests being logged
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Define configuration constants
|
||||
URL = "https://domain.tld"
|
||||
ADMIN_CHAT_ID = 123456
|
||||
PORT = 8000
|
||||
TOKEN = "123:ABC" # nosec B105
|
||||
|
||||
|
||||
@dataclass
|
||||
class WebhookUpdate:
|
||||
"""Simple dataclass to wrap a custom update type"""
|
||||
|
||||
user_id: int
|
||||
payload: str
|
||||
|
||||
|
||||
class CustomContext(CallbackContext[ExtBot, dict, dict, dict]):
|
||||
"""
|
||||
Custom CallbackContext class that makes `user_data` available for updates of type
|
||||
`WebhookUpdate`.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def from_update(
|
||||
cls,
|
||||
update: object,
|
||||
application: "Application",
|
||||
) -> "CustomContext":
|
||||
if isinstance(update, WebhookUpdate):
|
||||
return cls(application=application, user_id=update.user_id)
|
||||
return super().from_update(update, application)
|
||||
|
||||
|
||||
async def start(update: Update, context: CustomContext) -> None:
|
||||
"""Display a message with instructions on how to use this bot."""
|
||||
payload_url = html.escape(f"{URL}/submitpayload?user_id=<your user id>&payload=<payload>")
|
||||
text = (
|
||||
f"To check if the bot is still running, call <code>{URL}/healthcheck</code>.\n\n"
|
||||
f"To post a custom update, call <code>{payload_url}</code>."
|
||||
)
|
||||
await update.message.reply_html(text=text)
|
||||
|
||||
|
||||
async def webhook_update(update: WebhookUpdate, context: CustomContext) -> None:
|
||||
"""Handle custom updates."""
|
||||
chat_member = await context.bot.get_chat_member(chat_id=update.user_id, user_id=update.user_id)
|
||||
payloads = context.user_data.setdefault("payloads", [])
|
||||
payloads.append(update.payload)
|
||||
combined_payloads = "</code>\n• <code>".join(payloads)
|
||||
text = (
|
||||
f"The user {chat_member.user.mention_html()} has sent a new payload. "
|
||||
f"So far they have sent the following payloads: \n\n• <code>{combined_payloads}</code>"
|
||||
)
|
||||
await context.bot.send_message(chat_id=ADMIN_CHAT_ID, text=text, parse_mode=ParseMode.HTML)
|
||||
|
||||
|
||||
async def telegram(request: HttpRequest) -> HttpResponse:
|
||||
"""Handle incoming Telegram updates by putting them into the `update_queue`"""
|
||||
await ptb_application.update_queue.put(
|
||||
Update.de_json(data=json.loads(request.body), bot=ptb_application.bot)
|
||||
)
|
||||
return HttpResponse()
|
||||
|
||||
|
||||
async def custom_updates(request: HttpRequest) -> HttpResponse:
|
||||
"""
|
||||
Handle incoming webhook updates by also putting them into the `update_queue` if
|
||||
the required parameters were passed correctly.
|
||||
"""
|
||||
try:
|
||||
user_id = int(request.GET["user_id"])
|
||||
payload = request.GET["payload"]
|
||||
except KeyError:
|
||||
return HttpResponseBadRequest(
|
||||
"Please pass both `user_id` and `payload` as query parameters.",
|
||||
)
|
||||
except ValueError:
|
||||
return HttpResponseBadRequest("The `user_id` must be a string!")
|
||||
|
||||
await ptb_application.update_queue.put(WebhookUpdate(user_id=user_id, payload=payload))
|
||||
return HttpResponse()
|
||||
|
||||
|
||||
async def health(_: HttpRequest) -> HttpResponse:
|
||||
"""For the health endpoint, reply with a simple plain text message."""
|
||||
return HttpResponse("The bot is still running fine :)")
|
||||
|
||||
|
||||
# Set up PTB application and a web application for handling the incoming requests.
|
||||
|
||||
context_types = ContextTypes(context=CustomContext)
|
||||
# Here we set updater to None because we want our custom webhook server to handle the updates
|
||||
# and hence we don't need an Updater instance
|
||||
ptb_application = (
|
||||
Application.builder().token(TOKEN).updater(None).context_types(context_types).build()
|
||||
)
|
||||
|
||||
# register handlers
|
||||
ptb_application.add_handler(CommandHandler("start", start))
|
||||
ptb_application.add_handler(TypeHandler(type=WebhookUpdate, callback=webhook_update))
|
||||
|
||||
urlpatterns = [
|
||||
path("telegram", telegram, name="Telegram updates"),
|
||||
path("submitpayload", custom_updates, name="custom updates"),
|
||||
path("healthcheck", health, name="health check"),
|
||||
]
|
||||
settings.configure(ROOT_URLCONF=__name__, SECRET_KEY=uuid4().hex)
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
"""Finalize configuration and run the applications."""
|
||||
webserver = uvicorn.Server(
|
||||
config=uvicorn.Config(
|
||||
app=get_asgi_application(),
|
||||
port=PORT,
|
||||
use_colors=False,
|
||||
host="127.0.0.1",
|
||||
)
|
||||
)
|
||||
|
||||
# Pass webhook settings to telegram
|
||||
await ptb_application.bot.set_webhook(url=f"{URL}/telegram", allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
# Run application and webserver together
|
||||
async with ptb_application:
|
||||
await ptb_application.start()
|
||||
await webserver.serve()
|
||||
await ptb_application.stop()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,170 @@
|
||||
#!/usr/bin/env python
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
# pylint: disable=import-error,unused-argument
|
||||
"""
|
||||
Simple example of a bot that uses a custom webhook setup and handles custom updates.
|
||||
For the custom webhook setup, the libraries `flask`, `asgiref` and `uvicorn` are used. Please
|
||||
install them as `pip install flask[async]~=2.3.2 uvicorn~=0.23.2 asgiref~=3.7.2`.
|
||||
Note that any other `asyncio` based web server framework can be used for a custom webhook setup
|
||||
just as well.
|
||||
|
||||
Usage:
|
||||
Set bot Token, URL, admin CHAT_ID and PORT after the imports.
|
||||
You may also need to change the `listen` value in the uvicorn configuration to match your setup.
|
||||
Press Ctrl-C on the command line or send a signal to the process to stop the bot.
|
||||
"""
|
||||
import asyncio
|
||||
import html
|
||||
import logging
|
||||
from dataclasses import dataclass
|
||||
from http import HTTPStatus
|
||||
|
||||
import uvicorn
|
||||
from asgiref.wsgi import WsgiToAsgi
|
||||
from flask import Flask, Response, abort, make_response, request
|
||||
|
||||
from telegram import Update
|
||||
from telegram.constants import ParseMode
|
||||
from telegram.ext import (
|
||||
Application,
|
||||
CallbackContext,
|
||||
CommandHandler,
|
||||
ContextTypes,
|
||||
ExtBot,
|
||||
TypeHandler,
|
||||
)
|
||||
|
||||
# Enable logging
|
||||
logging.basicConfig(
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
|
||||
)
|
||||
# set higher logging level for httpx to avoid all GET and POST requests being logged
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Define configuration constants
|
||||
URL = "https://domain.tld"
|
||||
ADMIN_CHAT_ID = 123456
|
||||
PORT = 8000
|
||||
TOKEN = "123:ABC" # nosec B105
|
||||
|
||||
|
||||
@dataclass
|
||||
class WebhookUpdate:
|
||||
"""Simple dataclass to wrap a custom update type"""
|
||||
|
||||
user_id: int
|
||||
payload: str
|
||||
|
||||
|
||||
class CustomContext(CallbackContext[ExtBot, dict, dict, dict]):
|
||||
"""
|
||||
Custom CallbackContext class that makes `user_data` available for updates of type
|
||||
`WebhookUpdate`.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def from_update(
|
||||
cls,
|
||||
update: object,
|
||||
application: "Application",
|
||||
) -> "CustomContext":
|
||||
if isinstance(update, WebhookUpdate):
|
||||
return cls(application=application, user_id=update.user_id)
|
||||
return super().from_update(update, application)
|
||||
|
||||
|
||||
async def start(update: Update, context: CustomContext) -> None:
|
||||
"""Display a message with instructions on how to use this bot."""
|
||||
payload_url = html.escape(f"{URL}/submitpayload?user_id=<your user id>&payload=<payload>")
|
||||
text = (
|
||||
f"To check if the bot is still running, call <code>{URL}/healthcheck</code>.\n\n"
|
||||
f"To post a custom update, call <code>{payload_url}</code>."
|
||||
)
|
||||
await update.message.reply_html(text=text)
|
||||
|
||||
|
||||
async def webhook_update(update: WebhookUpdate, context: CustomContext) -> None:
|
||||
"""Handle custom updates."""
|
||||
chat_member = await context.bot.get_chat_member(chat_id=update.user_id, user_id=update.user_id)
|
||||
payloads = context.user_data.setdefault("payloads", [])
|
||||
payloads.append(update.payload)
|
||||
combined_payloads = "</code>\n• <code>".join(payloads)
|
||||
text = (
|
||||
f"The user {chat_member.user.mention_html()} has sent a new payload. "
|
||||
f"So far they have sent the following payloads: \n\n• <code>{combined_payloads}</code>"
|
||||
)
|
||||
await context.bot.send_message(chat_id=ADMIN_CHAT_ID, text=text, parse_mode=ParseMode.HTML)
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
"""Set up PTB application and a web application for handling the incoming requests."""
|
||||
context_types = ContextTypes(context=CustomContext)
|
||||
# Here we set updater to None because we want our custom webhook server to handle the updates
|
||||
# and hence we don't need an Updater instance
|
||||
application = (
|
||||
Application.builder().token(TOKEN).updater(None).context_types(context_types).build()
|
||||
)
|
||||
|
||||
# register handlers
|
||||
application.add_handler(CommandHandler("start", start))
|
||||
application.add_handler(TypeHandler(type=WebhookUpdate, callback=webhook_update))
|
||||
|
||||
# Pass webhook settings to telegram
|
||||
await application.bot.set_webhook(url=f"{URL}/telegram", allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
# Set up webserver
|
||||
flask_app = Flask(__name__)
|
||||
|
||||
@flask_app.post("/telegram") # type: ignore[misc]
|
||||
async def telegram() -> Response:
|
||||
"""Handle incoming Telegram updates by putting them into the `update_queue`"""
|
||||
await application.update_queue.put(Update.de_json(data=request.json, bot=application.bot))
|
||||
return Response(status=HTTPStatus.OK)
|
||||
|
||||
@flask_app.route("/submitpayload", methods=["GET", "POST"]) # type: ignore[misc]
|
||||
async def custom_updates() -> Response:
|
||||
"""
|
||||
Handle incoming webhook updates by also putting them into the `update_queue` if
|
||||
the required parameters were passed correctly.
|
||||
"""
|
||||
try:
|
||||
user_id = int(request.args["user_id"])
|
||||
payload = request.args["payload"]
|
||||
except KeyError:
|
||||
abort(
|
||||
HTTPStatus.BAD_REQUEST,
|
||||
"Please pass both `user_id` and `payload` as query parameters.",
|
||||
)
|
||||
except ValueError:
|
||||
abort(HTTPStatus.BAD_REQUEST, "The `user_id` must be a string!")
|
||||
|
||||
await application.update_queue.put(WebhookUpdate(user_id=user_id, payload=payload))
|
||||
return Response(status=HTTPStatus.OK)
|
||||
|
||||
@flask_app.get("/healthcheck") # type: ignore[misc]
|
||||
async def health() -> Response:
|
||||
"""For the health endpoint, reply with a simple plain text message."""
|
||||
response = make_response("The bot is still running fine :)", HTTPStatus.OK)
|
||||
response.mimetype = "text/plain"
|
||||
return response
|
||||
|
||||
webserver = uvicorn.Server(
|
||||
config=uvicorn.Config(
|
||||
app=WsgiToAsgi(flask_app),
|
||||
port=PORT,
|
||||
use_colors=False,
|
||||
host="127.0.0.1",
|
||||
)
|
||||
)
|
||||
|
||||
# Run application and webserver together
|
||||
async with application:
|
||||
await application.start()
|
||||
await webserver.serve()
|
||||
await application.stop()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,171 @@
|
||||
#!/usr/bin/env python
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
# pylint: disable=import-error,unused-argument
|
||||
"""
|
||||
Simple example of a bot that uses a custom webhook setup and handles custom updates.
|
||||
For the custom webhook setup, the libraries `quart` and `uvicorn` are used. Please
|
||||
install them as `pip install quart~=0.18.4 uvicorn~=0.23.2`.
|
||||
Note that any other `asyncio` based web server framework can be used for a custom webhook setup
|
||||
just as well.
|
||||
|
||||
Usage:
|
||||
Set bot Token, URL, admin CHAT_ID and PORT after the imports.
|
||||
You may also need to change the `listen` value in the uvicorn configuration to match your setup.
|
||||
Press Ctrl-C on the command line or send a signal to the process to stop the bot.
|
||||
"""
|
||||
import asyncio
|
||||
import html
|
||||
import logging
|
||||
from dataclasses import dataclass
|
||||
from http import HTTPStatus
|
||||
|
||||
import uvicorn
|
||||
from quart import Quart, Response, abort, make_response, request
|
||||
|
||||
from telegram import Update
|
||||
from telegram.constants import ParseMode
|
||||
from telegram.ext import (
|
||||
Application,
|
||||
CallbackContext,
|
||||
CommandHandler,
|
||||
ContextTypes,
|
||||
ExtBot,
|
||||
TypeHandler,
|
||||
)
|
||||
|
||||
# Enable logging
|
||||
logging.basicConfig(
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
|
||||
)
|
||||
# set higher logging level for httpx to avoid all GET and POST requests being logged
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Define configuration constants
|
||||
URL = "https://domain.tld"
|
||||
ADMIN_CHAT_ID = 123456
|
||||
PORT = 8000
|
||||
TOKEN = "123:ABC" # nosec B105
|
||||
|
||||
|
||||
@dataclass
|
||||
class WebhookUpdate:
|
||||
"""Simple dataclass to wrap a custom update type"""
|
||||
|
||||
user_id: int
|
||||
payload: str
|
||||
|
||||
|
||||
class CustomContext(CallbackContext[ExtBot, dict, dict, dict]):
|
||||
"""
|
||||
Custom CallbackContext class that makes `user_data` available for updates of type
|
||||
`WebhookUpdate`.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def from_update(
|
||||
cls,
|
||||
update: object,
|
||||
application: "Application",
|
||||
) -> "CustomContext":
|
||||
if isinstance(update, WebhookUpdate):
|
||||
return cls(application=application, user_id=update.user_id)
|
||||
return super().from_update(update, application)
|
||||
|
||||
|
||||
async def start(update: Update, context: CustomContext) -> None:
|
||||
"""Display a message with instructions on how to use this bot."""
|
||||
payload_url = html.escape(f"{URL}/submitpayload?user_id=<your user id>&payload=<payload>")
|
||||
text = (
|
||||
f"To check if the bot is still running, call <code>{URL}/healthcheck</code>.\n\n"
|
||||
f"To post a custom update, call <code>{payload_url}</code>."
|
||||
)
|
||||
await update.message.reply_html(text=text)
|
||||
|
||||
|
||||
async def webhook_update(update: WebhookUpdate, context: CustomContext) -> None:
|
||||
"""Handle custom updates."""
|
||||
chat_member = await context.bot.get_chat_member(chat_id=update.user_id, user_id=update.user_id)
|
||||
payloads = context.user_data.setdefault("payloads", [])
|
||||
payloads.append(update.payload)
|
||||
combined_payloads = "</code>\n• <code>".join(payloads)
|
||||
text = (
|
||||
f"The user {chat_member.user.mention_html()} has sent a new payload. "
|
||||
f"So far they have sent the following payloads: \n\n• <code>{combined_payloads}</code>"
|
||||
)
|
||||
await context.bot.send_message(chat_id=ADMIN_CHAT_ID, text=text, parse_mode=ParseMode.HTML)
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
"""Set up PTB application and a web application for handling the incoming requests."""
|
||||
context_types = ContextTypes(context=CustomContext)
|
||||
# Here we set updater to None because we want our custom webhook server to handle the updates
|
||||
# and hence we don't need an Updater instance
|
||||
application = (
|
||||
Application.builder().token(TOKEN).updater(None).context_types(context_types).build()
|
||||
)
|
||||
|
||||
# register handlers
|
||||
application.add_handler(CommandHandler("start", start))
|
||||
application.add_handler(TypeHandler(type=WebhookUpdate, callback=webhook_update))
|
||||
|
||||
# Pass webhook settings to telegram
|
||||
await application.bot.set_webhook(url=f"{URL}/telegram", allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
# Set up webserver
|
||||
quart_app = Quart(__name__)
|
||||
|
||||
@quart_app.post("/telegram") # type: ignore[misc]
|
||||
async def telegram() -> Response:
|
||||
"""Handle incoming Telegram updates by putting them into the `update_queue`"""
|
||||
await application.update_queue.put(
|
||||
Update.de_json(data=await request.get_json(), bot=application.bot)
|
||||
)
|
||||
return Response(status=HTTPStatus.OK)
|
||||
|
||||
@quart_app.route("/submitpayload", methods=["GET", "POST"]) # type: ignore[misc]
|
||||
async def custom_updates() -> Response:
|
||||
"""
|
||||
Handle incoming webhook updates by also putting them into the `update_queue` if
|
||||
the required parameters were passed correctly.
|
||||
"""
|
||||
try:
|
||||
user_id = int(request.args["user_id"])
|
||||
payload = request.args["payload"]
|
||||
except KeyError:
|
||||
abort(
|
||||
HTTPStatus.BAD_REQUEST,
|
||||
"Please pass both `user_id` and `payload` as query parameters.",
|
||||
)
|
||||
except ValueError:
|
||||
abort(HTTPStatus.BAD_REQUEST, "The `user_id` must be a string!")
|
||||
|
||||
await application.update_queue.put(WebhookUpdate(user_id=user_id, payload=payload))
|
||||
return Response(status=HTTPStatus.OK)
|
||||
|
||||
@quart_app.get("/healthcheck") # type: ignore[misc]
|
||||
async def health() -> Response:
|
||||
"""For the health endpoint, reply with a simple plain text message."""
|
||||
response = await make_response("The bot is still running fine :)", HTTPStatus.OK)
|
||||
response.mimetype = "text/plain"
|
||||
return response
|
||||
|
||||
webserver = uvicorn.Server(
|
||||
config=uvicorn.Config(
|
||||
app=quart_app,
|
||||
port=PORT,
|
||||
use_colors=False,
|
||||
host="127.0.0.1",
|
||||
)
|
||||
)
|
||||
|
||||
# Run application and webserver together
|
||||
async with application:
|
||||
await application.start()
|
||||
await webserver.serve()
|
||||
await application.stop()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -1,15 +1,15 @@
|
||||
#!/usr/bin/env python
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
# pylint: disable=import-error,wrong-import-position
|
||||
# pylint: disable=import-error,unused-argument
|
||||
"""
|
||||
Simple example of a bot that uses a custom webhook setup and handles custom updates.
|
||||
For the custom webhook setup, the libraries `starlette` and `uvicorn` are used. Please install
|
||||
them as `pip install starlette~=0.20.0 uvicorn~=0.17.0`.
|
||||
them as `pip install starlette~=0.20.0 uvicorn~=0.23.2`.
|
||||
Note that any other `asyncio` based web server framework can be used for a custom webhook setup
|
||||
just as well.
|
||||
|
||||
Usage:
|
||||
Set bot token, url, admin chat_id and port at the start of the `main` function.
|
||||
Set bot Token, URL, admin CHAT_ID and PORT after the imports.
|
||||
You may also need to change the `listen` value in the uvicorn configuration to match your setup.
|
||||
Press Ctrl-C on the command line or send a signal to the process to stop the bot.
|
||||
"""
|
||||
@@ -25,20 +25,6 @@ from starlette.requests import Request
|
||||
from starlette.responses import PlainTextResponse, Response
|
||||
from starlette.routing import Route
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
|
||||
from telegram import Update
|
||||
from telegram.constants import ParseMode
|
||||
from telegram.ext import (
|
||||
@@ -54,8 +40,17 @@ from telegram.ext import (
|
||||
logging.basicConfig(
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
|
||||
)
|
||||
# set higher logging level for httpx to avoid all GET and POST requests being logged
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Define configuration constants
|
||||
URL = "https://domain.tld"
|
||||
ADMIN_CHAT_ID = 123456
|
||||
PORT = 8000
|
||||
TOKEN = "123:ABC" # nosec B105
|
||||
|
||||
|
||||
@dataclass
|
||||
class WebhookUpdate:
|
||||
@@ -84,17 +79,16 @@ class CustomContext(CallbackContext[ExtBot, dict, dict, dict]):
|
||||
|
||||
async def start(update: Update, context: CustomContext) -> None:
|
||||
"""Display a message with instructions on how to use this bot."""
|
||||
url = context.bot_data["url"]
|
||||
payload_url = html.escape(f"{url}/submitpayload?user_id=<your user id>&payload=<payload>")
|
||||
payload_url = html.escape(f"{URL}/submitpayload?user_id=<your user id>&payload=<payload>")
|
||||
text = (
|
||||
f"To check if the bot is still running, call <code>{url}/healthcheck</code>.\n\n"
|
||||
f"To check if the bot is still running, call <code>{URL}/healthcheck</code>.\n\n"
|
||||
f"To post a custom update, call <code>{payload_url}</code>."
|
||||
)
|
||||
await update.message.reply_html(text=text)
|
||||
|
||||
|
||||
async def webhook_update(update: WebhookUpdate, context: CustomContext) -> None:
|
||||
"""Callback that handles the custom updates."""
|
||||
"""Handle custom updates."""
|
||||
chat_member = await context.bot.get_chat_member(chat_id=update.user_id, user_id=update.user_id)
|
||||
payloads = context.user_data.setdefault("payloads", [])
|
||||
payloads.append(update.payload)
|
||||
@@ -103,33 +97,24 @@ async def webhook_update(update: WebhookUpdate, context: CustomContext) -> None:
|
||||
f"The user {chat_member.user.mention_html()} has sent a new payload. "
|
||||
f"So far they have sent the following payloads: \n\n• <code>{combined_payloads}</code>"
|
||||
)
|
||||
await context.bot.send_message(
|
||||
chat_id=context.bot_data["admin_chat_id"], text=text, parse_mode=ParseMode.HTML
|
||||
)
|
||||
await context.bot.send_message(chat_id=ADMIN_CHAT_ID, text=text, parse_mode=ParseMode.HTML)
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
"""Set up the application and a custom webserver."""
|
||||
url = "https://domain.tld"
|
||||
admin_chat_id = 123456
|
||||
port = 8000
|
||||
|
||||
"""Set up PTB application and a web application for handling the incoming requests."""
|
||||
context_types = ContextTypes(context=CustomContext)
|
||||
# Here we set updater to None because we want our custom webhook server to handle the updates
|
||||
# and hence we don't need an Updater instance
|
||||
application = (
|
||||
Application.builder().token("TOKEN").updater(None).context_types(context_types).build()
|
||||
Application.builder().token(TOKEN).updater(None).context_types(context_types).build()
|
||||
)
|
||||
# save the values in `bot_data` such that we may easily access them in the callbacks
|
||||
application.bot_data["url"] = url
|
||||
application.bot_data["admin_chat_id"] = admin_chat_id
|
||||
|
||||
# register handlers
|
||||
application.add_handler(CommandHandler("start", start))
|
||||
application.add_handler(TypeHandler(type=WebhookUpdate, callback=webhook_update))
|
||||
|
||||
# Pass webhook settings to telegram
|
||||
await application.bot.set_webhook(url=f"{url}/telegram")
|
||||
await application.bot.set_webhook(url=f"{URL}/telegram", allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
# Set up webserver
|
||||
async def telegram(request: Request) -> Response:
|
||||
@@ -175,7 +160,7 @@ async def main() -> None:
|
||||
webserver = uvicorn.Server(
|
||||
config=uvicorn.Config(
|
||||
app=starlette_app,
|
||||
port=port,
|
||||
port=PORT,
|
||||
use_colors=False,
|
||||
host="127.0.0.1",
|
||||
)
|
||||
+5
-15
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument, import-error
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""Bot that explains Telegram's "Deep Linking Parameters" functionality.
|
||||
@@ -20,19 +20,6 @@ bot.
|
||||
|
||||
import logging
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update, helpers
|
||||
from telegram.constants import ParseMode
|
||||
from telegram.ext import Application, CallbackQueryHandler, CommandHandler, ContextTypes, filters
|
||||
@@ -42,6 +29,9 @@ logging.basicConfig(
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
|
||||
)
|
||||
|
||||
# set higher logging level for httpx to avoid all GET and POST requests being logged
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Define constants that will allow us to reuse the deep-linking parameters.
|
||||
@@ -144,7 +134,7 @@ def main() -> None:
|
||||
application.add_handler(CommandHandler("start", start))
|
||||
|
||||
# Run the bot until the user presses Ctrl-C
|
||||
application.run_polling()
|
||||
application.run_polling(allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
+5
-15
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument, import-error
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
@@ -17,19 +17,6 @@ bot.
|
||||
|
||||
import logging
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import ForceReply, Update
|
||||
from telegram.ext import Application, CommandHandler, ContextTypes, MessageHandler, filters
|
||||
|
||||
@@ -37,6 +24,9 @@ from telegram.ext import Application, CommandHandler, ContextTypes, MessageHandl
|
||||
logging.basicConfig(
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
|
||||
)
|
||||
# set higher logging level for httpx to avoid all GET and POST requests being logged
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -74,7 +64,7 @@ def main() -> None:
|
||||
application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, echo))
|
||||
|
||||
# Run the bot until the user presses Ctrl-C
|
||||
application.run_polling()
|
||||
application.run_polling(allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument, import-error
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""This is a very simple example on how one could implement a custom error handler."""
|
||||
@@ -8,19 +8,6 @@ import json
|
||||
import logging
|
||||
import traceback
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import Update
|
||||
from telegram.constants import ParseMode
|
||||
from telegram.ext import Application, CommandHandler, ContextTypes
|
||||
@@ -29,6 +16,9 @@ from telegram.ext import Application, CommandHandler, ContextTypes
|
||||
logging.basicConfig(
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
|
||||
)
|
||||
# set higher logging level for httpx to avoid all GET and POST requests being logged
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# This can be your own ID, or one for a developer group/channel.
|
||||
@@ -39,7 +29,7 @@ DEVELOPER_CHAT_ID = 123456789
|
||||
async def error_handler(update: object, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
"""Log the error and send a telegram message to notify the developer."""
|
||||
# Log the error before we do anything else, so we can see it even if something breaks.
|
||||
logger.error(msg="Exception while handling an update:", exc_info=context.error)
|
||||
logger.error("Exception while handling an update:", exc_info=context.error)
|
||||
|
||||
# traceback.format_exception returns the usual python message about an exception, but as a
|
||||
# list of strings rather than a single string, so we have to join them together.
|
||||
@@ -90,7 +80,7 @@ def main() -> None:
|
||||
application.add_error_handler(error_handler)
|
||||
|
||||
# Run the bot until the user presses Ctrl-C
|
||||
application.run_polling()
|
||||
application.run_polling(allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
+7
-17
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument, import-error
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
@@ -18,19 +18,6 @@ import logging
|
||||
from html import escape
|
||||
from uuid import uuid4
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import InlineQueryResultArticle, InputTextMessageContent, Update
|
||||
from telegram.constants import ParseMode
|
||||
from telegram.ext import Application, CommandHandler, ContextTypes, InlineQueryHandler
|
||||
@@ -39,6 +26,9 @@ from telegram.ext import Application, CommandHandler, ContextTypes, InlineQueryH
|
||||
logging.basicConfig(
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
|
||||
)
|
||||
# set higher logging level for httpx to avoid all GET and POST requests being logged
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -58,7 +48,7 @@ async def inline_query(update: Update, context: ContextTypes.DEFAULT_TYPE) -> No
|
||||
"""Handle the inline query. This is run when you type: @botusername <query>"""
|
||||
query = update.inline_query.query
|
||||
|
||||
if query == "":
|
||||
if not query: # empty query should not be handled
|
||||
return
|
||||
|
||||
results = [
|
||||
@@ -95,11 +85,11 @@ def main() -> None:
|
||||
application.add_handler(CommandHandler("start", start))
|
||||
application.add_handler(CommandHandler("help", help_command))
|
||||
|
||||
# on non command i.e message - echo the message on Telegram
|
||||
# on inline queries - show corresponding inline results
|
||||
application.add_handler(InlineQueryHandler(inline_query))
|
||||
|
||||
# Run the bot until the user presses Ctrl-C
|
||||
application.run_polling()
|
||||
application.run_polling(allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument, import-error
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
@@ -8,19 +8,6 @@ Basic example for a bot that uses inline keyboards. For an in-depth explanation,
|
||||
"""
|
||||
import logging
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
|
||||
from telegram.ext import Application, CallbackQueryHandler, CommandHandler, ContextTypes
|
||||
|
||||
@@ -28,6 +15,9 @@ from telegram.ext import Application, CallbackQueryHandler, CommandHandler, Cont
|
||||
logging.basicConfig(
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
|
||||
)
|
||||
# set higher logging level for httpx to avoid all GET and POST requests being logged
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -72,7 +62,7 @@ def main() -> None:
|
||||
application.add_handler(CommandHandler("help", help_command))
|
||||
|
||||
# Run the bot until the user presses Ctrl-C
|
||||
application.run_polling()
|
||||
application.run_polling(allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument, import-error
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""Simple inline keyboard bot with multiple CallbackQueryHandlers.
|
||||
@@ -16,19 +16,6 @@ Press Ctrl-C on the command line to stop the bot.
|
||||
"""
|
||||
import logging
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
|
||||
from telegram.ext import (
|
||||
Application,
|
||||
@@ -42,6 +29,9 @@ from telegram.ext import (
|
||||
logging.basicConfig(
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
|
||||
)
|
||||
# set higher logging level for httpx to avoid all GET and POST requests being logged
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Stages
|
||||
@@ -204,7 +194,7 @@ def main() -> None:
|
||||
application.add_handler(conv_handler)
|
||||
|
||||
# Run the bot until the user presses Ctrl-C
|
||||
application.run_polling()
|
||||
application.run_polling(allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument, import-error
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
@@ -17,19 +17,6 @@ bot.
|
||||
import logging
|
||||
from typing import Any, Dict, Tuple
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
|
||||
from telegram.ext import (
|
||||
Application,
|
||||
@@ -45,6 +32,9 @@ from telegram.ext import (
|
||||
logging.basicConfig(
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
|
||||
)
|
||||
# set higher logging level for httpx to avoid all GET and POST requests being logged
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# State definitions for top level conversation
|
||||
@@ -392,7 +382,7 @@ def main() -> None:
|
||||
application.add_handler(conv_handler)
|
||||
|
||||
# Run the bot until the user presses Ctrl-C
|
||||
application.run_polling()
|
||||
application.run_polling(allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
+6
-16
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument, import-error
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
@@ -12,24 +12,11 @@ See https://github.com/python-telegram-bot/python-telegram-bot/wiki/Telegram-Pas
|
||||
|
||||
Note:
|
||||
To use Telegram Passport, you must install PTB via
|
||||
`pip install python-telegram-bot[passport]`
|
||||
`pip install "python-telegram-bot[passport]"`
|
||||
"""
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 5):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import Update
|
||||
from telegram.ext import Application, ContextTypes, MessageHandler, filters
|
||||
|
||||
@@ -39,6 +26,9 @@ logging.basicConfig(
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
|
||||
)
|
||||
|
||||
# set higher logging level for httpx to avoid all GET and POST requests being logged
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -129,7 +119,7 @@ def main() -> None:
|
||||
application.add_handler(MessageHandler(filters.PASSPORT_DATA, msg))
|
||||
|
||||
# Run the bot until the user presses Ctrl-C
|
||||
application.run_polling()
|
||||
application.run_polling(allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
+5
-15
@@ -1,24 +1,11 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument, import-error
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""Basic example for a bot that can receive payment from user."""
|
||||
|
||||
import logging
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import LabeledPrice, ShippingOption, Update
|
||||
from telegram.ext import (
|
||||
Application,
|
||||
@@ -34,6 +21,9 @@ from telegram.ext import (
|
||||
logging.basicConfig(
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
|
||||
)
|
||||
# set higher logging level for httpx to avoid all GET and POST requests being logged
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
PAYMENT_PROVIDER_TOKEN = "PAYMENT_PROVIDER_TOKEN"
|
||||
@@ -165,7 +155,7 @@ def main() -> None:
|
||||
)
|
||||
|
||||
# Run the bot until the user presses Ctrl-C
|
||||
application.run_polling()
|
||||
application.run_polling(allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument, import-error
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
@@ -17,19 +17,6 @@ bot.
|
||||
import logging
|
||||
from typing import Dict
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, Update
|
||||
from telegram.ext import (
|
||||
Application,
|
||||
@@ -45,6 +32,9 @@ from telegram.ext import (
|
||||
logging.basicConfig(
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
|
||||
)
|
||||
# set higher logging level for httpx to avoid all GET and POST requests being logged
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
CHOOSING, TYPING_REPLY, TYPING_CHOICE = range(3)
|
||||
@@ -180,7 +170,7 @@ def main() -> None:
|
||||
application.add_handler(show_data_handler)
|
||||
|
||||
# Run the bot until the user presses Ctrl-C
|
||||
application.run_polling()
|
||||
application.run_polling(allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
+10
-17
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument, import-error
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
@@ -9,19 +9,6 @@ one the user sends the bot
|
||||
"""
|
||||
import logging
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import (
|
||||
KeyboardButton,
|
||||
KeyboardButtonPollType,
|
||||
@@ -45,9 +32,15 @@ from telegram.ext import (
|
||||
logging.basicConfig(
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
|
||||
)
|
||||
# set higher logging level for httpx to avoid all GET and POST requests being logged
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
TOTAL_VOTER_COUNT = 3
|
||||
|
||||
|
||||
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
"""Inform user about what this bot can do"""
|
||||
await update.message.reply_text(
|
||||
@@ -101,7 +94,7 @@ async def receive_poll_answer(update: Update, context: ContextTypes.DEFAULT_TYPE
|
||||
)
|
||||
answered_poll["answers"] += 1
|
||||
# Close poll after three participants voted
|
||||
if answered_poll["answers"] == 3:
|
||||
if answered_poll["answers"] == TOTAL_VOTER_COUNT:
|
||||
await context.bot.stop_poll(answered_poll["chat_id"], answered_poll["message_id"])
|
||||
|
||||
|
||||
@@ -123,7 +116,7 @@ async def receive_quiz_answer(update: Update, context: ContextTypes.DEFAULT_TYPE
|
||||
# the bot can receive closed poll updates we don't care about
|
||||
if update.poll.is_closed:
|
||||
return
|
||||
if update.poll.total_voter_count == 3:
|
||||
if update.poll.total_voter_count == TOTAL_VOTER_COUNT:
|
||||
try:
|
||||
quiz_data = context.bot_data[update.poll.id]
|
||||
# this means this poll answer update is from an old poll, we can't stop it then
|
||||
@@ -176,7 +169,7 @@ def main() -> None:
|
||||
application.add_handler(PollHandler(receive_quiz_answer))
|
||||
|
||||
# Run the bot until the user presses Ctrl-C
|
||||
application.run_polling()
|
||||
application.run_polling(allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
+8
-19
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=wrong-import-position
|
||||
# pylint: disable=import-error
|
||||
"""Simple Bot to reply to Telegram messages.
|
||||
|
||||
This is built on the API wrapper, see echobot.py to see the same example built
|
||||
@@ -7,28 +7,19 @@ on the telegram.ext bot framework.
|
||||
This program is dedicated to the public domain under the CC0 license.
|
||||
"""
|
||||
import asyncio
|
||||
import contextlib
|
||||
import logging
|
||||
from typing import NoReturn
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment] # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import Bot
|
||||
from telegram import Bot, Update
|
||||
from telegram.error import Forbidden, NetworkError
|
||||
|
||||
logging.basicConfig(
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
|
||||
)
|
||||
# set higher logging level for httpx to avoid all GET and POST requests being logged
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -57,7 +48,7 @@ async def main() -> NoReturn:
|
||||
async def echo(bot: Bot, update_id: int) -> int:
|
||||
"""Echo the message the user sent."""
|
||||
# Request updates after the last update_id
|
||||
updates = await bot.get_updates(offset=update_id, timeout=10)
|
||||
updates = await bot.get_updates(offset=update_id, timeout=10, allowed_updates=Update.ALL_TYPES)
|
||||
for update in updates:
|
||||
next_update_id = update.update_id + 1
|
||||
|
||||
@@ -72,7 +63,5 @@ async def echo(bot: Bot, update_id: int) -> int:
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
with contextlib.suppress(KeyboardInterrupt): # Ignore exception when Ctrl-C is pressed
|
||||
asyncio.run(main())
|
||||
except KeyboardInterrupt: # Ignore exception when Ctrl-C is pressed
|
||||
pass
|
||||
|
||||
+3
-16
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument, import-error
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
@@ -19,24 +19,11 @@ bot.
|
||||
|
||||
Note:
|
||||
To use the JobQueue, you must install PTB via
|
||||
`pip install python-telegram-bot[job-queue]`
|
||||
`pip install "python-telegram-bot[job-queue]"`
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import Update
|
||||
from telegram.ext import Application, CommandHandler, ContextTypes
|
||||
|
||||
@@ -114,7 +101,7 @@ def main() -> None:
|
||||
application.add_handler(CommandHandler("unset", unset))
|
||||
|
||||
# Run the bot until the user presses Ctrl-C
|
||||
application.run_polling()
|
||||
application.run_polling(allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
+5
-15
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument,wrong-import-position
|
||||
# pylint: disable=unused-argument,import-error
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
@@ -11,19 +11,6 @@ require a bot token.
|
||||
import json
|
||||
import logging
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove, Update, WebAppInfo
|
||||
from telegram.ext import Application, CommandHandler, ContextTypes, MessageHandler, filters
|
||||
|
||||
@@ -31,6 +18,9 @@ from telegram.ext import Application, CommandHandler, ContextTypes, MessageHandl
|
||||
logging.basicConfig(
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
|
||||
)
|
||||
# set higher logging level for httpx to avoid all GET and POST requests being logged
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -70,7 +60,7 @@ def main() -> None:
|
||||
application.add_handler(MessageHandler(filters.StatusUpdate.WEB_APP_DATA, web_app_data))
|
||||
|
||||
# Run the bot until the user presses Ctrl-C
|
||||
application.run_polling()
|
||||
application.run_polling(allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
+12
-2
@@ -1,6 +1,6 @@
|
||||
[tool.black]
|
||||
line-length = 99
|
||||
target-version = ['py37', 'py38', 'py39', 'py310', 'py311']
|
||||
target-version = ['py38', 'py39', 'py310', 'py311']
|
||||
|
||||
[tool.isort] # black config
|
||||
profile = "black"
|
||||
@@ -8,4 +8,14 @@ line_length = 99
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 99
|
||||
target-version = "py37"
|
||||
target-version = "py38"
|
||||
show-fixes = true
|
||||
ignore = ["PLR2004", "PLR0911", "PLR0912", "PLR0913", "PLR0915", "PERF203"]
|
||||
select = ["E", "F", "I", "PL", "UP", "RUF", "PTH", "C4", "B", "PIE", "SIM", "RET", "RSE",
|
||||
"G", "ISC", "PT", "ASYNC", "TCH", "CPY", "SLOT", "PERF", "PYI"]
|
||||
|
||||
[tool.ruff.per-file-ignores]
|
||||
"tests/*.py" = ["B018"]
|
||||
"**/__init__.py" = ["CPY001"]
|
||||
"examples/**.py" = ["CPY001"]
|
||||
"tests/**.py" = ["RUF012"]
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
pre-commit # needed for pre-commit hooks in the git commit command
|
||||
|
||||
# For the test suite
|
||||
pytest==7.2.2
|
||||
pytest-asyncio==0.21.0 # needed because pytest doesn't come with native support for coroutines as tests
|
||||
pytest-xdist==3.2.1 # xdist runs tests in parallel
|
||||
pytest==7.4.0
|
||||
pytest-asyncio==0.21.1 # needed because pytest doesn't come with native support for coroutines as tests
|
||||
pytest-xdist==3.3.1 # xdist runs tests in parallel
|
||||
flaky # Used for flaky tests (flaky decorator)
|
||||
beautifulsoup4 # used in test_official for parsing tg docs
|
||||
|
||||
|
||||
@@ -13,15 +13,15 @@
|
||||
httpx[socks] # socks
|
||||
httpx[http2] # http2
|
||||
cryptography!=3.4,!=3.4.1,!=3.4.2,!=3.4.3,>=39.0.1 # passport
|
||||
aiolimiter~=1.0.0 # rate-limiter!ext
|
||||
aiolimiter~=1.1.0 # rate-limiter!ext
|
||||
|
||||
# tornado is rather stable, but let's not allow the next mayor release without prior testing
|
||||
tornado~=6.2 # webhooks!ext
|
||||
|
||||
# Cachetools and APS don't have a strict stability policy.
|
||||
# Let's be cautious for now.
|
||||
cachetools~=5.3.0 # callback-data!ext
|
||||
APScheduler~=3.10.1 # job-queue!ext
|
||||
cachetools~=5.3.1 # callback-data!ext
|
||||
APScheduler~=3.10.4 # job-queue!ext
|
||||
|
||||
# pytz is required by APS and just needs the lower bound due to #2120
|
||||
pytz>=2018.6 # job-queue!ext
|
||||
|
||||
+1
-1
@@ -6,4 +6,4 @@
|
||||
# versions and only increase the lower bound if necessary
|
||||
|
||||
# httpx has no stable release yet, so let's be cautious for now
|
||||
httpx ~= 0.23.3
|
||||
httpx ~= 0.24.1
|
||||
|
||||
@@ -64,7 +64,6 @@ disallow_untyped_defs = True
|
||||
disallow_incomplete_defs = True
|
||||
disallow_untyped_decorators = True
|
||||
show_error_codes = True
|
||||
implicit_optional = True
|
||||
|
||||
# For some files, it's easier to just disable strict-optional all together instead of
|
||||
# cluttering the code with `# type: ignore`s or stuff like
|
||||
@@ -79,9 +78,17 @@ warn_unused_ignores = False
|
||||
[mypy-apscheduler.*]
|
||||
ignore_missing_imports = True
|
||||
|
||||
# uvicorn and starlette are only used for the `customwebhookbot.py` example
|
||||
# The libs listed below are only used for the `customwebhookbot_*.py` examples
|
||||
# let's just ignore type checking for them for now
|
||||
[mypy-uvicorn.*]
|
||||
ignore_missing_imports = True
|
||||
[mypy-starlette.*]
|
||||
ignore_missing_imports = True
|
||||
[mypy-asgiref.*]
|
||||
ignore_missing_imports = True
|
||||
[mypy-flask.*]
|
||||
ignore_missing_imports = True
|
||||
[mypy-quart.*]
|
||||
ignore_missing_imports = True
|
||||
[mypy-django.*]
|
||||
ignore_missing_imports = True
|
||||
|
||||
@@ -105,13 +105,13 @@ def get_setup_kwargs(raw=False):
|
||||
"Topic :: Internet",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.7",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
],
|
||||
python_requires=">=3.7",
|
||||
python_requires=">=3.8",
|
||||
)
|
||||
|
||||
return kwargs
|
||||
|
||||
@@ -38,6 +38,7 @@ __all__ = ( # Keep this alphabetically ordered
|
||||
"BotCommandScopeChatMember",
|
||||
"BotCommandScopeDefault",
|
||||
"BotDescription",
|
||||
"BotName",
|
||||
"BotShortDescription",
|
||||
"CallbackGame",
|
||||
"CallbackQuery",
|
||||
@@ -102,6 +103,7 @@ __all__ = ( # Keep this alphabetically ordered
|
||||
"InlineQueryResultLocation",
|
||||
"InlineQueryResultMpeg4Gif",
|
||||
"InlineQueryResultPhoto",
|
||||
"InlineQueryResultsButton",
|
||||
"InlineQueryResultVenue",
|
||||
"InlineQueryResultVideo",
|
||||
"InlineQueryResultVoice",
|
||||
@@ -168,7 +170,9 @@ __all__ = ( # Keep this alphabetically ordered
|
||||
"ShippingQuery",
|
||||
"Sticker",
|
||||
"StickerSet",
|
||||
"Story",
|
||||
"SuccessfulPayment",
|
||||
"SwitchInlineQueryChosenChat",
|
||||
"TelegramObject",
|
||||
"Update",
|
||||
"User",
|
||||
@@ -204,6 +208,7 @@ from ._botcommandscope import (
|
||||
BotCommandScopeDefault,
|
||||
)
|
||||
from ._botdescription import BotDescription, BotShortDescription
|
||||
from ._botname import BotName
|
||||
from ._callbackquery import CallbackQuery
|
||||
from ._chat import Chat
|
||||
from ._chatadministratorrights import ChatAdministratorRights
|
||||
@@ -280,6 +285,7 @@ from ._inline.inlinequeryresultgif import InlineQueryResultGif
|
||||
from ._inline.inlinequeryresultlocation import InlineQueryResultLocation
|
||||
from ._inline.inlinequeryresultmpeg4gif import InlineQueryResultMpeg4Gif
|
||||
from ._inline.inlinequeryresultphoto import InlineQueryResultPhoto
|
||||
from ._inline.inlinequeryresultsbutton import InlineQueryResultsButton
|
||||
from ._inline.inlinequeryresultvenue import InlineQueryResultVenue
|
||||
from ._inline.inlinequeryresultvideo import InlineQueryResultVideo
|
||||
from ._inline.inlinequeryresultvoice import InlineQueryResultVoice
|
||||
@@ -336,6 +342,8 @@ from ._replykeyboardmarkup import ReplyKeyboardMarkup
|
||||
from ._replykeyboardremove import ReplyKeyboardRemove
|
||||
from ._sentwebappmessage import SentWebAppMessage
|
||||
from ._shared import ChatShared, UserShared
|
||||
from ._story import Story
|
||||
from ._switchinlinequerychosenchat import SwitchInlineQueryChosenChat
|
||||
from ._telegramobject import TelegramObject
|
||||
from ._update import Update
|
||||
from ._user import User
|
||||
|
||||
+804
-1150
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,7 @@
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a Telegram Bot Command."""
|
||||
|
||||
from typing import ClassVar
|
||||
from typing import Final, Optional
|
||||
|
||||
from telegram import constants
|
||||
from telegram._telegramobject import TelegramObject
|
||||
@@ -52,7 +52,7 @@ class BotCommand(TelegramObject):
|
||||
|
||||
__slots__ = ("description", "command")
|
||||
|
||||
def __init__(self, command: str, description: str, *, api_kwargs: JSONDict = None):
|
||||
def __init__(self, command: str, description: str, *, api_kwargs: Optional[JSONDict] = None):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
self.command: str = command
|
||||
self.description: str = description
|
||||
@@ -61,22 +61,22 @@ class BotCommand(TelegramObject):
|
||||
|
||||
self._freeze()
|
||||
|
||||
MIN_COMMAND: ClassVar[int] = constants.BotCommandLimit.MIN_COMMAND
|
||||
MIN_COMMAND: Final[int] = constants.BotCommandLimit.MIN_COMMAND
|
||||
""":const:`telegram.constants.BotCommandLimit.MIN_COMMAND`
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
MAX_COMMAND: ClassVar[int] = constants.BotCommandLimit.MAX_COMMAND
|
||||
MAX_COMMAND: Final[int] = constants.BotCommandLimit.MAX_COMMAND
|
||||
""":const:`telegram.constants.BotCommandLimit.MAX_COMMAND`
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
MIN_DESCRIPTION: ClassVar[int] = constants.BotCommandLimit.MIN_DESCRIPTION
|
||||
MIN_DESCRIPTION: Final[int] = constants.BotCommandLimit.MIN_DESCRIPTION
|
||||
""":const:`telegram.constants.BotCommandLimit.MIN_DESCRIPTION`
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
MAX_DESCRIPTION: ClassVar[int] = constants.BotCommandLimit.MAX_DESCRIPTION
|
||||
MAX_DESCRIPTION: Final[int] = constants.BotCommandLimit.MAX_DESCRIPTION
|
||||
""":const:`telegram.constants.BotCommandLimit.MAX_DESCRIPTION`
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
# pylint: disable=redefined-builtin
|
||||
"""This module contains objects representing Telegram bot command scopes."""
|
||||
from typing import TYPE_CHECKING, ClassVar, Dict, Optional, Type, Union
|
||||
from typing import TYPE_CHECKING, Dict, Final, Optional, Type, Union
|
||||
|
||||
from telegram import constants
|
||||
from telegram._telegramobject import TelegramObject
|
||||
@@ -60,22 +60,22 @@ class BotCommandScope(TelegramObject):
|
||||
|
||||
__slots__ = ("type",)
|
||||
|
||||
DEFAULT: ClassVar[str] = constants.BotCommandScopeType.DEFAULT
|
||||
DEFAULT: Final[str] = constants.BotCommandScopeType.DEFAULT
|
||||
""":const:`telegram.constants.BotCommandScopeType.DEFAULT`"""
|
||||
ALL_PRIVATE_CHATS: ClassVar[str] = constants.BotCommandScopeType.ALL_PRIVATE_CHATS
|
||||
ALL_PRIVATE_CHATS: Final[str] = constants.BotCommandScopeType.ALL_PRIVATE_CHATS
|
||||
""":const:`telegram.constants.BotCommandScopeType.ALL_PRIVATE_CHATS`"""
|
||||
ALL_GROUP_CHATS: ClassVar[str] = constants.BotCommandScopeType.ALL_GROUP_CHATS
|
||||
ALL_GROUP_CHATS: Final[str] = constants.BotCommandScopeType.ALL_GROUP_CHATS
|
||||
""":const:`telegram.constants.BotCommandScopeType.ALL_GROUP_CHATS`"""
|
||||
ALL_CHAT_ADMINISTRATORS: ClassVar[str] = constants.BotCommandScopeType.ALL_CHAT_ADMINISTRATORS
|
||||
ALL_CHAT_ADMINISTRATORS: Final[str] = constants.BotCommandScopeType.ALL_CHAT_ADMINISTRATORS
|
||||
""":const:`telegram.constants.BotCommandScopeType.ALL_CHAT_ADMINISTRATORS`"""
|
||||
CHAT: ClassVar[str] = constants.BotCommandScopeType.CHAT
|
||||
CHAT: Final[str] = constants.BotCommandScopeType.CHAT
|
||||
""":const:`telegram.constants.BotCommandScopeType.CHAT`"""
|
||||
CHAT_ADMINISTRATORS: ClassVar[str] = constants.BotCommandScopeType.CHAT_ADMINISTRATORS
|
||||
CHAT_ADMINISTRATORS: Final[str] = constants.BotCommandScopeType.CHAT_ADMINISTRATORS
|
||||
""":const:`telegram.constants.BotCommandScopeType.CHAT_ADMINISTRATORS`"""
|
||||
CHAT_MEMBER: ClassVar[str] = constants.BotCommandScopeType.CHAT_MEMBER
|
||||
CHAT_MEMBER: Final[str] = constants.BotCommandScopeType.CHAT_MEMBER
|
||||
""":const:`telegram.constants.BotCommandScopeType.CHAT_MEMBER`"""
|
||||
|
||||
def __init__(self, type: str, *, api_kwargs: JSONDict = None):
|
||||
def __init__(self, type: str, *, api_kwargs: Optional[JSONDict] = None):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
self.type: str = type
|
||||
self._id_attrs = (self.type,)
|
||||
@@ -100,7 +100,7 @@ class BotCommandScope(TelegramObject):
|
||||
if not data:
|
||||
return None
|
||||
|
||||
_class_mapping: Dict[str, Type["BotCommandScope"]] = {
|
||||
_class_mapping: Dict[str, Type[BotCommandScope]] = {
|
||||
cls.DEFAULT: BotCommandScopeDefault,
|
||||
cls.ALL_PRIVATE_CHATS: BotCommandScopeAllPrivateChats,
|
||||
cls.ALL_GROUP_CHATS: BotCommandScopeAllGroupChats,
|
||||
@@ -128,7 +128,7 @@ class BotCommandScopeDefault(BotCommandScope):
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
def __init__(self, *, api_kwargs: JSONDict = None):
|
||||
def __init__(self, *, api_kwargs: Optional[JSONDict] = None):
|
||||
super().__init__(type=BotCommandScope.DEFAULT, api_kwargs=api_kwargs)
|
||||
self._freeze()
|
||||
|
||||
@@ -144,7 +144,7 @@ class BotCommandScopeAllPrivateChats(BotCommandScope):
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
def __init__(self, *, api_kwargs: JSONDict = None):
|
||||
def __init__(self, *, api_kwargs: Optional[JSONDict] = None):
|
||||
super().__init__(type=BotCommandScope.ALL_PRIVATE_CHATS, api_kwargs=api_kwargs)
|
||||
self._freeze()
|
||||
|
||||
@@ -159,7 +159,7 @@ class BotCommandScopeAllGroupChats(BotCommandScope):
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
def __init__(self, *, api_kwargs: JSONDict = None):
|
||||
def __init__(self, *, api_kwargs: Optional[JSONDict] = None):
|
||||
super().__init__(type=BotCommandScope.ALL_GROUP_CHATS, api_kwargs=api_kwargs)
|
||||
self._freeze()
|
||||
|
||||
@@ -174,7 +174,7 @@ class BotCommandScopeAllChatAdministrators(BotCommandScope):
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
def __init__(self, *, api_kwargs: JSONDict = None):
|
||||
def __init__(self, *, api_kwargs: Optional[JSONDict] = None):
|
||||
super().__init__(type=BotCommandScope.ALL_CHAT_ADMINISTRATORS, api_kwargs=api_kwargs)
|
||||
self._freeze()
|
||||
|
||||
@@ -197,7 +197,7 @@ class BotCommandScopeChat(BotCommandScope):
|
||||
|
||||
__slots__ = ("chat_id",)
|
||||
|
||||
def __init__(self, chat_id: Union[str, int], *, api_kwargs: JSONDict = None):
|
||||
def __init__(self, chat_id: Union[str, int], *, api_kwargs: Optional[JSONDict] = None):
|
||||
super().__init__(type=BotCommandScope.CHAT, api_kwargs=api_kwargs)
|
||||
with self._unfrozen():
|
||||
self.chat_id: Union[str, int] = (
|
||||
@@ -224,7 +224,7 @@ class BotCommandScopeChatAdministrators(BotCommandScope):
|
||||
|
||||
__slots__ = ("chat_id",)
|
||||
|
||||
def __init__(self, chat_id: Union[str, int], *, api_kwargs: JSONDict = None):
|
||||
def __init__(self, chat_id: Union[str, int], *, api_kwargs: Optional[JSONDict] = None):
|
||||
super().__init__(type=BotCommandScope.CHAT_ADMINISTRATORS, api_kwargs=api_kwargs)
|
||||
with self._unfrozen():
|
||||
self.chat_id: Union[str, int] = (
|
||||
@@ -254,7 +254,9 @@ class BotCommandScopeChatMember(BotCommandScope):
|
||||
|
||||
__slots__ = ("chat_id", "user_id")
|
||||
|
||||
def __init__(self, chat_id: Union[str, int], user_id: int, *, api_kwargs: JSONDict = None):
|
||||
def __init__(
|
||||
self, chat_id: Union[str, int], user_id: int, *, api_kwargs: Optional[JSONDict] = None
|
||||
):
|
||||
super().__init__(type=BotCommandScope.CHAT_MEMBER, api_kwargs=api_kwargs)
|
||||
with self._unfrozen():
|
||||
self.chat_id: Union[str, int] = (
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
# 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 two objects that represent a Telegram bots (short) description."""
|
||||
from typing import Optional
|
||||
|
||||
from telegram._telegramobject import TelegramObject
|
||||
from telegram._utils.types import JSONDict
|
||||
|
||||
@@ -39,9 +41,9 @@ class BotDescription(TelegramObject):
|
||||
|
||||
__slots__ = ("description",)
|
||||
|
||||
def __init__(self, description: str, *, api_kwargs: JSONDict = None):
|
||||
def __init__(self, description: str, *, api_kwargs: Optional[JSONDict] = None):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
self.description = description
|
||||
self.description: str = description
|
||||
|
||||
self._id_attrs = (self.description,)
|
||||
|
||||
@@ -66,9 +68,9 @@ class BotShortDescription(TelegramObject):
|
||||
|
||||
__slots__ = ("short_description",)
|
||||
|
||||
def __init__(self, short_description: str, *, api_kwargs: JSONDict = None):
|
||||
def __init__(self, short_description: str, *, api_kwargs: Optional[JSONDict] = None):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
self.short_description = short_description
|
||||
self.short_description: str = short_description
|
||||
|
||||
self._id_attrs = (self.short_description,)
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2023
|
||||
# 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 an object that represent a Telegram bots name."""
|
||||
from typing import Final, Optional
|
||||
|
||||
from telegram import constants
|
||||
from telegram._telegramobject import TelegramObject
|
||||
from telegram._utils.types import JSONDict
|
||||
|
||||
|
||||
class BotName(TelegramObject):
|
||||
"""This object represents the bot's name.
|
||||
|
||||
Objects of this class are comparable in terms of equality. Two objects of this class are
|
||||
considered equal, if their :attr:`name` is equal.
|
||||
|
||||
.. versionadded:: 20.3
|
||||
|
||||
Args:
|
||||
name (:obj:`str`): The bot's name.
|
||||
|
||||
Attributes:
|
||||
name (:obj:`str`): The bot's name.
|
||||
|
||||
"""
|
||||
|
||||
__slots__ = ("name",)
|
||||
|
||||
def __init__(self, name: str, *, api_kwargs: Optional[JSONDict] = None):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
self.name: str = name
|
||||
|
||||
self._id_attrs = (self.name,)
|
||||
|
||||
self._freeze()
|
||||
|
||||
MAX_LENGTH: Final[int] = constants.BotNameLimit.MAX_NAME_LENGTH
|
||||
""":const:`telegram.constants.BotNameLimit.MAX_NAME_LENGTH`"""
|
||||
+45
-45
@@ -18,7 +18,7 @@
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
# pylint: disable=redefined-builtin
|
||||
"""This module contains an object that represents a Telegram CallbackQuery"""
|
||||
from typing import TYPE_CHECKING, ClassVar, Optional, Sequence, Tuple, Union
|
||||
from typing import TYPE_CHECKING, Final, Optional, Sequence, Tuple, Union
|
||||
|
||||
from telegram import constants
|
||||
from telegram._files.location import Location
|
||||
@@ -118,12 +118,12 @@ class CallbackQuery(TelegramObject):
|
||||
id: str,
|
||||
from_user: User,
|
||||
chat_instance: str,
|
||||
message: Message = None,
|
||||
data: str = None,
|
||||
inline_message_id: str = None,
|
||||
game_short_name: str = None,
|
||||
message: Optional[Message] = None,
|
||||
data: Optional[str] = None,
|
||||
inline_message_id: Optional[str] = None,
|
||||
game_short_name: Optional[str] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
# Required
|
||||
@@ -155,16 +155,16 @@ class CallbackQuery(TelegramObject):
|
||||
|
||||
async def answer(
|
||||
self,
|
||||
text: str = None,
|
||||
show_alert: bool = None,
|
||||
url: str = None,
|
||||
cache_time: int = None,
|
||||
text: Optional[str] = None,
|
||||
show_alert: Optional[bool] = None,
|
||||
url: Optional[str] = None,
|
||||
cache_time: Optional[int] = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
connect_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
) -> bool:
|
||||
"""Shortcut for::
|
||||
|
||||
@@ -195,14 +195,14 @@ class CallbackQuery(TelegramObject):
|
||||
text: str,
|
||||
parse_mode: ODVInput[str] = DEFAULT_NONE,
|
||||
disable_web_page_preview: ODVInput[bool] = DEFAULT_NONE,
|
||||
reply_markup: "InlineKeyboardMarkup" = None,
|
||||
entities: Sequence["MessageEntity"] = None,
|
||||
reply_markup: Optional["InlineKeyboardMarkup"] = None,
|
||||
entities: Optional[Sequence["MessageEntity"]] = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
connect_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
) -> Union[Message, bool]:
|
||||
"""Shortcut for either::
|
||||
|
||||
@@ -253,16 +253,16 @@ class CallbackQuery(TelegramObject):
|
||||
|
||||
async def edit_message_caption(
|
||||
self,
|
||||
caption: str = None,
|
||||
reply_markup: "InlineKeyboardMarkup" = None,
|
||||
caption: Optional[str] = None,
|
||||
reply_markup: Optional["InlineKeyboardMarkup"] = None,
|
||||
parse_mode: ODVInput[str] = DEFAULT_NONE,
|
||||
caption_entities: Sequence["MessageEntity"] = None,
|
||||
caption_entities: Optional[Sequence["MessageEntity"]] = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
connect_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
) -> Union[Message, bool]:
|
||||
"""Shortcut for either::
|
||||
|
||||
@@ -317,7 +317,7 @@ class CallbackQuery(TelegramObject):
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
connect_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
) -> Union[Message, bool]:
|
||||
"""Shortcut for either::
|
||||
|
||||
@@ -362,13 +362,13 @@ class CallbackQuery(TelegramObject):
|
||||
async def edit_message_media(
|
||||
self,
|
||||
media: "InputMedia",
|
||||
reply_markup: "InlineKeyboardMarkup" = None,
|
||||
reply_markup: Optional["InlineKeyboardMarkup"] = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
connect_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
) -> Union[Message, bool]:
|
||||
"""Shortcut for either::
|
||||
|
||||
@@ -413,19 +413,19 @@ class CallbackQuery(TelegramObject):
|
||||
|
||||
async def edit_message_live_location(
|
||||
self,
|
||||
latitude: float = None,
|
||||
longitude: float = None,
|
||||
reply_markup: "InlineKeyboardMarkup" = None,
|
||||
horizontal_accuracy: float = None,
|
||||
heading: int = None,
|
||||
proximity_alert_radius: int = None,
|
||||
latitude: Optional[float] = None,
|
||||
longitude: Optional[float] = None,
|
||||
reply_markup: Optional["InlineKeyboardMarkup"] = None,
|
||||
horizontal_accuracy: Optional[float] = None,
|
||||
heading: Optional[int] = None,
|
||||
proximity_alert_radius: Optional[int] = None,
|
||||
*,
|
||||
location: Location = None,
|
||||
location: Optional[Location] = None,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
connect_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
) -> Union[Message, bool]:
|
||||
"""Shortcut for either::
|
||||
|
||||
@@ -481,13 +481,13 @@ class CallbackQuery(TelegramObject):
|
||||
|
||||
async def stop_message_live_location(
|
||||
self,
|
||||
reply_markup: "InlineKeyboardMarkup" = None,
|
||||
reply_markup: Optional["InlineKeyboardMarkup"] = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
connect_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
) -> Union[Message, bool]:
|
||||
"""Shortcut for either::
|
||||
|
||||
@@ -533,14 +533,14 @@ class CallbackQuery(TelegramObject):
|
||||
self,
|
||||
user_id: Union[int, str],
|
||||
score: int,
|
||||
force: bool = None,
|
||||
disable_edit_message: bool = None,
|
||||
force: Optional[bool] = None,
|
||||
disable_edit_message: Optional[bool] = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
connect_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
) -> Union[Message, bool]:
|
||||
"""Shortcut for either::
|
||||
|
||||
@@ -595,7 +595,7 @@ class CallbackQuery(TelegramObject):
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
connect_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
) -> Tuple["GameHighScore", ...]:
|
||||
"""Shortcut for either::
|
||||
|
||||
@@ -643,7 +643,7 @@ class CallbackQuery(TelegramObject):
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
connect_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
) -> bool:
|
||||
"""Shortcut for::
|
||||
|
||||
@@ -671,7 +671,7 @@ class CallbackQuery(TelegramObject):
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
connect_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
) -> bool:
|
||||
"""Shortcut for::
|
||||
|
||||
@@ -699,7 +699,7 @@ class CallbackQuery(TelegramObject):
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
connect_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
) -> bool:
|
||||
"""Shortcut for::
|
||||
|
||||
@@ -722,21 +722,21 @@ class CallbackQuery(TelegramObject):
|
||||
async def copy_message(
|
||||
self,
|
||||
chat_id: Union[int, str],
|
||||
caption: str = None,
|
||||
caption: Optional[str] = None,
|
||||
parse_mode: ODVInput[str] = DEFAULT_NONE,
|
||||
caption_entities: Sequence["MessageEntity"] = None,
|
||||
caption_entities: Optional[Sequence["MessageEntity"]] = None,
|
||||
disable_notification: DVInput[bool] = DEFAULT_NONE,
|
||||
reply_to_message_id: int = None,
|
||||
reply_to_message_id: Optional[int] = None,
|
||||
allow_sending_without_reply: DVInput[bool] = DEFAULT_NONE,
|
||||
reply_markup: ReplyMarkup = None,
|
||||
reply_markup: Optional[ReplyMarkup] = None,
|
||||
protect_content: ODVInput[bool] = DEFAULT_NONE,
|
||||
message_thread_id: int = None,
|
||||
message_thread_id: Optional[int] = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
connect_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
) -> "MessageId":
|
||||
"""Shortcut for::
|
||||
|
||||
@@ -771,7 +771,7 @@ class CallbackQuery(TelegramObject):
|
||||
message_thread_id=message_thread_id,
|
||||
)
|
||||
|
||||
MAX_ANSWER_TEXT_LENGTH: ClassVar[
|
||||
MAX_ANSWER_TEXT_LENGTH: Final[
|
||||
int
|
||||
] = constants.CallbackQueryLimit.ANSWER_CALLBACK_QUERY_TEXT_LENGTH
|
||||
"""
|
||||
|
||||
+346
-295
File diff suppressed because it is too large
Load Diff
@@ -127,12 +127,12 @@ class ChatAdministratorRights(TelegramObject):
|
||||
can_promote_members: bool,
|
||||
can_change_info: bool,
|
||||
can_invite_users: bool,
|
||||
can_post_messages: bool = None,
|
||||
can_edit_messages: bool = None,
|
||||
can_pin_messages: bool = None,
|
||||
can_manage_topics: bool = None,
|
||||
can_post_messages: Optional[bool] = None,
|
||||
can_edit_messages: Optional[bool] = None,
|
||||
can_pin_messages: Optional[bool] = None,
|
||||
can_manage_topics: Optional[bool] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
) -> None:
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
# Required
|
||||
|
||||
@@ -22,7 +22,7 @@ from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from telegram._telegramobject import TelegramObject
|
||||
from telegram._user import User
|
||||
from telegram._utils.datetime import from_timestamp
|
||||
from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp
|
||||
from telegram._utils.types import JSONDict
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -54,6 +54,9 @@ class ChatInviteLink(TelegramObject):
|
||||
is_revoked (:obj:`bool`): :obj:`True`, if the link is revoked.
|
||||
expire_date (:class:`datetime.datetime`, optional): Date when the link will expire or
|
||||
has been expired.
|
||||
|
||||
.. versionchanged:: 20.3
|
||||
|datetime_localization|
|
||||
member_limit (:obj:`int`, optional): Maximum number of users that can be members of the
|
||||
chat simultaneously after joining the chat via this invite link;
|
||||
:tg-const:`telegram.constants.ChatInviteLinkLimit.MIN_MEMBER_LIMIT`-
|
||||
@@ -78,6 +81,9 @@ class ChatInviteLink(TelegramObject):
|
||||
is_revoked (:obj:`bool`): :obj:`True`, if the link is revoked.
|
||||
expire_date (:class:`datetime.datetime`): Optional. Date when the link will expire or
|
||||
has been expired.
|
||||
|
||||
.. versionchanged:: 20.3
|
||||
|datetime_localization|
|
||||
member_limit (:obj:`int`): Optional. Maximum number of users that can be members
|
||||
of the chat simultaneously after joining the chat via this invite link;
|
||||
:tg-const:`telegram.constants.ChatInviteLinkLimit.MIN_MEMBER_LIMIT`-
|
||||
@@ -112,12 +118,12 @@ class ChatInviteLink(TelegramObject):
|
||||
creates_join_request: bool,
|
||||
is_primary: bool,
|
||||
is_revoked: bool,
|
||||
expire_date: datetime.datetime = None,
|
||||
member_limit: int = None,
|
||||
name: str = None,
|
||||
pending_join_request_count: int = None,
|
||||
expire_date: Optional[datetime.datetime] = None,
|
||||
member_limit: Optional[int] = None,
|
||||
name: Optional[str] = None,
|
||||
pending_join_request_count: Optional[int] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
# Required
|
||||
@@ -152,7 +158,10 @@ class ChatInviteLink(TelegramObject):
|
||||
if not data:
|
||||
return None
|
||||
|
||||
# Get the local timezone from the bot if it has defaults
|
||||
loc_tzinfo = extract_tzinfo_from_defaults(bot)
|
||||
|
||||
data["creator"] = User.de_json(data.get("creator"), bot)
|
||||
data["expire_date"] = from_timestamp(data.get("expire_date", None))
|
||||
data["expire_date"] = from_timestamp(data.get("expire_date", None), tzinfo=loc_tzinfo)
|
||||
|
||||
return super().de_json(data=data, bot=bot)
|
||||
|
||||
@@ -24,7 +24,7 @@ from telegram._chat import Chat
|
||||
from telegram._chatinvitelink import ChatInviteLink
|
||||
from telegram._telegramobject import TelegramObject
|
||||
from telegram._user import User
|
||||
from telegram._utils.datetime import from_timestamp
|
||||
from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp
|
||||
from telegram._utils.defaultvalue import DEFAULT_NONE
|
||||
from telegram._utils.types import JSONDict, ODVInput
|
||||
|
||||
@@ -41,7 +41,7 @@ class ChatJoinRequest(TelegramObject):
|
||||
Note:
|
||||
* Since Bot API 5.5, bots are allowed to contact users who sent a join request to a chat
|
||||
where the bot is an administrator with the
|
||||
:attr:`~telegram.ChatMemberAdministrator.can_invite_users` administrator right – even
|
||||
:attr:`~telegram.ChatMemberAdministrator.can_invite_users` administrator right - even
|
||||
if the user never interacted with the bot before.
|
||||
* Telegram does not guarantee that :attr:`from_user.id <from_user>` coincides with the
|
||||
``chat_id`` of the user. Please use :attr:`user_chat_id` to contact the user in
|
||||
@@ -56,6 +56,9 @@ class ChatJoinRequest(TelegramObject):
|
||||
chat (:class:`telegram.Chat`): Chat to which the request was sent.
|
||||
from_user (:class:`telegram.User`): User that sent the join request.
|
||||
date (:class:`datetime.datetime`): Date the request was sent.
|
||||
|
||||
.. versionchanged:: 20.3
|
||||
|datetime_localization|
|
||||
user_chat_id (:obj:`int`): Identifier of a private chat with the user who sent the join
|
||||
request. This number may have more than 32 significant bits and some programming
|
||||
languages may have difficulty/silent defects in interpreting it. But it has at most 52
|
||||
@@ -73,6 +76,9 @@ class ChatJoinRequest(TelegramObject):
|
||||
chat (:class:`telegram.Chat`): Chat to which the request was sent.
|
||||
from_user (:class:`telegram.User`): User that sent the join request.
|
||||
date (:class:`datetime.datetime`): Date the request was sent.
|
||||
|
||||
.. versionchanged:: 20.3
|
||||
|datetime_localization|
|
||||
user_chat_id (:obj:`int`): Identifier of a private chat with the user who sent the join
|
||||
request. This number may have more than 32 significant bits and some programming
|
||||
languages may have difficulty/silent defects in interpreting it. But it has at most 52
|
||||
@@ -86,6 +92,12 @@ class ChatJoinRequest(TelegramObject):
|
||||
invite_link (:class:`telegram.ChatInviteLink`): Optional. Chat invite link that was used
|
||||
by the user to send the join request.
|
||||
|
||||
Note:
|
||||
When a user joins a *public* group via an invite link, this attribute may not
|
||||
be present. However, this behavior is undocument and may be subject to change.
|
||||
See `this GitHub thread <https://github.com/tdlib/telegram-bot-api/issues/428>`_
|
||||
for some discussion.
|
||||
|
||||
"""
|
||||
|
||||
__slots__ = ("chat", "from_user", "date", "bio", "invite_link", "user_chat_id")
|
||||
@@ -96,10 +108,10 @@ class ChatJoinRequest(TelegramObject):
|
||||
from_user: User,
|
||||
date: datetime.datetime,
|
||||
user_chat_id: int,
|
||||
bio: str = None,
|
||||
invite_link: ChatInviteLink = None,
|
||||
bio: Optional[str] = None,
|
||||
invite_link: Optional[ChatInviteLink] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
# Required
|
||||
@@ -124,9 +136,12 @@ class ChatJoinRequest(TelegramObject):
|
||||
if not data:
|
||||
return None
|
||||
|
||||
# Get the local timezone from the bot if it has defaults
|
||||
loc_tzinfo = extract_tzinfo_from_defaults(bot)
|
||||
|
||||
data["chat"] = Chat.de_json(data.get("chat"), bot)
|
||||
data["from_user"] = User.de_json(data.pop("from", None), bot)
|
||||
data["date"] = from_timestamp(data.get("date", None))
|
||||
data["date"] = from_timestamp(data.get("date", None), tzinfo=loc_tzinfo)
|
||||
data["invite_link"] = ChatInviteLink.de_json(data.get("invite_link"), bot)
|
||||
|
||||
return super().de_json(data=data, bot=bot)
|
||||
@@ -138,7 +153,7 @@ class ChatJoinRequest(TelegramObject):
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
connect_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
) -> bool:
|
||||
"""Shortcut for::
|
||||
|
||||
@@ -170,7 +185,7 @@ class ChatJoinRequest(TelegramObject):
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
connect_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
) -> bool:
|
||||
"""Shortcut for::
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a location to which a chat is connected."""
|
||||
|
||||
from typing import TYPE_CHECKING, ClassVar, Optional
|
||||
from typing import TYPE_CHECKING, Final, Optional
|
||||
|
||||
from telegram import constants
|
||||
from telegram._files.location import Location
|
||||
@@ -57,7 +57,7 @@ class ChatLocation(TelegramObject):
|
||||
location: Location,
|
||||
address: str,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
self.location: Location = location
|
||||
@@ -79,12 +79,12 @@ class ChatLocation(TelegramObject):
|
||||
|
||||
return super().de_json(data=data, bot=bot)
|
||||
|
||||
MIN_ADDRESS: ClassVar[int] = constants.LocationLimit.MIN_CHAT_LOCATION_ADDRESS
|
||||
MIN_ADDRESS: Final[int] = constants.LocationLimit.MIN_CHAT_LOCATION_ADDRESS
|
||||
""":const:`telegram.constants.LocationLimit.MIN_CHAT_LOCATION_ADDRESS`
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
MAX_ADDRESS: ClassVar[int] = constants.LocationLimit.MAX_CHAT_LOCATION_ADDRESS
|
||||
MAX_ADDRESS: Final[int] = constants.LocationLimit.MAX_CHAT_LOCATION_ADDRESS
|
||||
""":const:`telegram.constants.LocationLimit.MAX_CHAT_LOCATION_ADDRESS`
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
+47
-36
@@ -18,12 +18,12 @@
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a Telegram ChatMember."""
|
||||
import datetime
|
||||
from typing import TYPE_CHECKING, ClassVar, Dict, Optional, Type
|
||||
from typing import TYPE_CHECKING, Dict, Final, Optional, Type
|
||||
|
||||
from telegram import constants
|
||||
from telegram._telegramobject import TelegramObject
|
||||
from telegram._user import User
|
||||
from telegram._utils.datetime import from_timestamp
|
||||
from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp
|
||||
from telegram._utils.types import JSONDict
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -74,17 +74,17 @@ class ChatMember(TelegramObject):
|
||||
|
||||
__slots__ = ("user", "status")
|
||||
|
||||
ADMINISTRATOR: ClassVar[str] = constants.ChatMemberStatus.ADMINISTRATOR
|
||||
ADMINISTRATOR: Final[str] = constants.ChatMemberStatus.ADMINISTRATOR
|
||||
""":const:`telegram.constants.ChatMemberStatus.ADMINISTRATOR`"""
|
||||
OWNER: ClassVar[str] = constants.ChatMemberStatus.OWNER
|
||||
OWNER: Final[str] = constants.ChatMemberStatus.OWNER
|
||||
""":const:`telegram.constants.ChatMemberStatus.OWNER`"""
|
||||
BANNED: ClassVar[str] = constants.ChatMemberStatus.BANNED
|
||||
BANNED: Final[str] = constants.ChatMemberStatus.BANNED
|
||||
""":const:`telegram.constants.ChatMemberStatus.BANNED`"""
|
||||
LEFT: ClassVar[str] = constants.ChatMemberStatus.LEFT
|
||||
LEFT: Final[str] = constants.ChatMemberStatus.LEFT
|
||||
""":const:`telegram.constants.ChatMemberStatus.LEFT`"""
|
||||
MEMBER: ClassVar[str] = constants.ChatMemberStatus.MEMBER
|
||||
MEMBER: Final[str] = constants.ChatMemberStatus.MEMBER
|
||||
""":const:`telegram.constants.ChatMemberStatus.MEMBER`"""
|
||||
RESTRICTED: ClassVar[str] = constants.ChatMemberStatus.RESTRICTED
|
||||
RESTRICTED: Final[str] = constants.ChatMemberStatus.RESTRICTED
|
||||
""":const:`telegram.constants.ChatMemberStatus.RESTRICTED`"""
|
||||
|
||||
def __init__(
|
||||
@@ -92,7 +92,7 @@ class ChatMember(TelegramObject):
|
||||
user: User,
|
||||
status: str,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
# Required by all subclasses
|
||||
@@ -111,7 +111,7 @@ class ChatMember(TelegramObject):
|
||||
if not data:
|
||||
return None
|
||||
|
||||
_class_mapping: Dict[str, Type["ChatMember"]] = {
|
||||
_class_mapping: Dict[str, Type[ChatMember]] = {
|
||||
cls.OWNER: ChatMemberOwner,
|
||||
cls.ADMINISTRATOR: ChatMemberAdministrator,
|
||||
cls.MEMBER: ChatMemberMember,
|
||||
@@ -125,7 +125,16 @@ class ChatMember(TelegramObject):
|
||||
|
||||
data["user"] = User.de_json(data.get("user"), bot)
|
||||
if "until_date" in data:
|
||||
data["until_date"] = from_timestamp(data["until_date"])
|
||||
# Get the local timezone from the bot if it has defaults
|
||||
loc_tzinfo = extract_tzinfo_from_defaults(bot)
|
||||
|
||||
data["until_date"] = from_timestamp(data["until_date"], tzinfo=loc_tzinfo)
|
||||
|
||||
# This is a deprecated field that TG still returns for backwards compatibility
|
||||
# Let's filter it out to speed up the de-json process
|
||||
if cls is ChatMemberRestricted and data.get("can_send_media_messages") is not None:
|
||||
api_kwargs = {"can_send_media_messages": data.pop("can_send_media_messages")}
|
||||
return super()._de_json(data=data, bot=bot, api_kwargs=api_kwargs)
|
||||
|
||||
return super().de_json(data=data, bot=bot)
|
||||
|
||||
@@ -159,9 +168,9 @@ class ChatMemberOwner(ChatMember):
|
||||
self,
|
||||
user: User,
|
||||
is_anonymous: bool,
|
||||
custom_title: str = None,
|
||||
custom_title: Optional[str] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(status=ChatMember.OWNER, user=user, api_kwargs=api_kwargs)
|
||||
with self._unfrozen():
|
||||
@@ -292,13 +301,13 @@ class ChatMemberAdministrator(ChatMember):
|
||||
can_promote_members: bool,
|
||||
can_change_info: bool,
|
||||
can_invite_users: bool,
|
||||
can_post_messages: bool = None,
|
||||
can_edit_messages: bool = None,
|
||||
can_pin_messages: bool = None,
|
||||
can_manage_topics: bool = None,
|
||||
custom_title: str = None,
|
||||
can_post_messages: Optional[bool] = None,
|
||||
can_edit_messages: Optional[bool] = None,
|
||||
can_pin_messages: Optional[bool] = None,
|
||||
can_manage_topics: Optional[bool] = None,
|
||||
custom_title: Optional[str] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(status=ChatMember.ADMINISTRATOR, user=user, api_kwargs=api_kwargs)
|
||||
with self._unfrozen():
|
||||
@@ -341,7 +350,7 @@ class ChatMemberMember(ChatMember):
|
||||
self,
|
||||
user: User,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(status=ChatMember.MEMBER, user=user, api_kwargs=api_kwargs)
|
||||
self._freeze()
|
||||
@@ -357,6 +366,9 @@ class ChatMemberRestricted(ChatMember):
|
||||
All arguments were made positional and their order was changed.
|
||||
The argument can_manage_topics was added.
|
||||
|
||||
.. versionchanged:: 20.5
|
||||
Removed deprecated argument and attribute ``can_send_media_messages``.
|
||||
|
||||
Args:
|
||||
user (:class:`telegram.User`): Information about the user.
|
||||
is_member (:obj:`bool`): :obj:`True`, if the user is a
|
||||
@@ -369,11 +381,6 @@ class ChatMemberRestricted(ChatMember):
|
||||
to pin messages; groups and supergroups only.
|
||||
can_send_messages (:obj:`bool`): :obj:`True`, if the user is allowed
|
||||
to send text messages, contacts, invoices, locations and venues.
|
||||
can_send_media_messages (:obj:`bool`): :obj:`True`, if the user is allowed
|
||||
to send audios, documents, photos, videos, video notes and voice notes.
|
||||
|
||||
.. deprecated:: 20.1
|
||||
Bot API 6.5 replaced this argument with granular media settings.
|
||||
can_send_polls (:obj:`bool`): :obj:`True`, if the user is allowed
|
||||
to send polls.
|
||||
can_send_other_messages (:obj:`bool`): :obj:`True`, if the user is allowed
|
||||
@@ -386,6 +393,9 @@ class ChatMemberRestricted(ChatMember):
|
||||
.. versionadded:: 20.0
|
||||
until_date (:class:`datetime.datetime`): Date when restrictions
|
||||
will be lifted for this user.
|
||||
|
||||
.. versionchanged:: 20.3
|
||||
|datetime_localization|
|
||||
can_send_audios (:obj:`bool`): :obj:`True`, if the user is allowed to send audios.
|
||||
|
||||
.. versionadded:: 20.1
|
||||
@@ -421,11 +431,6 @@ class ChatMemberRestricted(ChatMember):
|
||||
to pin messages; groups and supergroups only.
|
||||
can_send_messages (:obj:`bool`): :obj:`True`, if the user is allowed
|
||||
to send text messages, contacts, locations and venues.
|
||||
can_send_media_messages (:obj:`bool`): :obj:`True`, if the user is allowed
|
||||
to send audios, documents, photos, videos, video notes and voice notes.
|
||||
|
||||
.. deprecated:: 20.1
|
||||
Bot API 6.5 replaced this attribute with granular media settings.
|
||||
can_send_polls (:obj:`bool`): :obj:`True`, if the user is allowed
|
||||
to send polls.
|
||||
can_send_other_messages (:obj:`bool`): :obj:`True`, if the user is allowed
|
||||
@@ -438,6 +443,9 @@ class ChatMemberRestricted(ChatMember):
|
||||
.. versionadded:: 20.0
|
||||
until_date (:class:`datetime.datetime`): Date when restrictions
|
||||
will be lifted for this user.
|
||||
|
||||
.. versionchanged:: 20.3
|
||||
|datetime_localization|
|
||||
can_send_audios (:obj:`bool`): :obj:`True`, if the user is allowed to send audios.
|
||||
|
||||
.. versionadded:: 20.1
|
||||
@@ -467,7 +475,6 @@ class ChatMemberRestricted(ChatMember):
|
||||
"can_invite_users",
|
||||
"can_pin_messages",
|
||||
"can_send_messages",
|
||||
"can_send_media_messages",
|
||||
"can_send_polls",
|
||||
"can_send_other_messages",
|
||||
"can_add_web_page_previews",
|
||||
@@ -489,7 +496,6 @@ class ChatMemberRestricted(ChatMember):
|
||||
can_invite_users: bool,
|
||||
can_pin_messages: bool,
|
||||
can_send_messages: bool,
|
||||
can_send_media_messages: bool,
|
||||
can_send_polls: bool,
|
||||
can_send_other_messages: bool,
|
||||
can_add_web_page_previews: bool,
|
||||
@@ -502,7 +508,7 @@ class ChatMemberRestricted(ChatMember):
|
||||
can_send_video_notes: bool,
|
||||
can_send_voice_notes: bool,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(status=ChatMember.RESTRICTED, user=user, api_kwargs=api_kwargs)
|
||||
with self._unfrozen():
|
||||
@@ -511,7 +517,6 @@ class ChatMemberRestricted(ChatMember):
|
||||
self.can_invite_users: bool = can_invite_users
|
||||
self.can_pin_messages: bool = can_pin_messages
|
||||
self.can_send_messages: bool = can_send_messages
|
||||
self.can_send_media_messages: bool = can_send_media_messages
|
||||
self.can_send_polls: bool = can_send_polls
|
||||
self.can_send_other_messages: bool = can_send_other_messages
|
||||
self.can_add_web_page_previews: bool = can_add_web_page_previews
|
||||
@@ -547,7 +552,7 @@ class ChatMemberLeft(ChatMember):
|
||||
self,
|
||||
user: User,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(status=ChatMember.LEFT, user=user, api_kwargs=api_kwargs)
|
||||
self._freeze()
|
||||
@@ -565,6 +570,9 @@ class ChatMemberBanned(ChatMember):
|
||||
until_date (:class:`datetime.datetime`): Date when restrictions
|
||||
will be lifted for this user.
|
||||
|
||||
.. versionchanged:: 20.3
|
||||
|datetime_localization|
|
||||
|
||||
Attributes:
|
||||
status (:obj:`str`): The member's status in the chat,
|
||||
always :tg-const:`telegram.ChatMember.BANNED`.
|
||||
@@ -572,6 +580,9 @@ class ChatMemberBanned(ChatMember):
|
||||
until_date (:class:`datetime.datetime`): Date when restrictions
|
||||
will be lifted for this user.
|
||||
|
||||
.. versionchanged:: 20.3
|
||||
|datetime_localization|
|
||||
|
||||
"""
|
||||
|
||||
__slots__ = ("until_date",)
|
||||
@@ -581,7 +592,7 @@ class ChatMemberBanned(ChatMember):
|
||||
user: User,
|
||||
until_date: datetime.datetime,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(status=ChatMember.BANNED, user=user, api_kwargs=api_kwargs)
|
||||
with self._unfrozen():
|
||||
|
||||
@@ -25,7 +25,7 @@ from telegram._chatinvitelink import ChatInviteLink
|
||||
from telegram._chatmember import ChatMember
|
||||
from telegram._telegramobject import TelegramObject
|
||||
from telegram._user import User
|
||||
from telegram._utils.datetime import from_timestamp
|
||||
from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp
|
||||
from telegram._utils.types import JSONDict
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -52,20 +52,34 @@ class ChatMemberUpdated(TelegramObject):
|
||||
from_user (:class:`telegram.User`): Performer of the action, which resulted in the change.
|
||||
date (:class:`datetime.datetime`): Date the change was done in Unix time. Converted to
|
||||
:class:`datetime.datetime`.
|
||||
|
||||
.. versionchanged:: 20.3
|
||||
|datetime_localization|
|
||||
old_chat_member (:class:`telegram.ChatMember`): Previous information about the chat member.
|
||||
new_chat_member (:class:`telegram.ChatMember`): New information about the chat member.
|
||||
invite_link (:class:`telegram.ChatInviteLink`, optional): Chat invite link, which was used
|
||||
by the user to join the chat. For joining by invite link events only.
|
||||
via_chat_folder_invite_link (:obj:`bool`, optional): :obj:`True`, if the user joined the
|
||||
chat via a chat folder invite link
|
||||
|
||||
.. versionadded:: 20.3
|
||||
|
||||
Attributes:
|
||||
chat (:class:`telegram.Chat`): Chat the user belongs to.
|
||||
from_user (:class:`telegram.User`): Performer of the action, which resulted in the change.
|
||||
date (:class:`datetime.datetime`): Date the change was done in Unix time. Converted to
|
||||
:class:`datetime.datetime`.
|
||||
|
||||
.. versionchanged:: 20.3
|
||||
|datetime_localization|
|
||||
old_chat_member (:class:`telegram.ChatMember`): Previous information about the chat member.
|
||||
new_chat_member (:class:`telegram.ChatMember`): New information about the chat member.
|
||||
invite_link (:class:`telegram.ChatInviteLink`): Optional. Chat invite link, which was used
|
||||
by the user to join the chat. For joining by invite link events only.
|
||||
via_chat_folder_invite_link (:obj:`bool`): Optional. :obj:`True`, if the user joined the
|
||||
chat via a chat folder invite link
|
||||
|
||||
.. versionadded:: 20.3
|
||||
|
||||
"""
|
||||
|
||||
@@ -76,6 +90,7 @@ class ChatMemberUpdated(TelegramObject):
|
||||
"old_chat_member",
|
||||
"new_chat_member",
|
||||
"invite_link",
|
||||
"via_chat_folder_invite_link",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
@@ -85,9 +100,10 @@ class ChatMemberUpdated(TelegramObject):
|
||||
date: datetime.datetime,
|
||||
old_chat_member: ChatMember,
|
||||
new_chat_member: ChatMember,
|
||||
invite_link: ChatInviteLink = None,
|
||||
invite_link: Optional[ChatInviteLink] = None,
|
||||
via_chat_folder_invite_link: Optional[bool] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
# Required
|
||||
@@ -96,6 +112,7 @@ class ChatMemberUpdated(TelegramObject):
|
||||
self.date: datetime.datetime = date
|
||||
self.old_chat_member: ChatMember = old_chat_member
|
||||
self.new_chat_member: ChatMember = new_chat_member
|
||||
self.via_chat_folder_invite_link: Optional[bool] = via_chat_folder_invite_link
|
||||
|
||||
# Optionals
|
||||
self.invite_link: Optional[ChatInviteLink] = invite_link
|
||||
@@ -118,9 +135,12 @@ class ChatMemberUpdated(TelegramObject):
|
||||
if not data:
|
||||
return None
|
||||
|
||||
# Get the local timezone from the bot if it has defaults
|
||||
loc_tzinfo = extract_tzinfo_from_defaults(bot)
|
||||
|
||||
data["chat"] = Chat.de_json(data.get("chat"), bot)
|
||||
data["from_user"] = User.de_json(data.pop("from", None), bot)
|
||||
data["date"] = from_timestamp(data.get("date"))
|
||||
data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo)
|
||||
data["old_chat_member"] = ChatMember.de_json(data.get("old_chat_member"), bot)
|
||||
data["new_chat_member"] = ChatMember.de_json(data.get("new_chat_member"), bot)
|
||||
data["invite_link"] = ChatInviteLink.de_json(data.get("invite_link"), bot)
|
||||
|
||||
@@ -17,31 +17,36 @@
|
||||
# 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 an object that represents a Telegram ChatPermission."""
|
||||
from typing import Optional
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from telegram._telegramobject import TelegramObject
|
||||
from telegram._utils.types import JSONDict
|
||||
from telegram._utils.warnings import warn
|
||||
from telegram.warnings import PTBDeprecationWarning
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from telegram import Bot
|
||||
|
||||
|
||||
class ChatPermissions(TelegramObject):
|
||||
"""Describes actions that a non-administrator user is allowed to take in a chat.
|
||||
|
||||
Objects of this class are comparable in terms of equality. Two objects of this class are
|
||||
considered equal, if their :attr:`can_send_messages`, :attr:`can_send_media_messages`,
|
||||
considered equal, if their :attr:`can_send_messages`,
|
||||
:attr:`can_send_polls`, :attr:`can_send_other_messages`, :attr:`can_add_web_page_previews`,
|
||||
:attr:`can_change_info`, :attr:`can_invite_users`, :attr:`can_pin_messages`, and
|
||||
:attr:`can_change_info`, :attr:`can_invite_users`, :attr:`can_pin_messages`,
|
||||
:attr:`can_send_audios`, :attr:`can_send_documents`, :attr:`can_send_photos`,
|
||||
:attr:`can_send_videos`, :attr:`can_send_video_notes`, :attr:`can_send_voice_notes`, and
|
||||
:attr:`can_manage_topics` are equal.
|
||||
|
||||
.. versionchanged:: 20.0
|
||||
:attr:`can_manage_topics` is considered as well when comparing objects of
|
||||
this type in terms of equality.
|
||||
.. deprecated:: 20.1
|
||||
:attr:`can_send_audios`, :attr:`can_send_documents`, :attr:`can_send_photos`,
|
||||
:attr:`can_send_videos`, :attr:`can_send_video_notes` and :attr:`can_send_voice_notes`
|
||||
will be considered as well when comparing objects of this type in terms of equality in
|
||||
V21.
|
||||
.. versionchanged:: 20.5
|
||||
|
||||
* :attr:`can_send_audios`, :attr:`can_send_documents`, :attr:`can_send_photos`,
|
||||
:attr:`can_send_videos`, :attr:`can_send_video_notes` and :attr:`can_send_voice_notes`
|
||||
are considered as well when comparing objects of this type in terms of equality.
|
||||
* Removed deprecated argument and attribute ``can_send_media_messages``.
|
||||
|
||||
|
||||
Note:
|
||||
Though not stated explicitly in the official docs, Telegram changes not only the
|
||||
@@ -51,19 +56,11 @@ class ChatPermissions(TelegramObject):
|
||||
Args:
|
||||
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`.
|
||||
|
||||
.. deprecated:: 20.1
|
||||
Bot API 6.5 replaced this argument with granular media settings.
|
||||
can_send_polls (:obj:`bool`, optional): :obj:`True`, if the user is allowed to send polls,
|
||||
implies :attr:`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): :obj:`True`, if the user is allowed to
|
||||
send animations, games, stickers and use inline bots, implies
|
||||
:attr:`can_send_media_messages`.
|
||||
send animations, games, stickers and use inline bots.
|
||||
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`.
|
||||
add web page previews to their 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
|
||||
@@ -99,19 +96,12 @@ class ChatPermissions(TelegramObject):
|
||||
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`.
|
||||
|
||||
.. deprecated:: 20.1
|
||||
Bot API 6.5 replaced this attribute with granular media settings.
|
||||
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`.
|
||||
send animations, games, stickers and use inline bots.
|
||||
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`.
|
||||
add web page previews to their 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
|
||||
@@ -151,7 +141,6 @@ class ChatPermissions(TelegramObject):
|
||||
"can_invite_users",
|
||||
"can_send_polls",
|
||||
"can_send_messages",
|
||||
"can_send_media_messages",
|
||||
"can_change_info",
|
||||
"can_pin_messages",
|
||||
"can_add_web_page_previews",
|
||||
@@ -166,28 +155,26 @@ class ChatPermissions(TelegramObject):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
can_send_messages: bool = None,
|
||||
can_send_media_messages: bool = None,
|
||||
can_send_polls: bool = None,
|
||||
can_send_other_messages: bool = None,
|
||||
can_add_web_page_previews: bool = None,
|
||||
can_change_info: bool = None,
|
||||
can_invite_users: bool = None,
|
||||
can_pin_messages: bool = None,
|
||||
can_manage_topics: bool = None,
|
||||
can_send_audios: bool = None,
|
||||
can_send_documents: bool = None,
|
||||
can_send_photos: bool = None,
|
||||
can_send_videos: bool = None,
|
||||
can_send_video_notes: bool = None,
|
||||
can_send_voice_notes: bool = None,
|
||||
can_send_messages: Optional[bool] = None,
|
||||
can_send_polls: Optional[bool] = None,
|
||||
can_send_other_messages: Optional[bool] = None,
|
||||
can_add_web_page_previews: Optional[bool] = None,
|
||||
can_change_info: Optional[bool] = None,
|
||||
can_invite_users: Optional[bool] = None,
|
||||
can_pin_messages: Optional[bool] = None,
|
||||
can_manage_topics: Optional[bool] = None,
|
||||
can_send_audios: Optional[bool] = None,
|
||||
can_send_documents: Optional[bool] = None,
|
||||
can_send_photos: Optional[bool] = None,
|
||||
can_send_videos: Optional[bool] = None,
|
||||
can_send_video_notes: Optional[bool] = None,
|
||||
can_send_voice_notes: Optional[bool] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
# Required
|
||||
self.can_send_messages: Optional[bool] = can_send_messages
|
||||
self.can_send_media_messages: Optional[bool] = can_send_media_messages
|
||||
self.can_send_polls: Optional[bool] = can_send_polls
|
||||
self.can_send_other_messages: Optional[bool] = can_send_other_messages
|
||||
self.can_add_web_page_previews: Optional[bool] = can_add_web_page_previews
|
||||
@@ -204,7 +191,6 @@ class ChatPermissions(TelegramObject):
|
||||
|
||||
self._id_attrs = (
|
||||
self.can_send_messages,
|
||||
self.can_send_media_messages,
|
||||
self.can_send_polls,
|
||||
self.can_send_other_messages,
|
||||
self.can_add_web_page_previews,
|
||||
@@ -212,23 +198,16 @@ class ChatPermissions(TelegramObject):
|
||||
self.can_invite_users,
|
||||
self.can_pin_messages,
|
||||
self.can_manage_topics,
|
||||
self.can_send_audios,
|
||||
self.can_send_documents,
|
||||
self.can_send_photos,
|
||||
self.can_send_videos,
|
||||
self.can_send_video_notes,
|
||||
self.can_send_voice_notes,
|
||||
)
|
||||
|
||||
self._freeze()
|
||||
|
||||
def __eq__(self, other: object) -> bool:
|
||||
warn(
|
||||
"In v21, granular media settings will be considered as well when comparing"
|
||||
" ChatPermissions instances.",
|
||||
PTBDeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return super().__eq__(other)
|
||||
|
||||
def __hash__(self) -> int:
|
||||
# Intend: Added so support the own __eq__ function (which otherwise breaks hashing)
|
||||
return super().__hash__()
|
||||
|
||||
@classmethod
|
||||
def all_permissions(cls) -> "ChatPermissions":
|
||||
"""
|
||||
@@ -239,7 +218,7 @@ class ChatPermissions(TelegramObject):
|
||||
.. versionadded:: 20.0
|
||||
|
||||
"""
|
||||
return cls(*(15 * (True,)))
|
||||
return cls(*(14 * (True,)))
|
||||
|
||||
@classmethod
|
||||
def no_permissions(cls) -> "ChatPermissions":
|
||||
@@ -249,4 +228,20 @@ class ChatPermissions(TelegramObject):
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
return cls(*(15 * (False,)))
|
||||
return cls(*(14 * (False,)))
|
||||
|
||||
@classmethod
|
||||
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["ChatPermissions"]:
|
||||
"""See :meth:`telegram.TelegramObject.de_json`."""
|
||||
data = cls._parse_data(data)
|
||||
|
||||
if not data:
|
||||
return None
|
||||
|
||||
api_kwargs = {}
|
||||
# This is a deprecated field that TG still returns for backwards compatibility
|
||||
# Let's filter it out to speed up the de-json process
|
||||
if data.get("can_send_media_messages") is not None:
|
||||
api_kwargs["can_send_media_messages"] = data.pop("can_send_media_messages")
|
||||
|
||||
return super()._de_json(data=data, bot=bot, api_kwargs=api_kwargs)
|
||||
|
||||
@@ -72,10 +72,10 @@ class ChosenInlineResult(TelegramObject):
|
||||
result_id: str,
|
||||
from_user: User,
|
||||
query: str,
|
||||
location: Location = None,
|
||||
inline_message_id: str = None,
|
||||
location: Optional[Location] = None,
|
||||
inline_message_id: Optional[str] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
|
||||
|
||||
+16
-16
@@ -17,7 +17,7 @@
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a Telegram Dice."""
|
||||
from typing import ClassVar, List
|
||||
from typing import Final, List, Optional
|
||||
|
||||
from telegram import constants
|
||||
from telegram._telegramobject import TelegramObject
|
||||
@@ -89,7 +89,7 @@ class Dice(TelegramObject):
|
||||
|
||||
__slots__ = ("emoji", "value")
|
||||
|
||||
def __init__(self, value: int, emoji: str, *, api_kwargs: JSONDict = None):
|
||||
def __init__(self, value: int, emoji: str, *, api_kwargs: Optional[JSONDict] = None):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
self.value: int = value
|
||||
self.emoji: str = emoji
|
||||
@@ -98,62 +98,62 @@ class Dice(TelegramObject):
|
||||
|
||||
self._freeze()
|
||||
|
||||
DICE: ClassVar[str] = constants.DiceEmoji.DICE # skipcq: PTC-W0052
|
||||
DICE: Final[str] = constants.DiceEmoji.DICE # skipcq: PTC-W0052
|
||||
""":const:`telegram.constants.DiceEmoji.DICE`"""
|
||||
DARTS: ClassVar[str] = constants.DiceEmoji.DARTS
|
||||
DARTS: Final[str] = constants.DiceEmoji.DARTS
|
||||
""":const:`telegram.constants.DiceEmoji.DARTS`"""
|
||||
BASKETBALL: ClassVar[str] = constants.DiceEmoji.BASKETBALL
|
||||
BASKETBALL: Final[str] = constants.DiceEmoji.BASKETBALL
|
||||
""":const:`telegram.constants.DiceEmoji.BASKETBALL`"""
|
||||
FOOTBALL: ClassVar[str] = constants.DiceEmoji.FOOTBALL
|
||||
FOOTBALL: Final[str] = constants.DiceEmoji.FOOTBALL
|
||||
""":const:`telegram.constants.DiceEmoji.FOOTBALL`"""
|
||||
SLOT_MACHINE: ClassVar[str] = constants.DiceEmoji.SLOT_MACHINE
|
||||
SLOT_MACHINE: Final[str] = constants.DiceEmoji.SLOT_MACHINE
|
||||
""":const:`telegram.constants.DiceEmoji.SLOT_MACHINE`"""
|
||||
BOWLING: ClassVar[str] = constants.DiceEmoji.BOWLING
|
||||
BOWLING: Final[str] = constants.DiceEmoji.BOWLING
|
||||
"""
|
||||
:const:`telegram.constants.DiceEmoji.BOWLING`
|
||||
|
||||
.. versionadded:: 13.4
|
||||
"""
|
||||
ALL_EMOJI: ClassVar[List[str]] = list(constants.DiceEmoji)
|
||||
ALL_EMOJI: Final[List[str]] = list(constants.DiceEmoji)
|
||||
"""List[:obj:`str`]: A list of all available dice emoji."""
|
||||
|
||||
MIN_VALUE: ClassVar[int] = constants.DiceLimit.MIN_VALUE
|
||||
MIN_VALUE: Final[int] = constants.DiceLimit.MIN_VALUE
|
||||
""":const:`telegram.constants.DiceLimit.MIN_VALUE`
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
|
||||
MAX_VALUE_BOWLING: ClassVar[int] = constants.DiceLimit.MAX_VALUE_BOWLING
|
||||
MAX_VALUE_BOWLING: Final[int] = constants.DiceLimit.MAX_VALUE_BOWLING
|
||||
""":const:`telegram.constants.DiceLimit.MAX_VALUE_BOWLING`
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
|
||||
MAX_VALUE_DARTS: ClassVar[int] = constants.DiceLimit.MAX_VALUE_DARTS
|
||||
MAX_VALUE_DARTS: Final[int] = constants.DiceLimit.MAX_VALUE_DARTS
|
||||
""":const:`telegram.constants.DiceLimit.MAX_VALUE_DARTS`
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
|
||||
MAX_VALUE_DICE: ClassVar[int] = constants.DiceLimit.MAX_VALUE_DICE
|
||||
MAX_VALUE_DICE: Final[int] = constants.DiceLimit.MAX_VALUE_DICE
|
||||
""":const:`telegram.constants.DiceLimit.MAX_VALUE_DICE`
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
|
||||
MAX_VALUE_BASKETBALL: ClassVar[int] = constants.DiceLimit.MAX_VALUE_BASKETBALL
|
||||
MAX_VALUE_BASKETBALL: Final[int] = constants.DiceLimit.MAX_VALUE_BASKETBALL
|
||||
""":const:`telegram.constants.DiceLimit.MAX_VALUE_BASKETBALL`
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
|
||||
MAX_VALUE_FOOTBALL: ClassVar[int] = constants.DiceLimit.MAX_VALUE_FOOTBALL
|
||||
MAX_VALUE_FOOTBALL: Final[int] = constants.DiceLimit.MAX_VALUE_FOOTBALL
|
||||
""":const:`telegram.constants.DiceLimit.MAX_VALUE_FOOTBALL`
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
|
||||
MAX_VALUE_SLOT_MACHINE: ClassVar[int] = constants.DiceLimit.MAX_VALUE_SLOT_MACHINE
|
||||
MAX_VALUE_SLOT_MACHINE: Final[int] = constants.DiceLimit.MAX_VALUE_SLOT_MACHINE
|
||||
""":const:`telegram.constants.DiceLimit.MAX_VALUE_SLOT_MACHINE`
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
@@ -56,9 +56,9 @@ class _BaseMedium(TelegramObject):
|
||||
self,
|
||||
file_id: str,
|
||||
file_unique_id: str,
|
||||
file_size: int = None,
|
||||
file_size: Optional[int] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
|
||||
@@ -77,7 +77,7 @@ class _BaseMedium(TelegramObject):
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
connect_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
) -> "File":
|
||||
"""Convenience wrapper over :meth:`telegram.Bot.get_file`
|
||||
|
||||
|
||||
@@ -22,10 +22,6 @@ from typing import TYPE_CHECKING, Optional, Type, TypeVar
|
||||
from telegram._files._basemedium import _BaseMedium
|
||||
from telegram._files.photosize import PhotoSize
|
||||
from telegram._utils.types import JSONDict
|
||||
from telegram._utils.warnings_transition import (
|
||||
warn_about_deprecated_arg_return_new_arg,
|
||||
warn_about_deprecated_attr_in_property,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from telegram import Bot
|
||||
@@ -48,10 +44,6 @@ class _BaseThumbedMedium(_BaseMedium):
|
||||
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:`int`, optional): File size.
|
||||
thumb (:class:`telegram.PhotoSize`, optional): Thumbnail as defined by sender.
|
||||
|
||||
.. deprecated:: 20.2
|
||||
|thumbargumentdeprecation| :paramref:`thumbnail`.
|
||||
thumbnail (:class:`telegram.PhotoSize`, optional): Thumbnail as defined by sender.
|
||||
|
||||
.. versionadded:: 20.2
|
||||
@@ -74,11 +66,10 @@ class _BaseThumbedMedium(_BaseMedium):
|
||||
self,
|
||||
file_id: str,
|
||||
file_unique_id: str,
|
||||
file_size: int = None,
|
||||
thumb: PhotoSize = None,
|
||||
thumbnail: PhotoSize = None,
|
||||
file_size: Optional[int] = None,
|
||||
thumbnail: Optional[PhotoSize] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(
|
||||
file_id=file_id,
|
||||
@@ -87,26 +78,7 @@ class _BaseThumbedMedium(_BaseMedium):
|
||||
api_kwargs=api_kwargs,
|
||||
)
|
||||
|
||||
self.thumbnail: Optional[PhotoSize] = warn_about_deprecated_arg_return_new_arg(
|
||||
deprecated_arg=thumb,
|
||||
new_arg=thumbnail,
|
||||
deprecated_arg_name="thumb",
|
||||
new_arg_name="thumbnail",
|
||||
bot_api_version="6.6",
|
||||
stacklevel=4,
|
||||
)
|
||||
|
||||
@property
|
||||
def thumb(self) -> Optional[PhotoSize]:
|
||||
""":class:`telegram.PhotoSize`: Optional. Thumbnail as defined by sender.
|
||||
|
||||
.. deprecated:: 20.2
|
||||
|thumbattributedeprecation| :attr:`thumbnail`.
|
||||
"""
|
||||
warn_about_deprecated_attr_in_property(
|
||||
deprecated_attr_name="thumb", new_attr_name="thumbnail", bot_api_version="6.6"
|
||||
)
|
||||
return self.thumbnail
|
||||
self.thumbnail: Optional[PhotoSize] = thumbnail
|
||||
|
||||
@classmethod
|
||||
def de_json(
|
||||
|
||||
@@ -30,6 +30,9 @@ class Animation(_BaseThumbedMedium):
|
||||
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.
|
||||
|
||||
.. versionchanged:: 20.5
|
||||
|removed_thumb_note|
|
||||
|
||||
Args:
|
||||
file_id (:obj:`str`): Identifier for this file, which can be used to download
|
||||
or reuse the file.
|
||||
@@ -39,10 +42,6 @@ class Animation(_BaseThumbedMedium):
|
||||
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.
|
||||
|
||||
.. deprecated:: 20.2
|
||||
|thumbargumentdeprecation| :paramref:`thumbnail`.
|
||||
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 in bytes.
|
||||
@@ -79,19 +78,17 @@ class Animation(_BaseThumbedMedium):
|
||||
width: int,
|
||||
height: int,
|
||||
duration: int,
|
||||
thumb: PhotoSize = None,
|
||||
file_name: str = None,
|
||||
mime_type: str = None,
|
||||
file_size: int = None,
|
||||
thumbnail: PhotoSize = None,
|
||||
file_name: Optional[str] = None,
|
||||
mime_type: Optional[str] = None,
|
||||
file_size: Optional[int] = None,
|
||||
thumbnail: Optional[PhotoSize] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(
|
||||
file_id=file_id,
|
||||
file_unique_id=file_unique_id,
|
||||
file_size=file_size,
|
||||
thumb=thumb,
|
||||
api_kwargs=api_kwargs,
|
||||
thumbnail=thumbnail,
|
||||
)
|
||||
|
||||
+10
-14
@@ -30,6 +30,9 @@ class Audio(_BaseThumbedMedium):
|
||||
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.
|
||||
|
||||
.. versionchanged:: 20.5
|
||||
|removed_thumb_note|
|
||||
|
||||
|
||||
Args:
|
||||
file_id (:obj:`str`): Identifier for this file, which can be used to download
|
||||
@@ -43,11 +46,6 @@ class Audio(_BaseThumbedMedium):
|
||||
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 in bytes.
|
||||
thumb (:class:`telegram.PhotoSize`, optional): Thumbnail of the album cover to
|
||||
which the music file belongs.
|
||||
|
||||
.. deprecated:: 20.2
|
||||
|thumbargumentdeprecation| :paramref:`thumbnail`.
|
||||
thumbnail (:class:`telegram.PhotoSize`, optional): Thumbnail of the album cover to
|
||||
which the music file belongs.
|
||||
|
||||
@@ -80,21 +78,19 @@ class Audio(_BaseThumbedMedium):
|
||||
file_id: str,
|
||||
file_unique_id: str,
|
||||
duration: int,
|
||||
performer: str = None,
|
||||
title: str = None,
|
||||
mime_type: str = None,
|
||||
file_size: int = None,
|
||||
thumb: PhotoSize = None,
|
||||
file_name: str = None,
|
||||
thumbnail: PhotoSize = None,
|
||||
performer: Optional[str] = None,
|
||||
title: Optional[str] = None,
|
||||
mime_type: Optional[str] = None,
|
||||
file_size: Optional[int] = None,
|
||||
file_name: Optional[str] = None,
|
||||
thumbnail: Optional[PhotoSize] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(
|
||||
file_id=file_id,
|
||||
file_unique_id=file_unique_id,
|
||||
file_size=file_size,
|
||||
thumb=thumb,
|
||||
thumbnail=thumbnail,
|
||||
api_kwargs=api_kwargs,
|
||||
)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a Telegram ChatPhoto."""
|
||||
from typing import TYPE_CHECKING, ClassVar
|
||||
from typing import TYPE_CHECKING, Final, Optional
|
||||
|
||||
from telegram import constants
|
||||
from telegram._telegramobject import TelegramObject
|
||||
@@ -87,7 +87,7 @@ class ChatPhoto(TelegramObject):
|
||||
big_file_id: str,
|
||||
big_file_unique_id: str,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
self.small_file_id: str = small_file_id
|
||||
@@ -109,7 +109,7 @@ class ChatPhoto(TelegramObject):
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
connect_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
) -> "File":
|
||||
"""Convenience wrapper over :meth:`telegram.Bot.get_file` for getting the small
|
||||
(:tg-const:`telegram.ChatPhoto.SIZE_SMALL` x :tg-const:`telegram.ChatPhoto.SIZE_SMALL`)
|
||||
@@ -140,7 +140,7 @@ class ChatPhoto(TelegramObject):
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
connect_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
pool_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
) -> "File":
|
||||
"""Convenience wrapper over :meth:`telegram.Bot.get_file` for getting the
|
||||
big (:tg-const:`telegram.ChatPhoto.SIZE_BIG` x :tg-const:`telegram.ChatPhoto.SIZE_BIG`)
|
||||
@@ -164,12 +164,12 @@ class ChatPhoto(TelegramObject):
|
||||
api_kwargs=api_kwargs,
|
||||
)
|
||||
|
||||
SIZE_SMALL: ClassVar[int] = constants.ChatPhotoSize.SMALL
|
||||
SIZE_SMALL: Final[int] = constants.ChatPhotoSize.SMALL
|
||||
""":const:`telegram.constants.ChatPhotoSize.SMALL`
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
SIZE_BIG: ClassVar[int] = constants.ChatPhotoSize.BIG
|
||||
SIZE_BIG: Final[int] = constants.ChatPhotoSize.BIG
|
||||
""":const:`telegram.constants.ChatPhotoSize.BIG`
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
@@ -51,11 +51,11 @@ class Contact(TelegramObject):
|
||||
self,
|
||||
phone_number: str,
|
||||
first_name: str,
|
||||
last_name: str = None,
|
||||
user_id: int = None,
|
||||
vcard: str = None,
|
||||
last_name: Optional[str] = None,
|
||||
user_id: Optional[int] = None,
|
||||
vcard: Optional[str] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
# Required
|
||||
|
||||
@@ -31,15 +31,14 @@ class Document(_BaseThumbedMedium):
|
||||
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.
|
||||
|
||||
.. versionchanged:: 20.5
|
||||
|removed_thumb_note|
|
||||
|
||||
Args:
|
||||
file_id (:obj:`str`): Identifier for this file, which can be used to download
|
||||
or reuse the 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.
|
||||
thumb (:class:`telegram.PhotoSize`, optional): Document thumbnail as defined by sender.
|
||||
|
||||
.. deprecated:: 20.2
|
||||
|thumbargumentdeprecation| :paramref:`thumbnail`.
|
||||
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 in bytes.
|
||||
@@ -67,19 +66,17 @@ class Document(_BaseThumbedMedium):
|
||||
self,
|
||||
file_id: str,
|
||||
file_unique_id: str,
|
||||
thumb: PhotoSize = None,
|
||||
file_name: str = None,
|
||||
mime_type: str = None,
|
||||
file_size: int = None,
|
||||
thumbnail: PhotoSize = None,
|
||||
file_name: Optional[str] = None,
|
||||
mime_type: Optional[str] = None,
|
||||
file_size: Optional[int] = None,
|
||||
thumbnail: Optional[PhotoSize] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(
|
||||
file_id=file_id,
|
||||
file_unique_id=file_unique_id,
|
||||
file_size=file_size,
|
||||
thumb=thumb,
|
||||
thumbnail=thumbnail,
|
||||
api_kwargs=api_kwargs,
|
||||
)
|
||||
|
||||
@@ -85,10 +85,10 @@ class File(TelegramObject):
|
||||
self,
|
||||
file_id: str,
|
||||
file_unique_id: str,
|
||||
file_size: int = None,
|
||||
file_path: str = None,
|
||||
file_size: Optional[int] = None,
|
||||
file_path: Optional[str] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
|
||||
@@ -99,7 +99,7 @@ class File(TelegramObject):
|
||||
self.file_size: Optional[int] = file_size
|
||||
self.file_path: Optional[str] = file_path
|
||||
|
||||
self._credentials: Optional["FileCredentials"] = None
|
||||
self._credentials: Optional[FileCredentials] = None
|
||||
|
||||
self._id_attrs = (self.file_unique_id,)
|
||||
|
||||
@@ -119,7 +119,7 @@ class File(TelegramObject):
|
||||
|
||||
async def download_to_drive(
|
||||
self,
|
||||
custom_path: FilePathInput = None,
|
||||
custom_path: Optional[FilePathInput] = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
@@ -270,7 +270,7 @@ class File(TelegramObject):
|
||||
|
||||
async def download_as_bytearray(
|
||||
self,
|
||||
buf: bytearray = None,
|
||||
buf: Optional[bytearray] = None,
|
||||
*,
|
||||
read_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
write_timeout: ODVInput[float] = DEFAULT_NONE,
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a Telegram InputFile."""
|
||||
|
||||
import logging
|
||||
import mimetypes
|
||||
from typing import IO, Optional, Union
|
||||
from uuid import uuid4
|
||||
@@ -27,7 +26,6 @@ from telegram._utils.files import load_file
|
||||
from telegram._utils.types import FieldTuple
|
||||
|
||||
_DEFAULT_MIME_TYPE = "application/octet-stream"
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class InputFile:
|
||||
@@ -68,7 +66,10 @@ class InputFile:
|
||||
__slots__ = ("filename", "attach_name", "input_file_content", "mimetype")
|
||||
|
||||
def __init__(
|
||||
self, obj: Union[IO[bytes], bytes, str], filename: str = None, attach: bool = False
|
||||
self,
|
||||
obj: Union[IO[bytes], bytes, str],
|
||||
filename: Optional[str] = None,
|
||||
attach: bool = False,
|
||||
):
|
||||
if isinstance(obj, bytes):
|
||||
self.input_file_content: bytes = obj
|
||||
|
||||
+72
-150
@@ -31,10 +31,6 @@ from telegram._utils.argumentparsing import parse_sequence_arg
|
||||
from telegram._utils.defaultvalue import DEFAULT_NONE
|
||||
from telegram._utils.files import parse_file_input
|
||||
from telegram._utils.types import FileInput, JSONDict, ODVInput
|
||||
from telegram._utils.warnings_transition import (
|
||||
warn_about_deprecated_attr_in_property,
|
||||
warn_about_thumb_return_thumbnail,
|
||||
)
|
||||
from telegram.constants import InputMediaType
|
||||
|
||||
MediaType = Union[Animation, Audio, Document, PhotoSize, Video]
|
||||
@@ -91,11 +87,11 @@ class InputMedia(TelegramObject):
|
||||
self,
|
||||
media_type: str,
|
||||
media: Union[str, InputFile, MediaType],
|
||||
caption: str = None,
|
||||
caption_entities: Sequence[MessageEntity] = None,
|
||||
caption: Optional[str] = None,
|
||||
caption_entities: Optional[Sequence[MessageEntity]] = None,
|
||||
parse_mode: ODVInput[str] = DEFAULT_NONE,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
self.type: str = media_type
|
||||
@@ -107,11 +103,13 @@ class InputMedia(TelegramObject):
|
||||
self._freeze()
|
||||
|
||||
@staticmethod
|
||||
def _parse_thumb_input(thumb: Optional[FileInput]) -> Optional[Union[str, InputFile]]:
|
||||
def _parse_thumbnail_input(thumbnail: Optional[FileInput]) -> Optional[Union[str, InputFile]]:
|
||||
# We use local_mode=True because we don't have access to the actual setting and want
|
||||
# things to work in local mode.
|
||||
return (
|
||||
parse_file_input(thumb, attach=True, local_mode=True) if thumb is not None else thumb
|
||||
parse_file_input(thumbnail, attach=True, local_mode=True)
|
||||
if thumbnail is not None
|
||||
else thumbnail
|
||||
)
|
||||
|
||||
|
||||
@@ -125,6 +123,9 @@ class InputMediaAnimation(InputMedia):
|
||||
|
||||
.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
|
||||
|
||||
.. versionchanged:: 20.5
|
||||
|removed_thumb_note|
|
||||
|
||||
Args:
|
||||
media (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | \
|
||||
:class:`telegram.Animation`): File to send. |fileinputnopath|
|
||||
@@ -137,14 +138,6 @@ class InputMediaAnimation(InputMedia):
|
||||
:obj:`tempfile` module.
|
||||
|
||||
.. versionadded:: 13.1
|
||||
thumb (:term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | :obj:`str`, \
|
||||
optional): |thumbdocstringnopath|
|
||||
|
||||
.. versionchanged:: 13.2
|
||||
Accept :obj:`bytes` as input.
|
||||
|
||||
.. deprecated:: 20.2
|
||||
|thumbargumentdeprecation| :paramref:`thumbnail`.
|
||||
caption (:obj:`str`, optional): Caption of the animation to be sent,
|
||||
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
|
||||
after entities parsing.
|
||||
@@ -196,18 +189,17 @@ class InputMediaAnimation(InputMedia):
|
||||
def __init__(
|
||||
self,
|
||||
media: Union[FileInput, Animation],
|
||||
thumb: FileInput = None,
|
||||
caption: str = None,
|
||||
caption: Optional[str] = None,
|
||||
parse_mode: ODVInput[str] = DEFAULT_NONE,
|
||||
width: int = None,
|
||||
height: int = None,
|
||||
duration: int = None,
|
||||
caption_entities: Sequence[MessageEntity] = None,
|
||||
filename: str = None,
|
||||
has_spoiler: bool = None,
|
||||
thumbnail: FileInput = None,
|
||||
width: Optional[int] = None,
|
||||
height: Optional[int] = None,
|
||||
duration: Optional[int] = None,
|
||||
caption_entities: Optional[Sequence[MessageEntity]] = None,
|
||||
filename: Optional[str] = None,
|
||||
has_spoiler: Optional[bool] = None,
|
||||
thumbnail: Optional[FileInput] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
if isinstance(media, Animation):
|
||||
width = media.width if width is None else width
|
||||
@@ -219,7 +211,6 @@ class InputMediaAnimation(InputMedia):
|
||||
# things to work in local mode.
|
||||
media = parse_file_input(media, filename=filename, attach=True, local_mode=True)
|
||||
|
||||
thumbnail = warn_about_thumb_return_thumbnail(deprecated_arg=thumb, new_arg=thumbnail)
|
||||
super().__init__(
|
||||
InputMediaType.ANIMATION,
|
||||
media,
|
||||
@@ -229,26 +220,14 @@ class InputMediaAnimation(InputMedia):
|
||||
api_kwargs=api_kwargs,
|
||||
)
|
||||
with self._unfrozen():
|
||||
self.thumbnail: Optional[Union[str, InputFile]] = self._parse_thumb_input(thumbnail)
|
||||
self.thumbnail: Optional[Union[str, InputFile]] = self._parse_thumbnail_input(
|
||||
thumbnail
|
||||
)
|
||||
self.width: Optional[int] = width
|
||||
self.height: Optional[int] = height
|
||||
self.duration: Optional[int] = duration
|
||||
self.has_spoiler: Optional[bool] = has_spoiler
|
||||
|
||||
@property
|
||||
def thumb(self) -> Optional[Union[str, InputFile]]:
|
||||
""":class:`telegram.InputFile`: Optional. |thumbdocstringbase|
|
||||
|
||||
.. deprecated:: 20.2
|
||||
|thumbattributedeprecation| :attr:`thumbnail`.
|
||||
"""
|
||||
warn_about_deprecated_attr_in_property(
|
||||
deprecated_attr_name="thumb",
|
||||
new_attr_name="thumbnail",
|
||||
bot_api_version="6.6",
|
||||
)
|
||||
return self.thumbnail
|
||||
|
||||
|
||||
class InputMediaPhoto(InputMedia):
|
||||
"""Represents a photo to be sent.
|
||||
@@ -304,13 +283,13 @@ class InputMediaPhoto(InputMedia):
|
||||
def __init__(
|
||||
self,
|
||||
media: Union[FileInput, PhotoSize],
|
||||
caption: str = None,
|
||||
caption: Optional[str] = None,
|
||||
parse_mode: ODVInput[str] = DEFAULT_NONE,
|
||||
caption_entities: Sequence[MessageEntity] = None,
|
||||
filename: str = None,
|
||||
has_spoiler: bool = None,
|
||||
caption_entities: Optional[Sequence[MessageEntity]] = None,
|
||||
filename: Optional[str] = None,
|
||||
has_spoiler: Optional[bool] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
# We use local_mode=True because we don't have access to the actual setting and want
|
||||
# things to work in local mode.
|
||||
@@ -337,9 +316,12 @@ class InputMediaVideo(InputMedia):
|
||||
* 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.
|
||||
* :paramref:`thumb` will be ignored for small video files, for which Telegram can easily
|
||||
generate thumbnails. However, this behaviour is undocumented and might be changed
|
||||
by Telegram.
|
||||
* :paramref:`thumbnail` will be ignored for small video files, for which Telegram can
|
||||
easily generate thumbnails. However, this behaviour is undocumented and might be
|
||||
changed by Telegram.
|
||||
|
||||
.. versionchanged:: 20.5
|
||||
|removed_thumb_note|
|
||||
|
||||
Args:
|
||||
media (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | \
|
||||
@@ -367,14 +349,6 @@ class InputMediaVideo(InputMedia):
|
||||
duration (:obj:`int`, optional): Video duration in seconds.
|
||||
supports_streaming (:obj:`bool`, optional): Pass :obj:`True`, if the uploaded video is
|
||||
suitable for streaming.
|
||||
thumb (:term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | :obj:`str`, \
|
||||
optional): |thumbdocstringnopath|
|
||||
|
||||
.. versionchanged:: 13.2
|
||||
Accept :obj:`bytes` as input.
|
||||
|
||||
.. deprecated:: 20.2
|
||||
|thumbargumentdeprecation| :paramref:`thumbnail`.
|
||||
has_spoiler (:obj:`bool`, optional): Pass :obj:`True`, if the video needs to be covered
|
||||
with a spoiler animation.
|
||||
|
||||
@@ -423,19 +397,18 @@ class InputMediaVideo(InputMedia):
|
||||
def __init__(
|
||||
self,
|
||||
media: Union[FileInput, Video],
|
||||
caption: str = None,
|
||||
width: int = None,
|
||||
height: int = None,
|
||||
duration: int = None,
|
||||
supports_streaming: bool = None,
|
||||
caption: Optional[str] = None,
|
||||
width: Optional[int] = None,
|
||||
height: Optional[int] = None,
|
||||
duration: Optional[int] = None,
|
||||
supports_streaming: Optional[bool] = None,
|
||||
parse_mode: ODVInput[str] = DEFAULT_NONE,
|
||||
thumb: FileInput = None,
|
||||
caption_entities: Sequence[MessageEntity] = None,
|
||||
filename: str = None,
|
||||
has_spoiler: bool = None,
|
||||
thumbnail: FileInput = None,
|
||||
caption_entities: Optional[Sequence[MessageEntity]] = None,
|
||||
filename: Optional[str] = None,
|
||||
has_spoiler: Optional[bool] = None,
|
||||
thumbnail: Optional[FileInput] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
if isinstance(media, Video):
|
||||
width = width if width is not None else media.width
|
||||
@@ -447,7 +420,6 @@ class InputMediaVideo(InputMedia):
|
||||
# things to work in local mode.
|
||||
media = parse_file_input(media, filename=filename, attach=True, local_mode=True)
|
||||
|
||||
thumbnail = warn_about_thumb_return_thumbnail(deprecated_arg=thumb, new_arg=thumbnail)
|
||||
super().__init__(
|
||||
InputMediaType.VIDEO,
|
||||
media,
|
||||
@@ -460,24 +432,12 @@ class InputMediaVideo(InputMedia):
|
||||
self.width: Optional[int] = width
|
||||
self.height: Optional[int] = height
|
||||
self.duration: Optional[int] = duration
|
||||
self.thumbnail: Optional[Union[str, InputFile]] = self._parse_thumb_input(thumbnail)
|
||||
self.thumbnail: Optional[Union[str, InputFile]] = self._parse_thumbnail_input(
|
||||
thumbnail
|
||||
)
|
||||
self.supports_streaming: Optional[bool] = supports_streaming
|
||||
self.has_spoiler: Optional[bool] = has_spoiler
|
||||
|
||||
@property
|
||||
def thumb(self) -> Optional[Union[str, InputFile]]:
|
||||
""":class:`telegram.InputFile`: Optional. |thumbdocstringbase|
|
||||
|
||||
.. deprecated:: 20.2
|
||||
|thumbattributedeprecation| :attr:`thumbnail`.
|
||||
"""
|
||||
warn_about_deprecated_attr_in_property(
|
||||
deprecated_attr_name="thumb",
|
||||
new_attr_name="thumbnail",
|
||||
bot_api_version="6.6",
|
||||
)
|
||||
return self.thumbnail
|
||||
|
||||
|
||||
class InputMediaAudio(InputMedia):
|
||||
"""Represents an audio file to be treated as music to be sent.
|
||||
@@ -489,6 +449,9 @@ class InputMediaAudio(InputMedia):
|
||||
duration, performer and title from that video, unless otherwise specified with the
|
||||
optional arguments.
|
||||
|
||||
.. versionchanged:: 20.5
|
||||
|removed_thumb_note|
|
||||
|
||||
Args:
|
||||
media (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | \
|
||||
:class:`telegram.Audio`): File to send. |fileinputnopath|
|
||||
@@ -514,14 +477,6 @@ class InputMediaAudio(InputMedia):
|
||||
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 (:term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | :obj:`str`, \
|
||||
optional): |thumbdocstringnopath|
|
||||
|
||||
.. versionchanged:: 13.2
|
||||
Accept :obj:`bytes` as input.
|
||||
|
||||
.. deprecated:: 20.2
|
||||
|thumbargumentdeprecation| :paramref:`thumbnail`.
|
||||
thumbnail (:term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | :obj:`str`, \
|
||||
optional): |thumbdocstringnopath|
|
||||
|
||||
@@ -555,17 +510,16 @@ class InputMediaAudio(InputMedia):
|
||||
def __init__(
|
||||
self,
|
||||
media: Union[FileInput, Audio],
|
||||
thumb: FileInput = None,
|
||||
caption: str = None,
|
||||
caption: Optional[str] = None,
|
||||
parse_mode: ODVInput[str] = DEFAULT_NONE,
|
||||
duration: int = None,
|
||||
performer: str = None,
|
||||
title: str = None,
|
||||
caption_entities: Sequence[MessageEntity] = None,
|
||||
filename: str = None,
|
||||
thumbnail: FileInput = None,
|
||||
duration: Optional[int] = None,
|
||||
performer: Optional[str] = None,
|
||||
title: Optional[str] = None,
|
||||
caption_entities: Optional[Sequence[MessageEntity]] = None,
|
||||
filename: Optional[str] = None,
|
||||
thumbnail: Optional[FileInput] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
if isinstance(media, Audio):
|
||||
duration = media.duration if duration is None else duration
|
||||
@@ -577,7 +531,6 @@ class InputMediaAudio(InputMedia):
|
||||
# things to work in local mode.
|
||||
media = parse_file_input(media, filename=filename, attach=True, local_mode=True)
|
||||
|
||||
thumbnail = warn_about_thumb_return_thumbnail(deprecated_arg=thumb, new_arg=thumbnail)
|
||||
super().__init__(
|
||||
InputMediaType.AUDIO,
|
||||
media,
|
||||
@@ -587,31 +540,22 @@ class InputMediaAudio(InputMedia):
|
||||
api_kwargs=api_kwargs,
|
||||
)
|
||||
with self._unfrozen():
|
||||
self.thumbnail: Optional[Union[str, InputFile]] = self._parse_thumb_input(thumbnail)
|
||||
self.thumbnail: Optional[Union[str, InputFile]] = self._parse_thumbnail_input(
|
||||
thumbnail
|
||||
)
|
||||
self.duration: Optional[int] = duration
|
||||
self.title: Optional[str] = title
|
||||
self.performer: Optional[str] = performer
|
||||
|
||||
@property
|
||||
def thumb(self) -> Optional[Union[str, InputFile]]:
|
||||
""":class:`telegram.InputFile`: Optional. |thumbdocstringbase|
|
||||
|
||||
.. deprecated:: 20.2
|
||||
|thumbattributedeprecation| :attr:`thumbnail`.
|
||||
"""
|
||||
warn_about_deprecated_attr_in_property(
|
||||
deprecated_attr_name="thumb",
|
||||
new_attr_name="thumbnail",
|
||||
bot_api_version="6.6",
|
||||
)
|
||||
return self.thumbnail
|
||||
|
||||
|
||||
class InputMediaDocument(InputMedia):
|
||||
"""Represents a general file to be sent.
|
||||
|
||||
.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
|
||||
|
||||
.. versionchanged:: 20.5
|
||||
|removed_thumb_note|
|
||||
|
||||
Args:
|
||||
media (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | \
|
||||
:class:`telegram.Document`): File to send. |fileinputnopath|
|
||||
@@ -633,14 +577,6 @@ class InputMediaDocument(InputMedia):
|
||||
.. versionchanged:: 20.0
|
||||
|sequenceclassargs|
|
||||
|
||||
thumb (:term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | :obj:`str`, \
|
||||
optional): |thumbdocstringnopath|
|
||||
|
||||
.. versionchanged:: 13.2
|
||||
Accept :obj:`bytes` as input.
|
||||
|
||||
.. deprecated:: 20.2
|
||||
|thumbargumentdeprecation| :paramref:`thumbnail`.
|
||||
disable_content_type_detection (:obj:`bool`, optional): Disables automatic server-side
|
||||
content type detection for files uploaded using multipart/form-data. Always
|
||||
:obj:`True`, if the document is sent as part of an album.
|
||||
@@ -675,21 +611,19 @@ class InputMediaDocument(InputMedia):
|
||||
def __init__(
|
||||
self,
|
||||
media: Union[FileInput, Document],
|
||||
thumb: FileInput = None,
|
||||
caption: str = None,
|
||||
caption: Optional[str] = None,
|
||||
parse_mode: ODVInput[str] = DEFAULT_NONE,
|
||||
disable_content_type_detection: bool = None,
|
||||
caption_entities: Sequence[MessageEntity] = None,
|
||||
filename: str = None,
|
||||
thumbnail: FileInput = None,
|
||||
disable_content_type_detection: Optional[bool] = None,
|
||||
caption_entities: Optional[Sequence[MessageEntity]] = None,
|
||||
filename: Optional[str] = None,
|
||||
thumbnail: Optional[FileInput] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
# We use local_mode=True because we don't have access to the actual setting and want
|
||||
# things to work in local mode.
|
||||
media = parse_file_input(media, Document, filename=filename, attach=True, local_mode=True)
|
||||
|
||||
thumbnail = warn_about_thumb_return_thumbnail(deprecated_arg=thumb, new_arg=thumbnail)
|
||||
super().__init__(
|
||||
InputMediaType.DOCUMENT,
|
||||
media,
|
||||
@@ -699,19 +633,7 @@ class InputMediaDocument(InputMedia):
|
||||
api_kwargs=api_kwargs,
|
||||
)
|
||||
with self._unfrozen():
|
||||
self.thumbnail: Optional[Union[str, InputFile]] = self._parse_thumb_input(thumbnail)
|
||||
self.thumbnail: Optional[Union[str, InputFile]] = self._parse_thumbnail_input(
|
||||
thumbnail
|
||||
)
|
||||
self.disable_content_type_detection: Optional[bool] = disable_content_type_detection
|
||||
|
||||
@property
|
||||
def thumb(self) -> Optional[Union[str, InputFile]]:
|
||||
""":class:`telegram.InputFile`: Optional. |thumbdocstringbase|
|
||||
|
||||
.. deprecated:: 20.2
|
||||
|thumbattributedeprecation| :attr:`thumbnail`.
|
||||
"""
|
||||
warn_about_deprecated_attr_in_property(
|
||||
deprecated_attr_name="thumb",
|
||||
new_attr_name="thumbnail",
|
||||
bot_api_version="6.6",
|
||||
)
|
||||
return self.thumbnail
|
||||
|
||||
@@ -18,15 +18,17 @@
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a Telegram InputSticker."""
|
||||
|
||||
from typing import Optional, Sequence, Tuple, Union
|
||||
from typing import TYPE_CHECKING, Optional, Sequence, Tuple, Union
|
||||
|
||||
from telegram._files.inputfile import InputFile
|
||||
from telegram._files.sticker import MaskPosition
|
||||
from telegram._telegramobject import TelegramObject
|
||||
from telegram._utils.argumentparsing import parse_sequence_arg
|
||||
from telegram._utils.files import parse_file_input
|
||||
from telegram._utils.types import FileInput, JSONDict
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from telegram._files.inputfile import InputFile
|
||||
|
||||
|
||||
class InputSticker(TelegramObject):
|
||||
"""
|
||||
@@ -74,10 +76,10 @@ class InputSticker(TelegramObject):
|
||||
self,
|
||||
sticker: FileInput,
|
||||
emoji_list: Sequence[str],
|
||||
mask_position: MaskPosition = None,
|
||||
keywords: Sequence[str] = None,
|
||||
mask_position: Optional[MaskPosition] = None,
|
||||
keywords: Optional[Sequence[str]] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a Telegram Location."""
|
||||
|
||||
from typing import ClassVar, Optional
|
||||
from typing import Final, Optional
|
||||
|
||||
from telegram import constants
|
||||
from telegram._telegramobject import TelegramObject
|
||||
@@ -72,12 +72,12 @@ class Location(TelegramObject):
|
||||
self,
|
||||
longitude: float,
|
||||
latitude: float,
|
||||
horizontal_accuracy: float = None,
|
||||
live_period: int = None,
|
||||
heading: int = None,
|
||||
proximity_alert_radius: int = None,
|
||||
horizontal_accuracy: Optional[float] = None,
|
||||
live_period: Optional[int] = None,
|
||||
heading: Optional[int] = None,
|
||||
proximity_alert_radius: Optional[int] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
# Required
|
||||
@@ -96,17 +96,17 @@ class Location(TelegramObject):
|
||||
|
||||
self._freeze()
|
||||
|
||||
HORIZONTAL_ACCURACY: ClassVar[int] = constants.LocationLimit.HORIZONTAL_ACCURACY
|
||||
HORIZONTAL_ACCURACY: Final[int] = constants.LocationLimit.HORIZONTAL_ACCURACY
|
||||
""":const:`telegram.constants.LocationLimit.HORIZONTAL_ACCURACY`
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
MIN_HEADING: ClassVar[int] = constants.LocationLimit.MIN_HEADING
|
||||
MIN_HEADING: Final[int] = constants.LocationLimit.MIN_HEADING
|
||||
""":const:`telegram.constants.LocationLimit.MIN_HEADING`
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
MAX_HEADING: ClassVar[int] = constants.LocationLimit.MAX_HEADING
|
||||
MAX_HEADING: Final[int] = constants.LocationLimit.MAX_HEADING
|
||||
""":const:`telegram.constants.LocationLimit.MAX_HEADING`
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a Telegram PhotoSize."""
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from telegram._files._basemedium import _BaseMedium
|
||||
from telegram._utils.types import JSONDict
|
||||
|
||||
@@ -59,9 +61,9 @@ class PhotoSize(_BaseMedium):
|
||||
file_unique_id: str,
|
||||
width: int,
|
||||
height: int,
|
||||
file_size: int = None,
|
||||
file_size: Optional[int] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(
|
||||
file_id=file_id,
|
||||
|
||||
+27
-55
@@ -17,7 +17,7 @@
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains objects that represent stickers."""
|
||||
from typing import TYPE_CHECKING, ClassVar, Optional, Sequence, Tuple
|
||||
from typing import TYPE_CHECKING, Final, Optional, Sequence, Tuple
|
||||
|
||||
from telegram import constants
|
||||
from telegram._files._basethumbedmedium import _BaseThumbedMedium
|
||||
@@ -26,10 +26,6 @@ from telegram._files.photosize import PhotoSize
|
||||
from telegram._telegramobject import TelegramObject
|
||||
from telegram._utils.argumentparsing import parse_sequence_arg
|
||||
from telegram._utils.types import JSONDict
|
||||
from telegram._utils.warnings_transition import (
|
||||
warn_about_deprecated_attr_in_property,
|
||||
warn_about_thumb_return_thumbnail,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from telegram import Bot
|
||||
@@ -46,6 +42,9 @@ class Sticker(_BaseThumbedMedium):
|
||||
arguments had to be changed. Use keyword arguments to make sure that the arguments are
|
||||
passed correctly.
|
||||
|
||||
.. versionchanged:: 20.5
|
||||
|removed_thumb_note|
|
||||
|
||||
Args:
|
||||
file_id (:obj:`str`): Identifier for this file, which can be used to download
|
||||
or reuse the file.
|
||||
@@ -63,11 +62,6 @@ class Sticker(_BaseThumbedMedium):
|
||||
format, which is determined by the fields :attr:`is_animated` and :attr:`is_video`.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
thumb (:class:`telegram.PhotoSize`, optional): Sticker thumbnail in the ``.WEBP`` or
|
||||
``.JPG`` format.
|
||||
|
||||
.. deprecated:: 20.2
|
||||
|thumbargumentdeprecation| :paramref:`thumbnail`.
|
||||
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
|
||||
@@ -157,23 +151,21 @@ class Sticker(_BaseThumbedMedium):
|
||||
is_animated: bool,
|
||||
is_video: bool,
|
||||
type: str, # pylint: disable=redefined-builtin
|
||||
thumb: PhotoSize = None,
|
||||
emoji: str = None,
|
||||
file_size: int = None,
|
||||
set_name: str = None,
|
||||
mask_position: "MaskPosition" = None,
|
||||
premium_animation: "File" = None,
|
||||
custom_emoji_id: str = None,
|
||||
thumbnail: PhotoSize = None,
|
||||
needs_repainting: bool = None,
|
||||
emoji: Optional[str] = None,
|
||||
file_size: Optional[int] = None,
|
||||
set_name: Optional[str] = None,
|
||||
mask_position: Optional["MaskPosition"] = None,
|
||||
premium_animation: Optional["File"] = None,
|
||||
custom_emoji_id: Optional[str] = None,
|
||||
thumbnail: Optional[PhotoSize] = None,
|
||||
needs_repainting: Optional[bool] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(
|
||||
file_id=file_id,
|
||||
file_unique_id=file_unique_id,
|
||||
file_size=file_size,
|
||||
thumb=thumb,
|
||||
thumbnail=thumbnail,
|
||||
api_kwargs=api_kwargs,
|
||||
)
|
||||
@@ -192,11 +184,11 @@ class Sticker(_BaseThumbedMedium):
|
||||
self.custom_emoji_id: Optional[str] = custom_emoji_id
|
||||
self.needs_repainting: Optional[bool] = needs_repainting
|
||||
|
||||
REGULAR: ClassVar[str] = constants.StickerType.REGULAR
|
||||
REGULAR: Final[str] = constants.StickerType.REGULAR
|
||||
""":const:`telegram.constants.StickerType.REGULAR`"""
|
||||
MASK: ClassVar[str] = constants.StickerType.MASK
|
||||
MASK: Final[str] = constants.StickerType.MASK
|
||||
""":const:`telegram.constants.StickerType.MASK`"""
|
||||
CUSTOM_EMOJI: ClassVar[str] = constants.StickerType.CUSTOM_EMOJI
|
||||
CUSTOM_EMOJI: Final[str] = constants.StickerType.CUSTOM_EMOJI
|
||||
""":const:`telegram.constants.StickerType.CUSTOM_EMOJI`"""
|
||||
|
||||
@classmethod
|
||||
@@ -234,6 +226,9 @@ class StickerSet(TelegramObject):
|
||||
.. versionchanged:: 20.0
|
||||
The parameter ``contains_masks`` has been removed. Use :paramref:`sticker_type` instead.
|
||||
|
||||
.. versionchanged:: 20.5
|
||||
|removed_thumb_note|
|
||||
|
||||
Args:
|
||||
name (:obj:`str`): Sticker set name.
|
||||
title (:obj:`str`): Sticker set title.
|
||||
@@ -251,11 +246,6 @@ class StickerSet(TelegramObject):
|
||||
:attr:`telegram.Sticker.CUSTOM_EMOJI`.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
thumb (:class:`telegram.PhotoSize`, optional): Sticker set thumbnail in the ``.WEBP``,
|
||||
``.TGS``, or ``.WEBM`` format.
|
||||
|
||||
.. deprecated:: 20.2
|
||||
|thumbargumentdeprecation| :paramref:`thumbnail`.
|
||||
thumbnail (:class:`telegram.PhotoSize`, optional): Sticker set thumbnail in the ``.WEBP``,
|
||||
``.TGS``, or ``.WEBM`` format.
|
||||
|
||||
@@ -302,10 +292,9 @@ class StickerSet(TelegramObject):
|
||||
stickers: Sequence[Sticker],
|
||||
is_video: bool,
|
||||
sticker_type: str,
|
||||
thumb: PhotoSize = None,
|
||||
thumbnail: PhotoSize = None,
|
||||
thumbnail: Optional[PhotoSize] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
self.name: str = name
|
||||
@@ -316,28 +305,11 @@ class StickerSet(TelegramObject):
|
||||
self.sticker_type: str = sticker_type
|
||||
# Optional
|
||||
|
||||
self.thumbnail: Optional[PhotoSize] = warn_about_thumb_return_thumbnail(
|
||||
deprecated_arg=thumb, new_arg=thumbnail
|
||||
)
|
||||
self.thumbnail: Optional[PhotoSize] = thumbnail
|
||||
self._id_attrs = (self.name,)
|
||||
|
||||
self._freeze()
|
||||
|
||||
@property
|
||||
def thumb(self) -> Optional[PhotoSize]:
|
||||
""":class:`telegram.PhotoSize`: Optional. Sticker set thumbnail in the ``.WEBP``,
|
||||
``.TGS``, or ``.WEBM`` format.
|
||||
|
||||
.. deprecated:: 20.2
|
||||
|thumbattributedeprecation| :attr:`thumbnail`.
|
||||
"""
|
||||
warn_about_deprecated_attr_in_property(
|
||||
deprecated_attr_name="thumb",
|
||||
new_attr_name="thumbnail",
|
||||
bot_api_version="6.6",
|
||||
)
|
||||
return self.thumbnail
|
||||
|
||||
@classmethod
|
||||
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["StickerSet"]:
|
||||
"""See :meth:`telegram.TelegramObject.de_json`."""
|
||||
@@ -390,13 +362,13 @@ class MaskPosition(TelegramObject):
|
||||
|
||||
__slots__ = ("point", "scale", "x_shift", "y_shift")
|
||||
|
||||
FOREHEAD: ClassVar[str] = constants.MaskPosition.FOREHEAD
|
||||
FOREHEAD: Final[str] = constants.MaskPosition.FOREHEAD
|
||||
""":const:`telegram.constants.MaskPosition.FOREHEAD`"""
|
||||
EYES: ClassVar[str] = constants.MaskPosition.EYES
|
||||
EYES: Final[str] = constants.MaskPosition.EYES
|
||||
""":const:`telegram.constants.MaskPosition.EYES`"""
|
||||
MOUTH: ClassVar[str] = constants.MaskPosition.MOUTH
|
||||
MOUTH: Final[str] = constants.MaskPosition.MOUTH
|
||||
""":const:`telegram.constants.MaskPosition.MOUTH`"""
|
||||
CHIN: ClassVar[str] = constants.MaskPosition.CHIN
|
||||
CHIN: Final[str] = constants.MaskPosition.CHIN
|
||||
""":const:`telegram.constants.MaskPosition.CHIN`"""
|
||||
|
||||
def __init__(
|
||||
@@ -406,7 +378,7 @@ class MaskPosition(TelegramObject):
|
||||
y_shift: float,
|
||||
scale: float,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
self.point: str = point
|
||||
|
||||
@@ -79,12 +79,12 @@ class Venue(TelegramObject):
|
||||
location: Location,
|
||||
title: str,
|
||||
address: str,
|
||||
foursquare_id: str = None,
|
||||
foursquare_type: str = None,
|
||||
google_place_id: str = None,
|
||||
google_place_type: str = None,
|
||||
foursquare_id: Optional[str] = None,
|
||||
foursquare_type: Optional[str] = None,
|
||||
google_place_id: Optional[str] = None,
|
||||
google_place_type: Optional[str] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
|
||||
|
||||
@@ -30,6 +30,9 @@ class Video(_BaseThumbedMedium):
|
||||
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.
|
||||
|
||||
.. versionchanged:: 20.5
|
||||
|removed_thumb_note|
|
||||
|
||||
Args:
|
||||
file_id (:obj:`str`): Identifier for this file, which can be used to download
|
||||
or reuse the file.
|
||||
@@ -39,10 +42,6 @@ class Video(_BaseThumbedMedium):
|
||||
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.
|
||||
|
||||
.. deprecated:: 20.2
|
||||
|thumbargumentdeprecation| :paramref:`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 in bytes.
|
||||
@@ -76,19 +75,17 @@ class Video(_BaseThumbedMedium):
|
||||
width: int,
|
||||
height: int,
|
||||
duration: int,
|
||||
thumb: PhotoSize = None,
|
||||
mime_type: str = None,
|
||||
file_size: int = None,
|
||||
file_name: str = None,
|
||||
thumbnail: PhotoSize = None,
|
||||
mime_type: Optional[str] = None,
|
||||
file_size: Optional[int] = None,
|
||||
file_name: Optional[str] = None,
|
||||
thumbnail: Optional[PhotoSize] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(
|
||||
file_id=file_id,
|
||||
file_unique_id=file_unique_id,
|
||||
file_size=file_size,
|
||||
thumb=thumb,
|
||||
thumbnail=thumbnail,
|
||||
api_kwargs=api_kwargs,
|
||||
)
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
# 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 Optional
|
||||
|
||||
from telegram._files._basethumbedmedium import _BaseThumbedMedium
|
||||
from telegram._files.photosize import PhotoSize
|
||||
from telegram._utils.types import JSONDict
|
||||
@@ -29,6 +31,9 @@ class VideoNote(_BaseThumbedMedium):
|
||||
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.
|
||||
|
||||
.. versionchanged:: 20.5
|
||||
|removed_thumb_note|
|
||||
|
||||
Args:
|
||||
file_id (:obj:`str`): Identifier for this file, which can be used to download
|
||||
or reuse the file.
|
||||
@@ -38,10 +43,6 @@ class VideoNote(_BaseThumbedMedium):
|
||||
length (:obj:`int`): Video width and height (diameter of the video message) as defined
|
||||
by sender.
|
||||
duration (:obj:`int`): Duration of the video in seconds as defined by sender.
|
||||
thumb (:class:`telegram.PhotoSize`, optional): Video thumbnail.
|
||||
|
||||
.. deprecated:: 20.2
|
||||
|thumbargumentdeprecation| :paramref:`thumbnail`.
|
||||
file_size (:obj:`int`, optional): File size in bytes.
|
||||
thumbnail (:class:`telegram.PhotoSize`, optional): Video thumbnail.
|
||||
|
||||
@@ -71,17 +72,15 @@ class VideoNote(_BaseThumbedMedium):
|
||||
file_unique_id: str,
|
||||
length: int,
|
||||
duration: int,
|
||||
thumb: PhotoSize = None,
|
||||
file_size: int = None,
|
||||
thumbnail: PhotoSize = None,
|
||||
file_size: Optional[int] = None,
|
||||
thumbnail: Optional[PhotoSize] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(
|
||||
file_id=file_id,
|
||||
file_unique_id=file_unique_id,
|
||||
file_size=file_size,
|
||||
thumb=thumb,
|
||||
thumbnail=thumbnail,
|
||||
api_kwargs=api_kwargs,
|
||||
)
|
||||
|
||||
@@ -58,10 +58,10 @@ class Voice(_BaseMedium):
|
||||
file_id: str,
|
||||
file_unique_id: str,
|
||||
duration: int,
|
||||
mime_type: str = None,
|
||||
file_size: int = None,
|
||||
mime_type: Optional[str] = None,
|
||||
file_size: Optional[int] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(
|
||||
file_id=file_id,
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a Telegram ForceReply."""
|
||||
|
||||
from typing import ClassVar, Optional
|
||||
from typing import Final, Optional
|
||||
|
||||
from telegram import constants
|
||||
from telegram._telegramobject import TelegramObject
|
||||
@@ -79,10 +79,10 @@ class ForceReply(TelegramObject):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
selective: bool = None,
|
||||
input_field_placeholder: str = None,
|
||||
selective: Optional[bool] = None,
|
||||
input_field_placeholder: Optional[str] = None,
|
||||
*,
|
||||
api_kwargs: JSONDict = None,
|
||||
api_kwargs: Optional[JSONDict] = None,
|
||||
):
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
self.force_reply: bool = True
|
||||
@@ -93,12 +93,12 @@ class ForceReply(TelegramObject):
|
||||
|
||||
self._freeze()
|
||||
|
||||
MIN_INPUT_FIELD_PLACEHOLDER: ClassVar[int] = constants.ReplyLimit.MIN_INPUT_FIELD_PLACEHOLDER
|
||||
MIN_INPUT_FIELD_PLACEHOLDER: Final[int] = constants.ReplyLimit.MIN_INPUT_FIELD_PLACEHOLDER
|
||||
""":const:`telegram.constants.ReplyLimit.MIN_INPUT_FIELD_PLACEHOLDER`
|
||||
|
||||
.. versionadded:: 20.0
|
||||
"""
|
||||
MAX_INPUT_FIELD_PLACEHOLDER: ClassVar[int] = constants.ReplyLimit.MAX_INPUT_FIELD_PLACEHOLDER
|
||||
MAX_INPUT_FIELD_PLACEHOLDER: Final[int] = constants.ReplyLimit.MAX_INPUT_FIELD_PLACEHOLDER
|
||||
""":const:`telegram.constants.ReplyLimit.MAX_INPUT_FIELD_PLACEHOLDER`
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user