Compare commits

...

44 Commits

Author SHA1 Message Date
renovate[bot] fd3a17a8de Update dependency cryptography to v48.0.1 [SECURITY] (#5274)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-06-18 06:46:21 +00:00
renovate[bot] 0cead98fff Update dependency tornado to v6.5.7 [SECURITY] (#5273)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-06-18 02:05:06 +00:00
JSap0914 35810fe7d6 Fix parse_lpo_and_dwpp not raising ValueError under some circumstances (#5268)
Co-authored-by: JSap0914 <JSap0914@users.noreply.github.com>
2026-06-17 16:40:53 -04:00
renovate[bot] 6775884282 Update Ruff to v0.15.16 (#5265)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-06-14 02:11:40 +00:00
renovate[bot] 8504e323b6 Update dependency tornado to v6.5.6 [SECURITY] (#5264)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-06-12 23:04:49 +00:00
Poolitzer afb9fc4898 Fix: Delete the chango here
I wasn't able to in the PR, it was too quick
2026-06-12 10:03:03 +02:00
Poolitzer 5d663af824 Bump version to v22.8 (#5262) 2026-06-12 10:02:13 +02:00
Harshil 0dd6afc177 Documentation Improvements (#5240)
Co-authored-by: Poolitzer <github@poolitzer.eu>
2026-06-12 09:46:44 +02:00
Harshil 4c710a3455 Support Python 3.15 beta (#5259) 2026-06-12 09:36:40 +02:00
Abdelrahman Elkheir 0fb5678180 Full Support for Bot API 10.0 (#5229)
Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com>
Co-authored-by: poolitzer <github@poolitzer.eu>
Co-authored-by: Phil Bazun <Phil9lne@gmail.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-06-09 11:49:15 -04:00
renovate[bot] ab2996713d Update actions/stale action to v10.3.0 (#5255)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-06-01 04:01:27 +00:00
renovate[bot] cc7b55d837 Update github/codeql-action action to v4.36.0 (#5256)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-06-01 03:55:54 +00:00
renovate[bot] 6cfed61395 Update pypa/gh-action-pypi-publish action to v1.14.0 (#5257)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-06-01 03:44:49 +00:00
renovate[bot] 74e1d9fb5f Update dependency sphinxcontrib-mermaid to v2.0.2 (#5254)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-06-01 03:39:14 +00:00
renovate[bot] 351a282fa3 Update dependency astral-sh/uv to v0.11.16 (#5253)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-06-01 03:38:21 +00:00
Harshil 59d2f62f81 Disallow packages newer than last 7 days (#5247) 2026-05-31 13:23:01 -04:00
Harshil 1f343592de Make instantiation of TelegramObjects 15% faster (#5250) 2026-05-31 12:47:47 -04:00
renovate[bot] 4ad65a3b40 Update Ruff to v0.15.15 (#5252)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-05-31 01:37:51 +00:00
renovate[bot] 1a83d47fb3 Update Ruff to v0.15.14 (#5245)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-05-24 01:34:16 +00:00
karin0 6fdab3a58d Check channel_post and edited_channel_post in Update.effective_user (#5237) 2026-05-20 17:44:41 -04:00
renovate[bot] b4067ce363 Update Ruff to v0.15.13 (#5233)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-05-17 01:20:28 +00:00
Harshil 85294fb58d Full Support for Bot API 9.6 (#5196)
Co-authored-by: OuYoung <212045739+ouyooung@users.noreply.github.com>
2026-05-08 16:07:39 -04:00
Aleksandr Kovalko 7db5b4314a Correct isinstance check variable in _MergedFilter.__init__ (#5215) 2026-05-04 08:48:38 -04:00
renovate[bot] 6d9e17a5dc Update dependency astral-sh/uv to v0.11.8 (#5221)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-05-01 02:12:18 +00:00
renovate[bot] e79716ae35 Update jannekem/run-python-script-action action to v1.8 (#5224)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-05-01 02:08:53 +00:00
renovate[bot] 69af37ded9 Update Mypy to v1.20.2 (#5223)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-05-01 01:48:48 +00:00
renovate[bot] 818d17c44d Update github/codeql-action action to v4.35.2 (#5222)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-05-01 01:42:44 +00:00
renovate[bot] 80d515de39 Update actions/upload-artifact action to v7.0.1 (#5220)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-05-01 01:33:06 +00:00
renovate[bot] 229b61a3ae Update Ruff to v0.15.12 (#5217)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-26 01:57:29 +00:00
renovate[bot] f34db07d70 Update Ruff to v0.15.11 (#5209)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-19 09:21:14 +00:00
renovate[bot] d228b33916 Update Mypy to v1.20.1 (#5199)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: poolitzer <github@poolitzer.eu>
2026-04-15 09:06:25 +00:00
renovate[bot] 170dca0ac4 Update dependency pytest to v9.0.3 [SECURITY] (#5206)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-14 04:43:49 +00:00
renovate[bot] d9dbd9481f Update Ruff to v0.15.10 (#5205)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-12 00:40:39 +00:00
renovate[bot] fcceb91b1a Update dependency cryptography to v46.0.7 [SECURITY] (#5203)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-09 02:35:49 +00:00
renovate[bot] 875f4ab4e3 Update Ruff to v0.15.9 (#5198)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-05 05:40:40 +00:00
renovate[bot] 87ecfee99e Update github/codeql-action action to v4.35.1 (#5194)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-01 06:10:51 +00:00
renovate[bot] 98f4dae84f Update codecov/codecov-action action to v5.5.4 (#5190)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-01 06:09:21 +00:00
renovate[bot] 6827d3da75 Update dependency mypy to v1.20.0 (#5193)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-01 06:06:24 +00:00
renovate[bot] bc5f3de3c3 Update dependency astral-sh/uv to v0.11.2 (#5192)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-01 06:06:22 +00:00
renovate[bot] 5f406fb32f Update astral-sh/setup-uv action to v7.6.0 (#5191)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-01 01:18:16 +00:00
renovate[bot] 3ef646edbf Update dependency cryptography to v46.0.6 [SECURITY] (#5185)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-29 01:53:30 +00:00
renovate[bot] 1e82e6260b Update Ruff to v0.15.8 (#5184)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-29 00:46:04 +00:00
Krishna Chaitanya 26203b4474 Migrate from deprecated test-results-action to codecov-action (#5183) 2026-03-25 17:18:15 -07:00
renovate[bot] 73d54f4e20 Update Ruff to v0.15.7 (#5177)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-22 02:01:41 +00:00
155 changed files with 8372 additions and 1062 deletions
+3
View File
@@ -26,6 +26,9 @@
// Enable automerge globally:
"automerge": true,
// Only upgrade packages if 7 days have passed:
"minimumReleaseAge": "7 days",
// Group package updates together:
"packageRules": [
// Linting dependencies in pyproject.toml in sync with the pre-commit-config hooks:
+2 -2
View File
@@ -31,10 +31,10 @@ jobs:
persist-credentials: false
- name: Install uv
uses: astral-sh/setup-uv@e06108dd0aef18192324c70427afc47652e63a82 # v7.5.0
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0
with:
# Install a specific version of uv.
version: "0.10.10"
version: "0.11.16"
# Install 3.13:
python-version: 3.13
+1 -1
View File
@@ -35,7 +35,7 @@ jobs:
- name: Upload linkcheck output
# Run also if the previous steps failed
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: linkcheck-output
path: docs/build/html/output.*
+2 -2
View File
@@ -21,13 +21,13 @@ jobs:
with:
persist-credentials: false
- name: Install the latest version of uv
uses: astral-sh/setup-uv@e06108dd0aef18192324c70427afc47652e63a82 # v7.5.0
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0
- name: Run zizmor
run: uvx zizmor --persona=pedantic --format sarif . > results.sarif
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@fdbfb4d2750291e159f0156def62b853c2798ca2 # v4.31.5
uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0
with:
sarif_file: results.sarif
category: zizmor
+3 -3
View File
@@ -30,7 +30,7 @@ jobs:
- name: Build a binary wheel and a source tarball
run: python3 -m build
- name: Store the distribution packages
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: python-package-distributions
path: dist/
@@ -60,7 +60,7 @@ jobs:
name: python-package-distributions
path: dist/
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
compute-signatures:
name: Compute SHA1 Sums and Sign with Sigstore
@@ -92,7 +92,7 @@ jobs:
./dist/*.tar.gz
./dist/*.whl
- name: Store the distribution packages and signatures
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: python-package-distributions-and-signatures
path: dist/
+3 -3
View File
@@ -30,7 +30,7 @@ jobs:
- name: Build a binary wheel and a source tarball
run: python3 -m build
- name: Store the distribution packages
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: python-package-distributions
path: dist/
@@ -60,7 +60,7 @@ jobs:
name: python-package-distributions
path: dist/
- name: Publish to Test PyPI
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
with:
repository-url: https://test.pypi.org/legacy/
@@ -94,7 +94,7 @@ jobs:
./dist/*.tar.gz
./dist/*.whl
- name: Store the distribution packages and signatures
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: python-package-distributions-and-signatures
path: dist/
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
# For adding labels and closing
issues: write
steps:
- uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0
- uses: actions/stale@eb5cf3af3ac0a1aa4c9c45633dd1ae542a27a899 # v10.3.0
with:
# PRs never get stale
days-before-stale: 3
@@ -18,7 +18,7 @@ jobs:
python-version: 3.12
pyright-version: ~=1.1.367
- name: Check Output
uses: jannekem/run-python-script-action@bbfca66c612a28f3eeca0ae40e1f810265e2ea68 # v1.7
uses: jannekem/run-python-script-action@9d8e2e0878d575fb6073277f38ce3f10ebf4f059 # v1.8
env:
TYPE_COMPLETENESS: ${{ steps.pyright-type-completeness.outputs.base-completeness-score }}
with:
+4 -3
View File
@@ -19,7 +19,7 @@ jobs:
runs-on: ${{matrix.os}}
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12', '3.13', '3.14']
python-version: ['3.10', '3.11', '3.12', '3.13', '3.14', '3.15.0-beta.2']
os: [ubuntu-latest, windows-latest, macos-latest]
include:
- python-version: '3.14t'
@@ -87,15 +87,16 @@ jobs:
.test_report_optionals_junit.xml
- name: Submit coverage
uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
with:
env_vars: OS,PYTHON
name: ${{ matrix.os }}-${{ matrix.python-version }}
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }}
- name: Upload test results to Codecov
uses: codecov/test-results-action@0fa95f0e1eeaafde2c782583b36b28ad0d8c77d3 # v1.2.1
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
if: ${{ !cancelled() }}
with:
files: .test_report_no_optionals_junit.xml,.test_report_optionals_junit.xml
token: ${{ secrets.CODECOV_TOKEN }}
report_type: test_results
+2 -2
View File
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: 'v0.15.6'
rev: 'v0.15.16'
hooks:
# Run the linter:
- id: ruff-check
@@ -23,7 +23,7 @@ repos:
- . # this basically does `pip install -e .`
priority: 10
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.19.1
rev: v1.20.2
hooks:
- id: mypy
name: mypy-ptb
+2
View File
@@ -75,10 +75,12 @@ The following wonderful people contributed directly or indirectly to this projec
- `jossalgon <https://github.com/jossalgon>`_
- `JRoot3D <https://github.com/JRoot3D>`_
- `Juan Cuevas <https://github.com/cuevasrja>`
- `karin0 <https://github.com/karin0>`_
- `kenjitagawa <https://github.com/kenjitagawa>`_
- `kennethcheo <https://github.com/kennethcheo>`_
- `Kirill Vasin <https://github.com/vasinkd>`_
- `Kjwon15 <https://github.com/kjwon15>`_
- `Krishna Chaitanya Balusu <https://github.com/Krishnachaitanyakc>`_
- `Li-aung Yip <https://github.com/LiaungYip>`_
- `locobott <https://github.com/locobott>`_
- `Loo Zheng Yuan <https://github.com/loozhengyuan>`_
+2 -2
View File
@@ -11,7 +11,7 @@
:target: https://pypi.org/project/python-telegram-bot/
:alt: Supported Python versions
.. image:: https://img.shields.io/badge/Bot%20API-9.5-blue?logo=telegram
.. image:: https://img.shields.io/badge/Bot%20API-10.0-blue?logo=telegram
:target: https://core.telegram.org/bots/api-changelog
:alt: Supported Bot API version
@@ -77,7 +77,7 @@ After installing_ the library, be sure to check out the section on `working with
Telegram API support
~~~~~~~~~~~~~~~~~~~~
All types and methods of the Telegram Bot API **9.5** are natively supported by this library.
All types and methods of the Telegram Bot API **10.0** are natively supported by this library.
In addition, Bot API functionality not yet natively included can still be used as described `in our wiki <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Bot-API-Forward-Compatibility>`_.
Notable Features
@@ -0,0 +1,5 @@
bugfixes = "Fixed incorrect isinstance check in class telegram.ext.filters._MergedFilter for or_filter."
[[pull_requests]]
uid = "5125"
author_uids = ["gistrec"]
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Update Ruff to v0.15.7"
[[pull_requests]]
uid = "5177"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Migrate from deprecated test-results-action to codecov-action"
[[pull_requests]]
uid = "5183"
author_uids = ["Krishnachaitanyakc"]
closes_threads = ["5158"]
@@ -0,0 +1,5 @@
internal = "Update Ruff to v0.15.8"
[[pull_requests]]
uid = "5184"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
dependencies = "Update dependency cryptography to v46.0.6 [SECURITY]"
[[pull_requests]]
uid = "5185"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
other = "Update codecov/codecov-action action to v5.5.4"
[[pull_requests]]
uid = "5190"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Update astral-sh/setup-uv action to v7.6.0"
[[pull_requests]]
uid = "5191"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Update dependency astral-sh/uv to v0.11.2"
[[pull_requests]]
uid = "5192"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Update dependency mypy to v1.20.0"
[[pull_requests]]
uid = "5193"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Update github/codeql-action action to v4.35.1"
[[pull_requests]]
uid = "5194"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,24 @@
features = """
Full Support for Bot API 9.6
.. warning::
- Bot API 9.6 replaces the field ``correct_option_id`` of ``Poll`` with the new field ``correct_option_ids``. The field ``correct_option_id`` is still present in PTB for backward compatibility, but it will be removed in future releases.
- Bot API 9.6 replaces the argument ``correct_option_id`` of ``Bot.send_poll`` with the new argument ``correct_option_ids``. The argument ``correct_option_id`` is still present in PTB for backward compatibility, but it will be removed in future releases.
- Bot API 9.6 introduces a now required argument ``persistent_id`` to ``PollOption``. For backward compatibility, the argument is currently still marked as optional in the signature and its presence is enforced through a runtime check. In future versions, this argument will be made required in the signature as well.
- Bot API 9.6 introduces a now required argument ``option_persistent_ids`` to ``PollAnswer``. For backward compatibility, the argument is currently still marked as optional in the signature and its presence is enforced through a runtime check. In future versions, this argument will be made required in the signature as well.
- Bot API 9.6 introduces a now required argument ``allows_revoting`` to ``Poll``. For backward compatibility, the argument is currently still marked as optional in the signature and its presence is enforced through a runtime check. In future versions, this argument will be made required in the signature as well.
Please make sure to update your code accordingly to avoid potential issues in the future. We recommend using keyword arguments to ensure compatibility with future updates.
"""
pull_requests = [
{ uid = "5196", author_uid = "harshil21" },
{ uid = "5202", author_uid = "ouyooung" },
{ uid = "5197", author_uid = "harshil21" },
]
@@ -0,0 +1,5 @@
internal = "Update Ruff to v0.15.9"
[[pull_requests]]
uid = "5198"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Update Mypy to v1.20.1"
[[pull_requests]]
uid = "5199"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
dependencies = "Update dependency cryptography to v46.0.7 [SECURITY]"
[[pull_requests]]
uid = "5203"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Update Ruff to v0.15.10"
[[pull_requests]]
uid = "5205"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Update dependency pytest to v9.0.3 [SECURITY]"
[[pull_requests]]
uid = "5206"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Update Ruff to v0.15.11"
[[pull_requests]]
uid = "5209"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Update Ruff to v0.15.12"
[[pull_requests]]
uid = "5217"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Update actions/upload-artifact action to v7.0.1"
[[pull_requests]]
uid = "5220"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Update dependency astral-sh/uv to v0.11.8"
[[pull_requests]]
uid = "5221"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Update github/codeql-action action to v4.35.2"
[[pull_requests]]
uid = "5222"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Update Mypy to v1.20.2"
[[pull_requests]]
uid = "5223"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Update jannekem/run-python-script-action action to v1.8"
[[pull_requests]]
uid = "5224"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,33 @@
features = """
Full Support for Bot API 10.0
.. warning::
- Bot API 10.0 introduces a now required argument ``members_only`` to ``Poll``. For backward compatibility, the argument is currently still marked as optional in the signature and its presence is enforced through a runtime check. In future versions, this argument will be made required in the signature as well.
Please make sure to update your code accordingly to avoid potential issues in the future. We recommend using keyword arguments to ensure compatibility with future updates.
"""
deprecations = """
* Deprecated passing the ``filename`` parameter positionally to the classes:
* ``InputMediaAnimation``
* ``InputMediaAudio``
* ``InputMediaPhoto``
* ``InputMediaDocument``
* ``InputMediaVideo``
Please pass ``filename`` as a keyword argument instead, as this parameter will become keyword-only in the future.
* Deprecated ``InputPollOption.de_json``. The class ``InputPollOption`` is input only and its ``de_json`` method will be removed in future versions. The Bot API 10.0 ``media`` field of ``InputPollOption`` will not be included for deserialization.
"""
pull_requests = [
{ uid = "5229", author_uid = "aelkheir", closes_threads = ["5228"] },
{ uid = "5230", author_uid = "harshil21" },
{ uid = "5235", author_uid = "harshil21" },
{ uid = "5238", author_uid = "harshil21" },
{ uid = "5232", author_uid = "aelkheir" },
{ uid = "5232", author_uid = ["Poolitzer", "Phil9l", "harshil21", "aelkheir"] },
]
@@ -0,0 +1,5 @@
internal = "Update Ruff to v0.15.13"
[[pull_requests]]
uid = "5233"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
bugfixes = "`Update.effective_user` now checks for `channel_post` and `edited_channel_post`"
[[pull_requests]]
uid = "5237"
author_uids = ["karin0"]
closes_threads = ["5236"]
@@ -0,0 +1,6 @@
documentation = "Documentation Improvements"
pull_requests = [
{ uid = "5240", author_uids = ["harshil21", "Poolitzer"] },
{ uid = "5241", author_uids = ["harshil21"] },
]
@@ -0,0 +1,5 @@
internal = "Update Ruff to v0.15.14"
[[pull_requests]]
uid = "5245"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
security = "Disallow packages newer than last 7 days"
[[pull_requests]]
uid = "5247"
author_uids = ["harshil21"]
closes_threads = ["5195"]
@@ -0,0 +1,5 @@
other = "Make instantiation of ``TelegramObject``'s 15% faster"
[[pull_requests]]
uid = "5250"
author_uids = ["harshil21"]
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Update Ruff to v0.15.15"
[[pull_requests]]
uid = "5252"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Update dependency astral-sh/uv to v0.11.16"
[[pull_requests]]
uid = "5253"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Update dependency sphinxcontrib-mermaid to v2.0.2"
[[pull_requests]]
uid = "5254"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Update actions/stale action to v10.3.0"
[[pull_requests]]
uid = "5255"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Update github/codeql-action action to v4.36.0"
[[pull_requests]]
uid = "5256"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Update pypa/gh-action-pypi-publish action to v1.14.0"
[[pull_requests]]
uid = "5257"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,9 @@
other = """Support Python 3.15 Beta
* Python 3.15 free threading is not fully supported yet, as the optional dependency ``cryptography`` is not yet compatible with it.
"""
[[pull_requests]]
uid = "5259"
author_uids = ["harshil21"]
closes_threads = ["5231"]
@@ -0,0 +1,5 @@
other = "Bump Version to 22.8"
[[pull_requests]]
uid = "5262"
author_uids = ["Poolitzer"]
closes_threads = []
@@ -0,0 +1,5 @@
dependencies = "Update dependency tornado to v6.5.6 [SECURITY]"
[[pull_requests]]
uid = "5264"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Update Ruff to v0.15.16"
[[pull_requests]]
uid = "5265"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
bugfixes = "Fixed ``parse_lpo_and_dwpp`` silently overwriting ``link_preview_options`` when ``disable_web_page_preview=False``."
[[pull_requests]]
uid = "5268"
author_uids = ["JSap0914"]
closes_threads = []
@@ -0,0 +1,5 @@
dependencies = "Update dependency tornado to v6.5.7 [SECURITY]"
[[pull_requests]]
uid = "5273"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -0,0 +1,5 @@
dependencies = "Update dependency cryptography to v48.0.1 [SECURITY]"
[[pull_requests]]
uid = "5274"
author_uids = ["renovate[bot]"]
closes_threads = []
@@ -83,6 +83,13 @@ get_updates_read_timeout_addition = [
" ``2``.",
]
RAISES_BLOCK = [
"Raises:",
"",
" :class:`telegram.error.TelegramError`",
"",
]
def find_insert_pos_for_kwargs(lines: list[str]) -> int:
"""Finds the correct position to insert the keyword arguments and returns the index."""
@@ -92,6 +99,13 @@ def find_insert_pos_for_kwargs(lines: list[str]) -> int:
return False
def find_insert_pos_for_raises(lines: list[str]) -> int:
"""Finds the correct position to insert the Raises block and returns the index."""
if "Raises:" in lines:
return -1 # Don't insert if there's already a Raises block
return len(lines) # Insert at the end if there's no Raises block
def check_timeout_and_api_kwargs_presence(obj: object) -> int:
"""Checks if the method has timeout and api_kwargs keyword only parameters."""
sig = inspect.signature(obj)
+19 -4
View File
@@ -27,9 +27,11 @@ from sphinx.application import Sphinx
import telegram
import telegram.ext
from docs.auxil.admonition_inserter import AdmonitionInserter
from docs.auxil.kwargs_insertion import (
from docs.auxil.bot_insertion import (
RAISES_BLOCK,
check_timeout_and_api_kwargs_presence,
find_insert_pos_for_kwargs,
find_insert_pos_for_raises,
get_updates_read_timeout_addition,
keyword_args,
media_write_timeout_change,
@@ -52,6 +54,7 @@ PRIVATE_BASE_CLASSES = {
"_BaseMedium": "TelegramObject",
"_CredentialsBase": "TelegramObject",
"_ChatBase": "TelegramObject",
"_BaseInputMedia": "TelegramObject",
}
@@ -84,8 +87,8 @@ def autodoc_process_docstring(
app: Sphinx, what, name: str, obj: object, options, lines: list[str]
):
"""We do the following things:
1) Use this method to automatically insert the Keyword Args and "Shortcuts" admonitions
for the Bot methods.
1) Use this method to automatically insert the Keyword Args, "Shortcuts" admonitions,
and the Raises block, wherever applicable, for the Bot methods.
2) Use this method to automatically insert "Returned in" admonition into classes
that are returned from the Bot methods
@@ -101,13 +104,15 @@ def autodoc_process_docstring(
"""
# 1) Insert the Keyword Args and "Shortcuts" admonitions for the Bot methods
method_name = name.rsplit(".", maxsplit=1)[0]
method_name = name.rsplit(".", maxsplit=1)[-1]
if (
name.startswith("telegram.Bot.")
and what == "method"
and method_name.islower()
and check_timeout_and_api_kwargs_presence(obj)
):
# Logic for inserting keyword args into docstrings:
# -------------------------------------------------
insert_index = find_insert_pos_for_kwargs(lines)
if not insert_index:
raise ValueError(
@@ -133,6 +138,16 @@ def autodoc_process_docstring(
lines[insert_idx:insert_idx] = effective_insert
insert_idx += len(effective_insert)
# Logic for inserting Raises:
# -------------------------------------------------
# We will only insert the Raises block if there isn't already one.
insert_index = find_insert_pos_for_raises(lines)
if insert_index != -1:
lines[insert_index:insert_index] = RAISES_BLOCK
# Logic for inserting "Shortcuts" admonition:
# -------------------------------------------
ADMONITION_INSERTER.insert_admonitions(
obj=typing.cast("collections.abc.Callable", obj),
docstring_lines=lines,
+21
View File
@@ -41,6 +41,8 @@
- Used for sending paid media to channels
* - :meth:`~telegram.Bot.send_photo`
- Used for sending photos
* - :meth:`~telegram.Bot.send_live_photo`
- Used for sending live photos
* - :meth:`~telegram.Bot.send_poll`
- Used for sending polls
* - :meth:`~telegram.Bot.send_sticker`
@@ -80,6 +82,8 @@
- Used for answering the callback query
* - :meth:`~telegram.Bot.answer_inline_query`
- Used for answering the inline query
* - :meth:`~telegram.Bot.answer_guest_query`
- Used for replying to a received guest message
* - :meth:`~telegram.Bot.answer_pre_checkout_query`
- Used for answering a pre checkout query
* - :meth:`~telegram.Bot.answer_shipping_query`
@@ -104,6 +108,10 @@
- Used for stopping the running poll
* - :meth:`~telegram.Bot.set_message_reaction`
- Used for setting reactions on messages
* - :meth:`~telegram.Bot.delete_message_reaction`
- Used for deleting reactions on messages
* - :meth:`~telegram.Bot.delete_all_message_reactions`
- Used for deleting all reactions by a chat or user
.. raw:: html
@@ -167,6 +175,8 @@
- Used for unpinning a message
* - :meth:`~telegram.Bot.unpin_all_chat_messages`
- Used for unpinning all pinned chat messages
* - :meth:`~telegram.Bot.get_user_personal_chat_messages`
- Used for obtaining the personal chat messages of a user
* - :meth:`~telegram.Bot.get_user_profile_audios`
- Used for obtaining user's profile audios
* - :meth:`~telegram.Bot.get_user_profile_photos`
@@ -237,6 +247,10 @@
- Used for obtaining the menu button of a private chat or the default menu button
* - :meth:`~telegram.Bot.set_chat_menu_button`
- Used for setting the menu button of a private chat or the default menu button
* - :meth:`~telegram.Bot.set_managed_bot_access_settings`
- Used for changing the access settings of a managed bot
* - :meth:`~telegram.Bot.get_managed_bot_access_settings`
- Used for obtaining the access settings of a managed bot
* - :meth:`~telegram.Bot.set_my_description`
- Used for setting the description of the bot
* - :meth:`~telegram.Bot.get_my_description`
@@ -496,12 +510,19 @@
- Used for getting information about gifts available for sending
* - :meth:`~telegram.Bot.get_chat_gifts`
- Used for getting information about gifts owned and hosted by a chat
* - :meth:`~telegram.Bot.get_managed_bot_token`
- Used for getting the token of a managed bot
* - :meth:`~telegram.Bot.replace_managed_bot_token`
- Used for replacing the token of a managed bot
* - :meth:`~telegram.Bot.get_me`
- Used for getting basic information about the bot
* - :meth:`~telegram.Bot.get_user_gifts`
- Used for getting information about gifts owned and hosted by a user
* - :meth:`~telegram.Bot.save_prepared_inline_message`
- Used for storing a message to be sent by a user of a Mini App
* - :meth:`~telegram.Bot.save_prepared_keyboard_button`
- Used for saving a keyboard button to be used in a Mini App
.. raw:: html
+18
View File
@@ -8,6 +8,7 @@ Available Types
telegram.animation
telegram.audio
telegram.birthdate
telegram.botaccesssettings
telegram.botcommand
telegram.botcommandscope
telegram.botcommandscopeallchatadministrators
@@ -101,26 +102,37 @@ Available Types
telegram.inputmediaanimation
telegram.inputmediaaudio
telegram.inputmediadocument
telegram.inputmedialivephoto
telegram.inputmedialocation
telegram.inputmediaphoto
telegram.inputmediasticker
telegram.inputmediavenue
telegram.inputmediavideo
telegram.inputpaidmedia
telegram.inputpaidmedialivephoto
telegram.inputpaidmediaphoto
telegram.inputpaidmediavideo
telegram.inputpollmedia
telegram.inputprofilephoto
telegram.inputprofilephotoanimated
telegram.inputprofilephotostatic
telegram.inputpolloption
telegram.inputpolloptionmedia
telegram.inputstorycontent
telegram.inputstorycontentphoto
telegram.inputstorycontentvideo
telegram.keyboardbutton
telegram.keyboardbuttonpolltype
telegram.keyboardbuttonrequestchat
telegram.keyboardbuttonrequestmanagedbot
telegram.keyboardbuttonrequestusers
telegram.linkpreviewoptions
telegram.livephoto
telegram.location
telegram.locationaddress
telegram.loginurl
telegram.managedbotcreated
telegram.managedbotupdated
telegram.maybeinaccessiblemessage
telegram.menubutton
telegram.menubuttoncommands
@@ -143,6 +155,7 @@ Available Types
telegram.ownedgiftunique
telegram.paidmedia
telegram.paidmediainfo
telegram.paidmedialivephoto
telegram.paidmediaphoto
telegram.paidmediapreview
telegram.paidmediapurchased
@@ -151,7 +164,11 @@ Available Types
telegram.photosize
telegram.poll
telegram.pollanswer
telegram.pollmedia
telegram.polloption
telegram.polloptionadded
telegram.polloptiondeleted
telegram.preparedkeyboardbutton
telegram.proximityalerttriggered
telegram.reactioncount
telegram.reactiontype
@@ -161,6 +178,7 @@ Available Types
telegram.replykeyboardmarkup
telegram.replykeyboardremove
telegram.replyparameters
telegram.sentguestmessage
telegram.sentwebappmessage
telegram.shareduser
telegram.story
@@ -0,0 +1,6 @@
BotAccessSettings
=================
.. autoclass:: telegram.BotAccessSettings
:members:
:show-inheritance:
@@ -16,6 +16,7 @@ Handlers
telegram.ext.conversationhandler
telegram.ext.filters
telegram.ext.inlinequeryhandler
telegram.ext.managedbotupdatedhandler
telegram.ext.messagehandler
telegram.ext.messagereactionhandler
telegram.ext.paidmediapurchasedhandler
@@ -0,0 +1,6 @@
ManagedBotUpdatedHandler
========================
.. autoclass:: telegram.ext.ManagedBotUpdatedHandler
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
InputMediaLivePhoto
===================
.. autoclass:: telegram.InputMediaLivePhoto
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
InputMediaLocation
==================
.. autoclass:: telegram.InputMediaLocation
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
InputMediaSticker
=================
.. autoclass:: telegram.InputMediaSticker
:members:
:show-inheritance:
+6
View File
@@ -0,0 +1,6 @@
InputMediaVenue
===============
.. autoclass:: telegram.InputMediaVenue
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
InputPaidMediaLivePhoto
======================
.. autoclass:: telegram.InputPaidMediaLivePhoto
:members:
:show-inheritance:
+6
View File
@@ -0,0 +1,6 @@
InputPollMedia
==============
.. versionadded:: NEXT.VERSION
.. autoclass:: telegram.InputPollMedia
@@ -0,0 +1,6 @@
InputPollOptionMedia
====================
.. versionadded:: NEXT.VERSION
.. autoclass:: telegram.InputPollOptionMedia
@@ -0,0 +1,6 @@
KeyboardButtonRequestManagedBot
===============================
.. autoclass:: telegram.KeyboardButtonRequestManagedBot
:members:
:show-inheritance:
+6
View File
@@ -0,0 +1,6 @@
LivePhoto
=========
.. autoclass:: telegram.LivePhoto
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
ManagedBotCreated
=================
.. autoclass:: telegram.ManagedBotCreated
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
ManagedBotUpdated
=================
.. autoclass:: telegram.ManagedBotUpdated
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
PaidMediaLivePhoto
==================
.. autoclass:: telegram.PaidMediaLivePhoto
:members:
:show-inheritance:
+6
View File
@@ -0,0 +1,6 @@
PollMedia
=========
.. autoclass:: telegram.PollMedia
:members:
:show-inheritance:
+6
View File
@@ -0,0 +1,6 @@
PollOptionAdded
===============
.. autoclass:: telegram.PollOptionAdded
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
PollOptionDeleted
=================
.. autoclass:: telegram.PollOptionDeleted
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
PreparedKeyboardButton
======================
.. autoclass:: telegram.PreparedKeyboardButton
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
SentGuestMessage
================
.. autoclass:: telegram.SentGuestMessage
:members:
:show-inheritance:
+9 -4
View File
@@ -36,6 +36,7 @@ classifiers = [
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Programming Language :: Python :: 3.15",
]
dependencies = [
"httpx >=0.27,<0.29",
@@ -98,7 +99,7 @@ tests = [
# required for building the wheels for releases
"build",
# For the test suite
"pytest==9.0.2",
"pytest==9.0.3",
# needed because pytest doesn't come with native support for coroutines as tests
"pytest-asyncio==0.21.2",
# xdist runs tests in parallel
@@ -120,7 +121,7 @@ docs = [
"sphinx==9.1.0; python_version >= '3.12'",
"furo==2025.12.19",
"sphinx-paramlinks==0.6.0",
"sphinxcontrib-mermaid==2.0.1",
"sphinxcontrib-mermaid==2.0.2",
"sphinx-copybutton==0.5.2",
"sphinx-inline-tabs==2025.12.21.14",
# Temporary. See #4387
@@ -133,8 +134,8 @@ docs = [
]
linting = [
"prek",
"ruff==0.15.6",
"mypy==1.19.1",
"ruff==0.15.16",
"mypy==1.20.2",
"pylint==4.0.5"
]
all = [{ include-group = "tests" }, { include-group = "docs" }, { include-group = "linting"}]
@@ -153,6 +154,10 @@ exclude = [".venv*", "venv*", ".github", "uv.lock"]
[tool.hatch.build.targets.wheel]
packages = ["src/telegram"]
# uv
[tool.uv]
exclude-newer = "7 days"
# CHANGO
[tool.chango]
sys_path = "changes"
+64 -20
View File
@@ -35,6 +35,7 @@ __all__ = (
"BackgroundTypeWallpaper",
"Birthdate",
"Bot",
"BotAccessSettings",
"BotCommand",
"BotCommandScope",
"BotCommandScopeAllChatAdministrators",
@@ -157,13 +158,20 @@ __all__ = (
"InputMediaAnimation",
"InputMediaAudio",
"InputMediaDocument",
"InputMediaLivePhoto",
"InputMediaLocation",
"InputMediaPhoto",
"InputMediaSticker",
"InputMediaVenue",
"InputMediaVideo",
"InputMessageContent",
"InputPaidMedia",
"InputPaidMediaLivePhoto",
"InputPaidMediaPhoto",
"InputPaidMediaVideo",
"InputPollMedia",
"InputPollOption",
"InputPollOptionMedia",
"InputProfilePhoto",
"InputProfilePhotoAnimated",
"InputProfilePhotoStatic",
@@ -177,12 +185,16 @@ __all__ = (
"KeyboardButton",
"KeyboardButtonPollType",
"KeyboardButtonRequestChat",
"KeyboardButtonRequestManagedBot",
"KeyboardButtonRequestUsers",
"LabeledPrice",
"LinkPreviewOptions",
"LivePhoto",
"Location",
"LocationAddress",
"LoginUrl",
"ManagedBotCreated",
"ManagedBotUpdated",
"MaskPosition",
"MaybeInaccessibleMessage",
"MenuButton",
@@ -207,6 +219,7 @@ __all__ = (
"OwnedGifts",
"PaidMedia",
"PaidMediaInfo",
"PaidMediaLivePhoto",
"PaidMediaPhoto",
"PaidMediaPreview",
"PaidMediaPurchased",
@@ -228,9 +241,13 @@ __all__ = (
"PhotoSize",
"Poll",
"PollAnswer",
"PollMedia",
"PollOption",
"PollOptionAdded",
"PollOptionDeleted",
"PreCheckoutQuery",
"PreparedInlineMessage",
"PreparedKeyboardButton",
"ProximityAlertTriggered",
"ReactionCount",
"ReactionType",
@@ -248,6 +265,7 @@ __all__ = (
"RevenueWithdrawalStateSucceeded",
"SecureData",
"SecureValue",
"SentGuestMessage",
"SentWebAppMessage",
"SharedUser",
"ShippingAddress",
@@ -325,23 +343,12 @@ __all__ = (
"warnings",
)
from telegram._inputchecklist import InputChecklist, InputChecklistTask
from telegram._payment.stars.staramount import StarAmount
from telegram._payment.stars.startransactions import StarTransaction, StarTransactions
from telegram._payment.stars.transactionpartner import (
TransactionPartner,
TransactionPartnerAffiliateProgram,
TransactionPartnerChat,
TransactionPartnerFragment,
TransactionPartnerOther,
TransactionPartnerTelegramAds,
TransactionPartnerTelegramApi,
TransactionPartnerUser,
)
__lazy_modules__: list[str] = ["constants", "error", "helpers", "request", "warnings"]
from . import _version, constants, error, helpers, request, warnings
from ._birthdate import Birthdate
from ._bot import Bot
from ._botaccesssettings import BotAccessSettings
from ._botcommand import BotCommand
from ._botcommandscope import (
BotCommandScope,
@@ -412,11 +419,6 @@ from ._copytextbutton import CopyTextButton
from ._dice import Dice
from ._directmessagepricechanged import DirectMessagePriceChanged
from ._directmessagestopic import DirectMessagesTopic
from ._files._inputstorycontent import (
InputStoryContent,
InputStoryContentPhoto,
InputStoryContentVideo,
)
from ._files.animation import Animation
from ._files.audio import Audio
from ._files.chatphoto import ChatPhoto
@@ -429,11 +431,18 @@ from ._files.inputmedia import (
InputMediaAnimation,
InputMediaAudio,
InputMediaDocument,
InputMediaLivePhoto,
InputMediaLocation,
InputMediaPhoto,
InputMediaSticker,
InputMediaVenue,
InputMediaVideo,
InputPaidMedia,
InputPaidMediaLivePhoto,
InputPaidMediaPhoto,
InputPaidMediaVideo,
InputPollMedia,
InputPollOptionMedia,
)
from ._files.inputprofilephoto import (
InputProfilePhoto,
@@ -441,6 +450,12 @@ from ._files.inputprofilephoto import (
InputProfilePhotoStatic,
)
from ._files.inputsticker import InputSticker
from ._files.inputstorycontent import (
InputStoryContent,
InputStoryContentPhoto,
InputStoryContentVideo,
)
from ._files.livephoto import LivePhoto
from ._files.location import Location
from ._files.photosize import PhotoSize
from ._files.sticker import MaskPosition, Sticker, StickerSet
@@ -496,11 +511,17 @@ from ._inline.inputmessagecontent import InputMessageContent
from ._inline.inputtextmessagecontent import InputTextMessageContent
from ._inline.inputvenuemessagecontent import InputVenueMessageContent
from ._inline.preparedinlinemessage import PreparedInlineMessage
from ._inputchecklist import InputChecklist, InputChecklistTask
from ._keyboardbutton import KeyboardButton
from ._keyboardbuttonpolltype import KeyboardButtonPollType
from ._keyboardbuttonrequest import KeyboardButtonRequestChat, KeyboardButtonRequestUsers
from ._keyboardbuttonrequest import (
KeyboardButtonRequestChat,
KeyboardButtonRequestManagedBot,
KeyboardButtonRequestUsers,
)
from ._linkpreviewoptions import LinkPreviewOptions
from ._loginurl import LoginUrl
from ._managedbot import ManagedBotCreated, ManagedBotUpdated
from ._menubutton import MenuButton, MenuButtonCommands, MenuButtonDefault, MenuButtonWebApp
from ._message import InaccessibleMessage, MaybeInaccessibleMessage, Message
from ._messageautodeletetimerchanged import MessageAutoDeleteTimerChanged
@@ -518,6 +539,7 @@ from ._ownedgift import OwnedGift, OwnedGiftRegular, OwnedGifts, OwnedGiftUnique
from ._paidmedia import (
PaidMedia,
PaidMediaInfo,
PaidMediaLivePhoto,
PaidMediaPhoto,
PaidMediaPreview,
PaidMediaPurchased,
@@ -563,8 +585,29 @@ from ._payment.stars.revenuewithdrawalstate import (
RevenueWithdrawalStatePending,
RevenueWithdrawalStateSucceeded,
)
from ._payment.stars.staramount import StarAmount
from ._payment.stars.startransactions import StarTransaction, StarTransactions
from ._payment.stars.transactionpartner import (
TransactionPartner,
TransactionPartnerAffiliateProgram,
TransactionPartnerChat,
TransactionPartnerFragment,
TransactionPartnerOther,
TransactionPartnerTelegramAds,
TransactionPartnerTelegramApi,
TransactionPartnerUser,
)
from ._payment.successfulpayment import SuccessfulPayment
from ._poll import InputPollOption, Poll, PollAnswer, PollOption
from ._poll import (
InputPollOption,
Poll,
PollAnswer,
PollMedia,
PollOption,
PollOptionAdded,
PollOptionDeleted,
)
from ._preparedkeyboardbutton import PreparedKeyboardButton
from ._proximityalerttriggered import ProximityAlertTriggered
from ._reaction import (
ReactionCount,
@@ -576,6 +619,7 @@ from ._reaction import (
from ._reply import ExternalReplyInfo, ReplyParameters, TextQuote
from ._replykeyboardmarkup import ReplyKeyboardMarkup
from ._replykeyboardremove import ReplyKeyboardRemove
from ._sentguestmessage import SentGuestMessage
from ._sentwebappmessage import SentWebAppMessage
from ._shared import ChatShared, SharedUser, UsersShared
from ._story import Story
+719 -620
View File
File diff suppressed because it is too large Load Diff
+77
View File
@@ -0,0 +1,77 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2026
# 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 represents a Telegram Bot Access Settings."""
from collections.abc import Sequence
from typing import TYPE_CHECKING
from telegram._telegramobject import TelegramObject
from telegram._user import User
from telegram._utils.argumentparsing import de_list_optional, parse_sequence_arg
from telegram._utils.types import JSONDict
if TYPE_CHECKING:
from telegram import Bot
class BotAccessSettings(TelegramObject):
"""
This object describes the access settings of a bot.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`is_access_restricted` and :attr:`added_users` are equal.
.. versionadded:: 22.8
Args:
is_access_restricted (:obj:`bool`): :obj:`True`, if only selected users can access the bot.
The bot's owner can always access it.
added_users (Sequence[:class:`telegram.User`], optional): The list of other users who
have access to the bot if the access is restricted.
Attributes:
is_access_restricted (:obj:`bool`): :obj:`True`, if only selected users can access the bot.
The bot's owner can always access it.
added_users (Sequence[:class:`telegram.User`]): Optional. The list of other users who
have access to the bot if the access is restricted.
"""
__slots__ = ("added_users", "is_access_restricted")
def __init__(
self,
is_access_restricted: bool,
added_users: Sequence[User] | None = None,
*,
api_kwargs: JSONDict | None = None,
):
super().__init__(api_kwargs=api_kwargs)
self.is_access_restricted: bool = is_access_restricted
self.added_users: tuple[User, ...] = parse_sequence_arg(added_users)
self._id_attrs = (self.is_access_restricted, self.added_users)
self._freeze()
@classmethod
def de_json(cls, data: JSONDict, bot: "Bot | None" = None) -> "BotAccessSettings":
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
data["added_users"] = de_list_optional(data.get("added_users"), User, bot)
return super().de_json(data=data, bot=bot)
+181 -2
View File
@@ -34,6 +34,7 @@ from telegram._utils import enum
from telegram._utils.defaultvalue import DEFAULT_NONE
from telegram._utils.types import (
CorrectOptionID,
CorrectOptionIds,
FileInput,
JSONDict,
ODVInput,
@@ -57,12 +58,15 @@ if TYPE_CHECKING:
InputChecklist,
InputMediaAudio,
InputMediaDocument,
InputMediaLivePhoto,
InputMediaPhoto,
InputMediaVideo,
InputPaidMedia,
InputPollMedia,
InputPollOption,
LabeledPrice,
LinkPreviewOptions,
LivePhoto,
Location,
Message,
MessageEntity,
@@ -310,6 +314,7 @@ class _ChatBase(TelegramObject):
async def get_administrators(
self,
return_bots: bool | None = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -333,6 +338,7 @@ class _ChatBase(TelegramObject):
"""
return await self.get_bot().get_chat_administrators(
chat_id=self.id,
return_bots=return_bots,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
@@ -1087,7 +1093,7 @@ class _ChatBase(TelegramObject):
async def send_message_draft(
self,
draft_id: int,
text: str,
text: str | None = None,
message_thread_id: int | None = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
entities: Sequence["MessageEntity"] | None = None,
@@ -1104,6 +1110,9 @@ class _ChatBase(TelegramObject):
For the documentation of the arguments, please see :meth:`telegram.Bot.send_message_draft`.
.. versionchanged:: 22.8
Bot API 10.0 makes the ``text`` argument optional.
Returns:
:obj:`bool`: On success, :obj:`True` is returned.
@@ -1189,7 +1198,7 @@ class _ChatBase(TelegramObject):
async def send_media_group(
self,
media: Sequence[
"InputMediaAudio | InputMediaDocument | InputMediaPhoto | InputMediaVideo"
"InputMediaAudio | InputMediaDocument | InputMediaPhoto | InputMediaVideo | InputMediaLivePhoto" # noqa: E501 # pylint: disable=line-too-long
],
disable_notification: ODVInput[bool] = DEFAULT_NONE,
protect_content: ODVInput[bool] = DEFAULT_NONE,
@@ -1348,6 +1357,76 @@ class _ChatBase(TelegramObject):
suggested_post_parameters=suggested_post_parameters,
)
async def send_live_photo(
self,
live_photo: "FileInput | LivePhoto",
photo: "FileInput | PhotoSize",
business_connection_id: str | None = None,
message_thread_id: int | None = None,
direct_messages_topic_id: int | None = None,
caption: str | None = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Sequence["MessageEntity"] | None = None,
show_caption_above_media: bool | None = None,
has_spoiler: bool | None = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
protect_content: ODVInput[bool] = DEFAULT_NONE,
allow_paid_broadcast: bool | None = None,
message_effect_id: str | None = None,
suggested_post_parameters: "SuggestedPostParameters | None" = None,
reply_parameters: "ReplyParameters | None" = None,
reply_markup: "ReplyMarkup | None" = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: int | None = None,
filename: str | None = 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 = None,
) -> "Message":
"""Shortcut for::
await bot.send_live_photo(update.effective_chat.id, *args, **kwargs)
For the documentation of the arguments, please see :meth:`telegram.Bot.send_live_photo`.
.. versionadded:: 22.8
Returns:
:class:`telegram.Message`: On success, instance representing the message posted.
"""
return await self.get_bot().send_live_photo(
chat_id=self.id,
live_photo=live_photo,
photo=photo,
business_connection_id=business_connection_id,
message_thread_id=message_thread_id,
direct_messages_topic_id=direct_messages_topic_id,
caption=caption,
parse_mode=parse_mode,
caption_entities=caption_entities,
show_caption_above_media=show_caption_above_media,
has_spoiler=has_spoiler,
disable_notification=disable_notification,
protect_content=protect_content,
allow_paid_broadcast=allow_paid_broadcast,
message_effect_id=message_effect_id,
suggested_post_parameters=suggested_post_parameters,
reply_parameters=reply_parameters,
reply_markup=reply_markup,
allow_sending_without_reply=allow_sending_without_reply,
reply_to_message_id=reply_to_message_id,
filename=filename,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)
async def send_contact(
self,
phone_number: str | None = None,
@@ -2296,6 +2375,18 @@ class _ChatBase(TelegramObject):
question_entities: Sequence["MessageEntity"] | None = None,
message_effect_id: str | None = None,
allow_paid_broadcast: bool | None = None,
shuffle_options: bool | None = None,
allows_revoting: bool | None = None,
correct_option_ids: CorrectOptionIds | None = None,
allow_adding_options: bool | None = None,
hide_results_until_closes: bool | None = None,
description: str | None = None,
description_parse_mode: ODVInput[str] | None = None,
description_entities: Sequence["MessageEntity"] | None = None,
members_only: bool | None = None,
country_codes: Sequence[str] | None = None,
explanation_media: "InputPollMedia | None" = None,
media: "InputPollMedia | None" = None,
*,
reply_to_message_id: int | None = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2323,6 +2414,9 @@ class _ChatBase(TelegramObject):
type=type, # pylint=pylint,
allows_multiple_answers=allows_multiple_answers,
correct_option_id=correct_option_id,
allows_revoting=allows_revoting,
shuffle_options=shuffle_options,
correct_option_ids=correct_option_ids,
is_closed=is_closed,
disable_notification=disable_notification,
reply_to_message_id=reply_to_message_id,
@@ -2346,6 +2440,15 @@ class _ChatBase(TelegramObject):
business_connection_id=business_connection_id,
question_parse_mode=question_parse_mode,
question_entities=question_entities,
description=description,
description_parse_mode=description_parse_mode,
description_entities=description_entities,
hide_results_until_closes=hide_results_until_closes,
allow_adding_options=allow_adding_options,
members_only=members_only,
country_codes=country_codes,
explanation_media=explanation_media,
media=media,
)
async def send_copy(
@@ -4032,6 +4135,82 @@ class _ChatBase(TelegramObject):
api_kwargs=api_kwargs,
)
async def delete_reaction(
self,
message_id: int,
user_id: int | None = None,
actor_chat_id: int | None = 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 = None,
) -> bool:
"""
Shortcut for::
await bot.delete_message_reaction(chat_id=update.effective_chat.id, *args, **kwargs)
For the documentation of the arguments, please see
:meth:`telegram.Bot.delete_message_reaction`.
.. versionadded:: 22.8
Returns:
:obj:`bool`: On success, :obj:`True` is returned.
"""
return await self.get_bot().delete_message_reaction(
chat_id=self.id,
message_id=message_id,
user_id=user_id,
actor_chat_id=actor_chat_id,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)
async def delete_all_reactions(
self,
user_id: int | None = None,
actor_chat_id: int | None = 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 = None,
) -> bool:
"""
Shortcut for::
await bot.delete_all_message_reactions(
chat_id=update.effective_chat.id,
*args,
**kwargs
)
For the documentation of the arguments, please see
:meth:`telegram.Bot.delete_all_message_reactions`.
.. versionadded:: 22.8
Returns:
:obj:`bool`: On success, :obj:`True` is returned.
"""
return await self.get_bot().delete_all_message_reactions(
chat_id=self.id,
user_id=user_id,
actor_chat_id=actor_chat_id,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)
class Chat(_ChatBase):
"""This object represents a chat.
+1 -1
View File
@@ -245,7 +245,7 @@ class ChatFullInfo(_ChatBase):
.. versionadded:: 22.6
paid_message_star_count (:obj:`int`, optional): The number of Telegram Stars a general user
have to pay to send a message to the chat
has to pay to send a message to the chat
.. versionadded:: 22.6
first_profile_audio (:obj:`telegram.Audio`, optional): For private chats, the first audio
+19
View File
@@ -515,8 +515,13 @@ class ChatMemberRestricted(ChatMember):
.. versionadded:: 20.1
can_edit_tag (:obj:`bool`): :obj:`True`, if the user is allowed to edit their own tag.
If omitted, defaults to the value of :attr:`can_pin_messages`.
.. versionadded:: 22.7
can_react_to_messages (:obj:`bool`): :obj:`True`, if the user is allowed to react to
messages.
.. versionadded:: 22.8
tag (:obj:`str`, optional): Tag of the member.
.. versionadded:: 22.7
@@ -571,8 +576,13 @@ class ChatMemberRestricted(ChatMember):
.. versionadded:: 20.1
can_edit_tag (:obj:`bool`): :obj:`True`, if the user is allowed to edit their own tag.
If omitted, defaults to the value of :attr:`can_pin_messages`.
.. versionadded:: 22.7
can_react_to_messages (:obj:`bool`): :obj:`True`, if the user is allowed to react to
messages.
.. versionadded:: 22.8
tag (:obj:`str`): Optional. Tag of the member.
.. versionadded:: 22.7
@@ -586,6 +596,7 @@ class ChatMemberRestricted(ChatMember):
"can_invite_users",
"can_manage_topics",
"can_pin_messages",
"can_react_to_messages",
"can_send_audios",
"can_send_documents",
"can_send_messages",
@@ -621,10 +632,17 @@ class ChatMemberRestricted(ChatMember):
can_send_voice_notes: bool,
can_edit_tag: bool,
tag: str | None = None,
# tags: 22.8
# temporarily optional to make it not breaking
can_react_to_messages: bool | None = None,
*,
api_kwargs: JSONDict | None = None,
):
super().__init__(status=ChatMember.RESTRICTED, user=user, api_kwargs=api_kwargs)
if can_react_to_messages is None:
raise TypeError("`can_react_to_messages` is required and cannot be None")
with self._unfrozen():
self.is_member: bool = is_member
self.can_change_info: bool = can_change_info
@@ -643,6 +661,7 @@ class ChatMemberRestricted(ChatMember):
self.can_send_video_notes: bool = can_send_video_notes
self.can_send_voice_notes: bool = can_send_voice_notes
self.can_edit_tag: bool = can_edit_tag
self.can_react_to_messages: bool = can_react_to_messages
self.tag: str | None = tag
+2 -2
View File
@@ -79,11 +79,11 @@ class ChatOwnerLeft(TelegramObject):
.. versionadded:: 22.7
Args:
new_owner (:class:`telegram.User`, optional): The user which will be the new owner of the
new_owner (:class:`telegram.User`, optional): The user who will become the new owner of the
chat if the previous owner does not return to the chat
Attributes:
new_owner (:class:`telegram.User`): Optional. The user which will be the new owner of the
new_owner (:class:`telegram.User`): Optional. The user who will become the new owner of the
chat if the previous owner does not return to the chat
"""
+16 -1
View File
@@ -36,7 +36,7 @@ class ChatPermissions(TelegramObject):
: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`,
:attr:`can_manage_topics` and :attr:`can_edit_tag` are equal.
:attr:`can_manage_topics`, :attr:`can_edit_tag`, and :attr:`can_react_to_messages` are equal.
.. versionchanged:: 20.0
:attr:`can_manage_topics` is considered as well when comparing objects of
@@ -50,6 +50,9 @@ class ChatPermissions(TelegramObject):
.. versionchanged:: 22.7
:attr:`can_edit_tag` is considered as well when comparing objects of
this type in terms of equality.
.. versionchanged:: 22.8
:attr:`can_react_to_messages` is considered as well when comparing objects of
this type in terms of equality.
Note:
@@ -100,6 +103,10 @@ class ChatPermissions(TelegramObject):
tag.
.. versionadded:: 22.7
can_react_to_messages (:obj:`bool`, optional): :obj:`True`, if the user is allowed to react
to messages. If omitted, defaults to the value of :attr:`can_send_messages`.
.. versionadded:: 22.8
Attributes:
can_send_messages (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to send text
@@ -145,6 +152,10 @@ class ChatPermissions(TelegramObject):
tag.
.. versionadded:: 22.7
can_react_to_messages (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to react
to messages. If omitted, defaults to the value of :attr:`can_send_messages`.
.. versionadded:: 22.8
"""
@@ -155,6 +166,7 @@ class ChatPermissions(TelegramObject):
"can_invite_users",
"can_manage_topics",
"can_pin_messages",
"can_react_to_messages",
"can_send_audios",
"can_send_documents",
"can_send_messages",
@@ -183,6 +195,7 @@ class ChatPermissions(TelegramObject):
can_send_video_notes: bool | None = None,
can_send_voice_notes: bool | None = None,
can_edit_tag: bool | None = None,
can_react_to_messages: bool | None = None,
*,
api_kwargs: JSONDict | None = None,
):
@@ -203,6 +216,7 @@ class ChatPermissions(TelegramObject):
self.can_send_video_notes: bool | None = can_send_video_notes
self.can_send_voice_notes: bool | None = can_send_voice_notes
self.can_edit_tag: bool | None = can_edit_tag
self.can_react_to_messages: bool | None = can_react_to_messages
self._id_attrs = (
self.can_send_messages,
@@ -220,6 +234,7 @@ class ChatPermissions(TelegramObject):
self.can_send_video_notes,
self.can_send_voice_notes,
self.can_edit_tag,
self.can_react_to_messages,
)
self._freeze()
+528 -55
View File
@@ -16,7 +16,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/].
"""Base class for Telegram InputMedia Objects."""
"""Base classes for Telegram InputMedia, InputPaidMedia, InputPollMedia
and InputPollOptionMedia Objects."""
import datetime as dtm
from collections.abc import Sequence
@@ -28,6 +29,7 @@ from telegram._files.audio import Audio
from telegram._files.document import Document
from telegram._files.inputfile import InputFile
from telegram._files.photosize import PhotoSize
from telegram._files.sticker import Sticker
from telegram._files.video import Video
from telegram._messageentity import MessageEntity
from telegram._telegramobject import TelegramObject
@@ -37,17 +39,47 @@ from telegram._utils.datetime import get_timedelta_value
from telegram._utils.defaultvalue import DEFAULT_NONE
from telegram._utils.files import parse_file_input
from telegram._utils.types import JSONDict, ODVInput, TimePeriod
from telegram.constants import InputMediaType
from telegram._utils.warnings import warn
from telegram.constants import BaseInputMediaType
from telegram.warnings import PTBDeprecationWarning
if TYPE_CHECKING:
from telegram._utils.types import FileInput
MediaType: TypeAlias = Animation | Audio | Document | PhotoSize | Video
class InputMedia(TelegramObject):
class _BaseInputMedia(TelegramObject):
"""
Base class for Telegram InputMedia Objects.
Base class for objects representing the various input media types.
Args:
media_type (:obj:`str`): Type of media that the instance represents.
Attributes:
type (:obj:`str`): Type of media that the instance represents.
"""
__slots__ = ("type",)
def __init__(
self,
media_type: str,
*,
api_kwargs: JSONDict | None = None,
):
super().__init__(api_kwargs=api_kwargs)
self.type: str = enum.get_member(constants.BaseInputMediaType, media_type, media_type)
class InputMedia(_BaseInputMedia):
"""
This object represents the content of a media message to be sent. It should be one of:
* :class:`telegram.InputMediaAnimation`
* :class:`telegram.InputMediaAudio`
* :class:`telegram.InputMediaDocument`
* :class:`telegram.InputMediaLivePhoto`
* :class:`telegram.InputMediaPhoto`
* :class:`telegram.InputMediaVideo`
.. versionchanged:: 20.0
Added arguments and attributes :attr:`type`, :attr:`media`, :attr:`caption`,
@@ -85,7 +117,7 @@ class InputMedia(TelegramObject):
"""
__slots__ = ("caption", "caption_entities", "media", "parse_mode", "type")
__slots__ = ("caption", "caption_entities", "media", "parse_mode")
def __init__(
self,
@@ -97,14 +129,12 @@ class InputMedia(TelegramObject):
*,
api_kwargs: JSONDict | None = None,
):
super().__init__(api_kwargs=api_kwargs)
self.type: str = enum.get_member(constants.InputMediaType, media_type, media_type)
self.media: str | InputFile = media
self.caption: str | None = caption
self.caption_entities: tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.parse_mode: ODVInput[str] = parse_mode
self._freeze()
super().__init__(media_type=media_type, api_kwargs=api_kwargs)
with self._unfrozen():
self.media: str | InputFile = media
self.caption: str | None = caption
self.caption_entities: tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.parse_mode: ODVInput[str] = parse_mode
@staticmethod
def _parse_thumbnail_input(thumbnail: "FileInput | None") -> str | InputFile | None:
@@ -123,6 +153,7 @@ class InputPaidMedia(TelegramObject):
* :class:`telegram.InputPaidMediaPhoto`
* :class:`telegram.InputPaidMediaVideo`
* :class:`telegram.InputPaidMediaLivePhoto`
.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
@@ -142,6 +173,11 @@ class InputPaidMedia(TelegramObject):
""":const:`telegram.constants.InputPaidMediaType.PHOTO`"""
VIDEO: Final[str] = constants.InputPaidMediaType.VIDEO
""":const:`telegram.constants.InputPaidMediaType.VIDEO`"""
LIVE_PHOTO: Final[str] = constants.InputPaidMediaType.LIVE_PHOTO
""":const:`telegram.constants.InputPaidMediaType.LIVE_PHOTO`
.. versionadded:: 22.8
"""
__slots__ = ("media", "type")
@@ -300,6 +336,51 @@ class InputPaidMediaVideo(InputPaidMedia):
return get_timedelta_value(self._duration, attribute="duration")
class InputPaidMediaLivePhoto(InputPaidMedia):
"""
The paid media to send is a live photo.
.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
.. versionadded:: 22.8
Args:
media (:obj:`str` | :term:`file object` | :class:`~telegram.InputFile` | :obj:`bytes` \
| :class:`pathlib.Path` | :class:`~telegram.Video`): Video of the live photo to send.
Pass a ``file_id`` to send a file that exists on the Telegram servers (recommended).
|uploadinputnopath| Sending live photos by a URL is currently unsupported. Lastly you
can pass an existing :class:`telegram.Video` object to send.
photo (:obj:`str` | :term:`file object` | :class:`~telegram.InputFile` | :obj:`bytes` | \
:class:`pathlib.Path` | :class:`~telegram.PhotoSize`): Photo of the live photo to send.
Pass a ``file_id`` to send a file that exists on the Telegram servers (recommended).
|uploadinputnopath| Sending live photos by a URL is currently unsupported.
Lastly you can pass an existing :class:`telegram.PhotoSize` object to send.
Attributes:
type (:obj:`str`): Type of the media, always
:tg-const:`telegram.constants.InputPaidMediaType.LIVE_PHOTO`.
media (:obj:`str` | :class:`telegram.InputFile`): Video of the live photo to send.
|fileinputnopath|
photo (:obj:`str` | :class:`telegram.InputFile`): Photo of the live photo to send.
|fileinputnopath|
"""
__slots__ = ("photo",)
def __init__(
self,
media: "FileInput | Video",
photo: "FileInput | PhotoSize",
*,
api_kwargs: JSONDict | None = None,
):
media = parse_file_input(media, tg_type=Video, attach=True, local_mode=True)
photo = parse_file_input(photo, tg_type=PhotoSize, attach=True, local_mode=True)
super().__init__(type=InputPaidMedia.LIVE_PHOTO, media=media, api_kwargs=api_kwargs)
with self._unfrozen():
self.photo: str | InputFile = photo
class InputMediaAnimation(InputMedia):
"""Represents an animation file (GIF or H.264/MPEG-4 AVC video without sound) to be sent.
@@ -320,11 +401,12 @@ class InputMediaAnimation(InputMedia):
.. versionchanged:: 13.2
Accept :obj:`bytes` as input.
filename (:obj:`str`, optional): Custom file name for the animation, when uploading a
new file. Convenience parameter, useful e.g. when sending files generated by the
:obj:`tempfile` module.
filename_depr (:obj:`str`, optional): Positional placeholder for keyword only parameter
:paramref:`filename`. For backward compatibility.
.. versionadded:: 13.1
.. versionadded:: 22.8
.. deprecated:: 22.8
This parameter is deprecated, use :paramref:`filename` instead.
caption (:obj:`str`, optional): Caption of the animation to be sent,
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
@@ -353,8 +435,17 @@ class InputMediaAnimation(InputMedia):
.. versionadded:: 21.3
Keyword Args:
filename (:obj:`str`, optional): Custom file name for the animation, when uploading a
new file. Convenience parameter, useful e.g. when sending files generated by the
:obj:`tempfile` module.
.. versionadded:: 13.1
.. versionchanged:: 22.8
This parameter is now keyword-only.
Attributes:
type (:obj:`str`): :tg-const:`telegram.constants.InputMediaType.ANIMATION`.
type (:obj:`str`): :tg-const:`telegram.constants.BaseInputMediaType.ANIMATION`.
media (:obj:`str` | :class:`telegram.InputFile`): Animation to send.
caption (:obj:`str`): Optional. Caption of the animation to be sent,
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
@@ -403,13 +494,28 @@ class InputMediaAnimation(InputMedia):
height: int | None = None,
duration: TimePeriod | None = None,
caption_entities: Sequence[MessageEntity] | None = None,
filename: str | None = None,
# tag: deprecated 22.8
filename_depr: str | None = None,
# -
has_spoiler: bool | None = None,
thumbnail: "FileInput | None" = None,
show_caption_above_media: bool | None = None,
*,
filename: str | None = None,
api_kwargs: JSONDict | None = None,
):
if filename_depr is not None and filename is not None:
raise ValueError("`filename_depr` and `filename` are mutually exclusive.")
if filename_depr is not None:
warn(
PTBDeprecationWarning(
"22.8",
"Positional passing of `filename` or keyword usage of `filename_depr`"
" is deprecated. `filename` will become a keyword-only argument.",
),
stacklevel=2,
)
if isinstance(media, Animation):
width = media.width if width is None else width
height = media.height if height is None else height
@@ -418,10 +524,13 @@ class InputMediaAnimation(InputMedia):
else:
# 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, filename=filename, attach=True, local_mode=True)
effective_filename = filename_depr or filename
media = parse_file_input(
media, filename=effective_filename, attach=True, local_mode=True
)
super().__init__(
InputMediaType.ANIMATION,
BaseInputMediaType.ANIMATION,
media,
caption,
caption_entities,
@@ -453,11 +562,12 @@ class InputMediaPhoto(InputMedia):
.. versionchanged:: 13.2
Accept :obj:`bytes` as input.
filename (:obj:`str`, optional): Custom file name for the photo, when uploading a
new file. Convenience parameter, useful e.g. when sending files generated by the
:obj:`tempfile` module.
filename_depr (:obj:`str`, optional): Positional placeholder for keyword only parameter
:paramref:`filename`. For backward compatibility.
.. versionadded:: 13.1
.. versionadded:: 22.8
.. deprecated:: 22.8
This parameter is deprecated, use :paramref:`filename` instead.
caption (:obj:`str`, optional ): Caption of the photo to be sent,
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after
entities parsing.
@@ -474,8 +584,17 @@ class InputMediaPhoto(InputMedia):
.. versionadded:: 21.3
Keyword Args:
filename (:obj:`str`, optional): Custom file name for the photo, when uploading a
new file. Convenience parameter, useful e.g. when sending files generated by the
:obj:`tempfile` module.
.. versionadded:: 13.1
.. versionchanged:: 22.8
This parameter is now keyword-only.
Attributes:
type (:obj:`str`): :tg-const:`telegram.constants.InputMediaType.PHOTO`.
type (:obj:`str`): :tg-const:`telegram.constants.BaseInputMediaType.PHOTO`.
media (:obj:`str` | :class:`telegram.InputFile`): Photo to send.
caption (:obj:`str`): Optional. Caption of the photo to be sent,
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
@@ -507,17 +626,35 @@ class InputMediaPhoto(InputMedia):
caption: str | None = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Sequence[MessageEntity] | None = None,
filename: str | None = None,
# tag: deprecated 22.8
filename_depr: str | None = None,
# -
has_spoiler: bool | None = None,
show_caption_above_media: bool | None = None,
*,
filename: str | None = None,
api_kwargs: JSONDict | None = None,
):
if filename_depr is not None and filename is not None:
raise ValueError("`filename_depr` and `filename` are mutually exclusive.")
if filename_depr is not None:
warn(
PTBDeprecationWarning(
"22.8",
"Positional passing of `filename` or keyword usage of `filename_depr`"
" is deprecated. `filename` will become a keyword-only argument.",
),
stacklevel=2,
)
# 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, PhotoSize, filename=filename, attach=True, local_mode=True)
effective_filename = filename_depr or filename
media = parse_file_input(
media, PhotoSize, filename=effective_filename, attach=True, local_mode=True
)
super().__init__(
InputMediaType.PHOTO,
BaseInputMediaType.PHOTO,
media,
caption,
caption_entities,
@@ -553,11 +690,12 @@ class InputMediaVideo(InputMedia):
.. versionchanged:: 13.2
Accept :obj:`bytes` as input.
filename (:obj:`str`, optional): Custom file name for the video, when uploading a
new file. Convenience parameter, useful e.g. when sending files generated by the
:obj:`tempfile` module.
filename_depr (:obj:`str`, optional): Positional placeholder for keyword only parameter
:paramref:`filename`. For backward compatibility.
.. versionadded:: 13.1
.. versionadded:: 22.8
.. deprecated:: 22.8
This parameter is deprecated, use :paramref:`filename` instead.
caption (:obj:`str`, optional): Caption of the video to be sent,
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after
entities parsing.
@@ -594,8 +732,17 @@ class InputMediaVideo(InputMedia):
.. versionadded:: 21.3
Keyword Args:
filename (:obj:`str`, optional): Custom file name for the video, when uploading a
new file. Convenience parameter, useful e.g. when sending files generated by the
:obj:`tempfile` module.
.. versionadded:: 13.1
.. versionchanged:: 22.8
This parameter is now keyword-only.
Attributes:
type (:obj:`str`): :tg-const:`telegram.constants.InputMediaType.VIDEO`.
type (:obj:`str`): :tg-const:`telegram.constants.BaseInputMediaType.VIDEO`.
media (:obj:`str` | :class:`telegram.InputFile`): Video file to send.
caption (:obj:`str`): Optional. Caption of the video to be sent,
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
@@ -656,15 +803,30 @@ class InputMediaVideo(InputMedia):
supports_streaming: bool | None = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Sequence[MessageEntity] | None = None,
filename: str | None = None,
# tag: deprecated 22.8
filename_depr: str | None = None,
# -
has_spoiler: bool | None = None,
thumbnail: "FileInput | None" = None,
show_caption_above_media: bool | None = None,
cover: "FileInput | None" = None,
start_timestamp: int | None = None,
*,
filename: str | None = None,
api_kwargs: JSONDict | None = None,
):
if filename_depr is not None and filename is not None:
raise ValueError("`filename_depr` and `filename` are mutually exclusive.")
if filename_depr is not None:
warn(
PTBDeprecationWarning(
"22.8",
"Positional passing of `filename` or keyword usage of `filename_depr`"
" is deprecated. `filename` will become a keyword-only argument.",
),
stacklevel=2,
)
if isinstance(media, Video):
width = width if width is not None else media.width
height = height if height is not None else media.height
@@ -673,10 +835,13 @@ class InputMediaVideo(InputMedia):
else:
# 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, filename=filename, attach=True, local_mode=True)
effective_filename = filename_depr or filename
media = parse_file_input(
media, filename=effective_filename, attach=True, local_mode=True
)
super().__init__(
InputMediaType.VIDEO,
BaseInputMediaType.VIDEO,
media,
caption,
caption_entities,
@@ -701,6 +866,156 @@ class InputMediaVideo(InputMedia):
return get_timedelta_value(self._duration, attribute="duration")
class InputMediaLocation(_BaseInputMedia):
"""Represents a location to be sent.
.. versionadded:: 22.8
Args:
latitude (:obj:`float`): Latitude of the location.
longitude (:obj:`float`): Longitude of the location.
horizontal_accuracy (:obj:`float`, optional): The radius of uncertainty for the location,
measured in meters; 0-:tg-const:`telegram.Location.HORIZONTAL_ACCURACY`.
Attributes:
type (:obj:`str`): :tg-const:`telegram.constants.BaseInputMediaType.LOCATION`.
latitude (:obj:`float`): Latitude of the location.
longitude (:obj:`float`): Longitude of the location.
horizontal_accuracy (:obj:`float`): Optional. The radius of uncertainty for the location,
measured in meters; 0-:tg-const:`telegram.Location.HORIZONTAL_ACCURACY`.
"""
__slots__ = ("horizontal_accuracy", "latitude", "longitude")
def __init__(
self,
latitude: float,
longitude: float,
horizontal_accuracy: float | None = None,
*,
api_kwargs: JSONDict | None = None,
):
super().__init__(media_type=BaseInputMediaType.LOCATION, api_kwargs=api_kwargs)
with self._unfrozen():
self.latitude: float = latitude
self.longitude: float = longitude
self.horizontal_accuracy: float | None = horizontal_accuracy
class InputMediaVenue(_BaseInputMedia):
"""Represents a venue to be sent.
.. versionadded:: 22.8
Args:
latitude (:obj:`float`): Latitude of the location.
longitude (:obj:`float`): Longitude of the location.
title (:obj:`str`): Name of the venue.
address (:obj:`str`): Address of the venue.
foursquare_id (:obj:`str`, optional): Foursquare identifier of the venue.
foursquare_type (:obj:`str`, optional): Foursquare type of the venue, if known. (For
example, ``arts_entertainment/default``, ``arts_entertainment/aquarium``
or ``food/icecream``).
google_place_id (:obj:`str`, optional): Google Places identifier of the venue.
google_place_type (:obj:`str`, optional): Google Places type of the venue. (See\
`supported types <https://developers.google.com/places/web-service/supported_types>`__)
Attributes:
type (:obj:`str`): :tg-const:`telegram.constants.BaseInputMediaType.VENUE`.
latitude (:obj:`float`): Latitude of the location.
longitude (:obj:`float`): Longitude of the location.
title (:obj:`str`): Name of the venue.
address (:obj:`str`): Address of the venue.
foursquare_id (:obj:`str`): Optional. Foursquare identifier of the venue.
foursquare_type (:obj:`str`): Optional. Foursquare type of the venue, if known. (For
example, ``arts_entertainment/default``, ``arts_entertainment/aquarium``
or ``food/icecream``).
google_place_id (:obj:`str`): Optional. Google Places identifier of the venue.
google_place_type (:obj:`str`): Optional. Google Places type of the venue. (See\
`supported types <https://developers.google.com/places/web-service/supported_types>`__)
"""
__slots__ = (
"address",
"foursquare_id",
"foursquare_type",
"google_place_id",
"google_place_type",
"latitude",
"longitude",
"title",
)
def __init__(
self,
latitude: float,
longitude: float,
title: str,
address: str,
foursquare_id: str | None = None,
foursquare_type: str | None = None,
google_place_id: str | None = None,
google_place_type: str | None = None,
*,
api_kwargs: JSONDict | None = None,
):
super().__init__(media_type=BaseInputMediaType.VENUE, api_kwargs=api_kwargs)
with self._unfrozen():
self.latitude: float = latitude
self.longitude: float = longitude
self.title: str = title
self.address: str = address
self.foursquare_id: str | None = foursquare_id
self.foursquare_type: str | None = foursquare_type
self.google_place_id: str | None = google_place_id
self.google_place_type: str | None = google_place_type
class InputMediaSticker(_BaseInputMedia):
"""Represents a sticker file to be sent.
.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
.. versionadded:: 22.8
Args:
media (:obj:`str` | :term:`file object` | :class:`~telegram.InputFile` | :obj:`bytes` | \
:class:`pathlib.Path` | :class:`telegram.Sticker`): File to send. |fileinputnopath|
Lastly you can pass an existing :class:`telegram.Sticker` object to send.
emoji (:obj:`str`, optional): Emoji associated with the sticker; only for just uploaded
stickers.
Keyword Args:
filename (:obj:`str`, optional): Custom file name for the sticker, when uploading a
new file. Convenience parameter, useful e.g. when sending files generated by the
:obj:`tempfile` module.
Attributes:
type (:obj:`str`): :tg-const:`telegram.constants.BaseInputMediaType.STICKER`.
media (:obj:`str` | :class:`telegram.InputFile`): Sticker file to send.
emoji (:obj:`str`): Optional. Emoji associated with the sticker; only for just uploaded
stickers.
"""
__slots__ = ("emoji", "media")
def __init__(
self,
media: "FileInput | Sticker",
emoji: str | None = None,
*,
filename: str | None = None,
api_kwargs: JSONDict | None = None,
):
media = parse_file_input(media, Sticker, filename=filename, attach=True, local_mode=True)
super().__init__(media_type=BaseInputMediaType.STICKER, api_kwargs=api_kwargs)
with self._unfrozen():
self.media: str | InputFile = media
self.emoji: str | None = emoji
class InputMediaAudio(InputMedia):
"""Represents an audio file to be treated as music to be sent.
@@ -721,11 +1036,12 @@ class InputMediaAudio(InputMedia):
.. versionchanged:: 13.2
Accept :obj:`bytes` as input.
filename (:obj:`str`, optional): Custom file name for the audio, when uploading a
new file. Convenience parameter, useful e.g. when sending files generated by the
:obj:`tempfile` module.
filename_depr (:obj:`str`, optional): Positional placeholder for keyword only parameter
:paramref:`filename`. For backward compatibility.
.. versionadded:: 13.1
.. versionadded:: 22.8
.. deprecated:: 22.8
This parameter is deprecated, use :paramref:`filename` instead.
caption (:obj:`str`, optional): Caption of the audio to be sent,
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after
entities parsing.
@@ -748,8 +1064,17 @@ class InputMediaAudio(InputMedia):
.. versionadded:: 20.2
Keyword Args:
filename (:obj:`str`, optional): Custom file name for the audio, when uploading a
new file. Convenience parameter, useful e.g. when sending files generated by the
:obj:`tempfile` module.
.. versionadded:: 13.1
.. versionchanged:: 22.8
This parameter is now keyword-only.
Attributes:
type (:obj:`str`): :tg-const:`telegram.constants.InputMediaType.AUDIO`.
type (:obj:`str`): :tg-const:`telegram.constants.BaseInputMediaType.AUDIO`.
media (:obj:`str` | :class:`telegram.InputFile`): Audio file to send.
caption (:obj:`str`): Optional. Caption of the audio to be sent,
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
@@ -786,11 +1111,26 @@ class InputMediaAudio(InputMedia):
performer: str | None = None,
title: str | None = None,
caption_entities: Sequence[MessageEntity] | None = None,
filename: str | None = None,
# tag: deprecated 22.8
filename_depr: str | None = None,
# -
thumbnail: "FileInput | None" = None,
*,
filename: str | None = None,
api_kwargs: JSONDict | None = None,
):
if filename_depr is not None and filename is not None:
raise ValueError("`filename_depr` and `filename` are mutually exclusive.")
if filename_depr is not None:
warn(
PTBDeprecationWarning(
"22.8",
"Positional passing of `filename` or keyword usage of `filename_depr`"
" is deprecated. `filename` will become a keyword-only argument.",
),
stacklevel=2,
)
if isinstance(media, Audio):
duration = duration if duration is not None else media._duration
performer = media.performer if performer is None else performer
@@ -799,10 +1139,13 @@ class InputMediaAudio(InputMedia):
else:
# 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, filename=filename, attach=True, local_mode=True)
effective_filename = filename_depr or filename
media = parse_file_input(
media, filename=effective_filename, attach=True, local_mode=True
)
super().__init__(
InputMediaType.AUDIO,
BaseInputMediaType.AUDIO,
media,
caption,
caption_entities,
@@ -835,11 +1178,12 @@ class InputMediaDocument(InputMedia):
.. versionchanged:: 13.2
Accept :obj:`bytes` as input.
filename (:obj:`str`, optional): Custom file name for the document, when uploading a
new file. Convenience parameter, useful e.g. when sending files generated by the
:obj:`tempfile` module.
filename_depr (:obj:`str`, optional): Positional placeholder for keyword only parameter
:paramref:`filename`. For backward compatibility.
.. versionadded:: 13.1
.. versionadded:: 22.8
.. deprecated:: 22.8
This parameter is deprecated, use :paramref:`filename` instead.
caption (:obj:`str`, optional): Caption of the document to be sent,
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after
entities parsing.
@@ -857,8 +1201,17 @@ class InputMediaDocument(InputMedia):
.. versionadded:: 20.2
Keyword Args:
filename (:obj:`str`, optional): Custom file name for the document, when uploading a
new file. Convenience parameter, useful e.g. when sending files generated by the
:obj:`tempfile` module.
.. versionadded:: 13.1
.. versionchanged:: 22.8
This parameter is now keyword-only.
Attributes:
type (:obj:`str`): :tg-const:`telegram.constants.InputMediaType.DOCUMENT`.
type (:obj:`str`): :tg-const:`telegram.constants.BaseInputMediaType.DOCUMENT`.
media (:obj:`str` | :class:`telegram.InputFile`): File to send.
caption (:obj:`str`): Optional. Caption of the document to be sent,
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
@@ -887,17 +1240,35 @@ class InputMediaDocument(InputMedia):
parse_mode: ODVInput[str] = DEFAULT_NONE,
disable_content_type_detection: bool | None = None,
caption_entities: Sequence[MessageEntity] | None = None,
filename: str | None = None,
# tag: deprecated 22.8
filename_depr: str | None = None,
# -
thumbnail: "FileInput | None" = None,
*,
filename: str | None = None,
api_kwargs: JSONDict | None = None,
):
if filename_depr is not None and filename is not None:
raise ValueError("`filename_depr` and `filename` are mutually exclusive.")
if filename_depr is not None:
warn(
PTBDeprecationWarning(
"22.8",
"Positional passing of `filename` or keyword usage of `filename_depr`"
" is deprecated. `filename` will become a keyword-only argument.",
),
stacklevel=2,
)
# 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)
effective_filename = filename_depr or filename
media = parse_file_input(
media, Document, filename=effective_filename, attach=True, local_mode=True
)
super().__init__(
InputMediaType.DOCUMENT,
BaseInputMediaType.DOCUMENT,
media,
caption,
caption_entities,
@@ -907,3 +1278,105 @@ class InputMediaDocument(InputMedia):
with self._unfrozen():
self.thumbnail: str | InputFile | None = self._parse_thumbnail_input(thumbnail)
self.disable_content_type_detection: bool | None = disable_content_type_detection
class InputMediaLivePhoto(InputMedia):
"""Represents a live photo to be sent.
.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
.. versionadded:: 22.8
Args:
media (:obj:`str` | :term:`file object` | :class:`~telegram.InputFile` | :obj:`bytes` \
| :class:`pathlib.Path` | :class:`~telegram.Video`): Video of the live photo to send.
Pass a ``file_id`` to send a file that exists on the Telegram servers (recommended).
|uploadinputnopath| Sending live photos by a URL is currently unsupported. Lastly
you can pass an existing :class:`telegram.Video` object to send.
photo (:obj:`str` | :term:`file object` | :class:`~telegram.InputFile` | :obj:`bytes` \
| :class:`pathlib.Path` | :class:`~telegram.PhotoSize`): The static photo to send.
Pass a ``file_id`` to send a file that exists on the Telegram servers (recommended).
|uploadinputnopath| Sending live photos by a URL is currently unsupported. Lastly
you can pass an existing :class:`telegram.PhotoSize` object to send.
caption (:obj:`str`, optional): Caption of the live photo to be sent,
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after
entities parsing.
parse_mode (:obj:`str`, optional): |parse_mode|
caption_entities (Sequence[:class:`telegram.MessageEntity`], optional): |caption_entities|
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
has_spoiler (:obj:`bool`, optional): Pass :obj:`True`, if the video needs to be covered
with a spoiler animation.
Attributes:
type (:obj:`str`): :tg-const:`telegram.constants.BaseInputMediaType.LIVE_PHOTO`.
media (:obj:`str` | :class:`telegram.InputFile`): Video of the live photo to send.
photo (:obj:`str` | :class:`telegram.InputFile`): The static photo to send.
caption (:obj:`str`): Optional. Caption of the live photo to be sent,
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
show_caption_above_media (:obj:`bool`): Optional. |show_cap_above_med|
has_spoiler (:obj:`bool`): Optional. :obj:`True`, if the video is covered with a
spoiler animation.
"""
__slots__ = ("has_spoiler", "photo", "show_caption_above_media")
def __init__(
self,
media: "FileInput | Video",
photo: "FileInput | PhotoSize",
caption: str | None = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Sequence[MessageEntity] | None = None,
show_caption_above_media: bool | None = None,
has_spoiler: bool | None = None,
*,
api_kwargs: JSONDict | None = None,
):
media = parse_file_input(media, tg_type=Video, attach=True, local_mode=True)
photo = parse_file_input(photo, tg_type=PhotoSize, attach=True, local_mode=True)
super().__init__(
BaseInputMediaType.LIVE_PHOTO,
media,
caption,
caption_entities,
parse_mode,
api_kwargs=api_kwargs,
)
with self._unfrozen():
self.photo: str | InputFile = photo
self.show_caption_above_media: bool | None = show_caption_above_media
self.has_spoiler: bool | None = has_spoiler
InputPollMedia: TypeAlias = (
InputMediaAnimation
| InputMediaAudio
| InputMediaDocument
| InputMediaLivePhoto
| InputMediaLocation
| InputMediaPhoto
| InputMediaVenue
| InputMediaVideo
)
"""Type alias for InputPollMedia objects.
versionadded:: 22.8
"""
InputPollOptionMedia: TypeAlias = (
InputMediaAnimation
| InputMediaLivePhoto
| InputMediaLocation
| InputMediaPhoto
| InputMediaSticker
| InputMediaVenue
| InputMediaVideo
)
"""Type alias for InputPollOptionMedia objects.
.. versionadded:: 22.8
"""
+119
View File
@@ -0,0 +1,119 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2026
# 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 represents a Telegram LivePhoto."""
from collections.abc import Sequence
from typing import TYPE_CHECKING
from telegram._files._basemedium import _BaseMedium
from telegram._files.photosize import PhotoSize
from telegram._utils.argumentparsing import de_list_optional, parse_sequence_arg, to_timedelta
from telegram._utils.types import JSONDict, TimePeriod
if TYPE_CHECKING:
import datetime as dtm
from telegram import Bot
class LivePhoto(_BaseMedium):
"""
This object represents a live photo.
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.
.. versionadded:: 22.8
Args:
file_id (:obj:`str`): Identifier for the video 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.
width (:obj:`int`): Video width as defined by the sender.
height (:obj:`int`): Video height as defined by the sender.
duration (:obj:`int` | :class:`datetime.timedelta`): Duration of the video
in seconds as defined by the sender.
photo (Sequence[:obj:`telegram.PhotoSize`], optional): Available sizes of the corresponding
static photo.
mime_type (:obj:`str`, optional): MIME type of a file as defined by the sender.
file_size (:obj:`int`, optional): File size in bytes.
Attributes:
file_id (:obj:`str`): Identifier for the video 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.
width (:obj:`int`): Video width as defined by the sender.
height (:obj:`int`): Video height as defined by the sender.
duration (:class:`datetime.timedelta`): Duration of the video
in seconds as defined by the sender.
photo (tuple[:obj:`telegram.PhotoSize`]): Optional. Available sizes of the corresponding
static photo.
mime_type (:obj:`str`): Optional. MIME type of a file as defined by the sender.
file_size (:obj:`int`): Optional. File size in bytes.
"""
__slots__ = (
"duration",
"height",
"mime_type",
"photo",
"width",
)
def __init__(
self,
file_id: str,
file_unique_id: str,
width: int,
height: int,
duration: TimePeriod,
photo: Sequence[PhotoSize] | None = None,
mime_type: str | None = None,
file_size: int | None = None,
*,
api_kwargs: JSONDict | None = None,
):
super().__init__(
file_id=file_id,
file_unique_id=file_unique_id,
file_size=file_size,
api_kwargs=api_kwargs,
)
with self._unfrozen():
# Required
self.width: int = width
self.height: int = height
self.duration: dtm.timedelta = to_timedelta(duration)
# Optional
self.photo: Sequence[PhotoSize] | None = parse_sequence_arg(photo)
self.mime_type: str | None = mime_type
@classmethod
def de_json(cls, data: JSONDict, bot: "Bot | None" = None) -> "LivePhoto":
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
data["photo"] = de_list_optional(data.get("photo"), PhotoSize, bot)
return super().de_json(data=data, bot=bot)
+1 -1
View File
@@ -311,7 +311,7 @@ class StickerSet(TelegramObject):
data["thumbnail"] = de_json_optional(data.get("thumbnail"), PhotoSize, bot)
data["stickers"] = de_list_optional(data.get("stickers"), Sticker, bot)
api_kwargs = {}
api_kwargs: JSONDict = {}
# These are deprecated fields that TG still returns for backwards compatibility
# Let's filter them out to speed up the de-json process
for deprecated_field in ("contains_masks", "thumb", "is_animated", "is_video"):
+1 -1
View File
@@ -105,7 +105,7 @@ class Video(_BaseThumbedMedium):
.. deprecated:: v22.2
|time-period-int-deprecated|
qualities (Sequence[:class:`telegram.VideoQuality`]): Optional. List of available qualities
qualities (tuple[:class:`telegram.VideoQuality`]): Optional. List of available qualities
of the video
.. versionadded:: 22.7
+1 -1
View File
@@ -31,7 +31,7 @@ class ForceReply(TelegramObject):
the user (act as if the user has selected the bot's message and tapped 'Reply'). This can be
extremely useful if you want to create user-friendly step-by-step interfaces without having
to sacrifice `privacy mode <https://core.telegram.org/bots/features#privacy-mode>`_. Not
supported in channels and for messages sent on behalf of a Telegram Business account.
supported in channels and for messages sent on behalf of a user account.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`selective` is equal.
+5 -5
View File
@@ -49,8 +49,8 @@ class InputChecklistTask(TelegramObject):
|parse_mode|
text_entities (Sequence[:class:`telegram.MessageEntity`], optional):
List of special entities that appear in the text, which can be specified instead of
parse_mode. Currently, only bold, italic, underline, strikethrough, spoiler, and
custom_emoji entities are allowed.
parse_mode. Currently, only bold, italic, underline, strikethrough, spoiler,
custom_emoji, and date_time entities are allowed.
Attributes:
id (:obj:`int`):
@@ -66,7 +66,7 @@ class InputChecklistTask(TelegramObject):
text_entities (Sequence[:class:`telegram.MessageEntity`]):
Optional. List of special entities that appear in the text, which can be specified
instead of parse_mode. Currently, only bold, italic, underline, strikethrough, spoiler,
and custom_emoji entities are allowed.
custom_emoji, and date_time entities are allowed.
"""
@@ -117,7 +117,7 @@ class InputChecklist(TelegramObject):
title_entities (Sequence[:class:`telegram.MessageEntity`], optional):
List of special entities that appear in the title, which
can be specified instead of :paramref:`parse_mode`. Currently, only bold, italic,
underline, strikethrough, spoiler, and custom_emoji entities are allowed.
underline, strikethrough, spoiler, and custom_emoji, and date_time entities are allowed
tasks (Sequence[:class:`telegram.InputChecklistTask`]):
List of
:tg-const:`telegram.constants.InputChecklistLimit.MIN_TASK_NUMBER`\
@@ -139,7 +139,7 @@ class InputChecklist(TelegramObject):
title_entities (Sequence[:class:`telegram.MessageEntity`]):
Optional. List of special entities that appear in the title, which
can be specified instead of :paramref:`parse_mode`. Currently, only bold, italic,
underline, strikethrough, spoiler, and custom_emoji entities are allowed.
underline, strikethrough, spoiler, and custom_emoji, and date_time entities are allowed
tasks (Sequence[:class:`telegram.InputChecklistTask`]):
List of
:tg-const:`telegram.constants.InputChecklistLimit.MIN_TASK_NUMBER`\
+26 -1
View File
@@ -21,7 +21,11 @@
from typing import TYPE_CHECKING
from telegram._keyboardbuttonpolltype import KeyboardButtonPollType
from telegram._keyboardbuttonrequest import KeyboardButtonRequestChat, KeyboardButtonRequestUsers
from telegram._keyboardbuttonrequest import (
KeyboardButtonRequestChat,
KeyboardButtonRequestManagedBot,
KeyboardButtonRequestUsers,
)
from telegram._telegramobject import TelegramObject
from telegram._utils.argumentparsing import de_json_optional
from telegram._utils.types import JSONDict
@@ -120,6 +124,14 @@ class KeyboardButton(TelegramObject):
Premium subscription.
.. versionadded:: 22.7
request_managed_bot (:obj:`telegram.KeyboardButtonRequestManagedBot`, optional): If
specified, pressing the button will ask the user to create and share a bot that will
be managed by the current bot. Available for bots that enabled management of other bots
in the `@BotFather <https://telegram.me/BotFather>` Mini App. Available in private
chats only.
.. versionadded:: 22.8
Attributes:
text (:obj:`str`): Text of the button. If none of the fields other than :attr:`text`,
@@ -167,6 +179,13 @@ class KeyboardButton(TelegramObject):
Premium subscription.
.. versionadded:: 22.7
request_managed_bot (:obj:`telegram.KeyboardButtonRequestManagedBot`): Optional. If
specified, pressing the button will ask the user to create and share a bot that will
be managed by the current bot. Available for bots that enabled management of other bots
in the `@BotFather <https://telegram.me/BotFather>` Mini App. Available in private
chats only.
.. versionadded:: 22.8
"""
__slots__ = (
@@ -174,6 +193,7 @@ class KeyboardButton(TelegramObject):
"request_chat",
"request_contact",
"request_location",
"request_managed_bot",
"request_poll",
"request_users",
"style",
@@ -192,6 +212,7 @@ class KeyboardButton(TelegramObject):
request_users: KeyboardButtonRequestUsers | None = None,
style: str | None = None,
icon_custom_emoji_id: str | None = None,
request_managed_bot: KeyboardButtonRequestManagedBot | None = None,
*,
api_kwargs: JSONDict | None = None,
):
@@ -208,6 +229,7 @@ class KeyboardButton(TelegramObject):
self.request_chat: KeyboardButtonRequestChat | None = request_chat
self.style: str | None = style
self.icon_custom_emoji_id: str | None = icon_custom_emoji_id
self.request_managed_bot: KeyboardButtonRequestManagedBot | None = request_managed_bot
self._id_attrs = (
self.text,
@@ -238,6 +260,9 @@ class KeyboardButton(TelegramObject):
data.get("request_chat"), KeyboardButtonRequestChat, bot
)
data["web_app"] = de_json_optional(data.get("web_app"), WebAppInfo, bot)
data["request_managed_bot"] = de_json_optional(
data.get("request_managed_bot"), KeyboardButtonRequestManagedBot, bot
)
api_kwargs = {}
# This is a deprecated field that TG still returns for backwards compatibility
+50
View File
@@ -268,3 +268,53 @@ class KeyboardButtonRequestChat(TelegramObject):
)
return super().de_json(data=data, bot=bot)
class KeyboardButtonRequestManagedBot(TelegramObject):
"""
This object defines the parameters for the creation of a managed bot.
Information about the created bot will be shared with the bot using the update
managed_bot and a :obj:`telegram.Message` with the field
:attr:`telegram.Message.managed_bot_created`.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`request_id` is equal.
.. versionadded:: 22.8
Args:
request_id (:obj:`int`): Signed 32-bit identifier of the request. Must be unique
within the message.
suggested_name (:obj:`str`, optional): Suggested name for the bot.
suggested_username (:obj:`str`, optional): Suggested username for the bot.
Attributes:
request_id (:obj:`int`): Signed 32-bit identifier of the request. Must be unique
within the message.
suggested_name (:obj:`str`): Optional. Suggested name for the bot.
suggested_username (:obj:`str`): Optional. Suggested username for the bot.
"""
__slots__ = (
"request_id",
"suggested_name",
"suggested_username",
)
def __init__(
self,
request_id: int,
suggested_name: str | None = None,
suggested_username: str | None = None,
*,
api_kwargs: JSONDict | None = None,
):
super().__init__(api_kwargs=api_kwargs)
# Required
self.request_id: int = request_id
# Optional
self.suggested_name: str | None = suggested_name
self.suggested_username: str | None = suggested_username
self._id_attrs = (self.request_id,)
self._freeze()
+123
View File
@@ -0,0 +1,123 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2026
# 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 objects that represent managed bots in the Telegram Bot API."""
from typing import TYPE_CHECKING
from telegram._telegramobject import TelegramObject
from telegram._user import User
from telegram._utils.types import (
JSONDict,
)
if TYPE_CHECKING:
from telegram import Bot
class ManagedBotCreated(TelegramObject):
"""
This object contains information about the bot that was created to be managed by the current
bot.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`bot` is equal.
.. versionadded:: 22.8
Args:
bot (:class:`telegram.User`): Information about the bot. The bot's token can be fetched
using the method :meth:`~telegram.Bot.get_managed_bot_token`.
Attributes:
bot (:class:`telegram.User`): Information about the bot. The bot's token can be fetched
using the method :meth:`~telegram.Bot.get_managed_bot_token`.
"""
__slots__ = ("bot",)
def __init__(
self,
bot: User,
*,
api_kwargs: JSONDict | None = None,
):
super().__init__(api_kwargs=api_kwargs)
self.bot: User = bot
self._id_attrs = (self.bot,)
self._freeze()
@classmethod
def de_json(cls, data: JSONDict, bot: "Bot | None" = None) -> "ManagedBotCreated":
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data=data)
data["bot"] = User.de_json(data=data["bot"], bot=bot)
return super().de_json(data=data, bot=bot)
class ManagedBotUpdated(TelegramObject):
"""
This object contains information about the creation, token update, or owner update of a bot
that is managed by the current bot.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`user` and :attr:`bot` are equal.
.. versionadded:: 22.8
Args:
user (:class:`telegram.User`): User that created the bot.
bot (:class:`telegram.User`): Information about the bot. Token of the bot can be fetched
using the method :meth:`~telegram.Bot.get_managed_bot_token`.
Attributes:
user (:class:`telegram.User`): User that created the bot.
bot (:class:`telegram.User`): Information about the bot. Token of the bot can be fetched
using the method :meth:`~telegram.Bot.get_managed_bot_token`.
"""
__slots__ = ("bot", "user")
def __init__(
self,
user: User,
bot: User,
*,
api_kwargs: JSONDict | None = None,
):
super().__init__(api_kwargs=api_kwargs)
# Required
self.user: User = user
self.bot: User = bot
self._id_attrs = (
self.user,
self.bot,
)
self._freeze()
@classmethod
def de_json(cls, data: JSONDict, bot: "Bot | None" = None) -> "ManagedBotUpdated":
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data=data)
data["user"] = User.de_json(data=data["user"], bot=bot)
data["bot"] = User.de_json(data=data["bot"], bot=bot)
return super().de_json(data=data, bot=bot)
+311 -7
View File
@@ -37,6 +37,7 @@ from telegram._files.animation import Animation
from telegram._files.audio import Audio
from telegram._files.contact import Contact
from telegram._files.document import Document
from telegram._files.livephoto import LivePhoto
from telegram._files.location import Location
from telegram._files.photosize import PhotoSize
from telegram._files.sticker import Sticker
@@ -57,6 +58,7 @@ from telegram._gifts import GiftInfo
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inputchecklist import InputChecklist
from telegram._linkpreviewoptions import LinkPreviewOptions
from telegram._managedbot import ManagedBotCreated
from telegram._messageautodeletetimerchanged import MessageAutoDeleteTimerChanged
from telegram._messageentity import MessageEntity
from telegram._paidmedia import PaidMediaInfo
@@ -65,7 +67,7 @@ from telegram._passport.passportdata import PassportData
from telegram._payment.invoice import Invoice
from telegram._payment.refundedpayment import RefundedPayment
from telegram._payment.successfulpayment import SuccessfulPayment
from telegram._poll import Poll
from telegram._poll import Poll, PollOptionAdded, PollOptionDeleted
from telegram._proximityalerttriggered import ProximityAlertTriggered
from telegram._reply import ReplyParameters
from telegram._shared import ChatShared, UsersShared
@@ -80,6 +82,7 @@ from telegram._utils.entities import parse_message_entities, parse_message_entit
from telegram._utils.strings import TextEncoding
from telegram._utils.types import (
CorrectOptionID,
CorrectOptionIds,
JSONDict,
MarkdownVersion,
ODVInput,
@@ -107,17 +110,21 @@ if TYPE_CHECKING:
GiveawayCompleted,
GiveawayCreated,
GiveawayWinners,
InlineQueryResult,
InputMedia,
InputMediaAudio,
InputMediaDocument,
InputMediaLivePhoto,
InputMediaPhoto,
InputMediaVideo,
InputPaidMedia,
InputPollMedia,
InputPollOption,
LabeledPrice,
MessageId,
MessageOrigin,
ReactionType,
SentGuestMessage,
SuggestedPostApprovalFailed,
SuggestedPostApproved,
SuggestedPostDeclined,
@@ -686,9 +693,46 @@ class Message(MaybeInaccessibleMessage):
.. versionadded:: 22.7
sender_tag (:obj:`str`, optional): Tag or custom title of the sender of the message; for
supergroups only
supergroups only.
.. versionadded:: 22.7
poll_option_added (:class:`telegram.PollOptionAdded`, optional): Service message:
answer option was added to a poll.
.. versionadded:: 22.8
poll_option_deleted (:class:`telegram.PollOptionDeleted`, optional): Service message:
answer option was deleted from a poll.
.. versionadded:: 22.8
reply_to_poll_option_id (:obj:`str`, optional): Persistent
identifier of the specific poll option that is being replied to.
.. versionadded:: 22.8
managed_bot_created (:class:`telegram.ManagedBotCreated`, optional): Service message: user
created a bot that will be managed by the current bot.
.. versionadded:: 22.8
guest_bot_caller_user (:class:`telegram.User`, optional): For a message sent by a guest
bot, this is the user whose original message triggered the bot's response.
.. versionadded:: 22.8
guest_bot_caller_chat (:class:`telegram.Chat`, optional): For a message sent by a guest
bot, this is the chat whose original message triggered the bot's response.
.. versionadded:: 22.8
guest_query_id (:obj:`str`, optional): The unique identifier for the guest query. Use this
identifier with the method :meth:`telegram.Bot.answer_guest_query` to send a response
message. If non-empty, the message belongs to the chat where the guest bot was
summoned, which may not coincide with other existing bot chats sharing the same
identifier.
.. versionadded:: 22.8
live_photo (:class:`telegram.LivePhoto`, optional): Message is a live photo, information
about the live photo. For backward compatibility, when this field is set, the photo
field will also be set.
.. versionadded:: 22.8
Attributes:
message_id (:obj:`int`): Unique message identifier inside this chat. In specific instances
@@ -1102,9 +1146,45 @@ class Message(MaybeInaccessibleMessage):
.. versionadded:: 22.7
sender_tag (:obj:`str`): Optional. Tag or custom title of the sender of the message; for
supergroups only
supergroups only.
.. versionadded:: 22.7
poll_option_added (:class:`telegram.PollOptionAdded`): Optional. Service message:
answer option was added to a poll.
.. versionadded:: 22.8
poll_option_deleted (:class:`telegram.PollOptionDeleted`): Optional. Service message:
answer option was deleted from a poll.
.. versionadded:: 22.8
reply_to_poll_option_id (:obj:`str`): Optional. Persistent
identifier of the specific poll option that is being replied to.
.. versionadded:: 22.8
managed_bot_created (:class:`telegram.ManagedBotCreated`): Optional. Service message: user
created a bot that will be managed by the current bot.
.. versionadded:: 22.8
guest_bot_caller_user (:class:`telegram.User`): Optional. For a message sent by a guest
bot, this is the user whose original message triggered the bot's response.
.. versionadded:: 22.8
guest_bot_caller_chat (:class:`telegram.Chat`): Optional. For a message sent by a guest
bot, this is the chat whose original message triggered the bot's response.
.. versionadded:: 22.8
guest_query_id (:obj:`str`): Optional. The unique identifier for the guest query. Use this
identifier with the method :meth:`telegram.Bot.answer_guest_query` to send a response
message. If non-empty, the message belongs to the chat where the guest bot was
summoned, which may not coincide with other existing bot chats sharing the same
identifier.
.. versionadded:: 22.8
live_photo (:class:`telegram.LivePhoto`): Optional. Message is a live photo, information
about the live photo. For backward compatibility, when this field is set, the photo
field will also be set.
.. versionadded:: 22.8
.. |custom_emoji_no_md1_support| replace:: Since custom emoji entities are not supported by
:attr:`~telegram.constants.ParseMode.MARKDOWN`, this method now raises a
@@ -1166,6 +1246,9 @@ class Message(MaybeInaccessibleMessage):
"giveaway_created",
"giveaway_winners",
"group_chat_created",
"guest_bot_caller_chat",
"guest_bot_caller_user",
"guest_query_id",
"has_media_spoiler",
"has_protected_content",
"invoice",
@@ -1175,7 +1258,9 @@ class Message(MaybeInaccessibleMessage):
"is_topic_message",
"left_chat_member",
"link_preview_options",
"live_photo",
"location",
"managed_bot_created",
"media_group_id",
"message_auto_delete_timer_changed",
"message_thread_id",
@@ -1191,12 +1276,15 @@ class Message(MaybeInaccessibleMessage):
"photo",
"pinned_message",
"poll",
"poll_option_added",
"poll_option_deleted",
"proximity_alert_triggered",
"quote",
"refunded_payment",
"reply_markup",
"reply_to_checklist_task_id",
"reply_to_message",
"reply_to_poll_option_id",
"reply_to_story",
"sender_boost_count",
"sender_business_bot",
@@ -1337,6 +1425,14 @@ class Message(MaybeInaccessibleMessage):
chat_owner_changed: ChatOwnerChanged | None = None,
chat_owner_left: ChatOwnerLeft | None = None,
sender_tag: str | None = None,
poll_option_added: PollOptionAdded | None = None,
poll_option_deleted: PollOptionDeleted | None = None,
reply_to_poll_option_id: str | None = None,
managed_bot_created: ManagedBotCreated | None = None,
guest_bot_caller_user: User | None = None,
guest_bot_caller_chat: Chat | None = None,
guest_query_id: str | None = None,
live_photo: LivePhoto | None = None,
*,
api_kwargs: JSONDict | None = None,
):
@@ -1467,6 +1563,14 @@ class Message(MaybeInaccessibleMessage):
self.chat_owner_changed: ChatOwnerChanged | None = chat_owner_changed
self.chat_owner_left: ChatOwnerLeft | None = chat_owner_left
self.sender_tag: str | None = sender_tag
self.poll_option_added: PollOptionAdded | None = poll_option_added
self.poll_option_deleted: PollOptionDeleted | None = poll_option_deleted
self.reply_to_poll_option_id: str | None = reply_to_poll_option_id
self.managed_bot_created: ManagedBotCreated | None = managed_bot_created
self.guest_bot_caller_user: User | None = guest_bot_caller_user
self.guest_bot_caller_chat: Chat | None = guest_bot_caller_chat
self.guest_query_id: str | None = guest_query_id
self.live_photo: LivePhoto | None = live_photo
self._effective_attachment = DEFAULT_NONE
@@ -1687,6 +1791,22 @@ class Message(MaybeInaccessibleMessage):
data.get("chat_owner_changed"), ChatOwnerChanged, bot
)
data["chat_owner_left"] = de_json_optional(data.get("chat_owner_left"), ChatOwnerLeft, bot)
data["poll_option_added"] = de_json_optional(
data.get("poll_option_added"), PollOptionAdded, bot
)
data["poll_option_deleted"] = de_json_optional(
data.get("poll_option_deleted"), PollOptionDeleted, bot
)
data["managed_bot_created"] = de_json_optional(
data.get("managed_bot_created"), ManagedBotCreated, bot
)
data["guest_bot_caller_user"] = de_json_optional(
data.get("guest_bot_caller_user"), User, bot
)
data["guest_bot_caller_chat"] = de_json_optional(
data.get("guest_bot_caller_chat"), Chat, bot
)
data["live_photo"] = de_json_optional(data.get("live_photo"), LivePhoto, bot)
api_kwargs = {}
# This is a deprecated field that TG still returns for backwards compatibility
@@ -1718,6 +1838,7 @@ class Message(MaybeInaccessibleMessage):
| Document
| Game
| Invoice
| LivePhoto
| Location
| PassportData
| Sequence[PhotoSize]
@@ -1742,6 +1863,7 @@ class Message(MaybeInaccessibleMessage):
* :class:`telegram.Animation`
* :class:`telegram.Game`
* :class:`telegram.Invoice`
* :class:`telegram.LivePhoto`
* :class:`telegram.Location`
* :class:`telegram.PassportData`
* list[:class:`telegram.PhotoSize`]
@@ -2130,7 +2252,7 @@ class Message(MaybeInaccessibleMessage):
async def reply_text_draft(
self,
draft_id: int,
text: str,
text: str | None = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
entities: Sequence["MessageEntity"] | None = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
@@ -2157,6 +2279,9 @@ class Message(MaybeInaccessibleMessage):
.. versionadded:: 22.6
.. versionchanged:: 22.8
Bot API 10.0 makes the ``text`` argument optional.
Returns:
:obj:`bool`: On success, :obj:`True` is returned.
@@ -2429,7 +2554,7 @@ class Message(MaybeInaccessibleMessage):
async def reply_media_group(
self,
media: Sequence[
"InputMediaAudio | InputMediaDocument | InputMediaPhoto | InputMediaVideo"
"InputMediaAudio | InputMediaDocument | InputMediaPhoto | InputMediaVideo | InputMediaLivePhoto" # noqa: E501 # pylint: disable=line-too-long
],
disable_notification: ODVInput[bool] = DEFAULT_NONE,
protect_content: ODVInput[bool] = DEFAULT_NONE,
@@ -2590,6 +2715,87 @@ class Message(MaybeInaccessibleMessage):
suggested_post_parameters=suggested_post_parameters,
)
async def reply_live_photo(
self,
live_photo: "FileInput | LivePhoto",
photo: "FileInput | PhotoSize",
caption: str | None = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_markup: "ReplyMarkup | None" = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Sequence["MessageEntity"] | None = None,
show_caption_above_media: bool | None = None,
has_spoiler: bool | None = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
reply_parameters: "ReplyParameters | None" = None,
message_effect_id: str | None = None,
allow_paid_broadcast: bool | None = None,
suggested_post_parameters: "SuggestedPostParameters | None" = None,
*,
reply_to_message_id: int | None = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
filename: str | None = None,
do_quote: bool | (_ReplyKwargs | None) = 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 = None,
) -> "Message":
"""Shortcut for::
await bot.send_live_photo(
update.effective_message.chat_id,
message_thread_id=update.effective_message.message_thread_id,
business_connection_id=self.business_connection_id,
direct_messages_topic_id=self.direct_messages_topic.topic_id,
*args,
**kwargs,
)
For the documentation of the arguments, please see :meth:`telegram.Bot.send_live_photo`.
.. versionadded:: 22.8
Keyword Args:
do_quote (:obj:`bool` | :obj:`dict`, optional): |do_quote|
Returns:
:class:`telegram.Message`: On success, instance representing the message posted.
"""
chat_id, effective_reply_parameters = await self._parse_quote_arguments(
do_quote, reply_to_message_id, reply_parameters, allow_sending_without_reply
)
message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id)
return await self.get_bot().send_live_photo(
chat_id=chat_id,
live_photo=live_photo,
photo=photo,
caption=caption,
disable_notification=disable_notification,
reply_parameters=effective_reply_parameters,
reply_markup=reply_markup,
parse_mode=parse_mode,
caption_entities=caption_entities,
filename=filename,
protect_content=protect_content,
message_thread_id=message_thread_id,
has_spoiler=has_spoiler,
show_caption_above_media=show_caption_above_media,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
direct_messages_topic_id=self._extract_direct_messages_topic_id(),
suggested_post_parameters=suggested_post_parameters,
)
async def reply_audio(
self,
audio: "FileInput | Audio",
@@ -3473,6 +3679,18 @@ class Message(MaybeInaccessibleMessage):
question_entities: Sequence["MessageEntity"] | None = None,
message_effect_id: str | None = None,
allow_paid_broadcast: bool | None = None,
shuffle_options: bool | None = None,
allows_revoting: bool | None = None,
correct_option_ids: CorrectOptionIds | None = None,
allow_adding_options: bool | None = None,
hide_results_until_closes: bool | None = None,
description: str | None = None,
description_parse_mode: ODVInput[str] | None = None,
description_entities: Sequence["MessageEntity"] | None = None,
members_only: bool | None = None,
country_codes: Sequence[str] | None = None,
explanation_media: "InputPollMedia | None" = None,
media: "InputPollMedia | None" = None,
*,
reply_to_message_id: int | None = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -3522,6 +3740,9 @@ class Message(MaybeInaccessibleMessage):
type=type,
allows_multiple_answers=allows_multiple_answers,
correct_option_id=correct_option_id,
allows_revoting=allows_revoting,
shuffle_options=shuffle_options,
correct_option_ids=correct_option_ids,
is_closed=is_closed,
disable_notification=disable_notification,
reply_parameters=effective_reply_parameters,
@@ -3543,6 +3764,15 @@ class Message(MaybeInaccessibleMessage):
question_entities=question_entities,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
description=description,
description_parse_mode=description_parse_mode,
description_entities=description_entities,
hide_results_until_closes=hide_results_until_closes,
allow_adding_options=allow_adding_options,
members_only=members_only,
country_codes=country_codes,
explanation_media=explanation_media,
media=media,
)
async def reply_dice(
@@ -3661,7 +3891,7 @@ class Message(MaybeInaccessibleMessage):
)
return await self.get_bot().send_checklist(
business_connection_id=self.business_connection_id,
chat_id=chat_id, # type: ignore[arg-type]
chat_id=chat_id,
checklist=checklist,
disable_notification=disable_notification,
reply_parameters=effective_reply_parameters,
@@ -3773,7 +4003,7 @@ class Message(MaybeInaccessibleMessage):
)
message_thread_id = self._parse_message_thread_id(chat_id, message_thread_id)
return await self.get_bot().send_game(
chat_id=chat_id, # type: ignore[arg-type]
chat_id=chat_id,
game_short_name=game_short_name,
disable_notification=disable_notification,
reply_parameters=effective_reply_parameters,
@@ -5148,6 +5378,80 @@ class Message(MaybeInaccessibleMessage):
api_kwargs=api_kwargs,
)
async def delete_reaction(
self,
user_id: int | None = None,
actor_chat_id: int | None = 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 = None,
) -> bool:
"""Shortcut for::
await bot.delete_message_reaction(
chat_id=message.chat_id,
message_id=message.message_id,
*args, **kwargs
)
For the documentation of the arguments, please see
:meth:`telegram.Bot.delete_message_reaction`.
.. versionadded:: 22.8
Returns:
:obj:`bool` On success, :obj:`True` is returned.
"""
return await self.get_bot().delete_message_reaction(
chat_id=self.chat_id,
message_id=self.message_id,
user_id=user_id,
actor_chat_id=actor_chat_id,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)
async def answer_guest_query(
self,
result: "InlineQueryResult",
*,
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 = None,
) -> "SentGuestMessage":
"""Shortcut for::
await bot.answer_guest_query(
self.guest_query_id,
*args, **kwargs,
)
For the documentation of the arguments, please see :meth:`telegram.Bot.answer_guest_query`.
.. versionadded:: 22.8
Returns:
:class:`telegram.SentGuestMessage`: On success, a
:class:`telegram.SentGuestMessage` is returned.
"""
return await self.get_bot().answer_guest_query(
guest_query_id=self.guest_query_id,
result=result,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)
def parse_entity(self, entity: MessageEntity) -> str:
"""Returns the text from a given :class:`telegram.MessageEntity`.
+45
View File
@@ -23,6 +23,7 @@ from collections.abc import Sequence
from typing import TYPE_CHECKING, Final
from telegram import constants
from telegram._files.livephoto import LivePhoto
from telegram._files.photosize import PhotoSize
from telegram._files.video import Video
from telegram._telegramobject import TelegramObject
@@ -68,6 +69,8 @@ class PaidMedia(TelegramObject):
""":const:`telegram.constants.PaidMediaType.PHOTO`"""
VIDEO: Final[str] = constants.PaidMediaType.VIDEO
""":const:`telegram.constants.PaidMediaType.VIDEO`"""
LIVE_PHOTO: Final[str] = constants.PaidMediaType.LIVE_PHOTO
""":const:`telegram.constants.PaidMediaType.LIVE_PHOTO`"""
def __init__(
self,
@@ -100,6 +103,7 @@ class PaidMedia(TelegramObject):
cls.PREVIEW: PaidMediaPreview,
cls.PHOTO: PaidMediaPhoto,
cls.VIDEO: PaidMediaVideo,
cls.LIVE_PHOTO: PaidMediaLivePhoto,
}
if cls is PaidMedia and data.get("type") in _class_mapping:
@@ -251,6 +255,47 @@ class PaidMediaVideo(PaidMedia):
return super().de_json(data=data, bot=bot) # type: ignore[return-value]
class PaidMediaLivePhoto(PaidMedia):
"""
The paid media is a live photo.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`live_photo` are equal.
.. versionadded:: 22.8
Args:
type (:obj:`str`): Type of the paid media, always :tg-const:`telegram.PaidMedia.LIVE_PHOTO`
live_photo (:class:`telegram.LivePhoto`): The photo.
Attributes:
type (:obj:`str`): Type of the paid media, always :tg-const:`telegram.PaidMedia.LIVE_PHOTO`
live_photo (:class:`telegram.LivePhoto`): The photo.
"""
__slots__ = ("live_photo",)
def __init__(
self,
live_photo: LivePhoto,
*,
api_kwargs: JSONDict | None = None,
) -> None:
super().__init__(type=PaidMedia.LIVE_PHOTO, api_kwargs=api_kwargs)
with self._unfrozen():
self.live_photo: LivePhoto = live_photo
self._id_attrs = (self.type, self.live_photo)
@classmethod
def de_json(cls, data: JSONDict, bot: "Bot | None" = None) -> "PaidMediaLivePhoto":
data = cls._parse_data(data)
data["live_photo"] = de_json_optional(data.get("live_photo"), LivePhoto, bot)
return super().de_json(data=data, bot=bot) # type: ignore[return-value]
class PaidMediaInfo(TelegramObject):
"""
Describes the paid media added to a message.

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