Compare commits

..

35 Commits

Author SHA1 Message Date
Hinrich Mahler a9f6afd015 Bump version to v21.3 2024-06-07 16:52:22 +02:00
Bibo-Joshi 78c945d485 Documentation Improvements (#4264) 2024-06-07 16:13:55 +02:00
Trijeet Modak 9e70ac8b7a Add Parameter chat_id to ChatMemberHandler (#4290) 2024-06-06 17:31:45 +02:00
Harshil cf728496e4 API 7.4 (#4276, #4278, #4279, #4280, #4286, #4283, #4285)
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
2024-06-03 19:39:31 +02:00
dependabot[bot] 078d775250 Bump pytest from 8.2.0 to 8.2.1 (#4272)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-03 19:25:54 +02:00
Bibo-Joshi 57298aa076 Deprecate python-telegram-bot-raw (#4270) 2024-06-01 21:19:38 +02:00
Bibo-Joshi 2c299bb109 Add setuptools to requirements-dev.txt (#4282) 2024-05-30 21:02:41 +02:00
Harshil c1c5438f37 Remove Functionality Deprecated in Bot API 7.3 (#4266) 2024-05-29 19:59:23 +02:00
Bibo-Joshi 6ba7a097f4 Update Settings for pre-commit.ci (#4265) 2024-05-22 17:43:45 +02:00
Hinrich Mahler 6fc45a803d Bump version to v21.2 2024-05-20 17:23:38 +02:00
Harshil 512a0b7417 Add Version to PTBDeprecationWarning (#4262) 2024-05-20 16:12:34 +02:00
Bibo-Joshi 7d952d8707 Documentation Improvements (#4217)
Co-authored-by: poolitzer <github@poolitzer.eu>
2024-05-20 15:53:04 +02:00
Bibo-Joshi b496fabf62 Call Application.post_stop Only if Application.stop was called (#4211) 2024-05-20 15:52:30 +02:00
Bibo-Joshi 637b8e260b Handle SystemExit raised in Handlers (#4157) 2024-05-20 15:27:08 +02:00
Bibo-Joshi 912fe45d8c Handle Exceptions in building CallbackContext (#4222) 2024-05-20 15:25:56 +02:00
Bibo-Joshi 805b7bff32 API 7.3 (#4243, #4248, #4247, #4242, #4246, #4260)
Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com>
Co-authored-by: Abdelrahman Elkheir <90580077+aelkheir@users.noreply.github.com>
2024-05-20 15:25:25 +02:00
Harshil f3bd0f1462 Add New Rules to ruff Config (#4250) 2024-05-12 09:13:20 +02:00
dependabot[bot] 5b0e0b5f78 Bump furo from 2024.4.27 to 2024.5.6 (#4252)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-11 15:37:54 +02:00
Bibo-Joshi c4623c4476 Make Birthdate.to_date Return a datetime.date Object (#4251)
Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com>
2024-05-10 22:23:19 +02:00
Bibo-Joshi ee6e82d7ad Remove Functionality Deprecated by Bot API 7.2 (#4245) 2024-05-10 17:42:22 +02:00
pre-commit-ci[bot] c34f4811ea pre-commit autoupdate (#4239)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2024-05-07 07:42:09 +02:00
dependabot[bot] d768abdd6b Bump pytest from 8.1.1 to 8.2.0 (#4231)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-06 22:36:18 +02:00
dependabot[bot] 2561ffd16b Bump dependabot/fetch-metadata from 2.0.0 to 2.1.0 (#4228)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <dependabot[bot]@users.noreply.github.com>
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
2024-05-06 22:35:52 +02:00
Bibo-Joshi 622fdf7fa3 Adapt Test Suite to Changes in Error Messages (#4238) 2024-05-06 22:35:11 +02:00
dependabot[bot] 615f1bf20b Bump pytest-asyncio from 0.21.1 to 0.21.2 (#4232)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-05 10:03:38 +02:00
dependabot[bot] 7a8b1be5a4 Bump pytest-xdist from 3.6.0 to 3.6.1 (#4233)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-04 17:30:18 +02:00
dependabot[bot] 3a8ace2e8b Bump furo from 2024.1.29 to 2024.4.27 (#4230)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-04 11:12:26 +02:00
dependabot[bot] 169bd47de3 Bump srvaroa/labeler from 1.10.0 to 1.10.1 (#4227)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-04 11:07:21 +02:00
dependabot[bot] a956dcc6a4 Bump pytest from 7.4.4 to 8.1.1 (#4218)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com>
Co-authored-by: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com>
2024-04-28 22:32:20 +02:00
Bibo-Joshi ee88973fee Bump pytest-xdist from 3.5.0 to 3.6.0
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-20 10:44:39 +02:00
dependabot[bot] 8f9fc65be0 Bump sphinx from 7.2.6 to 7.3.7 (#4215)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-20 09:22:42 +02:00
Hinrich Mahler 75d946e4be Bump version to v21.1.1 2024-04-15 17:00:17 +02:00
Bibo-Joshi fed8d8875e Fix Bug With Parameter message_thread_id of Message.reply_* (#4207) 2024-04-15 16:49:36 +02:00
Nano 42b68f1a70 Remove Deprecation Warning in JobQueue.run_daily (#4206) 2024-04-14 14:14:45 +02:00
marinelay 58b8ef4ce4 Fix Annotation of EncryptedCredentials.decrypted_secret (#4199)
Co-authored-by: marinelay <marinelay@gmail.com>
2024-04-13 20:27:29 +02:00
151 changed files with 5117 additions and 1758 deletions
+2 -2
View File
@@ -157,7 +157,7 @@ Check-list for PRs
This checklist is a non-exhaustive reminder of things that should be done before a PR is merged, both for you as contributor and for the maintainers.
Feel free to copy (parts of) the checklist to the PR description to remind you or the maintainers of open points or if you have questions on anything.
- Added ``.. versionadded:: NEXT.VERSION``, ``.. versionchanged:: NEXT.VERSION`` or ``.. deprecated:: NEXT.VERSION`` to the docstrings for user facing changes (for methods/class descriptions, arguments and attributes)
- Added ``.. versionadded:: NEXT.VERSION``, ``.. versionchanged:: NEXT.VERSION``, ``.. deprecated:: NEXT.VERSION`` or ``.. versionremoved:: NEXT.VERSION`` to the docstrings for user facing changes (for methods/class descriptions, arguments and attributes)
- Created new or adapted existing unit tests
- Documented code changes according to the `CSI standard <https://standards.mousepawmedia.com/en/stable/csi.html>`__
- Added myself alphabetically to ``AUTHORS.rst`` (optional)
@@ -276,7 +276,7 @@ This gives us the flexibility to re-order arguments and more importantly
to add new required arguments. It's also more explicit and easier to read.
.. _`Code of Conduct`: https://www.python.org/psf/conduct/
.. _`Code of Conduct`: https://policies.python.org/python.org/code-of-conduct/
.. _`issue tracker`: https://github.com/python-telegram-bot/python-telegram-bot/issues
.. _`Telegram group`: https://telegram.me/pythontelegrambotgroup
.. _`PEP 8 Style Guide`: https://peps.python.org/pep-0008/
+2
View File
@@ -12,6 +12,8 @@ body:
To make it easier for us to help you, please read this [article](https://github.com/python-telegram-bot/python-telegram-bot/wiki/Ask-Right).
Please mind that there is also a users' [Telegram group](https://t.me/pythontelegrambotgroup) for questions about the library. Questions asked there might be answered quicker than here. Moreover, [GitHub Discussions](https://github.com/python-telegram-bot/python-telegram-bot/discussions) offer a slightly better format to discuss usage questions.
If you have asked the same question elsewhere (e.g. the [Telegram group](https://t.me/pythontelegrambotgroup) or [StackOverflow](https://stackoverflow.com/questions/tagged/python-telegram-bot)), provide a link to that thread.
- type: textarea
id: issue-faced
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
- name: Fetch Dependabot metadata
id: dependabot-metadata
uses: dependabot/fetch-metadata@v2.0.0
uses: dependabot/fetch-metadata@v2.1.0
- uses: actions/checkout@v4
with:
+1 -1
View File
@@ -11,7 +11,7 @@ jobs:
pull-requests: write # for srvaroa/labeler to add labels in PR
runs-on: ubuntu-latest
steps:
- uses: srvaroa/labeler@v1.10.0
- uses: srvaroa/labeler@v1.10.1
# Config file at .github/labeler.yml
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+1
View File
@@ -6,6 +6,7 @@ on:
- tests/**
- requirements.txt
- requirements-opts.txt
- requirements-dev.txt
push:
branches:
- master
+5 -4
View File
@@ -2,11 +2,12 @@
ci:
autofix_prs: false
autoupdate_schedule: monthly
autoupdate_schedule: quarterly
autoupdate_commit_msg: 'Bump `pre-commit` Hooks to Latest Versions'
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: 'v0.3.5'
rev: 'v0.4.3'
hooks:
- id: ruff
name: ruff
@@ -17,7 +18,7 @@ repos:
- cachetools~=5.3.3
- aiolimiter~=1.1.0
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 24.3.0
rev: 24.4.2
hooks:
- id: black
args:
@@ -40,7 +41,7 @@ repos:
- aiolimiter~=1.1.0
- . # this basically does `pip install -e .`
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.9.0
rev: v1.10.0
hooks:
- id: mypy
name: mypy-ptb
+1
View File
@@ -123,6 +123,7 @@ The following wonderful people contributed directly or indirectly to this projec
- `Vorobjev Simon <https://github.com/simonvorobjev>`_
- `Wagner Macedo <https://github.com/wagnerluis1982>`_
- `wjt <https://github.com/wjt>`_
- `Wonseok Oh <https://github.com/marinelay>`_
- `Yaw Danso <https://github.com/dglitxh>`_
- `Yao Kuan <https://github.com/thatguylah>`_
- `zeroone2numeral2 <https://github.com/zeroone2numeral2>`_
+105
View File
@@ -4,6 +4,111 @@
Changelog
=========
Version 21.3
============
*Released 2024-06-07*
This is the technical changelog for version 21.3. More elaborate release notes can be found in the news channel `@pythontelegrambotchannel <https://t.me/pythontelegrambotchannel>`_.
Major Changes
-------------
- Full Support for Bot API 7.4 (:pr:`4286`, :pr:`4276` closes :issue:`4275`, :pr:`4285`, :pr:`4283`, :pr:`4280`, :pr:`4278`, :pr:`4279`)
- Deprecate ``python-telegram-bot-raw`` (:pr:`4270`)
- Remove Functionality Deprecated in Bot API 7.3 (:pr:`4266` closes :issue:`4244`)
New Features
------------
- Add Parameter ``chat_id`` to ``ChatMemberHandler`` (:pr:`4290` by `uniquetrij <https://github.com/uniquetrij>`_ closes :issue:`4287`)
Documentation Improvements
--------------------------
- Documentation Improvements (:pr:`4264` closes :issue:`4240`)
Internal Changes
----------------
- Add ``setuptools`` to ``requirements-dev.txt`` (:pr:`4282`)
- Update Settings for pre-commit.ci (:pr:`4265`)
Dependency Updates
------------------
- Bump ``pytest`` from 8.2.0 to 8.2.1 (:pr:`4272`)
Version 21.2
============
*Released 2024-05-20*
This is the technical changelog for version 21.2. More elaborate release notes can be found in the news channel `@pythontelegrambotchannel <https://t.me/pythontelegrambotchannel>`_.
Major Changes
-------------
- Full Support for Bot API 7.3 (:pr:`4246`, :pr:`4260`, :pr:`4243`, :pr:`4248`, :pr:`4242` closes :issue:`4236`, :pr:`4247` by `aelkheir <https://github.com/aelkheir>`_)
- Remove Functionality Deprecated by Bot API 7.2 (:pr:`4245`)
New Features
------------
- Add Version to ``PTBDeprecationWarning`` (:pr:`4262` closes :issue:`4261`)
- Handle Exceptions in building ``CallbackContext`` (:pr:`4222`)
Bug Fixes
---------
- Call ``Application.post_stop`` Only if ``Application.stop`` was called (:pr:`4211` closes :issue:`4210`)
- Handle ``SystemExit`` raised in Handlers (:pr:`4157` closes :issue:`4155` and :issue:`4156`)
- Make ``Birthdate.to_date`` Return a ``datetime.date`` Object (:pr:`4251`)
Documentation Improvements
--------------------------
- Documentation Improvements (:pr:`4217`)
Internal Changes
----------------
- Add New Rules to ``ruff`` Config (:pr:`4250`)
- Adapt Test Suite to Changes in Error Messages (:pr:`4238`)
Dependency Updates
------------------
- Bump ``furo`` from 2024.4.27 to 2024.5.6 (:pr:`4252`)
- ``pre-commit`` autoupdate (:pr:`4239`)
- Bump ``pytest`` from 8.1.1 to 8.2.0 (:pr:`4231`)
- Bump ``dependabot/fetch-metadata`` from 2.0.0 to 2.1.0 (:pr:`4228`)
- Bump ``pytest-asyncio`` from 0.21.1 to 0.21.2 (:pr:`4232`)
- Bump ``pytest-xdist`` from 3.6.0 to 3.6.1 (:pr:`4233`)
- Bump ``furo`` from 2024.1.29 to 2024.4.27 (:pr:`4230`)
- Bump ``srvaroa/labeler`` from 1.10.0 to 1.10.1 (:pr:`4227`)
- Bump ``pytest`` from 7.4.4 to 8.1.1 (:pr:`4218`)
- Bump ``sphinx`` from 7.2.6 to 7.3.7 (:pr:`4215`)
- Bump ``pytest-xdist`` from 3.5.0 to 3.6.0 (:pr:`4215`)
Version 21.1.1
==============
*Released 2024-04-15*
This is the technical changelog for version 21.1.1. More elaborate release notes can be found in the news channel `@pythontelegrambotchannel <https://t.me/pythontelegrambotchannel>`__.
Bug Fixes
---------
- Fix Bug With Parameter ``message_thread_id`` of ``Message.reply_*`` (:pr:`4207` closes :issue:`4205`)
Minor Changes
-------------
- Remove Deprecation Warning in ``JobQueue.run_daily`` (:pr:`4206` by `@Konano <https://github.com/Konano>`__)
- Fix Annotation of ``EncryptedCredentials.decrypted_secret`` (:pr:`4199` by `@marinelay <https://github.com/marinelay>`__ closes :issue:`4198`)
Version 21.1
==============
+3 -13
View File
@@ -1,6 +1,3 @@
..
Make sure to apply any changes to this file to README_RAW.rst as well!
.. image:: https://raw.githubusercontent.com/python-telegram-bot/logos/master/logo-text/png/ptb-logo-text_768.png
:align: center
:target: https://python-telegram-bot.org
@@ -14,9 +11,9 @@
:target: https://pypi.org/project/python-telegram-bot/
:alt: Supported Python versions
.. image:: https://img.shields.io/badge/Bot%20API-7.2-blue?logo=telegram
.. image:: https://img.shields.io/badge/Bot%20API-7.4-blue?logo=telegram
:target: https://core.telegram.org/bots/api-changelog
:alt: Supported Bot API versions
:alt: Supported Bot API version
.. image:: https://img.shields.io/pypi/dm/python-telegram-bot
:target: https://pypistats.org/packages/python-telegram-bot
@@ -79,17 +76,10 @@ In addition to the pure API implementation, this library features a number of hi
make the development of bots easy and straightforward. These classes are contained in the
``telegram.ext`` submodule.
A pure API implementation *without* ``telegram.ext`` is available as the standalone package ``python-telegram-bot-raw``. `See here for details. <https://github.com/python-telegram-bot/python-telegram-bot/blob/master/README_RAW.rst>`_
Note
----
Installing both ``python-telegram-bot`` and ``python-telegram-bot-raw`` in conjunction will result in undesired side-effects, so only install *one* of both.
Telegram API support
====================
All types and methods of the Telegram Bot API **7.2** are supported.
All types and methods of the Telegram Bot API **7.4** are supported.
Installing
==========
+13 -6
View File
@@ -1,6 +1,3 @@
..
Make sure to apply any changes to this file to README.rst as well!
.. image:: https://github.com/python-telegram-bot/logos/blob/master/logo-text/png/ptb-raw-logo-text_768.png?raw=true
:align: center
:target: https://python-telegram-bot.org
@@ -14,9 +11,9 @@
:target: https://pypi.org/project/python-telegram-bot-raw/
:alt: Supported Python versions
.. image:: https://img.shields.io/badge/Bot%20API-7.2-blue?logo=telegram
.. image:: https://img.shields.io/badge/Bot%20API-7.4-blue?logo=telegram
:target: https://core.telegram.org/bots/api-changelog
:alt: Supported Bot API versions
:alt: Supported Bot API version
.. image:: https://img.shields.io/pypi/dm/python-telegram-bot-raw
:target: https://pypistats.org/packages/python-telegram-bot-raw
@@ -62,6 +59,16 @@
:target: https://telegram.me/pythontelegrambotgroup
:alt: Telegram Group
⚠️ Deprecation Notice
=====================
The ``python-telegram-bot-raw`` library will no longer be updated after 21.3.
Please instead use the ``python-telegram-bot`` `library <https://pypi.org/python-telegram-bot>`_.
The change requires no changes in your code and requires no additional dependencies.
For additional information, please see this `channel post <https://t.me/pythontelegrambotchannel/145>`_.
----
We have made you a wrapper you can't refuse
We have a vibrant community of developers helping each other in our `Telegram group <https://telegram.me/pythontelegrambotgroup>`_. Join us!
@@ -85,7 +92,7 @@ Installing both ``python-telegram-bot`` and ``python-telegram-bot-raw`` in conju
Telegram API support
====================
All types and methods of the Telegram Bot API **7.2** are supported.
All types and methods of the Telegram Bot API **7.4** are supported.
Installing
==========
+1
View File
@@ -46,6 +46,7 @@ PRIVATE_BASE_CLASSES = {
"_BaseThumbedMedium": "TelegramObject",
"_BaseMedium": "TelegramObject",
"_CredentialsBase": "TelegramObject",
"_ChatBase": "TelegramObject",
}
+2 -2
View File
@@ -1,5 +1,5 @@
sphinx==7.2.6
furo==2024.1.29
sphinx==7.3.7
furo==2024.5.6
furo-sphinx-search @ git+https://github.com/harshil21/furo-sphinx-search@v0.2.0.1
sphinx-paramlinks==0.6.0
sphinxcontrib-mermaid==0.9.2
+9 -3
View File
@@ -20,9 +20,13 @@ author = "Leandro Toledo"
# built documents.
#
# The short X.Y version.
version = "21.1" # telegram.__version__[:3]
# Import needs to be below the sys.path.insert above
import telegram # noqa: E402
version = telegram.__version__
# The full version, including alpha/beta/rc tags.
release = "21.1" # telegram.__version__
release = telegram.__version__
# If your documentation needs a minimal Sphinx version, state it here.
needs_sphinx = "6.1.3"
@@ -67,7 +71,9 @@ source_suffix = ".rst"
master_doc = "index"
# Global substitutions
rst_prolog = (Path.cwd() / "../substitutions/global.rst").read_text(encoding="utf-8")
rst_prolog = ""
for file in Path.cwd().glob("../substitutions/*.rst"):
rst_prolog += "\n" + file.read_text(encoding="utf-8")
# -- Extension settings ------------------------------------------------
napoleon_use_admonition_for_examples = True
+2
View File
@@ -369,6 +369,8 @@
- Used for getting basic info about a file
* - :meth:`~telegram.Bot.get_me`
- Used for getting basic information about the bot
* - :meth:`~telegram.Bot.refund_star_payment`
- Used for refunding a payment in Telegram Stars
.. raw:: html
+12
View File
@@ -28,6 +28,16 @@ Available Types
telegram.callbackquery
telegram.chat
telegram.chatadministratorrights
telegram.chatbackground
telegram.backgroundtype
telegram.backgroundtypefill
telegram.backgroundtypewallpaper
telegram.backgroundtypepattern
telegram.backgroundtypechattheme
telegram.backgroundfill
telegram.backgroundfillsolid
telegram.backgroundfillgradient
telegram.backgroundfillfreeformgradient
telegram.chatboost
telegram.chatboostadded
telegram.chatboostremoved
@@ -36,6 +46,7 @@ Available Types
telegram.chatboostsourcegiveaway
telegram.chatboostsourcepremium
telegram.chatboostupdated
telegram.chatfullinfo
telegram.chatinvitelink
telegram.chatjoinrequest
telegram.chatlocation
@@ -77,6 +88,7 @@ Available Types
telegram.inputmediadocument
telegram.inputmediaphoto
telegram.inputmediavideo
telegram.inputpolloption
telegram.inputsticker
telegram.keyboardbutton
telegram.keyboardbuttonpolltype
+8
View File
@@ -0,0 +1,8 @@
BackgroundFill
==============
.. versionadded:: 21.2
.. autoclass:: telegram.BackgroundFill
:members:
:show-inheritance:
@@ -0,0 +1,8 @@
BackgroundFillFreeformGradient
==============================
.. versionadded:: 21.2
.. autoclass:: telegram.BackgroundFillFreeformGradient
:members:
:show-inheritance:
@@ -0,0 +1,8 @@
BackgroundFillGradient
======================
.. versionadded:: 21.2
.. autoclass:: telegram.BackgroundFillGradient
:members:
:show-inheritance:
@@ -0,0 +1,8 @@
BackgroundFillSolid
===================
.. versionadded:: 21.2
.. autoclass:: telegram.BackgroundFillSolid
:members:
:show-inheritance:
+8
View File
@@ -0,0 +1,8 @@
BackgroundType
==============
.. versionadded:: 21.2
.. autoclass:: telegram.BackgroundType
:members:
:show-inheritance:
@@ -0,0 +1,8 @@
BackgroundTypeChatTheme
=======================
.. versionadded:: 21.2
.. autoclass:: telegram.BackgroundTypeChatTheme
:members:
:show-inheritance:
@@ -0,0 +1,8 @@
BackgroundTypeFill
==================
.. versionadded:: 21.2
.. autoclass:: telegram.BackgroundTypeFill
:members:
:show-inheritance:
@@ -0,0 +1,8 @@
BackgroundTypePattern
=====================
.. versionadded:: 21.2
.. autoclass:: telegram.BackgroundTypePattern
:members:
:show-inheritance:
@@ -0,0 +1,8 @@
BackgroundTypeWallpaper
=======================
.. versionadded:: 21.2
.. autoclass:: telegram.BackgroundTypeWallpaper
:members:
:show-inheritance:
+2
View File
@@ -1,6 +1,8 @@
Chat
====
.. Also lists methods of _ChatBase, but not the ones of TelegramObject
.. autoclass:: telegram.Chat
:members:
:show-inheritance:
:inherited-members: TelegramObject
+8
View File
@@ -0,0 +1,8 @@
ChatBackground
==============
.. versionadded:: 21.2
.. autoclass:: telegram.ChatBackground
:members:
:show-inheritance:
+8
View File
@@ -0,0 +1,8 @@
ChatFullInfo
============
.. Also lists methods of _ChatBase, but not the ones of TelegramObject
.. autoclass:: telegram.ChatFullInfo
:members:
:show-inheritance:
:inherited-members: TelegramObject
+6
View File
@@ -0,0 +1,6 @@
InputPollOption
===============
.. autoclass:: telegram.InputPollOption
:members:
:show-inheritance:
+1 -1
View File
@@ -1,6 +1,6 @@
PhotoSize
=========
.. Also lists methods of _BaseThumbedMedium, but not the ones of TelegramObject
.. Also lists methods of _BaseMedium, but not the ones of TelegramObject
.. autoclass:: telegram.PhotoSize
:members:
+1
View File
@@ -0,0 +1 @@
.. |app_run_shutdown| replace:: The app will shut down when :exc:`KeyboardInterrupt` or :exc:`SystemExit` is raised. This also works from within handlers, error handlers and jobs. However, using :meth:`~telegram.ext.Application.stop_running` will give a somewhat cleaner shutdown behavior than manually raising those exceptions. On unix, the app will also shut down on receiving the signals specified by
+6
View File
@@ -81,3 +81,9 @@
.. |non_optional_story_argument| replace:: As of this version, this argument is now required. In accordance with our `stability policy <https://docs.python-telegram-bot.org/en/stable/stability_policy.html>`__, the signature will be kept as optional for now, though they are mandatory and an error will be raised if you don't pass it.
.. |business_id_str| replace:: Unique identifier of the business connection on behalf of which the message will be sent.
.. |message_effect_id| replace:: Unique identifier of the message effect to be added to the message; for private chats only.
.. |show_cap_above_med| replace:: :obj:`True`, if the caption must be shown above the message media.
.. |tg_stars| replace:: `Telegram Stars <https://t.me/BotNews/90>`__
+6 -4
View File
@@ -20,13 +20,15 @@ explicit-preview-rules = true
ignore = ["PLR2004", "PLR0911", "PLR0912", "PLR0913", "PLR0915", "PERF203"]
select = ["E", "F", "I", "PL", "UP", "RUF", "PTH", "C4", "B", "PIE", "SIM", "RET", "RSE",
"G", "ISC", "PT", "ASYNC", "TCH", "SLOT", "PERF", "PYI", "FLY", "AIR", "RUF022",
"RUF023", "Q", "INP", "W"]
"RUF023", "Q", "INP", "W", "YTT", "DTZ", "ARG"]
# Add "FURB" after it's out of preview
# Add "A (flake8-builtins)" after we drop pylint
[tool.ruff.lint.per-file-ignores]
"tests/*.py" = ["B018"]
"tests/**.py" = ["RUF012", "ASYNC101"]
"docs/**.py" = ["INP001"]
"tests/**.py" = ["RUF012", "ASYNC101", "DTZ", "ARG"]
"docs/**.py" = ["INP001", "ARG"]
"examples/**.py" = ["ARG"]
# PYLINT:
[tool.pylint."messages control"]
@@ -48,7 +50,7 @@ exclude-protected = ["_unfrozen"]
# PYTEST:
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "--no-success-flaky-report -rsxX"
addopts = "--no-success-flaky-report -rX"
filterwarnings = [
"error",
"ignore::DeprecationWarning",
+4 -3
View File
@@ -1,9 +1,10 @@
pre-commit # needed for pre-commit hooks in the git commit command
# For the test suite
pytest==7.4.4
pytest-asyncio==0.21.1 # needed because pytest doesn't come with native support for coroutines as tests
pytest-xdist==3.5.0 # xdist runs tests in parallel
setuptools # required for test_meta
pytest==8.2.1
pytest-asyncio==0.21.2 # needed because pytest doesn't come with native support for coroutines as tests
pytest-xdist==3.6.1 # xdist runs tests in parallel
flaky # Used for flaky tests (flaky decorator)
beautifulsoup4 # used in test_official for parsing tg docs
+53 -1
View File
@@ -22,6 +22,15 @@ __author__ = "devs@python-telegram-bot.org"
__all__ = (
"Animation",
"Audio",
"BackgroundFill",
"BackgroundFillFreeformGradient",
"BackgroundFillGradient",
"BackgroundFillSolid",
"BackgroundType",
"BackgroundTypeChatTheme",
"BackgroundTypeFill",
"BackgroundTypePattern",
"BackgroundTypeWallpaper",
"Birthdate",
"Bot",
"BotCommand",
@@ -46,6 +55,7 @@ __all__ = (
"CallbackQuery",
"Chat",
"ChatAdministratorRights",
"ChatBackground",
"ChatBoost",
"ChatBoostAdded",
"ChatBoostRemoved",
@@ -54,6 +64,7 @@ __all__ = (
"ChatBoostSourceGiveaway",
"ChatBoostSourcePremium",
"ChatBoostUpdated",
"ChatFullInfo",
"ChatInviteLink",
"ChatJoinRequest",
"ChatLocation",
@@ -131,6 +142,7 @@ __all__ = (
"InputMediaPhoto",
"InputMediaVideo",
"InputMessageContent",
"InputPollOption",
"InputSticker",
"InputTextMessageContent",
"InputVenueMessageContent",
@@ -230,6 +242,7 @@ __all__ = (
"warnings",
)
from pathlib import Path
from . import _version, constants, error, helpers, request, warnings
from ._birthdate import Birthdate
@@ -258,6 +271,18 @@ from ._business import (
from ._callbackquery import CallbackQuery
from ._chat import Chat
from ._chatadministratorrights import ChatAdministratorRights
from ._chatbackground import (
BackgroundFill,
BackgroundFillFreeformGradient,
BackgroundFillGradient,
BackgroundFillSolid,
BackgroundType,
BackgroundTypeChatTheme,
BackgroundTypeFill,
BackgroundTypePattern,
BackgroundTypeWallpaper,
ChatBackground,
)
from ._chatboost import (
ChatBoost,
ChatBoostAdded,
@@ -269,6 +294,7 @@ from ._chatboost import (
ChatBoostUpdated,
UserChatBoosts,
)
from ._chatfullinfo import ChatFullInfo
from ._chatinvitelink import ChatInviteLink
from ._chatjoinrequest import ChatJoinRequest
from ._chatlocation import ChatLocation
@@ -403,7 +429,7 @@ from ._payment.shippingaddress import ShippingAddress
from ._payment.shippingoption import ShippingOption
from ._payment.shippingquery import ShippingQuery
from ._payment.successfulpayment import SuccessfulPayment
from ._poll import Poll, PollAnswer, PollOption
from ._poll import InputPollOption, Poll, PollAnswer, PollOption
from ._proximityalerttriggered import ProximityAlertTriggered
from ._reaction import ReactionCount, ReactionType, ReactionTypeCustomEmoji, ReactionTypeEmoji
from ._reply import ExternalReplyInfo, ReplyParameters, TextQuote
@@ -417,6 +443,7 @@ from ._telegramobject import TelegramObject
from ._update import Update
from ._user import User
from ._userprofilephotos import UserProfilePhotos
from ._utils.warnings import warn
from ._videochat import (
VideoChatEnded,
VideoChatParticipantsInvited,
@@ -450,3 +477,28 @@ __bot_api_version__: str = _version.__bot_api_version__
#:
#: .. versionadded:: 20.0
__bot_api_version_info__: constants._BotAPIVersion = _version.__bot_api_version_info__
if not (Path(__file__).parent.resolve().absolute() / "ext").exists():
_MESSAGE = (
"Hey. You seem to be using the `python-telegram-bot-raw` library. "
"Please note that this libray has been deprecated and will no longer be updated. "
"Please instead use the `python-telegram-bot` library. The change requires no "
"changes in your code and requires no additional dependencies. For additional "
"information, please see the channel post at "
"https://t.me/pythontelegrambotchannel/145."
)
# DeprecationWarning is ignored by default in Python 3.7 and later by default outside
# __main__ modules. We use both warning categories to increase the chance of the user
# seeing the warning.
warn(
warnings.PTBDeprecationWarning(version="21.3", message=_MESSAGE),
stacklevel=2,
)
warn(
message=_MESSAGE,
category=warnings.PTBUserWarning,
stacklevel=2,
)
+10 -6
View File
@@ -17,7 +17,7 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram Birthday."""
from datetime import datetime
from datetime import date
from typing import Optional
from telegram._telegramobject import TelegramObject
@@ -26,7 +26,7 @@ from telegram._utils.types import JSONDict
class Birthdate(TelegramObject):
"""
This object represents a user's birthday.
This object describes the birthdate of a user.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`day`, and :attr:`month` are equal.
@@ -70,19 +70,23 @@ class Birthdate(TelegramObject):
self._freeze()
def to_date(self, year: Optional[int] = None) -> datetime:
"""Return the birthdate as a datetime object.
def to_date(self, year: Optional[int] = None) -> date:
"""Return the birthdate as a date object.
.. versionchanged:: 21.2
Now returns a :obj:`datetime.date` object instead of a :obj:`datetime.datetime` object,
as was originally intended.
Args:
year (:obj:`int`, optional): The year to use. Required, if the :attr:`year` was not
present.
Returns:
:obj:`datetime.datetime`: The birthdate as a datetime object.
:obj:`datetime.date`: The birthdate as a date object.
"""
if self.year is None and year is None:
raise ValueError(
"The `year` argument is required if the `year` attribute was not present."
)
return datetime(year or self.year, self.month, self.day) # type: ignore[arg-type]
return date(year or self.year, self.month, self.day) # type: ignore[arg-type]
+279 -74
View File
@@ -58,9 +58,9 @@ from telegram._botcommandscope import BotCommandScope
from telegram._botdescription import BotDescription, BotShortDescription
from telegram._botname import BotName
from telegram._business import BusinessConnection
from telegram._chat import Chat
from telegram._chatadministratorrights import ChatAdministratorRights
from telegram._chatboost import UserChatBoosts
from telegram._chatfullinfo import ChatFullInfo
from telegram._chatinvitelink import ChatInviteLink
from telegram._chatmember import ChatMember
from telegram._chatpermissions import ChatPermissions
@@ -84,7 +84,7 @@ from telegram._inline.inlinequeryresultsbutton import InlineQueryResultsButton
from telegram._menubutton import MenuButton
from telegram._message import Message
from telegram._messageid import MessageId
from telegram._poll import Poll
from telegram._poll import InputPollOption, Poll
from telegram._reaction import ReactionType, ReactionTypeCustomEmoji, ReactionTypeEmoji
from telegram._reply import ReplyParameters
from telegram._sentwebappmessage import SentWebAppMessage
@@ -524,7 +524,10 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
@classmethod
def _warn(
cls, message: str, category: Type[Warning] = PTBUserWarning, stacklevel: int = 0
cls,
message: Union[str, PTBUserWarning],
category: Type[Warning] = PTBUserWarning,
stacklevel: int = 0,
) -> None:
"""Convenience method to issue a warning. This method is here mostly to make it easier
for ExtBot to add 1 level to all warning calls.
@@ -669,6 +672,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
link_preview_options: ODVInput["LinkPreviewOptions"] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -708,7 +712,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
data["disable_notification"] = disable_notification
data["protect_content"] = protect_content
data["parse_mode"] = parse_mode
data["reply_parameters"] = reply_parameters
if reply_parameters is not None:
data["reply_parameters"] = reply_parameters
if link_preview_options is not None:
data["link_preview_options"] = link_preview_options
@@ -728,6 +734,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
if business_connection_id is not None:
data["business_connection_id"] = business_connection_id
if message_effect_id is not None:
data["message_effect_id"] = message_effect_id
result = await self._post(
endpoint,
data,
@@ -837,7 +846,6 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
f"Please use 'Bot.{endpoint}' instead of "
f"'Bot.do_api_request(\"{endpoint}\", ...)'"
),
PTBDeprecationWarning,
stacklevel=2,
)
@@ -917,6 +925,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
link_preview_options: ODVInput["LinkPreviewOptions"] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -965,6 +974,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
business_connection_id (:obj:`str`, optional): |business_id_str|
.. versionadded:: 21.1
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -1022,6 +1034,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
parse_mode=parse_mode,
link_preview_options=link_preview_options,
reply_parameters=reply_parameters,
message_effect_id=message_effect_id,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
@@ -1150,7 +1163,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
Note:
Since the release of Bot API 5.5 it can be impossible to forward messages from
some chats. Use the attributes :attr:`telegram.Message.has_protected_content` and
:attr:`telegram.Chat.has_protected_content` to check this.
:attr:`telegram.ChatFullInfo.has_protected_content` to check this.
As a workaround, it is still possible to use :meth:`copy_message`. However, this
behaviour is undocumented and might be changed by Telegram.
@@ -1270,6 +1283,8 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
has_spoiler: Optional[bool] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
show_caption_above_media: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -1333,6 +1348,12 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
business_connection_id (:obj:`str`, optional): |business_id_str|
.. versionadded:: 21.1
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
.. versionadded:: 21.3
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -1370,6 +1391,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
"chat_id": chat_id,
"photo": self._parse_file_input(photo, PhotoSize, filename=filename),
"has_spoiler": has_spoiler,
"show_caption_above_media": show_caption_above_media,
}
return await self._send_message(
@@ -1391,6 +1413,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def send_audio(
@@ -1410,6 +1433,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -1482,6 +1506,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
business_connection_id (:obj:`str`, optional): |business_id_str|
.. versionadded:: 21.1
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -1543,6 +1570,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def send_document(
@@ -1560,6 +1588,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -1631,6 +1660,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
business_connection_id (:obj:`str`, optional): |business_id_str|
.. versionadded:: 21.1
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -1688,6 +1720,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def send_sticker(
@@ -1701,6 +1734,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
emoji: Optional[str] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -1752,6 +1786,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
business_connection_id (:obj:`str`, optional): |business_id_str|
.. versionadded:: 21.1
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -1801,6 +1838,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def send_video(
@@ -1822,6 +1860,8 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
show_caption_above_media: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -1902,6 +1942,12 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
business_connection_id (:obj:`str`, optional): |business_id_str|
.. versionadded:: 21.1
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
.. versionadded:: 21.3
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -1944,6 +1990,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
"supports_streaming": supports_streaming,
"thumbnail": self._parse_file_input(thumbnail, attach=True) if thumbnail else None,
"has_spoiler": has_spoiler,
"show_caption_above_media": show_caption_above_media,
}
return await self._send_message(
@@ -1965,6 +2012,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def send_video_note(
@@ -1980,6 +2028,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -2045,6 +2094,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
business_connection_id (:obj:`str`, optional): |business_id_str|
.. versionadded:: 21.1
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -2102,6 +2154,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def send_animation(
@@ -2122,6 +2175,8 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
show_caption_above_media: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -2196,6 +2251,12 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
business_connection_id (:obj:`str`, optional): |business_id_str|
.. versionadded:: 21.1
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
.. versionadded:: 21.3
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -2237,6 +2298,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
"height": height,
"thumbnail": self._parse_file_input(thumbnail, attach=True) if thumbnail else None,
"has_spoiler": has_spoiler,
"show_caption_above_media": show_caption_above_media,
}
return await self._send_message(
@@ -2258,6 +2320,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def send_voice(
@@ -2274,6 +2337,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -2287,9 +2351,10 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
"""
Use this method to send audio files, if you want Telegram clients to display the file
as a playable voice message. For this to work, your audio must be in an ``.ogg`` file
encoded with OPUS (other formats may be sent as Audio or Document). Bots can currently
send voice messages of up to :tg-const:`telegram.constants.FileSizeLimit.FILESIZE_UPLOAD`
in size, this limit may be changed in the future.
encoded with OPUS , or in .MP3 format, or in .M4A format (other formats may be sent as
:class:`~telegram.Audio` or :class:`~telegram.Document`). Bots can currently send voice
messages of up to :tg-const:`telegram.constants.FileSizeLimit.FILESIZE_UPLOAD` in size,
this limit may be changed in the future.
Note:
To use this method, the file must have the type :mimetype:`audio/ogg` and be no more
@@ -2341,6 +2406,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
business_connection_id (:obj:`str`, optional): |business_id_str|
.. versionadded:: 21.1
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -2399,6 +2467,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def send_media_group(
@@ -2412,6 +2481,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -2462,6 +2532,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
business_connection_id (:obj:`str`, optional): |business_id_str|
.. versionadded:: 21.1
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -2555,6 +2628,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
"message_thread_id": message_thread_id,
"reply_parameters": reply_parameters,
"business_connection_id": business_connection_id,
"message_effect_id": message_effect_id,
}
result = await self._post(
@@ -2584,6 +2658,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -2610,7 +2685,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
live_period (:obj:`int`, optional): Period in seconds for which the location will be
updated, should be between
:tg-const:`telegram.constants.LocationLimit.MIN_LIVE_PERIOD` and
:tg-const:`telegram.constants.LocationLimit.MAX_LIVE_PERIOD`.
:tg-const:`telegram.constants.LocationLimit.MAX_LIVE_PERIOD`, or
:tg-const:`telegram.constants.LocationLimit.LIVE_PERIOD_FOREVER` for live
locations that can be edited indefinitely.
heading (:obj:`int`, optional): For live locations, a direction in which the user is
moving, in degrees. Must be between
:tg-const:`telegram.constants.LocationLimit.MIN_HEADING` and
@@ -2638,6 +2715,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
business_connection_id (:obj:`str`, optional): |business_id_str|
.. versionadded:: 21.1
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -2707,6 +2787,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def edit_message_live_location(
@@ -2720,6 +2801,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
horizontal_accuracy: Optional[float] = None,
heading: Optional[int] = None,
proximity_alert_radius: Optional[int] = None,
live_period: Optional[int] = None,
*,
location: Optional[Location] = None,
read_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -2758,6 +2840,15 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
if specified.
reply_markup (:class:`telegram.InlineKeyboardMarkup`, optional): An object for a new
inline keyboard.
live_period (:obj:`int`, optional): New period in seconds during which the location
can be updated, starting from the message send date. If
:tg-const:`telegram.constants.LocationLimit.LIVE_PERIOD_FOREVER` is specified,
then the location can be updated forever. Otherwise, the new value must not exceed
the current ``live_period`` by more than a day, and the live location expiration
date must remain within the next 90 days. If not specified, then ``live_period``
remains unchanged
.. versionadded:: 21.2.
Keyword Args:
location (:class:`telegram.Location`, optional): The location to send.
@@ -2790,6 +2881,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
"horizontal_accuracy": horizontal_accuracy,
"heading": heading,
"proximity_alert_radius": proximity_alert_radius,
"live_period": live_period,
}
return await self._send_message(
@@ -2867,6 +2959,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -2919,6 +3012,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
business_connection_id (:obj:`str`, optional): |business_id_str|
.. versionadded:: 21.1
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -2999,6 +3095,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def send_contact(
@@ -3014,6 +3111,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -3056,6 +3154,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
business_connection_id (:obj:`str`, optional): |business_id_str|
.. versionadded:: 21.1
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -3127,6 +3228,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def send_game(
@@ -3139,6 +3241,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -3171,6 +3274,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
business_connection_id (:obj:`str`, optional): |business_id_str|
.. versionadded:: 21.1
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -3217,6 +3323,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def send_chat_action(
@@ -3938,6 +4045,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
reply_markup: Optional["InlineKeyboardMarkup"] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
show_caption_above_media: Optional[bool] = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -3969,6 +4077,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
|sequenceargs|
reply_markup (:class:`telegram.InlineKeyboardMarkup`, optional): An object for an
inline keyboard.
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
.. versionadded:: 21.3
Returns:
:class:`telegram.Message`: On success, if edited message is not an inline message, the
@@ -3982,6 +4093,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
"chat_id": chat_id,
"message_id": message_id,
"inline_message_id": inline_message_id,
"show_caption_above_media": show_caption_above_media,
}
return await self._send_message(
@@ -4195,10 +4307,12 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
except NotImplementedError:
arg_read_timeout = 2
self._warn(
f"The class {self._request[0].__class__.__name__} does not override "
"the property `read_timeout`. Overriding this property will be mandatory in "
"future versions. Using 2 seconds as fallback.",
PTBDeprecationWarning,
PTBDeprecationWarning(
"20.7",
f"The class {self._request[0].__class__.__name__} does not override "
"the property `read_timeout`. Overriding this property will be mandatory "
"in future versions. Using 2 seconds as fallback.",
),
stacklevel=2,
)
@@ -4434,16 +4548,19 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Chat:
) -> ChatFullInfo:
"""
Use this method to get up to date information about the chat (current name of the user for
one-on-one conversations, current username of a user, group or channel, etc.).
.. versionchanged:: 21.2
In accordance to Bot API 7.3, this method now returns a :class:`telegram.ChatFullInfo`.
Args:
chat_id (:obj:`int` | :obj:`str`): |chat_id_channel|
Returns:
:class:`telegram.Chat`
:class:`telegram.ChatFullInfo`
Raises:
:class:`telegram.error.TelegramError`
@@ -4461,7 +4578,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
api_kwargs=api_kwargs,
)
return Chat.de_json(result, self) # type: ignore[return-value]
return ChatFullInfo.de_json(result, self) # type: ignore[return-value]
async def get_chat_administrators(
self,
@@ -4589,8 +4706,8 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
) -> bool:
"""Use this method to set a new group sticker set for a supergroup.
The bot must be an administrator in the chat for this to work and must have the appropriate
admin rights. Use the field :attr:`telegram.Chat.can_set_sticker_set` optionally returned
in :meth:`get_chat` requests to check if the bot can use this method.
admin rights. Use the field :attr:`telegram.ChatFullInfo.can_set_sticker_set` optionally
returned in :meth:`get_chat` requests to check if the bot can use this method.
Args:
chat_id (:obj:`int` | :obj:`str`): |chat_id_group|
@@ -4623,7 +4740,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
) -> bool:
"""Use this method to delete a group sticker set from a supergroup. The bot must be an
administrator in the chat for this to work and must have the appropriate admin rights.
Use the field :attr:`telegram.Chat.can_set_sticker_set` optionally returned in
Use the field :attr:`telegram.ChatFullInfo.can_set_sticker_set` optionally returned in
:meth:`get_chat` requests to check if the bot can use this method.
Args:
@@ -4801,7 +4918,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
title: str,
description: str,
payload: str,
provider_token: str,
provider_token: Optional[str], # This arg is now optional as of Bot API 7.4
currency: str,
prices: Sequence["LabeledPrice"],
start_parameter: Optional[str] = None,
@@ -4824,6 +4941,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -4855,12 +4973,19 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
:tg-const:`telegram.Invoice.MAX_PAYLOAD_LENGTH` bytes. This will not be
displayed to the user, use for your internal processes.
provider_token (:obj:`str`): Payments provider token, obtained via
`@BotFather <https://t.me/BotFather>`_.
`@BotFather <https://t.me/BotFather>`_. Pass an empty string for payments in
|tg_stars|.
.. deprecated:: 21.3
As of Bot API 7.4, this parameter is now optional and future versions of the
library will make it optional as well.
currency (:obj:`str`): Three-letter ISO 4217 currency code, see `more on currencies
<https://core.telegram.org/bots/payments#supported-currencies>`_.
<https://core.telegram.org/bots/payments#supported-currencies>`_. Pass ``XTR`` for
payment in |tg_stars|.
prices (Sequence[:class:`telegram.LabeledPrice`]): Price breakdown, a sequence
of components (e.g. product price, tax, discount, delivery cost, delivery tax,
bonus, etc.).
bonus, etc.). Must contain exactly one item for payment in |tg_stars|.
.. versionchanged:: 20.0
|sequenceargs|
@@ -4869,7 +4994,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
a maximum tip of US$ 1.45 pass ``max_tip_amount = 145``. See the exp parameter in
`currencies.json <https://core.telegram.org/bots/payments/currencies.json>`_, it
shows the number of digits past the decimal point for each currency (2 for the
majority of currencies). Defaults to ``0``.
majority of currencies). Defaults to ``0``. Not supported for payment in |tg_stars|
.. versionadded:: 13.5
suggested_tip_amounts (Sequence[:obj:`int`], optional): An array of
@@ -4902,19 +5027,20 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
photo_width (:obj:`int`, optional): Photo width.
photo_height (:obj:`int`, optional): Photo height.
need_name (:obj:`bool`, optional): Pass :obj:`True`, if you require the user's full
name to complete the order.
name to complete the order. Ignored for payments in |tg_stars|.
need_phone_number (:obj:`bool`, optional): Pass :obj:`True`, if you require the user's
phone number to complete the order.
phone number to complete the order. Ignored for payments in |tg_stars|.
need_email (:obj:`bool`, optional): Pass :obj:`True`, if you require the user's email
to complete the order.
to complete the order. Ignored for payments in |tg_stars|.
need_shipping_address (:obj:`bool`, optional): Pass :obj:`True`, if you require the
user's shipping address to complete the order.
user's shipping address to complete the order. Ignored for payments in
|tg_stars|.
send_phone_number_to_provider (:obj:`bool`, optional): Pass :obj:`True`, if user's
phone number should be sent to provider.
phone number should be sent to provider. Ignored for payments in |tg_stars|.
send_email_to_provider (:obj:`bool`, optional): Pass :obj:`True`, if user's email
address should be sent to provider.
address should be sent to provider. Ignored for payments in |tg_stars|.
is_flexible (:obj:`bool`, optional): Pass :obj:`True`, if the final price depends on
the shipping method.
the shipping method. Ignored for payments in |tg_stars|.
disable_notification (:obj:`bool`, optional): |disable_notification|
protect_content (:obj:`bool`, optional): |protect_content|
@@ -4929,6 +5055,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
reply_parameters (:class:`telegram.ReplyParameters`, optional): |reply_parameters|
.. versionadded:: 20.8
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -4997,6 +5126,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
message_effect_id=message_effect_id,
)
async def answer_shipping_query(
@@ -5311,7 +5441,8 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
.. versionadded:: 20.6
can_edit_stories (:obj:`bool`, optional): Pass :obj:`True`, if the administrator can
edit stories posted by other users.
edit stories posted by other users, post stories to the chat page, pin chat
stories, and access the chat's story archive
.. versionadded:: 20.6
can_delete_stories (:obj:`bool`, optional): Pass :obj:`True`, if the administrator can
@@ -6312,7 +6443,6 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
name: str,
title: str,
stickers: Sequence["InputSticker"],
sticker_format: Optional[str] = None,
sticker_type: Optional[str] = None,
needs_repainting: Optional[bool] = None,
*,
@@ -6339,6 +6469,9 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
Removed the deprecated parameters mentioned above and adjusted the order of the
parameters.
.. versionremoved:: 21.2
Removed the deprecated parameter ``sticker_format``.
Args:
user_id (:obj:`int`): User identifier of created sticker set owner.
name (:obj:`str`): Short name of sticker set, to be used in t.me/addstickers/ URLs
@@ -6358,16 +6491,6 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
.. versionadded:: 20.2
sticker_format (:obj:`str`): Format of stickers in the set, must be one of
:attr:`~telegram.constants.StickerFormat.STATIC`,
:attr:`~telegram.constants.StickerFormat.ANIMATED` or
:attr:`~telegram.constants.StickerFormat.VIDEO`.
.. versionadded:: 20.2
.. deprecated:: 21.1
Use :paramref:`telegram.InputSticker.format` instead.
sticker_type (:obj:`str`, optional): Type of stickers in the set, pass
:attr:`telegram.Sticker.REGULAR` or :attr:`telegram.Sticker.MASK`, or
:attr:`telegram.Sticker.CUSTOM_EMOJI`. By default, a regular sticker set is created
@@ -6387,20 +6510,11 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
Raises:
:class:`telegram.error.TelegramError`
"""
if sticker_format is not None:
warn(
"The parameter `sticker_format` is deprecated. Use the parameter"
" `InputSticker.format` in the parameter `stickers` instead.",
stacklevel=2,
category=PTBDeprecationWarning,
)
data: JSONDict = {
"user_id": user_id,
"name": name,
"title": title,
"stickers": stickers,
"sticker_format": sticker_format,
"sticker_type": sticker_type,
"needs_repainting": needs_repainting,
}
@@ -6815,7 +6929,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
self,
chat_id: Union[int, str],
question: str,
options: Sequence[str],
options: Sequence[Union[str, "InputPollOption"]],
is_anonymous: Optional[bool] = None,
type: Optional[str] = None, # pylint: disable=redefined-builtin
allows_multiple_answers: Optional[bool] = None,
@@ -6832,6 +6946,9 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
question_parse_mode: ODVInput[str] = DEFAULT_NONE,
question_entities: Optional[Sequence["MessageEntity"]] = None,
message_effect_id: Optional[str] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -6848,14 +6965,20 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
chat_id (:obj:`int` | :obj:`str`): |chat_id_channel|
question (:obj:`str`): Poll question, :tg-const:`telegram.Poll.MIN_QUESTION_LENGTH`-
:tg-const:`telegram.Poll.MAX_QUESTION_LENGTH` characters.
options (Sequence[:obj:`str`]): Sequence of answer options,
options (Sequence[:obj:`str` | :class:`telegram.InputPollOption`]): Sequence of
:tg-const:`telegram.Poll.MIN_OPTION_NUMBER`-
:tg-const:`telegram.Poll.MAX_OPTION_NUMBER` strings
:tg-const:`telegram.Poll.MAX_OPTION_NUMBER` answer options. Each option may either
be a string with
:tg-const:`telegram.Poll.MIN_OPTION_LENGTH`-
:tg-const:`telegram.Poll.MAX_OPTION_LENGTH` characters each.
:tg-const:`telegram.Poll.MAX_OPTION_LENGTH` characters or an
:class:`~telegram.InputPollOption` object. Strings are converted to
:class:`~telegram.InputPollOption` objects automatically.
.. versionchanged:: 20.0
|sequenceargs|
.. versionchanged:: 21.2
Bot API 7.3 adds support for :class:`~telegram.InputPollOption` objects.
is_anonymous (:obj:`bool`, optional): :obj:`True`, if the poll needs to be anonymous,
defaults to :obj:`True`.
type (:obj:`str`, optional): Poll type, :tg-const:`telegram.Poll.QUIZ` or
@@ -6910,6 +7033,19 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
business_connection_id (:obj:`str`, optional): |business_id_str|
.. versionadded:: 21.1
question_parse_mode (:obj:`str`, optional): Mode for parsing entities in the question.
See the constants in :class:`telegram.constants.ParseMode` for the available modes.
Currently, only custom emoji entities are allowed.
.. versionadded:: 21.2
question_entities (Sequence[:class:`telegram.Message`], optional): Special entities
that appear in the poll :paramref:`question`. It can be specified instead of
:paramref:`question_parse_mode`.
.. versionadded:: 21.2
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -6941,7 +7077,10 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
data: JSONDict = {
"chat_id": chat_id,
"question": question,
"options": options,
"options": [
InputPollOption(option) if isinstance(option, str) else option
for option in options
],
"explanation_parse_mode": explanation_parse_mode,
"is_anonymous": is_anonymous,
"type": type,
@@ -6952,6 +7091,8 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
"explanation_entities": explanation_entities,
"open_period": open_period,
"close_date": close_date,
"question_parse_mode": question_parse_mode,
"question_entities": question_entities,
}
return await self._send_message(
@@ -6970,6 +7111,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def stop_poll(
@@ -7027,6 +7169,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -7073,6 +7216,9 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
business_connection_id (:obj:`str`, optional): |business_id_str|
.. versionadded:: 21.1
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -7120,6 +7266,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def get_my_default_administrator_rights(
@@ -7389,7 +7536,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
minutes.
Returns:
:obj:`True`: On success
:obj:`True`: On success, :obj:`True` is returned.
Raises:
:class:`telegram.error.TelegramError`
@@ -7420,7 +7567,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
10 minutes after the bot is launched.
Returns:
:obj:`True`: On success
:obj:`True`: On success, :obj:`True` is returned.
Raises:
:class:`telegram.error.TelegramError`
@@ -7448,6 +7595,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
show_caption_above_media: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -7491,6 +7639,9 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
reply_parameters (:class:`telegram.ReplyParameters`, optional): |reply_parameters|
.. versionadded:: 20.8
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
.. versionadded:: 21.3
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -7513,7 +7664,8 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|keyword_only_arg|
Returns:
:class:`telegram.MessageId`: On success
:class:`telegram.MessageId`: On success, the :class:`telegram.MessageId` of the sent
message is returned.
Raises:
:class:`telegram.error.TelegramError`
@@ -7547,6 +7699,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
"reply_markup": reply_markup,
"message_thread_id": message_thread_id,
"reply_parameters": reply_parameters,
"show_caption_above_media": show_caption_above_media,
}
result = await self._post(
@@ -7715,7 +7868,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
title: str,
description: str,
payload: str,
provider_token: str,
provider_token: Optional[str], # This arg is now optional as of Bot API 7.4
currency: str,
prices: Sequence["LabeledPrice"],
max_tip_amount: Optional[int] = None,
@@ -7754,12 +7907,19 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
:tg-const:`telegram.Invoice.MAX_PAYLOAD_LENGTH` bytes. This will not be
displayed to the user, use for your internal processes.
provider_token (:obj:`str`): Payments provider token, obtained via
`@BotFather <https://t.me/BotFather>`_.
`@BotFather <https://t.me/BotFather>`_. Pass an empty string for payments in
|tg_stars|.
.. deprecated:: 21.3
As of Bot API 7.4, this parameter is now optional and future versions of the
library will make it optional as well.
currency (:obj:`str`): Three-letter ISO 4217 currency code, see `more on currencies
<https://core.telegram.org/bots/payments#supported-currencies>`_.
<https://core.telegram.org/bots/payments#supported-currencies>`_. Pass ``XTR`` for
payments in |tg_stars|.
prices (Sequence[:class:`telegram.LabeledPrice`)]: Price breakdown, a sequence
of components (e.g. product price, tax, discount, delivery cost, delivery tax,
bonus, etc.).
bonus, etc.). Must contain exactly one item for payments in |tg_stars|.
.. versionchanged:: 20.0
|sequenceargs|
@@ -7768,7 +7928,8 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
a maximum tip of US$ 1.45 pass ``max_tip_amount = 145``. See the exp parameter in
`currencies.json <https://core.telegram.org/bots/payments/currencies.json>`_, it
shows the number of digits past the decimal point for each currency (2 for the
majority of currencies). Defaults to ``0``.
majority of currencies). Defaults to ``0``. Not supported for payments in
|tg_stars|.
suggested_tip_amounts (Sequence[:obj:`int`], optional): An array of
suggested amounts of tips in the *smallest* units of the currency (integer, **not**
float/double). At most :tg-const:`telegram.Invoice.MAX_TIP_AMOUNTS` suggested tip
@@ -7787,19 +7948,20 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
photo_width (:obj:`int`, optional): Photo width.
photo_height (:obj:`int`, optional): Photo height.
need_name (:obj:`bool`, optional): Pass :obj:`True`, if you require the user's full
name to complete the order.
name to complete the order. Ignored for payments in |tg_stars|.
need_phone_number (:obj:`bool`, optional): Pass :obj:`True`, if you require the user's
phone number to complete the order.
phone number to complete the order. Ignored for payments in |tg_stars|.
need_email (:obj:`bool`, optional): Pass :obj:`True`, if you require the user's email
address to complete the order.
address to complete the order. Ignored for payments in |tg_stars|.
need_shipping_address (:obj:`bool`, optional): Pass :obj:`True`, if you require the
user's shipping address to complete the order.
user's shipping address to complete the order. Ignored for payments in
|tg_stars|.
send_phone_number_to_provider (:obj:`bool`, optional): Pass :obj:`True`, if user's
phone number should be sent to provider.
phone number should be sent to provider. Ignored for payments in |tg_stars|.
send_email_to_provider (:obj:`bool`, optional): Pass :obj:`True`, if user's email
address should be sent to provider.
address should be sent to provider. Ignored for payments in |tg_stars|.
is_flexible (:obj:`bool`, optional): Pass :obj:`True`, if the final price depends on
the shipping method.
the shipping method. Ignored for payments in |tg_stars|.
Returns:
:class:`str`: On success, the created invoice link is returned.
@@ -8867,7 +9029,48 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
api_kwargs=api_kwargs,
)
def to_dict(self, recursive: bool = True) -> JSONDict:
async def refund_star_payment(
self,
user_id: int,
telegram_payment_charge_id: str,
*,
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: Optional[JSONDict] = None,
) -> bool:
"""Refunds a successful payment in |tg_stars|.
.. versionadded:: 21.3
Args:
user_id (:obj:`int`): User identifier of the user whose payment will be refunded.
telegram_payment_charge_id (:obj:`str`): Telegram payment identifier.
Returns:
:obj:`bool`: On success, :obj:`True` is returned.
Raises:
:class:`telegram.error.TelegramError`
"""
data: JSONDict = {
"user_id": user_id,
"telegram_payment_charge_id": telegram_payment_charge_id,
}
return await self._post(
"refundStarPayment",
data,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)
def to_dict(self, recursive: bool = True) -> JSONDict: # noqa: ARG002
"""See :meth:`telegram.TelegramObject.to_dict`."""
data: JSONDict = {"id": self.id, "username": self.username, "first_name": self.first_name}
@@ -9117,3 +9320,5 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
"""Alias for :meth:`get_business_connection`"""
replaceStickerInSet = replace_sticker_in_set
"""Alias for :meth:`replace_sticker_in_set`"""
refundStarPayment = refund_star_payment
"""Alias for :meth:`refund_star_payment`"""
+4 -4
View File
@@ -189,7 +189,7 @@ class BusinessMessagesDeleted(TelegramObject):
class BusinessIntro(TelegramObject):
"""
This object represents the intro of a business account.
This object contains information about the start page settings of a Telegram Business account.
Objects of this class are comparable in terms of equality.
Two objects of this class are considered equal, if their
@@ -246,7 +246,7 @@ class BusinessIntro(TelegramObject):
class BusinessLocation(TelegramObject):
"""
This object represents the location of a business account.
This object contains information about the location of a Telegram Business account.
Objects of this class are comparable in terms of equality.
Two objects of this class are considered equal, if their
@@ -298,7 +298,7 @@ class BusinessLocation(TelegramObject):
class BusinessOpeningHoursInterval(TelegramObject):
"""
This object represents the time intervals describing business opening hours.
This object describes an interval of time during which a business is open.
Objects of this class are comparable in terms of equality.
Two objects of this class are considered equal, if their
@@ -390,7 +390,7 @@ class BusinessOpeningHoursInterval(TelegramObject):
class BusinessOpeningHours(TelegramObject):
"""
This object represents the opening hours of a business account.
This object describes the opening hours of a business.
Objects of this class are comparable in terms of equality.
Two objects of this class are considered equal, if their
+8
View File
@@ -281,6 +281,7 @@ class CallbackQuery(TelegramObject):
reply_markup: Optional["InlineKeyboardMarkup"] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
show_caption_above_media: Optional[bool] = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -326,6 +327,7 @@ class CallbackQuery(TelegramObject):
caption_entities=caption_entities,
chat_id=None,
message_id=None,
show_caption_above_media=show_caption_above_media,
)
return await self._get_message().edit_caption(
caption=caption,
@@ -337,6 +339,7 @@ class CallbackQuery(TelegramObject):
parse_mode=parse_mode,
api_kwargs=api_kwargs,
caption_entities=caption_entities,
show_caption_above_media=show_caption_above_media,
)
async def edit_message_reply_markup(
@@ -461,6 +464,7 @@ class CallbackQuery(TelegramObject):
horizontal_accuracy: Optional[float] = None,
heading: Optional[int] = None,
proximity_alert_radius: Optional[int] = None,
live_period: Optional[int] = None,
*,
location: Optional[Location] = None,
read_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -509,6 +513,7 @@ class CallbackQuery(TelegramObject):
horizontal_accuracy=horizontal_accuracy,
heading=heading,
proximity_alert_radius=proximity_alert_radius,
live_period=live_period,
chat_id=None,
message_id=None,
)
@@ -525,6 +530,7 @@ class CallbackQuery(TelegramObject):
horizontal_accuracy=horizontal_accuracy,
heading=heading,
proximity_alert_radius=proximity_alert_radius,
live_period=live_period,
)
async def stop_message_live_location(
@@ -812,6 +818,7 @@ class CallbackQuery(TelegramObject):
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
show_caption_above_media: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -858,6 +865,7 @@ class CallbackQuery(TelegramObject):
protect_content=protect_content,
message_thread_id=message_thread_id,
reply_parameters=reply_parameters,
show_caption_above_media=show_caption_above_media,
)
MAX_ANSWER_TEXT_LENGTH: Final[int] = (
+161 -573
View File
File diff suppressed because it is too large Load Diff
+6 -4
View File
@@ -80,8 +80,9 @@ class ChatAdministratorRights(TelegramObject):
.. versionadded:: 20.6
.. versionchanged:: 21.0
|non_optional_story_argument|
can_edit_stories (:obj:`bool`): :obj:`True`, if the administrator can edit
stories posted by other users.
can_edit_stories (:obj:`bool`): :obj:`True`, if the administrator can edit stories posted
by other users, post stories to the chat page, pin chat stories, and access the chat's
story archive
.. versionadded:: 20.6
.. versionchanged:: 21.0
@@ -128,8 +129,9 @@ class ChatAdministratorRights(TelegramObject):
.. versionadded:: 20.6
.. versionchanged:: 21.0
|non_optional_story_argument|
can_edit_stories (:obj:`bool`): :obj:`True`, if the administrator can edit
stories posted by other users.
can_edit_stories (:obj:`bool`): :obj:`True`, if the administrator can edit stories posted
by other users, post stories to the chat page, pin chat stories, and access the chat's
story archive
.. versionadded:: 20.6
.. versionchanged:: 21.0
+540
View File
@@ -0,0 +1,540 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2024
# 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 related to chat backgrounds."""
from typing import TYPE_CHECKING, Dict, Final, Optional, Sequence, Tuple, Type
from telegram import constants
from telegram._files.document import Document
from telegram._telegramobject import TelegramObject
from telegram._utils import enum
from telegram._utils.argumentparsing import parse_sequence_arg
from telegram._utils.types import JSONDict
if TYPE_CHECKING:
from telegram import Bot
class BackgroundFill(TelegramObject):
"""Base class for Telegram BackgroundFill Objects. It can be one of:
* :class:`telegram.BackgroundFillSolid`
* :class:`telegram.BackgroundFillGradient`
* :class:`telegram.BackgroundFillFreeformGradient`
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`type` is equal.
.. versionadded:: 21.2
Args:
type (:obj:`str`): Type of the background fill. Can be one of:
:attr:`~telegram.BackgroundFill.SOLID`, :attr:`~telegram.BackgroundFill.GRADIENT`
or :attr:`~telegram.BackgroundFill.FREEFORM_GRADIENT`.
Attributes:
type (:obj:`str`): Type of the background fill. Can be one of:
:attr:`~telegram.BackgroundFill.SOLID`, :attr:`~telegram.BackgroundFill.GRADIENT`
or :attr:`~telegram.BackgroundFill.FREEFORM_GRADIENT`.
"""
__slots__ = ("type",)
SOLID: Final[constants.BackgroundFillType] = constants.BackgroundFillType.SOLID
""":const:`telegram.constants.BackgroundFillType.SOLID`"""
GRADIENT: Final[constants.BackgroundFillType] = constants.BackgroundFillType.GRADIENT
""":const:`telegram.constants.BackgroundFillType.GRADIENT`"""
FREEFORM_GRADIENT: Final[constants.BackgroundFillType] = (
constants.BackgroundFillType.FREEFORM_GRADIENT
)
""":const:`telegram.constants.BackgroundFillType.FREEFORM_GRADIENT`"""
def __init__(
self,
type: str, # pylint: disable=redefined-builtin
*,
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(api_kwargs=api_kwargs)
# Required by all subclasses
self.type: str = enum.get_member(constants.BackgroundFillType, type, type)
self._id_attrs = (self.type,)
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["BackgroundFill"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if not data:
return None
_class_mapping: Dict[str, Type[BackgroundFill]] = {
cls.SOLID: BackgroundFillSolid,
cls.GRADIENT: BackgroundFillGradient,
cls.FREEFORM_GRADIENT: BackgroundFillFreeformGradient,
}
if cls is BackgroundFill and data.get("type") in _class_mapping:
return _class_mapping[data.pop("type")].de_json(data=data, bot=bot)
return super().de_json(data=data, bot=bot)
class BackgroundFillSolid(BackgroundFill):
"""
The background is filled using the selected color.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`color` is equal.
.. versionadded:: 21.2
Args:
color (:obj:`int`): The color of the background fill in the `RGB24` format.
Attributes:
type (:obj:`str`): Type of the background fill. Always
:attr:`~telegram.BackgroundFill.SOLID`.
color (:obj:`int`): The color of the background fill in the `RGB24` format.
"""
__slots__ = ("color",)
def __init__(
self,
color: int,
*,
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(type=self.SOLID, api_kwargs=api_kwargs)
with self._unfrozen():
self.color: int = color
self._id_attrs = (self.color,)
class BackgroundFillGradient(BackgroundFill):
"""
The background is a gradient fill.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`top_color`, :attr:`bottom_color`
and :attr:`rotation_angle` are equal.
.. versionadded:: 21.2
Args:
top_color (:obj:`int`): Top color of the gradient in the `RGB24` format.
bottom_color (:obj:`int`): Bottom color of the gradient in the `RGB24` format.
rotation_angle (:obj:`int`): Clockwise rotation angle of the background
fill in degrees;
0-:tg-const:`telegram.constants.BackgroundFillLimit.MAX_ROTATION_ANGLE`.
Attributes:
type (:obj:`str`): Type of the background fill. Always
:attr:`~telegram.BackgroundFill.GRADIENT`.
top_color (:obj:`int`): Top color of the gradient in the `RGB24` format.
bottom_color (:obj:`int`): Bottom color of the gradient in the `RGB24` format.
rotation_angle (:obj:`int`): Clockwise rotation angle of the background
fill in degrees;
0-:tg-const:`telegram.constants.BackgroundFillLimit.MAX_ROTATION_ANGLE`.
"""
__slots__ = ("bottom_color", "rotation_angle", "top_color")
def __init__(
self,
top_color: int,
bottom_color: int,
rotation_angle: int,
*,
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(type=self.GRADIENT, api_kwargs=api_kwargs)
with self._unfrozen():
self.top_color: int = top_color
self.bottom_color: int = bottom_color
self.rotation_angle: int = rotation_angle
self._id_attrs = (self.top_color, self.bottom_color, self.rotation_angle)
class BackgroundFillFreeformGradient(BackgroundFill):
"""
The background is a freeform gradient that rotates after every message in the chat.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`colors` is equal.
.. versionadded:: 21.2
Args:
colors (Sequence[:obj:`int`]): A list of the 3 or 4 base colors that are used to
generate the freeform gradient in the `RGB24` format
Attributes:
type (:obj:`str`): Type of the background fill. Always
:attr:`~telegram.BackgroundFill.FREEFORM_GRADIENT`.
colors (Sequence[:obj:`int`]): A list of the 3 or 4 base colors that are used to
generate the freeform gradient in the `RGB24` format
"""
__slots__ = ("colors",)
def __init__(
self,
colors: Sequence[int],
*,
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(type=self.FREEFORM_GRADIENT, api_kwargs=api_kwargs)
with self._unfrozen():
self.colors: Tuple[int, ...] = parse_sequence_arg(colors)
self._id_attrs = (self.colors,)
class BackgroundType(TelegramObject):
"""Base class for Telegram BackgroundType Objects. It can be one of:
* :class:`telegram.BackgroundTypeFill`
* :class:`telegram.BackgroundTypeWallpaper`
* :class:`telegram.BackgroundTypePattern`
* :class:`telegram.BackgroundTypeChatTheme`.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`type` is equal.
.. versionadded:: 21.2
Args:
type (:obj:`str`): Type of the background. Can be one of:
:attr:`~telegram.BackgroundType.FILL`, :attr:`~telegram.BackgroundType.WALLPAPER`
:attr:`~telegram.BackgroundType.PATTERN` or
:attr:`~telegram.BackgroundType.CHAT_THEME`.
Attributes:
type (:obj:`str`): Type of the background. Can be one of:
:attr:`~telegram.BackgroundType.FILL`, :attr:`~telegram.BackgroundType.WALLPAPER`
:attr:`~telegram.BackgroundType.PATTERN` or
:attr:`~telegram.BackgroundType.CHAT_THEME`.
"""
__slots__ = ("type",)
FILL: Final[constants.BackgroundTypeType] = constants.BackgroundTypeType.FILL
""":const:`telegram.constants.BackgroundTypeType.FILL`"""
WALLPAPER: Final[constants.BackgroundTypeType] = constants.BackgroundTypeType.WALLPAPER
""":const:`telegram.constants.BackgroundTypeType.WALLPAPER`"""
PATTERN: Final[constants.BackgroundTypeType] = constants.BackgroundTypeType.PATTERN
""":const:`telegram.constants.BackgroundTypeType.PATTERN`"""
CHAT_THEME: Final[constants.BackgroundTypeType] = constants.BackgroundTypeType.CHAT_THEME
""":const:`telegram.constants.BackgroundTypeType.CHAT_THEME`"""
def __init__(
self,
type: str, # pylint: disable=redefined-builtin
*,
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(api_kwargs=api_kwargs)
# Required by all subclasses
self.type: str = enum.get_member(constants.BackgroundTypeType, type, type)
self._id_attrs = (self.type,)
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["BackgroundType"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if not data:
return None
_class_mapping: Dict[str, Type[BackgroundType]] = {
cls.FILL: BackgroundTypeFill,
cls.WALLPAPER: BackgroundTypeWallpaper,
cls.PATTERN: BackgroundTypePattern,
cls.CHAT_THEME: BackgroundTypeChatTheme,
}
if cls is BackgroundType and data.get("type") in _class_mapping:
return _class_mapping[data.pop("type")].de_json(data=data, bot=bot)
if "fill" in data:
data["fill"] = BackgroundFill.de_json(data.get("fill"), bot)
if "document" in data:
data["document"] = Document.de_json(data.get("document"), bot)
return super().de_json(data=data, bot=bot)
class BackgroundTypeFill(BackgroundType):
"""
The background is automatically filled based on the selected colors.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`fill` and :attr:`dark_theme_dimming` are equal.
.. versionadded:: 21.2
Args:
fill (:obj:`telegram.BackgroundFill`): The background fill.
dark_theme_dimming (:obj:`int`): Dimming of the background in dark themes, as a
percentage;
0-:tg-const:`telegram.constants.BackgroundTypeLimit.MAX_DIMMING`.
Attributes:
type (:obj:`str`): Type of the background. Always
:attr:`~telegram.BackgroundType.FILL`.
fill (:obj:`telegram.BackgroundFill`): The background fill.
dark_theme_dimming (:obj:`int`): Dimming of the background in dark themes, as a
percentage;
0-:tg-const:`telegram.constants.BackgroundTypeLimit.MAX_DIMMING`.
"""
__slots__ = ("dark_theme_dimming", "fill")
def __init__(
self,
fill: BackgroundFill,
dark_theme_dimming: int,
*,
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(type=self.FILL, api_kwargs=api_kwargs)
with self._unfrozen():
self.fill: BackgroundFill = fill
self.dark_theme_dimming: int = dark_theme_dimming
self._id_attrs = (self.fill, self.dark_theme_dimming)
class BackgroundTypeWallpaper(BackgroundType):
"""
The background is a wallpaper in the `JPEG` format.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`document` and :attr:`dark_theme_dimming` are equal.
.. versionadded:: 21.2
Args:
document (:obj:`telegram.Document`): Document with the wallpaper
dark_theme_dimming (:obj:`int`): Dimming of the background in dark themes, as a
percentage;
0-:tg-const:`telegram.constants.BackgroundTypeLimit.MAX_DIMMING`.
is_blurred (:obj:`bool`, optional): :obj:`True`, if the wallpaper is downscaled to fit
in a 450x450 square and then box-blurred with radius 12
is_moving (:obj:`bool`, optional): :obj:`True`, if the background moves slightly
when the device is tilted
Attributes:
type (:obj:`str`): Type of the background. Always
:attr:`~telegram.BackgroundType.WALLPAPER`.
document (:obj:`telegram.Document`): Document with the wallpaper
dark_theme_dimming (:obj:`int`): Dimming of the background in dark themes, as a
percentage;
0-:tg-const:`telegram.constants.BackgroundTypeLimit.MAX_DIMMING`.
is_blurred (:obj:`bool`): Optional. :obj:`True`, if the wallpaper is downscaled to fit
in a 450x450 square and then box-blurred with radius 12
is_moving (:obj:`bool`): Optional. :obj:`True`, if the background moves slightly
when the device is tilted
"""
__slots__ = ("dark_theme_dimming", "document", "is_blurred", "is_moving")
def __init__(
self,
document: Document,
dark_theme_dimming: int,
is_blurred: Optional[bool] = None,
is_moving: Optional[bool] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(type=self.WALLPAPER, api_kwargs=api_kwargs)
with self._unfrozen():
# Required
self.document: Document = document
self.dark_theme_dimming: int = dark_theme_dimming
# Optionals
self.is_blurred: Optional[bool] = is_blurred
self.is_moving: Optional[bool] = is_moving
self._id_attrs = (self.document, self.dark_theme_dimming)
class BackgroundTypePattern(BackgroundType):
"""
The background is a `PNG` or `TGV` (gzipped subset of `SVG` with `MIME` type
`"application/x-tgwallpattern"`) pattern to be combined with the background fill
chosen by the user.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`document` and :attr:`fill` and :attr:`intensity` are equal.
.. versionadded:: 21.2
Args:
document (:obj:`telegram.Document`): Document with the pattern.
fill (:obj:`telegram.BackgroundFill`): The background fill that is combined with
the pattern.
intensity (:obj:`int`): Intensity of the pattern when it is shown above the filled
background;
0-:tg-const:`telegram.constants.BackgroundTypeLimit.MAX_INTENSITY`.
is_inverted (:obj:`int`, optional): :obj:`True`, if the background fill must be applied
only to the pattern itself. All other pixels are black in this case. For dark
themes only.
is_moving (:obj:`bool`, optional): :obj:`True`, if the background moves slightly
when the device is tilted.
Attributes:
type (:obj:`str`): Type of the background. Always
:attr:`~telegram.BackgroundType.PATTERN`.
document (:obj:`telegram.Document`): Document with the pattern.
fill (:obj:`telegram.BackgroundFill`): The background fill that is combined with
the pattern.
intensity (:obj:`int`): Intensity of the pattern when it is shown above the filled
background;
0-:tg-const:`telegram.constants.BackgroundTypeLimit.MAX_INTENSITY`.
is_inverted (:obj:`int`): Optional. :obj:`True`, if the background fill must be applied
only to the pattern itself. All other pixels are black in this case. For dark
themes only.
is_moving (:obj:`bool`): Optional. :obj:`True`, if the background moves slightly
when the device is tilted.
"""
__slots__ = (
"document",
"fill",
"intensity",
"is_inverted",
"is_moving",
)
def __init__(
self,
document: Document,
fill: BackgroundFill,
intensity: int,
is_inverted: Optional[bool] = None,
is_moving: Optional[bool] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(type=self.PATTERN, api_kwargs=api_kwargs)
with self._unfrozen():
# Required
self.document: Document = document
self.fill: BackgroundFill = fill
self.intensity: int = intensity
# Optionals
self.is_inverted: Optional[bool] = is_inverted
self.is_moving: Optional[bool] = is_moving
self._id_attrs = (self.document, self.fill, self.intensity)
class BackgroundTypeChatTheme(BackgroundType):
"""
The background is taken directly from a built-in chat theme.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`theme_name` is equal.
.. versionadded:: 21.2
Args:
theme_name (:obj:`str`): Name of the chat theme, which is usually an emoji.
Attributes:
type (:obj:`str`): Type of the background. Always
:attr:`~telegram.BackgroundType.CHAT_THEME`.
theme_name (:obj:`str`): Name of the chat theme, which is usually an emoji.
"""
__slots__ = ("theme_name",)
def __init__(
self,
theme_name: str,
*,
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(type=self.CHAT_THEME, api_kwargs=api_kwargs)
with self._unfrozen():
self.theme_name: str = theme_name
self._id_attrs = (self.theme_name,)
class ChatBackground(TelegramObject):
"""
This object represents a chat background.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`type` is equal.
.. versionadded:: 21.2
Args:
type (:obj:`telegram.BackgroundType`): Type of the background.
Attributes:
type (:obj:`telegram.BackgroundType`): Type of the background.
"""
__slots__ = ("type",)
def __init__(
self,
type: BackgroundType, # pylint: disable=redefined-builtin
*,
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(api_kwargs=api_kwargs)
self.type: BackgroundType = type
self._id_attrs = (self.type,)
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["ChatBackground"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if not data:
return None
data["type"] = BackgroundType.de_json(data.get("type"), bot)
return super().de_json(data=data, bot=bot)
+534
View File
@@ -0,0 +1,534 @@
#!/usr/bin/env python
# pylint: disable=redefined-builtin
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2024
# 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 ChatFullInfo."""
from datetime import datetime
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from telegram._birthdate import Birthdate
from telegram._chat import Chat, _ChatBase
from telegram._chatlocation import ChatLocation
from telegram._chatpermissions import ChatPermissions
from telegram._files.chatphoto import ChatPhoto
from telegram._reaction import ReactionType
from telegram._utils.argumentparsing import parse_sequence_arg
from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp
from telegram._utils.types import JSONDict
if TYPE_CHECKING:
from telegram import Bot, BusinessIntro, BusinessLocation, BusinessOpeningHours, Message
class ChatFullInfo(_ChatBase):
"""
This object contains full information about a chat.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`~telegram.Chat.id` is equal.
.. versionadded:: 21.2
.. versionchanged:: 21.3
Explicit support for all shortcut methods known from :class:`telegram.Chat` on this
object. Previously those were only available because this class inherited from
:class:`telegram.Chat`.
Args:
id (:obj:`int`): Unique identifier for this chat.
type (:obj:`str`): Type of chat, can be either :attr:`PRIVATE`, :attr:`GROUP`,
:attr:`SUPERGROUP` or :attr:`CHANNEL`.
accent_color_id (:obj:`int`, optional): Identifier of the
:class:`accent color <telegram.constants.AccentColor>` for the chat name and
backgrounds of the chat photo, reply header, and link preview. See `accent colors`_
for more details.
.. versionadded:: 20.8
max_reaction_count (:obj:`int`): The maximum number of reactions that can be set on a
message in the chat.
.. versionadded:: 21.2
title (:obj:`str`, optional): Title, for supergroups, channels and group chats.
username (:obj:`str`, optional): Username, for private chats, supergroups and channels if
available.
first_name (:obj:`str`, optional): First name of the other party in a private chat.
last_name (:obj:`str`, optional): Last name of the other party in a private chat.
is_forum (:obj:`bool`, optional): :obj:`True`, if the supergroup chat is a forum
(has topics_ enabled).
.. versionadded:: 20.0
photo (:class:`telegram.ChatPhoto`, optional): Chat photo.
active_usernames (Sequence[:obj:`str`], optional): If set, the list of all `active chat
usernames <https://telegram.org/blog/topics-in-groups-collectible-usernames\
#collectible-usernames>`_; for private chats, supergroups and channels.
.. versionadded:: 20.0
birthdate (:obj:`telegram.Birthdate`, optional): For private chats,
the date of birth of the user.
.. versionadded:: 21.1
business_intro (:class:`telegram.BusinessIntro`, optional): For private chats with
business accounts, the intro of the business.
.. versionadded:: 21.1
business_location (:class:`telegram.BusinessLocation`, optional): For private chats with
business accounts, the location of the business.
.. versionadded:: 21.1
business_opening_hours (:class:`telegram.BusinessOpeningHours`, optional): For private
chats with business accounts, the opening hours of the business.
.. versionadded:: 21.1
personal_chat (:obj:`telegram.Chat`, optional): For private chats, the personal channel of
the user.
.. versionadded:: 21.1
available_reactions (Sequence[:class:`telegram.ReactionType`], optional): List of available
reactions allowed in the chat. If omitted, then all of
:const:`telegram.constants.ReactionEmoji` are allowed.
.. versionadded:: 20.8
background_custom_emoji_id (:obj:`str`, optional): Custom emoji identifier of emoji chosen
by the chat for the reply header and link preview background.
.. versionadded:: 20.8
profile_accent_color_id (:obj:`int`, optional): Identifier of the
:class:`accent color <telegram.constants.ProfileAccentColor>` for the chat's profile
background. See profile `accent colors`_ for more details.
.. versionadded:: 20.8
profile_background_custom_emoji_id (:obj:`str`, optional): Custom emoji identifier of
the emoji chosen by the chat for its profile background.
.. versionadded:: 20.8
emoji_status_custom_emoji_id (:obj:`str`, optional): Custom emoji identifier of emoji
status of the chat or the other party in a private chat.
.. versionadded:: 20.0
emoji_status_expiration_date (:class:`datetime.datetime`, optional): Expiration date of
emoji status of the chat or the other party in a private chat, in seconds.
|datetime_localization|
.. versionadded:: 20.5
bio (:obj:`str`, optional): Bio of the other party in a private chat.
has_private_forwards (:obj:`bool`, optional): :obj:`True`, if privacy settings of the other
party in the private chat allows to use ``tg://user?id=<user_id>`` links only in chats
with the user.
.. versionadded:: 13.9
has_restricted_voice_and_video_messages (:obj:`bool`, optional): :obj:`True`, if the
privacy settings of the other party restrict sending voice and video note messages
in the private chat.
.. versionadded:: 20.0
join_to_send_messages (:obj:`bool`, optional): :obj:`True`, if users need to join the
supergroup before they can send messages.
.. versionadded:: 20.0
join_by_request (:obj:`bool`, optional): :obj:`True`, if all users directly joining the
supergroup without using an invite link need to be approved by supergroup
administrators.
.. versionadded:: 20.0
description (:obj:`str`, optional): Description, for groups, supergroups and channel chats.
invite_link (:obj:`str`, optional): Primary invite link, for groups, supergroups and
channel.
pinned_message (:class:`telegram.Message`, optional): The most recent pinned message
(by sending date).
permissions (:class:`telegram.ChatPermissions`): Optional. Default chat member permissions,
for groups and supergroups.
slow_mode_delay (:obj:`int`, optional): For supergroups, the minimum allowed delay between
consecutive messages sent by each unprivileged user.
unrestrict_boost_count (:obj:`int`, optional): For supergroups, the minimum number of
boosts that a non-administrator user needs to add in order to ignore slow mode and chat
permissions.
.. versionadded:: 21.0
message_auto_delete_time (:obj:`int`, optional): The time after which all messages sent to
the chat will be automatically deleted; in seconds.
.. versionadded:: 13.4
has_aggressive_anti_spam_enabled (:obj:`bool`, optional): :obj:`True`, if aggressive
anti-spam checks are enabled in the supergroup. The field is only available to chat
administrators.
.. versionadded:: 20.0
has_hidden_members (:obj:`bool`, optional): :obj:`True`, if non-administrators can only
get the list of bots and administrators in the chat.
.. versionadded:: 20.0
has_protected_content (:obj:`bool`, optional): :obj:`True`, if messages from the chat can't
be forwarded to other chats.
.. versionadded:: 13.9
has_visible_history (:obj:`bool`, optional): :obj:`True`, if new chat members will have
access to old messages; available only to chat administrators.
.. versionadded:: 20.8
sticker_set_name (:obj:`str`, optional): For supergroups, name of group sticker set.
can_set_sticker_set (:obj:`bool`, optional): :obj:`True`, if the bot can change group the
sticker set.
custom_emoji_sticker_set_name (:obj:`str`, optional): For supergroups, the name of the
group's custom emoji sticker set. Custom emoji from this set can be used by all users
and bots in the group.
.. versionadded:: 21.0
linked_chat_id (:obj:`int`, optional): Unique identifier for the linked chat, i.e. the
discussion group identifier for a channel and vice versa; for supergroups and channel
chats.
location (:class:`telegram.ChatLocation`, optional): For supergroups, the location to which
the supergroup is connected.
Attributes:
id (:obj:`int`): Unique identifier for this chat.
type (:obj:`str`): Type of chat, can be either :attr:`PRIVATE`, :attr:`GROUP`,
:attr:`SUPERGROUP` or :attr:`CHANNEL`.
accent_color_id (:obj:`int`): Optional. Identifier of the
:class:`accent color <telegram.constants.AccentColor>` for the chat name and
backgrounds of the chat photo, reply header, and link preview. See `accent colors`_
for more details.
.. versionadded:: 20.8
max_reaction_count (:obj:`int`): The maximum number of reactions that can be set on a
message in the chat.
.. versionadded:: 21.2
title (:obj:`str`, optional): Title, for supergroups, channels and group chats.
username (:obj:`str`, optional): Username, for private chats, supergroups and channels if
available.
first_name (:obj:`str`, optional): First name of the other party in a private chat.
last_name (:obj:`str`, optional): Last name of the other party in a private chat.
is_forum (:obj:`bool`, optional): :obj:`True`, if the supergroup chat is a forum
(has topics_ enabled).
.. versionadded:: 20.0
photo (:class:`telegram.ChatPhoto`): Optional. Chat photo.
active_usernames (Tuple[:obj:`str`]): Optional. If set, the list of all `active chat
usernames <https://telegram.org/blog/topics-in-groups-collectible-usernames\
#collectible-usernames>`_; for private chats, supergroups and channels.
This list is empty if the chat has no active usernames or this chat instance was not
obtained via :meth:`~telegram.Bot.get_chat`.
.. versionadded:: 20.0
birthdate (:obj:`telegram.Birthdate`): Optional. For private chats,
the date of birth of the user.
.. versionadded:: 21.1
business_intro (:class:`telegram.BusinessIntro`): Optional. For private chats with
business accounts, the intro of the business.
.. versionadded:: 21.1
business_location (:class:`telegram.BusinessLocation`): Optional. For private chats with
business accounts, the location of the business.
.. versionadded:: 21.1
business_opening_hours (:class:`telegram.BusinessOpeningHours`): Optional. For private
chats with business accounts, the opening hours of the business.
.. versionadded:: 21.1
personal_chat (:obj:`telegram.Chat`): Optional. For private chats, the personal channel of
the user.
.. versionadded:: 21.1
available_reactions (Tuple[:class:`telegram.ReactionType`]): Optional. List of available
reactions allowed in the chat. If omitted, then all of
:const:`telegram.constants.ReactionEmoji` are allowed.
.. versionadded:: 20.8
background_custom_emoji_id (:obj:`str`): Optional. Custom emoji identifier of emoji chosen
by the chat for the reply header and link preview background.
.. versionadded:: 20.8
profile_accent_color_id (:obj:`int`): Optional. Identifier of the
:class:`accent color <telegram.constants.ProfileAccentColor>` for the chat's profile
background. See profile `accent colors`_ for more details.
.. versionadded:: 20.8
profile_background_custom_emoji_id (:obj:`str`): Optional. Custom emoji identifier of
the emoji chosen by the chat for its profile background.
.. versionadded:: 20.8
emoji_status_custom_emoji_id (:obj:`str`): Optional. Custom emoji identifier of emoji
status of the chat or the other party in a private chat.
.. versionadded:: 20.0
emoji_status_expiration_date (:class:`datetime.datetime`): Optional. Expiration date of
emoji status of the chat or the other party in a private chat, in seconds.
|datetime_localization|
.. versionadded:: 20.5
bio (:obj:`str`): Optional. Bio of the other party in a private chat.
has_private_forwards (:obj:`bool`): Optional. :obj:`True`, if privacy settings of the other
party in the private chat allows to use ``tg://user?id=<user_id>`` links only in chats
with the user.
.. versionadded:: 13.9
has_restricted_voice_and_video_messages (:obj:`bool`): Optional. :obj:`True`, if the
privacy settings of the other party restrict sending voice and video note messages
in the private chat.
.. versionadded:: 20.0
join_to_send_messages (:obj:`bool`): Optional. :obj:`True`, if users need to join
the supergroup before they can send messages.
.. versionadded:: 20.0
join_by_request (:obj:`bool`): Optional. :obj:`True`, if all users directly joining the
supergroup without using an invite link need to be approved by supergroup
administrators.
.. versionadded:: 20.0
description (:obj:`str`): Optional. Description, for groups, supergroups and channel chats.
invite_link (:obj:`str`): Optional. Primary invite link, for groups, supergroups and
channel.
pinned_message (:class:`telegram.Message`): Optional. The most recent pinned message
(by sending date).
permissions (:class:`telegram.ChatPermissions`): Optional. Default chat member permissions,
for groups and supergroups.
slow_mode_delay (:obj:`int`): Optional. For supergroups, the minimum allowed delay between
consecutive messages sent by each unprivileged user.
unrestrict_boost_count (:obj:`int`): Optional. For supergroups, the minimum number of
boosts that a non-administrator user needs to add in order to ignore slow mode and chat
permissions.
.. versionadded:: 21.0
message_auto_delete_time (:obj:`int`): Optional. The time after which all messages sent to
the chat will be automatically deleted; in seconds.
.. versionadded:: 13.4
has_aggressive_anti_spam_enabled (:obj:`bool`): Optional. :obj:`True`, if aggressive
anti-spam checks are enabled in the supergroup. The field is only available to chat
administrators.
.. versionadded:: 20.0
has_hidden_members (:obj:`bool`): Optional. :obj:`True`, if non-administrators can only
get the list of bots and administrators in the chat.
.. versionadded:: 20.0
has_protected_content (:obj:`bool`): Optional. :obj:`True`, if messages from the chat can't
be forwarded to other chats.
.. versionadded:: 13.9
has_visible_history (:obj:`bool`): Optional. :obj:`True`, if new chat members will have
access to old messages; available only to chat administrators.
.. versionadded:: 20.8
sticker_set_name (:obj:`str`): Optional. For supergroups, name of Group sticker set.
can_set_sticker_set (:obj:`bool`): Optional. :obj:`True`, if the bot can change group the
sticker set.
custom_emoji_sticker_set_name (:obj:`str`): Optional. For supergroups, the name of the
group's custom emoji sticker set. Custom emoji from this set can be used by all users
and bots in the group.
.. versionadded:: 21.0
linked_chat_id (:obj:`int`): Optional. Unique identifier for the linked chat, i.e. the
discussion group identifier for a channel and vice versa; for supergroups and channel
chats.
location (:class:`telegram.ChatLocation`): Optional. For supergroups, the location to which
the supergroup is connected.
.. _accent colors: https://core.telegram.org/bots/api#accent-colors
.. _topics: https://telegram.org/blog/topics-in-groups-collectible-usernames#topics-in-groups
"""
__slots__ = (
"accent_color_id",
"active_usernames",
"available_reactions",
"background_custom_emoji_id",
"bio",
"birthdate",
"business_intro",
"business_location",
"business_opening_hours",
"can_set_sticker_set",
"custom_emoji_sticker_set_name",
"description",
"emoji_status_custom_emoji_id",
"emoji_status_expiration_date",
"has_aggressive_anti_spam_enabled",
"has_hidden_members",
"has_private_forwards",
"has_protected_content",
"has_restricted_voice_and_video_messages",
"has_visible_history",
"invite_link",
"join_by_request",
"join_to_send_messages",
"linked_chat_id",
"location",
"max_reaction_count",
"message_auto_delete_time",
"permissions",
"personal_chat",
"photo",
"pinned_message",
"profile_accent_color_id",
"profile_background_custom_emoji_id",
"slow_mode_delay",
"sticker_set_name",
"unrestrict_boost_count",
)
def __init__(
self,
id: int,
type: str,
accent_color_id: int,
max_reaction_count: int,
title: Optional[str] = None,
username: Optional[str] = None,
first_name: Optional[str] = None,
last_name: Optional[str] = None,
is_forum: Optional[bool] = None,
photo: Optional[ChatPhoto] = None,
active_usernames: Optional[Sequence[str]] = None,
birthdate: Optional[Birthdate] = None,
business_intro: Optional["BusinessIntro"] = None,
business_location: Optional["BusinessLocation"] = None,
business_opening_hours: Optional["BusinessOpeningHours"] = None,
personal_chat: Optional["Chat"] = None,
available_reactions: Optional[Sequence[ReactionType]] = None,
background_custom_emoji_id: Optional[str] = None,
profile_accent_color_id: Optional[int] = None,
profile_background_custom_emoji_id: Optional[str] = None,
emoji_status_custom_emoji_id: Optional[str] = None,
emoji_status_expiration_date: Optional[datetime] = None,
bio: Optional[str] = None,
has_private_forwards: Optional[bool] = None,
has_restricted_voice_and_video_messages: Optional[bool] = None,
join_to_send_messages: Optional[bool] = None,
join_by_request: Optional[bool] = None,
description: Optional[str] = None,
invite_link: Optional[str] = None,
pinned_message: Optional["Message"] = None,
permissions: Optional[ChatPermissions] = None,
slow_mode_delay: Optional[int] = None,
unrestrict_boost_count: Optional[int] = None,
message_auto_delete_time: Optional[int] = None,
has_aggressive_anti_spam_enabled: Optional[bool] = None,
has_hidden_members: Optional[bool] = None,
has_protected_content: Optional[bool] = None,
has_visible_history: Optional[bool] = None,
sticker_set_name: Optional[str] = None,
can_set_sticker_set: Optional[bool] = None,
custom_emoji_sticker_set_name: Optional[str] = None,
linked_chat_id: Optional[int] = None,
location: Optional[ChatLocation] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(
id=id,
type=type,
title=title,
username=username,
first_name=first_name,
last_name=last_name,
is_forum=is_forum,
api_kwargs=api_kwargs,
)
# Required and unique to this class-
with self._unfrozen():
self.max_reaction_count: int = max_reaction_count
self.photo: Optional[ChatPhoto] = photo
self.bio: Optional[str] = bio
self.has_private_forwards: Optional[bool] = has_private_forwards
self.description: Optional[str] = description
self.invite_link: Optional[str] = invite_link
self.pinned_message: Optional[Message] = pinned_message
self.permissions: Optional[ChatPermissions] = permissions
self.slow_mode_delay: Optional[int] = slow_mode_delay
self.message_auto_delete_time: Optional[int] = (
int(message_auto_delete_time) if message_auto_delete_time is not None else None
)
self.has_protected_content: Optional[bool] = has_protected_content
self.has_visible_history: Optional[bool] = has_visible_history
self.sticker_set_name: Optional[str] = sticker_set_name
self.can_set_sticker_set: Optional[bool] = can_set_sticker_set
self.linked_chat_id: Optional[int] = linked_chat_id
self.location: Optional[ChatLocation] = location
self.join_to_send_messages: Optional[bool] = join_to_send_messages
self.join_by_request: Optional[bool] = join_by_request
self.has_restricted_voice_and_video_messages: Optional[bool] = (
has_restricted_voice_and_video_messages
)
self.active_usernames: Tuple[str, ...] = parse_sequence_arg(active_usernames)
self.emoji_status_custom_emoji_id: Optional[str] = emoji_status_custom_emoji_id
self.emoji_status_expiration_date: Optional[datetime] = emoji_status_expiration_date
self.has_aggressive_anti_spam_enabled: Optional[bool] = (
has_aggressive_anti_spam_enabled
)
self.has_hidden_members: Optional[bool] = has_hidden_members
self.available_reactions: Optional[Tuple[ReactionType, ...]] = parse_sequence_arg(
available_reactions
)
self.accent_color_id: Optional[int] = accent_color_id
self.background_custom_emoji_id: Optional[str] = background_custom_emoji_id
self.profile_accent_color_id: Optional[int] = profile_accent_color_id
self.profile_background_custom_emoji_id: Optional[str] = (
profile_background_custom_emoji_id
)
self.unrestrict_boost_count: Optional[int] = unrestrict_boost_count
self.custom_emoji_sticker_set_name: Optional[str] = custom_emoji_sticker_set_name
self.birthdate: Optional[Birthdate] = birthdate
self.personal_chat: Optional["Chat"] = personal_chat
self.business_intro: Optional["BusinessIntro"] = business_intro
self.business_location: Optional["BusinessLocation"] = business_location
self.business_opening_hours: Optional["BusinessOpeningHours"] = business_opening_hours
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["ChatFullInfo"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if not data:
return None
# Get the local timezone from the bot if it has defaults
loc_tzinfo = extract_tzinfo_from_defaults(bot)
data["emoji_status_expiration_date"] = from_timestamp(
data.get("emoji_status_expiration_date"), tzinfo=loc_tzinfo
)
data["photo"] = ChatPhoto.de_json(data.get("photo"), bot)
from telegram import ( # pylint: disable=import-outside-toplevel
BusinessIntro,
BusinessLocation,
BusinessOpeningHours,
Message,
)
data["pinned_message"] = Message.de_json(data.get("pinned_message"), bot)
data["permissions"] = ChatPermissions.de_json(data.get("permissions"), bot)
data["location"] = ChatLocation.de_json(data.get("location"), bot)
data["available_reactions"] = ReactionType.de_list(data.get("available_reactions"), bot)
data["birthdate"] = Birthdate.de_json(data.get("birthdate"), bot)
data["personal_chat"] = Chat.de_json(data.get("personal_chat"), bot)
data["business_intro"] = BusinessIntro.de_json(data.get("business_intro"), bot)
data["business_location"] = BusinessLocation.de_json(data.get("business_location"), bot)
data["business_opening_hours"] = BusinessOpeningHours.de_json(
data.get("business_opening_hours"), bot
)
return super().de_json(data=data, bot=bot)
+6 -4
View File
@@ -235,8 +235,9 @@ class ChatMemberAdministrator(ChatMember):
.. versionadded:: 20.6
.. versionchanged:: 21.0
|non_optional_story_argument|
can_edit_stories (:obj:`bool`): :obj:`True`, if the administrator can edit
stories posted by other users.
can_edit_stories (:obj:`bool`): :obj:`True`, if the administrator can edit stories posted
by other users, post stories to the chat page, pin chat stories, and access the chat's
story archive
.. versionadded:: 20.6
.. versionchanged:: 21.0
@@ -294,8 +295,9 @@ class ChatMemberAdministrator(ChatMember):
.. versionadded:: 20.6
.. versionchanged:: 21.0
|non_optional_story_argument|
can_edit_stories (:obj:`bool`): :obj:`True`, if the administrator can edit
stories posted by other users.
can_edit_stories (:obj:`bool`): :obj:`True`, if the administrator can edit stories posted
by other users, post stories to the chat page, pin chat stories, and access the chat's
story archive
.. versionadded:: 20.6
.. versionchanged:: 21.0
+13
View File
@@ -63,6 +63,11 @@ class ChatMemberUpdated(TelegramObject):
chat via a chat folder invite link
.. versionadded:: 20.3
via_join_request (:obj:`bool`, optional): :obj:`True`, if the user joined the chat after
sending a direct join request without using an invite link and being approved by
an administrator
.. versionadded:: 21.2
Attributes:
chat (:class:`telegram.Chat`): Chat the user belongs to.
@@ -80,6 +85,11 @@ class ChatMemberUpdated(TelegramObject):
chat via a chat folder invite link
.. versionadded:: 20.3
via_join_request (:obj:`bool`): Optional. :obj:`True`, if the user joined the chat after
sending a direct join request without using an invite link and being approved
by an administrator
.. versionadded:: 21.2
"""
@@ -91,6 +101,7 @@ class ChatMemberUpdated(TelegramObject):
"new_chat_member",
"old_chat_member",
"via_chat_folder_invite_link",
"via_join_request",
)
def __init__(
@@ -102,6 +113,7 @@ class ChatMemberUpdated(TelegramObject):
new_chat_member: ChatMember,
invite_link: Optional[ChatInviteLink] = None,
via_chat_folder_invite_link: Optional[bool] = None,
via_join_request: Optional[bool] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
@@ -116,6 +128,7 @@ class ChatMemberUpdated(TelegramObject):
# Optionals
self.invite_link: Optional[ChatInviteLink] = invite_link
self.via_join_request: Optional[bool] = via_join_request
self._id_attrs = (
self.chat,
+37 -2
View File
@@ -160,6 +160,9 @@ class InputMediaAnimation(InputMedia):
optional): |thumbdocstringnopath|
.. versionadded:: 20.2
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
.. versionadded:: 21.3
Attributes:
type (:obj:`str`): :tg-const:`telegram.constants.InputMediaType.ANIMATION`.
@@ -184,9 +187,19 @@ class InputMediaAnimation(InputMedia):
thumbnail (:class:`telegram.InputFile`): Optional. |thumbdocstringbase|
.. versionadded:: 20.2
show_caption_above_media (:obj:`bool`): Optional. |show_cap_above_med|
.. versionadded:: 21.3
"""
__slots__ = ("duration", "has_spoiler", "height", "thumbnail", "width")
__slots__ = (
"duration",
"has_spoiler",
"height",
"show_caption_above_media",
"thumbnail",
"width",
)
def __init__(
self,
@@ -200,6 +213,7 @@ class InputMediaAnimation(InputMedia):
filename: Optional[str] = None,
has_spoiler: Optional[bool] = None,
thumbnail: Optional[FileInput] = None,
show_caption_above_media: Optional[bool] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
@@ -229,6 +243,7 @@ class InputMediaAnimation(InputMedia):
self.height: Optional[int] = height
self.duration: Optional[int] = duration
self.has_spoiler: Optional[bool] = has_spoiler
self.show_caption_above_media: Optional[bool] = show_caption_above_media
class InputMediaPhoto(InputMedia):
@@ -260,6 +275,9 @@ class InputMediaPhoto(InputMedia):
with a spoiler animation.
.. versionadded:: 20.0
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
.. versionadded:: 21.3
Attributes:
type (:obj:`str`): :tg-const:`telegram.constants.InputMediaType.PHOTO`.
@@ -278,9 +296,15 @@ class InputMediaPhoto(InputMedia):
spoiler animation.
.. versionadded:: 20.0
show_caption_above_media (:obj:`bool`): Optional. |show_cap_above_med|
.. versionadded:: 21.3
"""
__slots__ = ("has_spoiler",)
__slots__ = (
"has_spoiler",
"show_caption_above_media",
)
def __init__(
self,
@@ -290,6 +314,7 @@ class InputMediaPhoto(InputMedia):
caption_entities: Optional[Sequence[MessageEntity]] = None,
filename: Optional[str] = None,
has_spoiler: Optional[bool] = None,
show_caption_above_media: Optional[bool] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
@@ -307,6 +332,7 @@ class InputMediaPhoto(InputMedia):
with self._unfrozen():
self.has_spoiler: Optional[bool] = has_spoiler
self.show_caption_above_media: Optional[bool] = show_caption_above_media
class InputMediaVideo(InputMedia):
@@ -359,6 +385,9 @@ class InputMediaVideo(InputMedia):
optional): |thumbdocstringnopath|
.. versionadded:: 20.2
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
.. versionadded:: 21.3
Attributes:
type (:obj:`str`): :tg-const:`telegram.constants.InputMediaType.VIDEO`.
@@ -385,12 +414,16 @@ class InputMediaVideo(InputMedia):
thumbnail (:class:`telegram.InputFile`): Optional. |thumbdocstringbase|
.. versionadded:: 20.2
show_caption_above_media (:obj:`bool`): Optional. |show_cap_above_med|
.. versionadded:: 21.3
"""
__slots__ = (
"duration",
"has_spoiler",
"height",
"show_caption_above_media",
"supports_streaming",
"thumbnail",
"width",
@@ -409,6 +442,7 @@ class InputMediaVideo(InputMedia):
filename: Optional[str] = None,
has_spoiler: Optional[bool] = None,
thumbnail: Optional[FileInput] = None,
show_caption_above_media: Optional[bool] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
@@ -439,6 +473,7 @@ class InputMediaVideo(InputMedia):
)
self.supports_streaming: Optional[bool] = supports_streaming
self.has_spoiler: Optional[bool] = has_spoiler
self.show_caption_above_media: Optional[bool] = show_caption_above_media
class InputMediaAudio(InputMedia):
+4 -38
View File
@@ -27,8 +27,6 @@ from telegram._telegramobject import TelegramObject
from telegram._utils import enum
from telegram._utils.argumentparsing import parse_sequence_arg
from telegram._utils.types import JSONDict
from telegram._utils.warnings import warn
from telegram.warnings import PTBDeprecationWarning
if TYPE_CHECKING:
from telegram import Bot
@@ -237,20 +235,12 @@ class StickerSet(TelegramObject):
.. versionchanged:: 20.5
|removed_thumb_note|
.. versionremoved:: 21.2
Removed the deprecated arguments and attributes ``is_animated`` and ``is_video``.
Args:
name (:obj:`str`): Sticker set name.
title (:obj:`str`): Sticker set title.
is_animated (:obj:`bool`): :obj:`True`, if the sticker set contains animated stickers.
.. deprecated:: 21.1
Bot API 7.2 deprecated this field. This parameter will be removed in a future
version of the library.
is_video (:obj:`bool`): :obj:`True`, if the sticker set contains video stickers.
.. versionadded:: 13.11
.. deprecated:: 21.1
Bot API 7.2 deprecated this field. This parameter will be removed in a future
version of the library.
stickers (Sequence[:class:`telegram.Sticker`]): List of all set stickers.
.. versionchanged:: 20.0
@@ -269,17 +259,6 @@ class StickerSet(TelegramObject):
Attributes:
name (:obj:`str`): Sticker set name.
title (:obj:`str`): Sticker set title.
is_animated (:obj:`bool`): :obj:`True`, if the sticker set contains animated stickers.
.. deprecated:: 21.1
Bot API 7.2 deprecated this field. This parameter will be removed in a future
version of the library.
is_video (:obj:`bool`): :obj:`True`, if the sticker set contains video stickers.
.. versionadded:: 13.11
.. deprecated:: 21.1
Bot API 7.2 deprecated this field. This parameter will be removed in a future
version of the library.
stickers (Tuple[:class:`telegram.Sticker`]): List of all set stickers.
.. versionchanged:: 20.0
@@ -297,8 +276,6 @@ class StickerSet(TelegramObject):
"""
__slots__ = (
"is_animated",
"is_video",
"name",
"sticker_type",
"stickers",
@@ -312,8 +289,6 @@ class StickerSet(TelegramObject):
title: str,
stickers: Sequence[Sticker],
sticker_type: str,
is_animated: Optional[bool] = None,
is_video: Optional[bool] = None,
thumbnail: Optional[PhotoSize] = None,
*,
api_kwargs: Optional[JSONDict] = None,
@@ -325,15 +300,6 @@ class StickerSet(TelegramObject):
self.sticker_type: str = sticker_type
# Optional
self.thumbnail: Optional[PhotoSize] = thumbnail
if is_animated is not None or is_video is not None:
warn(
"The parameters `is_animated` and `is_video` are deprecated and will be removed "
"in a future version.",
PTBDeprecationWarning,
stacklevel=2,
)
self.is_animated: Optional[bool] = is_animated
self.is_video: Optional[bool] = is_video
self._id_attrs = (self.name,)
self._freeze()
@@ -350,7 +316,7 @@ class StickerSet(TelegramObject):
api_kwargs = {}
# 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"):
for deprecated_field in ("contains_masks", "thumb", "is_animated", "is_video"):
if deprecated_field in data:
api_kwargs[deprecated_field] = data.pop(deprecated_field)
+2 -1
View File
@@ -30,7 +30,8 @@ class ForceReply(TelegramObject):
Upon receiving a message with this object, Telegram clients will display a reply interface to
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.
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.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`selective` is equal.
+54 -37
View File
@@ -41,7 +41,8 @@ class InlineKeyboardButton(TelegramObject):
:attr:`web_app` and :attr:`pay` are equal.
Note:
* You must use exactly one of the optional fields. Mind that :attr:`callback_game` is not
* Exactly one of the optional fields must be used to specify type of the button.
* Mind that :attr:`callback_game` is not
working as expected. Putting a game short name in it might, but is not guaranteed to
work.
* If your bot allows for arbitrary callback data, in keyboards returned in a response
@@ -91,6 +92,7 @@ class InlineKeyboardButton(TelegramObject):
to the bot when button is pressed, UTF-8
:tg-const:`telegram.InlineKeyboardButton.MIN_CALLBACK_DATA`-
:tg-const:`telegram.InlineKeyboardButton.MAX_CALLBACK_DATA` bytes.
Not supported for messages sent on behalf of a Telegram Business account.
If the bot instance allows arbitrary callback data, anything can be passed.
Tip:
@@ -102,35 +104,42 @@ class InlineKeyboardButton(TelegramObject):
<https://core.telegram.org/bots/webapps>`_ that will be launched when the user presses
the button. The Web App will be able to send an arbitrary message on behalf of the user
using the method :meth:`~telegram.Bot.answer_web_app_query`. Available only in
private chats between a user and the bot.
private chats between a user and the bot. Not supported for messages sent on behalf of
a Telegram Business account.
.. versionadded:: 20.0
switch_inline_query (:obj:`str`, optional): If set, pressing the button will prompt the
user to select one of their chats, open that chat and insert the bot's username and the
specified inline query in the input field. Can be empty, in which case just the bot's
username will be inserted. This offers an easy way for users to start using your bot
in inline mode when they are currently in a private chat with it. Especially useful
when combined with ``switch_pm*`` actions - in this case the user will be automatically
returned to the chat they switched from, skipping the chat selection screen.
switch_inline_query (:obj:`str`, optional): If set, pressing the button will insert the
bot's username and the specified inline query in the current chat's input field. May be
empty, in which case only the bot's username will be inserted.
This offers a quick way for the user to open your bot in inline mode in the same chat -
good for selecting something from multiple options. Not supported in channels and for
messages sent on behalf of a Telegram Business account.
Tip:
This is similar to the new parameter :paramref:`switch_inline_query_chosen_chat`,
but gives no control over which chats can be selected.
switch_inline_query_current_chat (:obj:`str`, optional): If set, pressing the button will
insert the bot's username and the specified inline query in the current chat's input
field. Can be empty, in which case only the bot's username will be inserted. This
offers a quick way for the user to open your bot in inline mode in the same chat - good
for selecting something from multiple options.
prompt the user to select one of their chats of the specified type, open that chat and
insert the bot's username and the specified inline query in the input field. Not
supported for messages sent on behalf of a Telegram Business account.
callback_game (:class:`telegram.CallbackGame`, optional): Description of the game that will
be launched when the user presses the button. This type of button **must** always be
the **first** button in the first row.
pay (:obj:`bool`, optional): Specify :obj:`True`, to send a Pay button. This type of button
**must** always be the **first** button in the first row and can only be used in
invoice messages.
be launched when the user presses the button
Note:
This type of button **must** always be the first button in the first row.
pay (:obj:`bool`, optional): Specify :obj:`True`, to send a Pay button.
Substrings ```` and ``XTR`` in the buttons's text will be replaced with a
Telegram Star icon.
Note:
This type of button **must** always be the first button in the first row and can
only be used in invoice messages.
switch_inline_query_chosen_chat (:obj:`telegram.SwitchInlineQueryChosenChat`, optional):
If set, pressing the button will prompt the user to select one of their chats of the
specified type, open that chat and insert the bot's username and the specified inline
query in the input field.
query in the input field. Not supported for messages sent on behalf of a Telegram
Business account.
.. versionadded:: 20.3
@@ -159,39 +168,47 @@ class InlineKeyboardButton(TelegramObject):
to the bot when button is pressed, UTF-8
:tg-const:`telegram.InlineKeyboardButton.MIN_CALLBACK_DATA`-
:tg-const:`telegram.InlineKeyboardButton.MAX_CALLBACK_DATA` bytes.
Not supported for messages sent on behalf of a Telegram Business account.
web_app (:obj:`telegram.WebAppInfo`): Optional. Description of the `Web App
<https://core.telegram.org/bots/webapps>`_ that will be launched when the user presses
the button. The Web App will be able to send an arbitrary message on behalf of the user
using the method :meth:`~telegram.Bot.answer_web_app_query`. Available only in
private chats between a user and the bot.
private chats between a user and the bot. Not supported for messages sent on behalf of
a Telegram Business account.
.. versionadded:: 20.0
switch_inline_query (:obj:`str`): Optional. If set, pressing the button will prompt the
user to select one of their chats, open that chat and insert the bot's username and the
specified inline query in the input field. Can be empty, in which case just the bot's
username will be inserted. This offers an easy way for users to start using your bot
in inline mode when they are currently in a private chat with it. Especially useful
when combined with ``switch_pm*`` actions - in this case the user will be automatically
returned to the chat they switched from, skipping the chat selection screen.
switch_inline_query (:obj:`str`): Optional. If set, pressing the button will insert the
bot's username and the specified inline query in the current chat's input field. May be
empty, in which case only the bot's username will be inserted.
This offers a quick way for the user to open your bot in inline mode in the same chat -
good for selecting something from multiple options. Not supported in channels and for
messages sent on behalf of a Telegram Business account.
Tip:
This is similar to the new parameter :paramref:`switch_inline_query_chosen_chat`,
but gives no control over which chats can be selected.
switch_inline_query_current_chat (:obj:`str`): Optional. If set, pressing the button will
insert the bot's username and the specified inline query in the current chat's input
field. Can be empty, in which case only the bot's username will be inserted. This
offers a quick way for the user to open your bot in inline mode in the same chat - good
for selecting something from multiple options.
prompt the user to select one of their chats of the specified type, open that chat and
insert the bot's username and the specified inline query in the input field. Not
supported for messages sent on behalf of a Telegram Business account.
callback_game (:class:`telegram.CallbackGame`): Optional. Description of the game that will
be launched when the user presses the button. This type of button **must** always be
the **first** button in the first row.
pay (:obj:`bool`): Optional. Specify :obj:`True`, to send a Pay button. This type of button
**must** always be the **first** button in the first row and can only be used in
invoice messages.
be launched when the user presses the button.
Note:
This type of button **must** always be the first button in the first row.
pay (:obj:`bool`): Optional. Specify :obj:`True`, to send a Pay button.
Substrings ```` and ``XTR`` in the buttons's text will be replaced with a
Telegram Star icon.
Note:
This type of button **must** always be the first button in the first row and can
only be used in invoice messages.
switch_inline_query_chosen_chat (:obj:`telegram.SwitchInlineQueryChosenChat`): Optional.
If set, pressing the button will prompt the user to select one of their chats of the
specified type, open that chat and insert the bot's username and the specified inline
query in the input field.
query in the input field. Not supported for messages sent on behalf of a Telegram
Business account.
.. versionadded:: 20.3
@@ -59,6 +59,9 @@ class InlineQueryResultCachedGif(InlineQueryResult):
to the message.
input_message_content (:class:`telegram.InputMessageContent`, optional): Content of the
message to be sent instead of the gif.
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
.. versionadded:: 21.3
Attributes:
type (:obj:`str`): :tg-const:`telegram.constants.InlineQueryResultType.GIF`.
@@ -81,6 +84,9 @@ class InlineQueryResultCachedGif(InlineQueryResult):
to the message.
input_message_content (:class:`telegram.InputMessageContent`): Optional. Content of the
message to be sent instead of the gif.
show_caption_above_media (:obj:`bool`): Optional. |show_cap_above_med|
.. versionadded:: 21.3
"""
@@ -91,6 +97,7 @@ class InlineQueryResultCachedGif(InlineQueryResult):
"input_message_content",
"parse_mode",
"reply_markup",
"show_caption_above_media",
"title",
)
@@ -104,6 +111,7 @@ class InlineQueryResultCachedGif(InlineQueryResult):
input_message_content: Optional["InputMessageContent"] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence[MessageEntity]] = None,
show_caption_above_media: Optional[bool] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
@@ -119,3 +127,4 @@ class InlineQueryResultCachedGif(InlineQueryResult):
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup
self.input_message_content: Optional[InputMessageContent] = input_message_content
self.show_caption_above_media: Optional[bool] = show_caption_above_media
@@ -59,6 +59,9 @@ class InlineQueryResultCachedMpeg4Gif(InlineQueryResult):
to the message.
input_message_content (:class:`telegram.InputMessageContent`, optional): Content of the
message to be sent instead of the MPEG-4 file.
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
.. versionadded:: 21.3
Attributes:
type (:obj:`str`): :tg-const:`telegram.constants.InlineQueryResultType.MPEG4GIF`.
@@ -81,6 +84,9 @@ class InlineQueryResultCachedMpeg4Gif(InlineQueryResult):
to the message.
input_message_content (:class:`telegram.InputMessageContent`): Optional. Content of the
message to be sent instead of the MPEG-4 file.
show_caption_above_media (:obj:`bool`): Optional. |show_cap_above_med|
.. versionadded:: 21.3
"""
@@ -91,6 +97,7 @@ class InlineQueryResultCachedMpeg4Gif(InlineQueryResult):
"mpeg4_file_id",
"parse_mode",
"reply_markup",
"show_caption_above_media",
"title",
)
@@ -104,6 +111,7 @@ class InlineQueryResultCachedMpeg4Gif(InlineQueryResult):
input_message_content: Optional["InputMessageContent"] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence[MessageEntity]] = None,
show_caption_above_media: Optional[bool] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
@@ -119,3 +127,4 @@ class InlineQueryResultCachedMpeg4Gif(InlineQueryResult):
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup
self.input_message_content: Optional[InputMessageContent] = input_message_content
self.show_caption_above_media: Optional[bool] = show_caption_above_media
@@ -60,6 +60,9 @@ class InlineQueryResultCachedPhoto(InlineQueryResult):
to the message.
input_message_content (:class:`telegram.InputMessageContent`, optional): Content of the
message to be sent instead of the photo.
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
.. versionadded:: 21.3
Attributes:
type (:obj:`str`): :tg-const:`telegram.constants.InlineQueryResultType.PHOTO`.
@@ -83,6 +86,9 @@ class InlineQueryResultCachedPhoto(InlineQueryResult):
to the message.
input_message_content (:class:`telegram.InputMessageContent`): Optional. Content of the
message to be sent instead of the photo.
show_caption_above_media (:obj:`bool`): Optional. |show_cap_above_med|
.. versionadded:: 21.3
"""
@@ -94,6 +100,7 @@ class InlineQueryResultCachedPhoto(InlineQueryResult):
"parse_mode",
"photo_file_id",
"reply_markup",
"show_caption_above_media",
"title",
)
@@ -108,6 +115,7 @@ class InlineQueryResultCachedPhoto(InlineQueryResult):
input_message_content: Optional["InputMessageContent"] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence[MessageEntity]] = None,
show_caption_above_media: Optional[bool] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
@@ -124,3 +132,4 @@ class InlineQueryResultCachedPhoto(InlineQueryResult):
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup
self.input_message_content: Optional[InputMessageContent] = input_message_content
self.show_caption_above_media: Optional[bool] = show_caption_above_media
@@ -56,6 +56,9 @@ class InlineQueryResultCachedVideo(InlineQueryResult):
to the message.
input_message_content (:class:`telegram.InputMessageContent`, optional): Content of the
message to be sent instead of the video.
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
.. versionadded:: 21.3
Attributes:
type (:obj:`str`): :tg-const:`telegram.constants.InlineQueryResultType.VIDEO`.
@@ -79,6 +82,9 @@ class InlineQueryResultCachedVideo(InlineQueryResult):
to the message.
input_message_content (:class:`telegram.InputMessageContent`): Optional. Content of the
message to be sent instead of the video.
show_caption_above_media (:obj:`bool`): Optional. |show_cap_above_med|
.. versionadded:: 21.3
"""
@@ -89,6 +95,7 @@ class InlineQueryResultCachedVideo(InlineQueryResult):
"input_message_content",
"parse_mode",
"reply_markup",
"show_caption_above_media",
"title",
"video_file_id",
)
@@ -104,6 +111,7 @@ class InlineQueryResultCachedVideo(InlineQueryResult):
input_message_content: Optional["InputMessageContent"] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence[MessageEntity]] = None,
show_caption_above_media: Optional[bool] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
@@ -120,3 +128,4 @@ class InlineQueryResultCachedVideo(InlineQueryResult):
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup
self.input_message_content: Optional[InputMessageContent] = input_message_content
self.show_caption_above_media: Optional[bool] = show_caption_above_media
+9
View File
@@ -78,6 +78,9 @@ class InlineQueryResultGif(InlineQueryResult):
to the message.
input_message_content (:class:`telegram.InputMessageContent`, optional): Content of the
message to be sent instead of the GIF animation.
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
.. versionadded:: 21.3
Raises:
:class:`ValueError`: If neither :paramref:`thumbnail_url` nor :paramref:`thumb_url` is
@@ -115,6 +118,9 @@ class InlineQueryResultGif(InlineQueryResult):
to the message.
input_message_content (:class:`telegram.InputMessageContent`): Optional. Content of the
message to be sent instead of the GIF animation.
show_caption_above_media (:obj:`bool`): Optional. |show_cap_above_med|
.. versionadded:: 21.3
"""
@@ -128,6 +134,7 @@ class InlineQueryResultGif(InlineQueryResult):
"input_message_content",
"parse_mode",
"reply_markup",
"show_caption_above_media",
"thumbnail_mime_type",
"thumbnail_url",
"title",
@@ -148,6 +155,7 @@ class InlineQueryResultGif(InlineQueryResult):
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence[MessageEntity]] = None,
thumbnail_mime_type: Optional[str] = None,
show_caption_above_media: Optional[bool] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
@@ -168,3 +176,4 @@ class InlineQueryResultGif(InlineQueryResult):
self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup
self.input_message_content: Optional[InputMessageContent] = input_message_content
self.thumbnail_mime_type: Optional[str] = thumbnail_mime_type
self.show_caption_above_media: Optional[bool] = show_caption_above_media
@@ -89,7 +89,9 @@ class InlineQueryResultLocation(InlineQueryResult):
live_period (:obj:`int`): Optional. Period in seconds for which the location will be
updated, should be between
:tg-const:`telegram.InlineQueryResultLocation.MIN_LIVE_PERIOD` and
:tg-const:`telegram.InlineQueryResultLocation.MAX_LIVE_PERIOD`.
:tg-const:`telegram.InlineQueryResultLocation.MAX_LIVE_PERIOD` or
:tg-const:`telegram.constants.LocationLimit.LIVE_PERIOD_FOREVER` for live
locations that can be edited indefinitely.
heading (:obj:`int`): Optional. For live locations, a direction in which the user is
moving, in degrees. Must be between
:tg-const:`telegram.InlineQueryResultLocation.MIN_HEADING` and
@@ -80,7 +80,9 @@ class InlineQueryResultMpeg4Gif(InlineQueryResult):
to the message.
input_message_content (:class:`telegram.InputMessageContent`, optional): Content of the
message to be sent instead of the video animation.
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
.. versionadded:: 21.3
Raises:
:class:`ValueError`: If neither :paramref:`thumbnail_url` nor :paramref:`thumb_url` is
supplied or if both are supplied and are not equal.
@@ -118,7 +120,9 @@ class InlineQueryResultMpeg4Gif(InlineQueryResult):
to the message.
input_message_content (:class:`telegram.InputMessageContent`): Optional. Content of the
message to be sent instead of the video animation.
show_caption_above_media (:obj:`bool`): Optional. |show_cap_above_med|
.. versionadded:: 21.3
"""
__slots__ = (
@@ -131,6 +135,7 @@ class InlineQueryResultMpeg4Gif(InlineQueryResult):
"mpeg4_width",
"parse_mode",
"reply_markup",
"show_caption_above_media",
"thumbnail_mime_type",
"thumbnail_url",
"title",
@@ -151,6 +156,7 @@ class InlineQueryResultMpeg4Gif(InlineQueryResult):
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence[MessageEntity]] = None,
thumbnail_mime_type: Optional[str] = None,
show_caption_above_media: Optional[bool] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
@@ -171,3 +177,4 @@ class InlineQueryResultMpeg4Gif(InlineQueryResult):
self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup
self.input_message_content: Optional[InputMessageContent] = input_message_content
self.thumbnail_mime_type: Optional[str] = thumbnail_mime_type
self.show_caption_above_media: Optional[bool] = show_caption_above_media
@@ -74,6 +74,9 @@ class InlineQueryResultPhoto(InlineQueryResult):
to the message.
input_message_content (:class:`telegram.InputMessageContent`, optional): Content of the
message to be sent instead of the photo.
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
.. versionadded:: 21.3
Raises:
:class:`ValueError`: If neither :paramref:`thumbnail_url` nor :paramref:`thumb_url` is
@@ -105,6 +108,9 @@ class InlineQueryResultPhoto(InlineQueryResult):
to the message.
input_message_content (:class:`telegram.InputMessageContent`): Optional. Content of the
message to be sent instead of the photo.
show_caption_above_media (:obj:`bool`): Optional. |show_cap_above_med|
.. versionadded:: 21.3
"""
@@ -118,6 +124,7 @@ class InlineQueryResultPhoto(InlineQueryResult):
"photo_url",
"photo_width",
"reply_markup",
"show_caption_above_media",
"thumbnail_url",
"title",
)
@@ -136,6 +143,7 @@ class InlineQueryResultPhoto(InlineQueryResult):
input_message_content: Optional["InputMessageContent"] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence[MessageEntity]] = None,
show_caption_above_media: Optional[bool] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
@@ -155,3 +163,4 @@ class InlineQueryResultPhoto(InlineQueryResult):
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup
self.input_message_content: Optional[InputMessageContent] = input_message_content
self.show_caption_above_media: Optional[bool] = show_caption_above_media
@@ -88,6 +88,9 @@ class InlineQueryResultVideo(InlineQueryResult):
message to be sent instead of the video. This field is required if
``InlineQueryResultVideo`` is used to send an HTML-page as a result
(e.g., a YouTube video).
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
.. versionadded:: 21.3
Raises:
:class:`ValueError`: If neither :paramref:`thumbnail_url` nor :paramref:`thumb_url` is
@@ -127,6 +130,9 @@ class InlineQueryResultVideo(InlineQueryResult):
message to be sent instead of the video. This field is required if
``InlineQueryResultVideo`` is used to send an HTML-page as a result
(e.g., a YouTube video).
show_caption_above_media (:obj:`bool`): Optional. |show_cap_above_med|
.. versionadded:: 21.3
"""
@@ -138,6 +144,7 @@ class InlineQueryResultVideo(InlineQueryResult):
"mime_type",
"parse_mode",
"reply_markup",
"show_caption_above_media",
"thumbnail_url",
"title",
"video_duration",
@@ -162,6 +169,7 @@ class InlineQueryResultVideo(InlineQueryResult):
input_message_content: Optional["InputMessageContent"] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence[MessageEntity]] = None,
show_caption_above_media: Optional[bool] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
@@ -183,3 +191,4 @@ class InlineQueryResultVideo(InlineQueryResult):
self.description: Optional[str] = description
self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup
self.input_message_content: Optional[InputMessageContent] = input_message_content
self.show_caption_above_media: Optional[bool] = show_caption_above_media
+38 -29
View File
@@ -49,12 +49,18 @@ class InputInvoiceMessageContent(InputMessageContent):
:tg-const:`telegram.Invoice.MAX_PAYLOAD_LENGTH` bytes. This will not be displayed
to the user, use for your internal processes.
provider_token (:obj:`str`): Payment provider token, obtained via
`@Botfather <https://t.me/Botfather>`_.
`@Botfather <https://t.me/Botfather>`_. Pass an empty string for payments in
|tg_stars|.
.. deprecated:: 21.3
As of Bot API 7.4, this parameter is now optional and future versions of the
library will make it optional as well.
currency (:obj:`str`): Three-letter ISO 4217 currency code, see more on
`currencies <https://core.telegram.org/bots/payments#supported-currencies>`_
`currencies <https://core.telegram.org/bots/payments#supported-currencies>`_.
Pass ``XTR`` for payments in |tg_stars|.
prices (Sequence[:class:`telegram.LabeledPrice`]): Price breakdown, a list of
components (e.g. product price, tax, discount, delivery cost, delivery tax, bonus,
etc.)
etc.). Must contain exactly one item for payments in |tg_stars|.
.. versionchanged:: 20.0
|sequenceclassargs|
@@ -64,7 +70,8 @@ class InputInvoiceMessageContent(InputMessageContent):
maximum tip of US$ 1.45 pass ``max_tip_amount = 145``. See the ``exp`` parameter in
`currencies.json <https://core.telegram.org/bots/payments/currencies.json>`_, it
shows the number of digits past the decimal point for each currency (2 for the majority
of currencies). Defaults to ``0``.
of currencies). Defaults to ``0``. Defaults to ``0``. Not supported for payments in
|tg_stars|.
suggested_tip_amounts (Sequence[:obj:`int`], optional): An array of suggested
amounts of tip in the *smallest* units of the currency (integer, **not** float/double).
At most 4 suggested tip amounts can be specified. The suggested tip amounts must be
@@ -85,20 +92,20 @@ class InputInvoiceMessageContent(InputMessageContent):
photo_size (:obj:`int`, optional): Photo size.
photo_width (:obj:`int`, optional): Photo width.
photo_height (:obj:`int`, optional): Photo height.
need_name (:obj:`bool`, optional): Pass :obj:`True`, if you require the user's full name to
complete the order.
need_name (:obj:`bool`, optional): Pass :obj:`True`, if you require the user's full
name to complete the order. Ignored for payments in |tg_stars|.
need_phone_number (:obj:`bool`, optional): Pass :obj:`True`, if you require the user's
phone number to complete the order
phone number to complete the order. Ignored for payments in |tg_stars|.
need_email (:obj:`bool`, optional): Pass :obj:`True`, if you require the user's email
address to complete the order.
need_shipping_address (:obj:`bool`, optional): Pass :obj:`True`, if you require the user's
shipping address to complete the order
send_phone_number_to_provider (:obj:`bool`, optional): Pass :obj:`True`, if user's phone
number should be sent to provider.
send_email_to_provider (:obj:`bool`, optional): Pass :obj:`True`, if user's email address
should be sent to provider.
is_flexible (:obj:`bool`, optional): Pass :obj:`True`, if the final price depends on the
shipping method.
address to complete the order. Ignored for payments in |tg_stars|.
need_shipping_address (:obj:`bool`, optional): Pass :obj:`True`, if you require the
user's shipping address to complete the order. Ignored for payments in |tg_stars|
send_phone_number_to_provider (:obj:`bool`, optional): Pass :obj:`True`, if user's
phone number should be sent to provider. Ignored for payments in |tg_stars|.
send_email_to_provider (:obj:`bool`, optional): Pass :obj:`True`, if user's email
address should be sent to provider. Ignored for payments in |tg_stars|.
is_flexible (:obj:`bool`, optional): Pass :obj:`True`, if the final price depends on
the shipping method. Ignored for payments in |tg_stars|.
Attributes:
title (:obj:`str`): Product name. :tg-const:`telegram.Invoice.MIN_TITLE_LENGTH`-
@@ -111,12 +118,14 @@ class InputInvoiceMessageContent(InputMessageContent):
:tg-const:`telegram.Invoice.MAX_PAYLOAD_LENGTH` bytes. This will not be displayed
to the user, use for your internal processes.
provider_token (:obj:`str`): Payment provider token, obtained via
`@Botfather <https://t.me/Botfather>`_.
`@Botfather <https://t.me/Botfather>`_. Pass an empty string for payments in `Telegram
Stars <https://t.me/BotNews/90>`_.
currency (:obj:`str`): Three-letter ISO 4217 currency code, see more on
`currencies <https://core.telegram.org/bots/payments#supported-currencies>`_
`currencies <https://core.telegram.org/bots/payments#supported-currencies>`_.
Pass ``XTR`` for payments in |tg_stars|.
prices (Tuple[:class:`telegram.LabeledPrice`]): Price breakdown, a list of
components (e.g. product price, tax, discount, delivery cost, delivery tax, bonus,
etc.)
etc.). Must contain exactly one item for payments in |tg_stars|.
.. versionchanged:: 20.0
|tupleclassattrs|
@@ -126,7 +135,7 @@ class InputInvoiceMessageContent(InputMessageContent):
maximum tip of US$ 1.45 ``max_tip_amount`` is ``145``. See the ``exp`` parameter in
`currencies.json <https://core.telegram.org/bots/payments/currencies.json>`_, it
shows the number of digits past the decimal point for each currency (2 for the majority
of currencies). Defaults to ``0``.
of currencies). Defaults to ``0``. Not supported for payments in |tg_stars|.
suggested_tip_amounts (Tuple[:obj:`int`]): Optional. An array of suggested
amounts of tip in the *smallest* units of the currency (integer, **not** float/double).
At most 4 suggested tip amounts can be specified. The suggested tip amounts must be
@@ -146,19 +155,19 @@ class InputInvoiceMessageContent(InputMessageContent):
photo_width (:obj:`int`): Optional. Photo width.
photo_height (:obj:`int`): Optional. Photo height.
need_name (:obj:`bool`): Optional. Pass :obj:`True`, if you require the user's full name to
complete the order.
complete the order. Ignored for payments in |tg_stars|.
need_phone_number (:obj:`bool`): Optional. Pass :obj:`True`, if you require the user's
phone number to complete the order
phone number to complete the order. Ignored for payments in |tg_stars|.
need_email (:obj:`bool`): Optional. Pass :obj:`True`, if you require the user's email
address to complete the order.
address to complete the order. Ignored for payments in |tg_stars|.
need_shipping_address (:obj:`bool`): Optional. Pass :obj:`True`, if you require the user's
shipping address to complete the order
shipping address to complete the order. Ignored for payments in |tg_stars|.
send_phone_number_to_provider (:obj:`bool`): Optional. Pass :obj:`True`, if user's phone
number should be sent to provider.
number should be sent to provider. Ignored for payments in |tg_stars|.
send_email_to_provider (:obj:`bool`): Optional. Pass :obj:`True`, if user's email address
should be sent to provider.
should be sent to provider. Ignored for payments in |tg_stars|.
is_flexible (:obj:`bool`): Optional. Pass :obj:`True`, if the final price depends on the
shipping method.
shipping method. Ignored for payments in |tg_stars|.
"""
@@ -190,7 +199,7 @@ class InputInvoiceMessageContent(InputMessageContent):
title: str,
description: str,
payload: str,
provider_token: str,
provider_token: Optional[str], # This arg is now optional since Bot API 7.4
currency: str,
prices: Sequence[LabeledPrice],
max_tip_amount: Optional[int] = None,
@@ -216,7 +225,7 @@ class InputInvoiceMessageContent(InputMessageContent):
self.title: str = title
self.description: str = description
self.payload: str = payload
self.provider_token: str = provider_token
self.provider_token: Optional[str] = provider_token
self.currency: str = currency
self.prices: Tuple[LabeledPrice, ...] = parse_sequence_arg(prices)
# Optionals
@@ -42,7 +42,9 @@ class InputLocationMessageContent(InputMessageContent):
live_period (:obj:`int`, optional): Period in seconds for which the location will be
updated, should be between
:tg-const:`telegram.InputLocationMessageContent.MIN_LIVE_PERIOD` and
:tg-const:`telegram.InputLocationMessageContent.MAX_LIVE_PERIOD`.
:tg-const:`telegram.InputLocationMessageContent.MAX_LIVE_PERIOD` or
:tg-const:`telegram.constants.LocationLimit.LIVE_PERIOD_FOREVER` for live
locations that can be edited indefinitely.
heading (:obj:`int`, optional): For live locations, a direction in which the user is
moving, in degrees. Must be between
:tg-const:`telegram.InputLocationMessageContent.MIN_HEADING` and
+2 -1
View File
@@ -32,7 +32,8 @@ if TYPE_CHECKING:
class KeyboardButton(TelegramObject):
"""
This object represents one button of the reply keyboard. For simple text buttons, :obj:`str`
This object represents one button of the reply keyboard. At most one of the optional fields
must be used to specify type of the button. For simple text buttons, :obj:`str`
can be used instead of this object to specify text of the button.
Objects of this class are comparable in terms of equality. Two objects of this class are
+163 -64
View File
@@ -25,6 +25,7 @@ from html import escape
from typing import TYPE_CHECKING, Dict, List, Optional, Sequence, Tuple, TypedDict, Union
from telegram._chat import Chat
from telegram._chatbackground import ChatBackground
from telegram._chatboost import ChatBoostAdded
from telegram._dice import Dice
from telegram._files.animation import Animation
@@ -64,6 +65,7 @@ from telegram._user import User
from telegram._utils.argumentparsing import parse_sequence_arg
from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp
from telegram._utils.defaultvalue import DEFAULT_NONE, DefaultValue
from telegram._utils.entities import parse_message_entities, parse_message_entity
from telegram._utils.types import (
CorrectOptionID,
FileInput,
@@ -99,6 +101,7 @@ if TYPE_CHECKING:
InputMediaDocument,
InputMediaPhoto,
InputMediaVideo,
InputPollOption,
LabeledPrice,
MessageId,
MessageOrigin,
@@ -198,7 +201,7 @@ class MaybeInaccessibleMessage(TelegramObject):
data["date"] = from_timestamp(data["date"], tzinfo=loc_tzinfo)
data["chat"] = Chat.de_json(data.get("chat"), bot)
return super()._de_json(data=data, bot=bot)
return super()._de_json(data=data, bot=bot, api_kwargs=api_kwargs)
class InaccessibleMessage(MaybeInaccessibleMessage):
@@ -252,8 +255,8 @@ class Message(MaybeInaccessibleMessage):
.. versionchanged:: 20.8
* This class is now a subclass of :class:`telegram.MaybeInaccessibleMessage`.
* The :paramref:`pinned_message` now can be either class:`telegram.Message` or
class:`telegram.InaccessibleMessage`.
* The :paramref:`pinned_message` now can be either :class:`telegram.Message` or
:class:`telegram.InaccessibleMessage`.
.. versionchanged:: 20.0
@@ -325,6 +328,11 @@ class Message(MaybeInaccessibleMessage):
.. versionadded:: 20.8
effect_id (:obj:`str`, optional): Unique identifier of the message effect added to the
message.
..versionadded:: 21.3
caption_entities (Sequence[:class:`telegram.MessageEntity`], optional): For messages with a
Caption. Special entities like usernames, URLs, bot commands, etc. that appear in the
caption. See :attr:`Message.parse_caption_entity` and :attr:`parse_caption_entities`
@@ -334,6 +342,9 @@ class Message(MaybeInaccessibleMessage):
.. versionchanged:: 20.0
|sequenceclassargs|
show_caption_above_media (:obj:`bool`, optional): |show_cap_above_med|
.. versionadded:: 21.3
audio (:class:`telegram.Audio`, optional): Message is an audio file, information
about the file.
document (:class:`telegram.Document`, optional): Message is a general file, information
@@ -408,8 +419,8 @@ class Message(MaybeInaccessibleMessage):
:attr:`reply_to_message` fields even if it is itself a reply.
.. versionchanged:: 20.8
This attribute now is either class:`telegram.Message` or
class:`telegram.InaccessibleMessage`.
This attribute now is either :class:`telegram.Message` or
:class:`telegram.InaccessibleMessage`.
invoice (:class:`telegram.Invoice`, optional): Message is an invoice for a payment,
information about the invoice.
successful_payment (:class:`telegram.SuccessfulPayment`, optional): Message is a service
@@ -553,6 +564,11 @@ class Message(MaybeInaccessibleMessage):
.. versionadded:: 21.1
chat_background_set (:obj:`telegram.ChatBackground`, optional): Service message: chat
background set.
.. versionadded:: 21.2
Attributes:
message_id (:obj:`int`): Unique message identifier inside this chat.
from_user (:class:`telegram.User`): Optional. Sender of the message; empty for messages
@@ -609,6 +625,11 @@ class Message(MaybeInaccessibleMessage):
.. versionadded:: 20.8
effect_id (:obj:`str`): Optional. Unique identifier of the message effect added to the
message.
..versionadded:: 21.3
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. For messages with a
Caption. Special entities like usernames, URLs, bot commands, etc. that appear in the
caption. See :attr:`Message.parse_caption_entity` and :attr:`parse_caption_entities`
@@ -618,6 +639,9 @@ class Message(MaybeInaccessibleMessage):
.. versionchanged:: 20.0
|tupleclassattrs|
show_caption_above_media (:obj:`bool`): Optional. |show_cap_above_med|
.. versionadded:: 21.3
audio (:class:`telegram.Audio`): Optional. Message is an audio file, information
about the file.
@@ -707,8 +731,8 @@ class Message(MaybeInaccessibleMessage):
:attr:`reply_to_message` fields even if it is itself a reply.
.. versionchanged:: 20.8
This attribute now is either class:`telegram.Message` or
class:`telegram.InaccessibleMessage`.
This attribute now is either :class:`telegram.Message` or
:class:`telegram.InaccessibleMessage`.
invoice (:class:`telegram.Invoice`): Optional. Message is an invoice for a payment,
information about the invoice.
successful_payment (:class:`telegram.SuccessfulPayment`): Optional. Message is a service
@@ -853,6 +877,11 @@ class Message(MaybeInaccessibleMessage):
.. versionadded:: 21.1
chat_background_set (:obj:`telegram.ChatBackground`): Optional. Service message: chat
background set
.. versionadded:: 21.2
.. |custom_emoji_no_md1_support| replace:: Since custom emoji entities are not supported by
:attr:`~telegram.constants.ParseMode.MARKDOWN`, this method now raises a
:exc:`ValueError` when encountering a custom emoji.
@@ -876,6 +905,7 @@ class Message(MaybeInaccessibleMessage):
"caption",
"caption_entities",
"channel_chat_created",
"chat_background_set",
"chat_shared",
"connected_website",
"contact",
@@ -883,6 +913,7 @@ class Message(MaybeInaccessibleMessage):
"dice",
"document",
"edit_date",
"effect_id",
"entities",
"external_reply",
"forum_topic_closed",
@@ -928,6 +959,7 @@ class Message(MaybeInaccessibleMessage):
"sender_boost_count",
"sender_business_bot",
"sender_chat",
"show_caption_above_media",
"sticker",
"story",
"successful_payment",
@@ -1029,6 +1061,9 @@ class Message(MaybeInaccessibleMessage):
business_connection_id: Optional[str] = None,
sender_business_bot: Optional[User] = None,
is_from_offline: Optional[bool] = None,
chat_background_set: Optional[ChatBackground] = None,
effect_id: Optional[str] = None,
show_caption_above_media: Optional[bool] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
@@ -1127,6 +1162,9 @@ class Message(MaybeInaccessibleMessage):
self.business_connection_id: Optional[str] = business_connection_id
self.sender_business_bot: Optional[User] = sender_business_bot
self.is_from_offline: Optional[bool] = is_from_offline
self.chat_background_set: Optional[ChatBackground] = chat_background_set
self.effect_id: Optional[str] = effect_id
self.show_caption_above_media: Optional[bool] = show_caption_above_media
self._effective_attachment = DEFAULT_NONE
@@ -1241,6 +1279,7 @@ class Message(MaybeInaccessibleMessage):
)
data["users_shared"] = UsersShared.de_json(data.get("users_shared"), bot)
data["chat_shared"] = ChatShared.de_json(data.get("chat_shared"), bot)
data["chat_background_set"] = ChatBackground.de_json(data.get("chat_background_set"), bot)
# Unfortunately, this needs to be here due to cyclic imports
from telegram._giveaway import ( # pylint: disable=import-outside-toplevel
@@ -1462,7 +1501,7 @@ class Message(MaybeInaccessibleMessage):
quote_index: Optional[int] = None,
target_chat_id: Optional[Union[int, str]] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
) -> _ReplyKwargs:
"""
Builds a dictionary with the keys ``chat_id`` and ``reply_parameters``. This dictionary can
@@ -1562,9 +1601,11 @@ class Message(MaybeInaccessibleMessage):
if quote is not None:
warn(
"The `quote` parameter is deprecated in favor of the `do_quote` parameter. Please "
"update your code to use `do_quote` instead.",
PTBDeprecationWarning,
PTBDeprecationWarning(
"20.8",
"The `quote` parameter is deprecated in favor of the `do_quote` parameter. "
"Please update your code to use `do_quote` instead.",
),
stacklevel=2,
)
@@ -1587,11 +1628,22 @@ class Message(MaybeInaccessibleMessage):
def _parse_message_thread_id(
self,
chat_id: Union[str, int],
message_thread_id: Optional[int] = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
) -> Optional[int]:
return message_thread_id or (
self.message_thread_id if chat_id in {self.chat_id, self.chat.username} else None
)
# values set by user have the highest priority
if not isinstance(message_thread_id, DefaultValue):
return message_thread_id
# self.message_thread_id can be used for send_*.param.message_thread_id only if the
# thread is a forum topic. It does not work if the thread is a chain of replies to a
# message in a normal group. In that case, self.message_thread_id is just the message_id
# of the first message in the chain.
if not self.is_topic_message:
return None
# Setting message_thread_id=self.message_thread_id only makes sense if we're replying in
# the same chat.
return self.message_thread_id if chat_id in {self.chat_id, self.chat.username} else None
async def reply_text(
self,
@@ -1601,9 +1653,10 @@ class Message(MaybeInaccessibleMessage):
reply_markup: Optional[ReplyMarkup] = None,
entities: Optional[Sequence["MessageEntity"]] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
link_preview_options: ODVInput["LinkPreviewOptions"] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1668,6 +1721,7 @@ class Message(MaybeInaccessibleMessage):
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
)
async def reply_markdown(
@@ -1677,9 +1731,10 @@ class Message(MaybeInaccessibleMessage):
reply_markup: Optional[ReplyMarkup] = None,
entities: Optional[Sequence["MessageEntity"]] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
link_preview_options: ODVInput["LinkPreviewOptions"] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1750,6 +1805,7 @@ class Message(MaybeInaccessibleMessage):
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
)
async def reply_markdown_v2(
@@ -1759,9 +1815,10 @@ class Message(MaybeInaccessibleMessage):
reply_markup: Optional[ReplyMarkup] = None,
entities: Optional[Sequence["MessageEntity"]] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
link_preview_options: ODVInput["LinkPreviewOptions"] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1828,6 +1885,7 @@ class Message(MaybeInaccessibleMessage):
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
)
async def reply_html(
@@ -1837,9 +1895,10 @@ class Message(MaybeInaccessibleMessage):
reply_markup: Optional[ReplyMarkup] = None,
entities: Optional[Sequence["MessageEntity"]] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
link_preview_options: ODVInput["LinkPreviewOptions"] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1906,6 +1965,7 @@ class Message(MaybeInaccessibleMessage):
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
)
async def reply_media_group(
@@ -1915,8 +1975,9 @@ class Message(MaybeInaccessibleMessage):
],
disable_notification: ODVInput[bool] = DEFAULT_NONE,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1983,6 +2044,7 @@ class Message(MaybeInaccessibleMessage):
parse_mode=parse_mode,
caption_entities=caption_entities,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
)
async def reply_photo(
@@ -1994,9 +2056,11 @@ class Message(MaybeInaccessibleMessage):
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
has_spoiler: Optional[bool] = None,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
show_caption_above_media: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2062,6 +2126,8 @@ class Message(MaybeInaccessibleMessage):
api_kwargs=api_kwargs,
has_spoiler=has_spoiler,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
show_caption_above_media=show_caption_above_media,
)
async def reply_audio(
@@ -2076,9 +2142,10 @@ class Message(MaybeInaccessibleMessage):
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2147,6 +2214,7 @@ class Message(MaybeInaccessibleMessage):
api_kwargs=api_kwargs,
thumbnail=thumbnail,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
)
async def reply_document(
@@ -2159,9 +2227,10 @@ class Message(MaybeInaccessibleMessage):
disable_content_type_detection: Optional[bool] = None,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2228,6 +2297,7 @@ class Message(MaybeInaccessibleMessage):
message_thread_id=message_thread_id,
thumbnail=thumbnail,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
)
async def reply_animation(
@@ -2242,10 +2312,12 @@ class Message(MaybeInaccessibleMessage):
reply_markup: Optional[ReplyMarkup] = None,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
has_spoiler: Optional[bool] = None,
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
show_caption_above_media: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2315,6 +2387,8 @@ class Message(MaybeInaccessibleMessage):
has_spoiler=has_spoiler,
thumbnail=thumbnail,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
show_caption_above_media=show_caption_above_media,
)
async def reply_sticker(
@@ -2323,9 +2397,10 @@ class Message(MaybeInaccessibleMessage):
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_markup: Optional[ReplyMarkup] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
emoji: Optional[str] = None,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2386,6 +2461,7 @@ class Message(MaybeInaccessibleMessage):
message_thread_id=message_thread_id,
emoji=emoji,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
)
async def reply_video(
@@ -2401,10 +2477,12 @@ class Message(MaybeInaccessibleMessage):
supports_streaming: Optional[bool] = None,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
has_spoiler: Optional[bool] = None,
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
show_caption_above_media: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2475,6 +2553,8 @@ class Message(MaybeInaccessibleMessage):
has_spoiler=has_spoiler,
thumbnail=thumbnail,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
show_caption_above_media=show_caption_above_media,
)
async def reply_video_note(
@@ -2485,9 +2565,10 @@ class Message(MaybeInaccessibleMessage):
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_markup: Optional[ReplyMarkup] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2552,6 +2633,7 @@ class Message(MaybeInaccessibleMessage):
message_thread_id=message_thread_id,
thumbnail=thumbnail,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
)
async def reply_voice(
@@ -2564,8 +2646,9 @@ class Message(MaybeInaccessibleMessage):
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2631,6 +2714,7 @@ class Message(MaybeInaccessibleMessage):
protect_content=protect_content,
message_thread_id=message_thread_id,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
)
async def reply_location(
@@ -2644,8 +2728,9 @@ class Message(MaybeInaccessibleMessage):
heading: Optional[int] = None,
proximity_alert_radius: Optional[int] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2712,6 +2797,7 @@ class Message(MaybeInaccessibleMessage):
protect_content=protect_content,
message_thread_id=message_thread_id,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
)
async def reply_venue(
@@ -2727,8 +2813,9 @@ class Message(MaybeInaccessibleMessage):
google_place_id: Optional[str] = None,
google_place_type: Optional[str] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2797,6 +2884,7 @@ class Message(MaybeInaccessibleMessage):
protect_content=protect_content,
message_thread_id=message_thread_id,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
)
async def reply_contact(
@@ -2808,8 +2896,9 @@ class Message(MaybeInaccessibleMessage):
reply_markup: Optional[ReplyMarkup] = None,
vcard: Optional[str] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2874,12 +2963,13 @@ class Message(MaybeInaccessibleMessage):
protect_content=protect_content,
message_thread_id=message_thread_id,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
)
async def reply_poll(
self,
question: str,
options: Sequence[str],
options: Sequence[Union[str, "InputPollOption"]],
is_anonymous: Optional[bool] = None,
type: Optional[str] = None, # pylint: disable=redefined-builtin
allows_multiple_answers: Optional[bool] = None,
@@ -2893,8 +2983,11 @@ class Message(MaybeInaccessibleMessage):
close_date: Optional[Union[int, datetime.datetime]] = None,
explanation_entities: Optional[Sequence["MessageEntity"]] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
question_parse_mode: ODVInput[str] = DEFAULT_NONE,
question_entities: Optional[Sequence["MessageEntity"]] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2965,6 +3058,9 @@ class Message(MaybeInaccessibleMessage):
protect_content=protect_content,
message_thread_id=message_thread_id,
business_connection_id=self.business_connection_id,
question_parse_mode=question_parse_mode,
question_entities=question_entities,
message_effect_id=message_effect_id,
)
async def reply_dice(
@@ -2973,8 +3069,9 @@ class Message(MaybeInaccessibleMessage):
reply_markup: Optional[ReplyMarkup] = None,
emoji: Optional[str] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -3034,12 +3131,13 @@ class Message(MaybeInaccessibleMessage):
protect_content=protect_content,
message_thread_id=message_thread_id,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
)
async def reply_chat_action(
self,
action: str,
message_thread_id: Optional[int] = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -3086,8 +3184,9 @@ class Message(MaybeInaccessibleMessage):
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_markup: Optional["InlineKeyboardMarkup"] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -3149,6 +3248,7 @@ class Message(MaybeInaccessibleMessage):
protect_content=protect_content,
message_thread_id=message_thread_id,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
)
async def reply_invoice(
@@ -3156,7 +3256,7 @@ class Message(MaybeInaccessibleMessage):
title: str,
description: str,
payload: str,
provider_token: str,
provider_token: Optional[str],
currency: str,
prices: Sequence["LabeledPrice"],
start_parameter: Optional[str] = None,
@@ -3177,8 +3277,9 @@ class Message(MaybeInaccessibleMessage):
max_tip_amount: Optional[int] = None,
suggested_tip_amounts: Optional[Sequence[int]] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -3268,6 +3369,7 @@ class Message(MaybeInaccessibleMessage):
suggested_tip_amounts=suggested_tip_amounts,
protect_content=protect_content,
message_thread_id=message_thread_id,
message_effect_id=message_effect_id,
)
async def forward(
@@ -3297,7 +3399,7 @@ class Message(MaybeInaccessibleMessage):
Note:
Since the release of Bot API 5.5 it can be impossible to forward messages from
some chats. Use the attributes :attr:`telegram.Message.has_protected_content` and
:attr:`telegram.Chat.has_protected_content` to check this.
:attr:`telegram.ChatFullInfo.has_protected_content` to check this.
As a workaround, it is still possible to use :meth:`copy`. However, this
behaviour is undocumented and might be changed by Telegram.
@@ -3331,6 +3433,7 @@ class Message(MaybeInaccessibleMessage):
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
show_caption_above_media: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -3375,6 +3478,7 @@ class Message(MaybeInaccessibleMessage):
api_kwargs=api_kwargs,
protect_content=protect_content,
message_thread_id=message_thread_id,
show_caption_above_media=show_caption_above_media,
)
async def reply_copy(
@@ -3387,8 +3491,9 @@ class Message(MaybeInaccessibleMessage):
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_markup: Optional[ReplyMarkup] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
message_thread_id: ODVInput[int] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
show_caption_above_media: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -3452,6 +3557,7 @@ class Message(MaybeInaccessibleMessage):
api_kwargs=api_kwargs,
protect_content=protect_content,
message_thread_id=message_thread_id,
show_caption_above_media=show_caption_above_media,
)
async def edit_text(
@@ -3510,6 +3616,7 @@ class Message(MaybeInaccessibleMessage):
reply_markup: Optional["InlineKeyboardMarkup"] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
show_caption_above_media: Optional[bool] = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -3549,6 +3656,7 @@ class Message(MaybeInaccessibleMessage):
api_kwargs=api_kwargs,
caption_entities=caption_entities,
inline_message_id=None,
show_caption_above_media=show_caption_above_media,
)
async def edit_media(
@@ -3642,6 +3750,7 @@ class Message(MaybeInaccessibleMessage):
horizontal_accuracy: Optional[float] = None,
heading: Optional[int] = None,
proximity_alert_radius: Optional[int] = None,
live_period: Optional[int] = None,
*,
location: Optional[Location] = None,
read_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -3683,6 +3792,7 @@ class Message(MaybeInaccessibleMessage):
horizontal_accuracy=horizontal_accuracy,
heading=heading,
proximity_alert_radius=proximity_alert_radius,
live_period=live_period,
inline_message_id=None,
)
@@ -4173,9 +4283,7 @@ class Message(MaybeInaccessibleMessage):
if not self.text:
raise RuntimeError("This Message has no 'text'.")
entity_text = self.text.encode("utf-16-le")
entity_text = entity_text[entity.offset * 2 : (entity.offset + entity.length) * 2]
return entity_text.decode("utf-16-le")
return parse_message_entity(self.text, entity)
def parse_caption_entity(self, entity: MessageEntity) -> str:
"""Returns the text from a given :class:`telegram.MessageEntity`.
@@ -4199,9 +4307,7 @@ class Message(MaybeInaccessibleMessage):
if not self.caption:
raise RuntimeError("This Message has no 'caption'.")
entity_text = self.caption.encode("utf-16-le")
entity_text = entity_text[entity.offset * 2 : (entity.offset + entity.length) * 2]
return entity_text.decode("utf-16-le")
return parse_message_entity(self.caption, entity)
def parse_entities(self, types: Optional[List[str]] = None) -> Dict[MessageEntity, str]:
"""
@@ -4226,12 +4332,7 @@ class Message(MaybeInaccessibleMessage):
the text that belongs to them, calculated based on UTF-16 codepoints.
"""
if types is None:
types = MessageEntity.ALL_TYPES
return {
entity: self.parse_entity(entity) for entity in self.entities if entity.type in types
}
return parse_message_entities(self.text, self.entities, types=types)
def parse_caption_entities(
self, types: Optional[List[str]] = None
@@ -4258,14 +4359,7 @@ class Message(MaybeInaccessibleMessage):
the text that belongs to them, calculated based on UTF-16 codepoints.
"""
if types is None:
types = MessageEntity.ALL_TYPES
return {
entity: self.parse_caption_entity(entity)
for entity in self.caption_entities
if entity.type in types
}
return parse_message_entities(self.caption, self.caption_entities, types=types)
@classmethod
def _parse_html(
@@ -4313,6 +4407,8 @@ class Message(MaybeInaccessibleMessage):
insert = f'<a href="{escaped_text}">{escaped_text}</a>'
elif entity.type == MessageEntity.BLOCKQUOTE:
insert = f"<blockquote>{escaped_text}</blockquote>"
elif entity.type == MessageEntity.EXPANDABLE_BLOCKQUOTE:
insert = f"<blockquote expandable>{escaped_text}</blockquote>"
elif entity.type == MessageEntity.BOLD:
insert = f"<b>{escaped_text}</b>"
elif entity.type == MessageEntity.ITALIC:
@@ -4463,11 +4559,12 @@ class Message(MaybeInaccessibleMessage):
) -> Optional[str]:
if version == 1:
for entity_type in (
MessageEntity.UNDERLINE,
MessageEntity.STRIKETHROUGH,
MessageEntity.SPOILER,
MessageEntity.EXPANDABLE_BLOCKQUOTE,
MessageEntity.BLOCKQUOTE,
MessageEntity.CUSTOM_EMOJI,
MessageEntity.SPOILER,
MessageEntity.STRIKETHROUGH,
MessageEntity.UNDERLINE,
):
if any(entity.type == entity_type for entity in entities):
name = entity_type.name.title().replace("_", " ") # type:ignore[attr-defined]
@@ -4547,8 +4644,10 @@ class Message(MaybeInaccessibleMessage):
insert = f"~{escaped_text}~"
elif entity.type == MessageEntity.SPOILER:
insert = f"||{escaped_text}||"
elif entity.type == MessageEntity.BLOCKQUOTE:
elif entity.type in (MessageEntity.BLOCKQUOTE, MessageEntity.EXPANDABLE_BLOCKQUOTE):
insert = ">" + "\n>".join(escaped_text.splitlines())
if entity.type == MessageEntity.EXPANDABLE_BLOCKQUOTE:
insert = f"{insert}||"
elif entity.type == MessageEntity.CUSTOM_EMOJI:
# This should never be needed because ids are numeric but the documentation
# specifically mentions it so here we are
+40 -35
View File
@@ -140,50 +140,55 @@ class MessageEntity(TelegramObject):
return super().de_json(data=data, bot=bot)
MENTION: Final[str] = constants.MessageEntityType.MENTION
""":const:`telegram.constants.MessageEntityType.MENTION`"""
HASHTAG: Final[str] = constants.MessageEntityType.HASHTAG
""":const:`telegram.constants.MessageEntityType.HASHTAG`"""
CASHTAG: Final[str] = constants.MessageEntityType.CASHTAG
""":const:`telegram.constants.MessageEntityType.CASHTAG`"""
PHONE_NUMBER: Final[str] = constants.MessageEntityType.PHONE_NUMBER
""":const:`telegram.constants.MessageEntityType.PHONE_NUMBER`"""
BOT_COMMAND: Final[str] = constants.MessageEntityType.BOT_COMMAND
""":const:`telegram.constants.MessageEntityType.BOT_COMMAND`"""
URL: Final[str] = constants.MessageEntityType.URL
""":const:`telegram.constants.MessageEntityType.URL`"""
EMAIL: Final[str] = constants.MessageEntityType.EMAIL
""":const:`telegram.constants.MessageEntityType.EMAIL`"""
ALL_TYPES: Final[List[str]] = list(constants.MessageEntityType)
"""List[:obj:`str`]: A list of all available message entity types."""
BLOCKQUOTE: Final[str] = constants.MessageEntityType.BLOCKQUOTE
""":const:`telegram.constants.MessageEntityType.BLOCKQUOTE`
.. versionadded:: 20.8
"""
BOLD: Final[str] = constants.MessageEntityType.BOLD
""":const:`telegram.constants.MessageEntityType.BOLD`"""
ITALIC: Final[str] = constants.MessageEntityType.ITALIC
""":const:`telegram.constants.MessageEntityType.ITALIC`"""
BOT_COMMAND: Final[str] = constants.MessageEntityType.BOT_COMMAND
""":const:`telegram.constants.MessageEntityType.BOT_COMMAND`"""
CASHTAG: Final[str] = constants.MessageEntityType.CASHTAG
""":const:`telegram.constants.MessageEntityType.CASHTAG`"""
CODE: Final[str] = constants.MessageEntityType.CODE
""":const:`telegram.constants.MessageEntityType.CODE`"""
CUSTOM_EMOJI: Final[str] = constants.MessageEntityType.CUSTOM_EMOJI
""":const:`telegram.constants.MessageEntityType.CUSTOM_EMOJI`
.. versionadded:: 20.0
"""
EMAIL: Final[str] = constants.MessageEntityType.EMAIL
""":const:`telegram.constants.MessageEntityType.EMAIL`"""
EXPANDABLE_BLOCKQUOTE: Final[str] = constants.MessageEntityType.EXPANDABLE_BLOCKQUOTE
""":const:`telegram.constants.MessageEntityType.EXPANDABLE_BLOCKQUOTE`
.. versionadded:: 21.3
"""
HASHTAG: Final[str] = constants.MessageEntityType.HASHTAG
""":const:`telegram.constants.MessageEntityType.HASHTAG`"""
ITALIC: Final[str] = constants.MessageEntityType.ITALIC
""":const:`telegram.constants.MessageEntityType.ITALIC`"""
MENTION: Final[str] = constants.MessageEntityType.MENTION
""":const:`telegram.constants.MessageEntityType.MENTION`"""
PHONE_NUMBER: Final[str] = constants.MessageEntityType.PHONE_NUMBER
""":const:`telegram.constants.MessageEntityType.PHONE_NUMBER`"""
PRE: Final[str] = constants.MessageEntityType.PRE
""":const:`telegram.constants.MessageEntityType.PRE`"""
SPOILER: Final[str] = constants.MessageEntityType.SPOILER
""":const:`telegram.constants.MessageEntityType.SPOILER`
.. versionadded:: 13.10
"""
STRIKETHROUGH: Final[str] = constants.MessageEntityType.STRIKETHROUGH
""":const:`telegram.constants.MessageEntityType.STRIKETHROUGH`"""
TEXT_LINK: Final[str] = constants.MessageEntityType.TEXT_LINK
""":const:`telegram.constants.MessageEntityType.TEXT_LINK`"""
TEXT_MENTION: Final[str] = constants.MessageEntityType.TEXT_MENTION
""":const:`telegram.constants.MessageEntityType.TEXT_MENTION`"""
UNDERLINE: Final[str] = constants.MessageEntityType.UNDERLINE
""":const:`telegram.constants.MessageEntityType.UNDERLINE`"""
STRIKETHROUGH: Final[str] = constants.MessageEntityType.STRIKETHROUGH
""":const:`telegram.constants.MessageEntityType.STRIKETHROUGH`"""
SPOILER: Final[str] = constants.MessageEntityType.SPOILER
""":const:`telegram.constants.MessageEntityType.SPOILER`
.. versionadded:: 13.10
"""
CUSTOM_EMOJI: Final[str] = constants.MessageEntityType.CUSTOM_EMOJI
""":const:`telegram.constants.MessageEntityType.CUSTOM_EMOJI`
.. versionadded:: 20.0
"""
BLOCKQUOTE: Final[str] = constants.MessageEntityType.BLOCKQUOTE
""":const:`telegram.constants.MessageEntityType.BLOCKQUOTE`
.. versionadded:: 20.8
"""
ALL_TYPES: Final[List[str]] = list(constants.MessageEntityType)
"""List[:obj:`str`]: A list of all available message entity types."""
URL: Final[str] = constants.MessageEntityType.URL
""":const:`telegram.constants.MessageEntityType.URL`"""
+3 -3
View File
@@ -153,15 +153,15 @@ class EncryptedCredentials(TelegramObject):
self._id_attrs = (self.data, self.hash, self.secret)
self._decrypted_secret: Optional[str] = None
self._decrypted_secret: Optional[bytes] = None
self._decrypted_data: Optional[Credentials] = None
self._freeze()
@property
def decrypted_secret(self) -> str:
def decrypted_secret(self) -> bytes:
"""
:obj:`str`: Lazily decrypt and return secret.
:obj:`bytes`: Lazily decrypt and return secret.
Raises:
telegram.error.PassportDecryptionError: Decryption failed. Usually due to bad
@@ -157,7 +157,10 @@ class EncryptedPassportElement(TelegramObject):
reverse_side: Optional[PassportFile] = None,
selfie: Optional[PassportFile] = None,
translation: Optional[Sequence[PassportFile]] = None,
credentials: Optional["Credentials"] = None, # pylint: disable=unused-argument
# TODO: Remove the credentials argument in 22.0 or later
credentials: Optional[ # pylint: disable=unused-argument # noqa: ARG002
"Credentials"
] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
+11 -7
View File
@@ -210,9 +210,11 @@ class PassportElementErrorFiles(PassportElementError):
This attribute will return a tuple instead of a list in future major versions.
"""
warn(
"The attribute `file_hashes` will return a tuple instead of a list in future major"
" versions.",
PTBDeprecationWarning,
PTBDeprecationWarning(
"20.6",
"The attribute `file_hashes` will return a tuple instead of a list in future major"
" versions.",
),
stacklevel=2,
)
return self._file_hashes
@@ -427,10 +429,12 @@ class PassportElementErrorTranslationFiles(PassportElementError):
This attribute will return a tuple instead of a list in future major versions.
"""
warn(
"The attribute `file_hashes` will return a tuple instead of a list in future major"
" versions. See the stability policy:"
" https://docs.python-telegram-bot.org/en/stable/stability_policy.html",
PTBDeprecationWarning,
PTBDeprecationWarning(
"20.6",
"The attribute `file_hashes` will return a tuple instead of a list in future major"
" versions. See the stability policy:"
" https://docs.python-telegram-bot.org/en/stable/stability_policy.html",
),
stacklevel=2,
)
return self._file_hashes
+5 -3
View File
@@ -107,9 +107,11 @@ class PassportFile(TelegramObject):
This attribute will return a datetime instead of a integer in future major versions.
"""
warn(
"The attribute `file_date` will return a datetime instead of an integer in future"
" major versions.",
PTBDeprecationWarning,
PTBDeprecationWarning(
"20.6",
"The attribute `file_date` will return a datetime instead of an integer in future"
" major versions.",
),
stacklevel=2,
)
return self._file_date
+4 -2
View File
@@ -37,7 +37,8 @@ class Invoice(TelegramObject):
description (:obj:`str`): Product description.
start_parameter (:obj:`str`): Unique bot deep-linking parameter that can be used to
generate this invoice.
currency (:obj:`str`): Three-letter ISO 4217 currency code.
currency (:obj:`str`): Three-letter ISO 4217 currency code, or ``XTR`` for payments in
|tg_stars|.
total_amount (:obj:`int`): Total price in the smallest units of the currency (integer, not
float/double). For example, for a price of US$ 1.45 pass ``amount = 145``. See the
``exp`` parameter in
@@ -50,7 +51,8 @@ class Invoice(TelegramObject):
description (:obj:`str`): Product description.
start_parameter (:obj:`str`): Unique bot deep-linking parameter that can be used to
generate this invoice.
currency (:obj:`str`): Three-letter ISO 4217 currency code.
currency (:obj:`str`): Three-letter ISO 4217 currency code, or ``XTR`` for payments in
|tg_stars|.
total_amount (:obj:`int`): Total price in the smallest units of the currency (integer, not
float/double). For example, for a price of US$ 1.45 ``amount`` is ``145``. See the
``exp`` parameter in
+4 -2
View File
@@ -42,7 +42,8 @@ class PreCheckoutQuery(TelegramObject):
Args:
id (:obj:`str`): Unique query identifier.
from_user (:class:`telegram.User`): User who sent the query.
currency (:obj:`str`): Three-letter ISO 4217 currency code.
currency (:obj:`str`): Three-letter ISO 4217 currency code, or ``XTR`` for payments in
|tg_stars|.
total_amount (:obj:`int`): Total price in the smallest units of the currency (integer, not
float/double). For example, for a price of US$ 1.45 pass ``amount = 145``.
See the ``exp`` parameter in
@@ -57,7 +58,8 @@ class PreCheckoutQuery(TelegramObject):
Attributes:
id (:obj:`str`): Unique query identifier.
from_user (:class:`telegram.User`): User who sent the query.
currency (:obj:`str`): Three-letter ISO 4217 currency code.
currency (:obj:`str`): Three-letter ISO 4217 currency code, or ``XTR`` for payments in
|tg_stars|.
total_amount (:obj:`int`): Total price in the smallest units of the currency (integer, not
float/double). For example, for a price of US$ 1.45 ``amount`` is ``145``.
See the ``exp`` parameter in
+4 -2
View File
@@ -36,7 +36,8 @@ class SuccessfulPayment(TelegramObject):
:attr:`provider_payment_charge_id` are equal.
Args:
currency (:obj:`str`): Three-letter ISO 4217 currency code.
currency (:obj:`str`): Three-letter ISO 4217 currency code, or ``XTR`` for payments in
|tg_stars|.
total_amount (:obj:`int`): Total price in the smallest units of the currency (integer, not
float/double). For example, for a price of US$ 1.45 pass ``amount = 145``.
See the ``exp`` parameter in
@@ -51,7 +52,8 @@ class SuccessfulPayment(TelegramObject):
provider_payment_charge_id (:obj:`str`): Provider payment identifier.
Attributes:
currency (:obj:`str`): Three-letter ISO 4217 currency code.
currency (:obj:`str`): Three-letter ISO 4217 currency code, or ``XTR`` for payments in
|tg_stars|.
total_amount (:obj:`int`): Total price in the smallest units of the currency (integer, not
float/double). For example, for a price of US$ 1.45 ``amount`` is ``145``.
See the ``exp`` parameter in
+219 -17
View File
@@ -28,12 +28,80 @@ from telegram._user import User
from telegram._utils import enum
from telegram._utils.argumentparsing import parse_sequence_arg
from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp
from telegram._utils.types import JSONDict
from telegram._utils.defaultvalue import DEFAULT_NONE
from telegram._utils.entities import parse_message_entities, parse_message_entity
from telegram._utils.types import JSONDict, ODVInput
if TYPE_CHECKING:
from telegram import Bot
class InputPollOption(TelegramObject):
"""
This object contains information about one answer option in a poll to send.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`text` is equal.
.. versionadded:: 21.2
Args:
text (:obj:`str`): Option text,
:tg-const:`telegram.PollOption.MIN_LENGTH`-:tg-const:`telegram.PollOption.MAX_LENGTH`
characters.
text_parse_mode (:obj:`str`, optional): |parse_mode|
Currently, only custom emoji entities are allowed.
text_entities (Sequence[:class:`telegram.MessageEntity`], optional): Special entities
that appear in the option :paramref:`text`. It can be specified instead of
:paramref:`text_parse_mode`.
Currently, only custom emoji entities are allowed.
This list is empty if the text does not contain entities.
Attributes:
text (:obj:`str`): Option text,
:tg-const:`telegram.PollOption.MIN_LENGTH`-:tg-const:`telegram.PollOption.MAX_LENGTH`
characters.
text_parse_mode (:obj:`str`): Optional. |parse_mode|
Currently, only custom emoji entities are allowed.
text_entities (Sequence[:class:`telegram.MessageEntity`]): Special entities
that appear in the option :paramref:`text`. It can be specified instead of
:paramref:`text_parse_mode`.
Currently, only custom emoji entities are allowed.
This list is empty if the text does not contain entities.
"""
__slots__ = ("text", "text_entities", "text_parse_mode")
def __init__(
self,
text: str,
text_parse_mode: ODVInput[str] = DEFAULT_NONE,
text_entities: Optional[Sequence[MessageEntity]] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(api_kwargs=api_kwargs)
self.text: str = text
self.text_parse_mode: ODVInput[str] = text_parse_mode
self.text_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(text_entities)
self._id_attrs = (self.text,)
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["InputPollOption"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if not data:
return None
data["text_entities"] = MessageEntity.de_list(data.get("text_entities"), bot)
return super().de_json(data=data, bot=bot)
class PollOption(TelegramObject):
"""
This object contains information about one answer option in a poll.
@@ -46,26 +114,101 @@ class PollOption(TelegramObject):
:tg-const:`telegram.PollOption.MIN_LENGTH`-:tg-const:`telegram.PollOption.MAX_LENGTH`
characters.
voter_count (:obj:`int`): Number of users that voted for this option.
text_entities (Sequence[:class:`telegram.MessageEntity`], optional): Special entities
that appear in the option text. Currently, only custom emoji entities are allowed in
poll option texts.
.. versionadded:: 21.2
Attributes:
text (:obj:`str`): Option text,
:tg-const:`telegram.PollOption.MIN_LENGTH`-:tg-const:`telegram.PollOption.MAX_LENGTH`
characters.
voter_count (:obj:`int`): Number of users that voted for this option.
text_entities (Tuple[:class:`telegram.MessageEntity`]): Special entities
that appear in the option text. Currently, only custom emoji entities are allowed in
poll option texts.
This list is empty if the question does not contain entities.
.. versionadded:: 21.2
"""
__slots__ = ("text", "voter_count")
__slots__ = ("text", "text_entities", "voter_count")
def __init__(self, text: str, voter_count: int, *, api_kwargs: Optional[JSONDict] = None):
def __init__(
self,
text: str,
voter_count: int,
text_entities: Optional[Sequence[MessageEntity]] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(api_kwargs=api_kwargs)
self.text: str = text
self.voter_count: int = voter_count
self.text_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(text_entities)
self._id_attrs = (self.text, self.voter_count)
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["PollOption"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if not data:
return None
data["text_entities"] = MessageEntity.de_list(data.get("text_entities"), bot)
return super().de_json(data=data, bot=bot)
def parse_entity(self, entity: MessageEntity) -> str:
"""Returns the text in :attr:`text`
from a given :class:`telegram.MessageEntity` of :attr:`text_entities`.
Note:
This method is present because Telegram calculates the offset and length in
UTF-16 codepoint pairs, which some versions of Python don't handle automatically.
(That is, you can't just slice ``Message.text`` with the offset and length.)
.. versionadded:: 21.2
Args:
entity (:class:`telegram.MessageEntity`): The entity to extract the text from. It must
be an entity that belongs to :attr:`text_entities`.
Returns:
:obj:`str`: The text of the given entity.
"""
return parse_message_entity(self.text, entity)
def parse_entities(self, types: Optional[List[str]] = None) -> Dict[MessageEntity, str]:
"""
Returns a :obj:`dict` that maps :class:`telegram.MessageEntity` to :obj:`str`.
It contains entities from this polls question filtered by their ``type`` attribute as
the key, and the text that each entity belongs to as the value of the :obj:`dict`.
Note:
This method should always be used instead of the :attr:`text_entities`
attribute, since it calculates the correct substring from the message text based on
UTF-16 codepoints. See :attr:`parse_entity` for more info.
.. versionadded:: 21.2
Args:
types (List[:obj:`str`], optional): List of ``MessageEntity`` types as strings. If the
``type`` attribute of an entity is contained in this list, it will be returned.
Defaults to :attr:`telegram.MessageEntity.ALL_TYPES`.
Returns:
Dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
the text that belongs to them, calculated based on UTF-16 codepoints.
"""
return parse_message_entities(self.text, self.text_entities, types)
MIN_LENGTH: Final[int] = constants.PollLimit.MIN_OPTION_LENGTH
""":const:`telegram.constants.PollLimit.MIN_OPTION_LENGTH`
@@ -215,6 +358,11 @@ class Poll(TelegramObject):
.. versionchanged:: 20.3
|datetime_localization|
question_entities (Sequence[:class:`telegram.MessageEntity`], optional): Special entities
that appear in the :attr:`question`. Currently, only custom emoji entities are allowed
in poll questions.
.. versionadded:: 21.2
Attributes:
id (:obj:`str`): Unique poll identifier.
@@ -251,6 +399,12 @@ class Poll(TelegramObject):
.. versionchanged:: 20.3
|datetime_localization|
question_entities (Tuple[:class:`telegram.MessageEntity`]): Special entities
that appear in the :attr:`question`. Currently, only custom emoji entities are allowed
in poll questions.
This list is empty if the question does not contain entities.
.. versionadded:: 21.2
"""
@@ -266,6 +420,7 @@ class Poll(TelegramObject):
"open_period",
"options",
"question",
"question_entities",
"total_voter_count",
"type",
)
@@ -285,6 +440,7 @@ class Poll(TelegramObject):
explanation_entities: Optional[Sequence[MessageEntity]] = None,
open_period: Optional[int] = None,
close_date: Optional[datetime.datetime] = None,
question_entities: Optional[Sequence[MessageEntity]] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
@@ -304,6 +460,7 @@ class Poll(TelegramObject):
)
self.open_period: Optional[int] = open_period
self.close_date: Optional[datetime.datetime] = close_date
self.question_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(question_entities)
self._id_attrs = (self.id,)
@@ -323,11 +480,13 @@ class Poll(TelegramObject):
data["options"] = [PollOption.de_json(option, bot) for option in data["options"]]
data["explanation_entities"] = MessageEntity.de_list(data.get("explanation_entities"), bot)
data["close_date"] = from_timestamp(data.get("close_date"), tzinfo=loc_tzinfo)
data["question_entities"] = MessageEntity.de_list(data.get("question_entities"), bot)
return super().de_json(data=data, bot=bot)
def parse_explanation_entity(self, entity: MessageEntity) -> str:
"""Returns the text from a given :class:`telegram.MessageEntity`.
"""Returns the text in :attr:`explanation` from a given :class:`telegram.MessageEntity` of
:attr:`explanation_entities`.
Note:
This method is present because Telegram calculates the offset and length in
@@ -336,7 +495,7 @@ class Poll(TelegramObject):
Args:
entity (:class:`telegram.MessageEntity`): The entity to extract the text from. It must
be an entity that belongs to this message.
be an entity that belongs to :attr:`explanation_entities`.
Returns:
:obj:`str`: The text of the given entity.
@@ -348,10 +507,7 @@ class Poll(TelegramObject):
if not self.explanation:
raise RuntimeError("This Poll has no 'explanation'.")
entity_text = self.explanation.encode("utf-16-le")
entity_text = entity_text[entity.offset * 2 : (entity.offset + entity.length) * 2]
return entity_text.decode("utf-16-le")
return parse_message_entity(self.explanation, entity)
def parse_explanation_entities(
self, types: Optional[List[str]] = None
@@ -375,15 +531,61 @@ class Poll(TelegramObject):
Dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
the text that belongs to them, calculated based on UTF-16 codepoints.
"""
if types is None:
types = MessageEntity.ALL_TYPES
Raises:
RuntimeError: If the poll has no explanation.
return {
entity: self.parse_explanation_entity(entity)
for entity in self.explanation_entities
if entity.type in types
}
"""
if not self.explanation:
raise RuntimeError("This Poll has no 'explanation'.")
return parse_message_entities(self.explanation, self.explanation_entities, types)
def parse_question_entity(self, entity: MessageEntity) -> str:
"""Returns the text in :attr:`question` from a given :class:`telegram.MessageEntity` of
:attr:`question_entities`.
.. versionadded:: 21.2
Note:
This method is present because Telegram calculates the offset and length in
UTF-16 codepoint pairs, which some versions of Python don't handle automatically.
(That is, you can't just slice ``Message.text`` with the offset and length.)
Args:
entity (:class:`telegram.MessageEntity`): The entity to extract the text from. It must
be an entity that belongs to :attr:`question_entities`.
Returns:
:obj:`str`: The text of the given entity.
"""
return parse_message_entity(self.question, entity)
def parse_question_entities(
self, types: Optional[List[str]] = None
) -> Dict[MessageEntity, str]:
"""
Returns a :obj:`dict` that maps :class:`telegram.MessageEntity` to :obj:`str`.
It contains entities from this polls question filtered by their ``type`` attribute as
the key, and the text that each entity belongs to as the value of the :obj:`dict`.
.. versionadded:: 21.2
Note:
This method should always be used instead of the :attr:`question_entities`
attribute, since it calculates the correct substring from the message text based on
UTF-16 codepoints. See :attr:`parse_question_entity` for more info.
Args:
types (List[:obj:`str`], optional): List of ``MessageEntity`` types as strings. If the
``type`` attribute of an entity is contained in this list, it will be returned.
Defaults to :attr:`telegram.MessageEntity.ALL_TYPES`.
Returns:
Dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
the text that belongs to them, calculated based on UTF-16 codepoints.
"""
return parse_message_entities(self.question, self.question_entities, types)
REGULAR: Final[str] = constants.PollType.REGULAR
""":const:`telegram.constants.PollType.REGULAR`"""
+2
View File
@@ -355,6 +355,7 @@ class ReplyParameters(TelegramObject):
chat, or in the chat :paramref:`chat_id` if it is specified.
chat_id (:obj:`int` | :obj:`str`, optional): If the message to be replied to is from a
different chat, |chat_id_channel|
Not supported for messages sent on behalf of a business account.
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply| Can be
used only for replies in the same chat and forum topic.
quote (:obj:`str`, optional): Quoted part of the message to be replied to; 0-1024
@@ -376,6 +377,7 @@ class ReplyParameters(TelegramObject):
chat, or in the chat :paramref:`chat_id` if it is specified.
chat_id (:obj:`int` | :obj:`str`): Optional. If the message to be replied to is from a
different chat, |chat_id_channel|
Not supported for messages sent on behalf of a business account.
allow_sending_without_reply (:obj:`bool`): Optional. |allow_sending_without_reply| Can be
used only for replies in the same chat and forum topic.
quote (:obj:`str`): Optional. Quoted part of the message to be replied to; 0-1024
+2 -1
View File
@@ -28,7 +28,8 @@ from telegram._utils.types import JSONDict
class ReplyKeyboardMarkup(TelegramObject):
"""This object represents a custom keyboard with reply options.
"""This object represents a custom keyboard with reply options. Not supported in channels and
for messages sent on behalf of a Telegram Business account.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their size of :attr:`keyboard` and all the buttons are equal.
+1
View File
@@ -29,6 +29,7 @@ class ReplyKeyboardRemove(TelegramObject):
keyboard and display the default letter-keyboard. By default, custom keyboards are displayed
until a new keyboard is sent by a bot. An exception is made for one-time keyboards that are
hidden immediately after the user presses a button (see :class:`telegram.ReplyKeyboardMarkup`).
Not supported in channels and for messages sent on behalf of a Telegram Business account.
Note:
User will not be able to summon this keyboard; if you want to hide the keyboard from
+8 -60
View File
@@ -23,12 +23,6 @@ from telegram._files.photosize import PhotoSize
from telegram._telegramobject import TelegramObject
from telegram._utils.argumentparsing import parse_sequence_arg
from telegram._utils.types import JSONDict
from telegram._utils.warnings import warn
from telegram._utils.warnings_transition import (
build_deprecation_warning_message,
warn_about_deprecated_attr_in_property,
)
from telegram.warnings import PTBDeprecationWarning
if TYPE_CHECKING:
from telegram._bot import Bot
@@ -44,11 +38,14 @@ class UsersShared(TelegramObject):
.. versionadded:: 20.8
Bot API 7.0 replaces ``UserShared`` with this class. The only difference is that now
the :attr:`user_ids` is a sequence instead of a single integer.
the ``user_ids`` is a sequence instead of a single integer.
.. versionchanged:: 21.1
The argument :attr:`users` is now considered for the equality comparison instead of
:attr:`user_ids`.
``user_ids``.
.. versionremoved:: 21.2
Removed the deprecated argument and attribute ``user_ids``.
Args:
request_id (:obj:`int`): Identifier of the request.
@@ -57,18 +54,8 @@ class UsersShared(TelegramObject):
.. versionadded:: 21.1
.. deprecated:: 21.1
In future versions, this argument will become keyword only.
user_ids (Sequence[:obj:`int`], optional): Identifiers of the shared users. These numbers
may have more than 32 significant bits and some programming languages may have
difficulty/silent defects in interpreting them. But they have at most 52 significant
bits, so 64-bit integers or double-precision float types are safe for storing these
identifiers. The bot may not have access to the users and could be unable to use
these identifiers, unless the users are already known to the bot by some other means.
.. deprecated:: 21.1
Bot API 7.2 introduced by :paramref:`users`, replacing this argument. Hence, this
argument is now optional and will be removed in future versions.
.. versionchanged:: 21.2
This argument is now required.
Attributes:
request_id (:obj:`int`): Identifier of the request.
@@ -83,31 +70,14 @@ class UsersShared(TelegramObject):
def __init__(
self,
request_id: int,
user_ids: Optional[Sequence[int]] = None,
users: Optional[Sequence["SharedUser"]] = None,
users: Sequence["SharedUser"],
*,
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(api_kwargs=api_kwargs)
self.request_id: int = request_id
if users is None:
raise TypeError("`users` is a required argument since Bot API 7.2")
self.users: Tuple[SharedUser, ...] = parse_sequence_arg(users)
if user_ids is not None:
warn(
build_deprecation_warning_message(
deprecated_name="user_ids",
new_name="users",
object_type="parameter",
bot_api_version="7.2",
),
PTBDeprecationWarning,
stacklevel=2,
)
self._id_attrs = (self.request_id, self.users)
self._freeze()
@@ -130,28 +100,6 @@ class UsersShared(TelegramObject):
return super()._de_json(data=data, bot=bot, api_kwargs=api_kwargs)
@property
def user_ids(self) -> Tuple[int, ...]:
"""
Tuple[:obj:`int`]: Identifiers of the shared users. These numbers may have
more than 32 significant bits and some programming languages may have difficulty/silent
defects in interpreting them. But they have at most 52 significant bits, so 64-bit
integers or double-precision float types are safe for storing these identifiers. The
bot may not have access to the users and could be unable to use these identifiers,
unless the users are already known to the bot by some other means.
.. deprecated:: 21.1
As Bot API 7.2 replaces this attribute with :attr:`users`, this attribute will be
removed in future versions.
"""
warn_about_deprecated_attr_in_property(
deprecated_attr_name="user_ids",
new_attr_name="users",
bot_api_version="7.2",
stacklevel=2,
)
return tuple(user.user_id for user in self.users)
class ChatShared(TelegramObject):
"""
+4 -4
View File
@@ -141,8 +141,8 @@ class Update(TelegramObject):
.. versionadded:: 21.1
business_message (:class:`telegram.Message`, optional): New non-service message
from a connected business account.
business_message (:class:`telegram.Message`, optional): New message from a connected
business account.
.. versionadded:: 21.1
@@ -249,8 +249,8 @@ class Update(TelegramObject):
.. versionadded:: 21.1
business_message (:class:`telegram.Message`): Optional. New non-service message
from a connected business account.
business_message (:class:`telegram.Message`): Optional. New message from a connected
business account.
.. versionadded:: 21.1
+83 -2
View File
@@ -40,6 +40,7 @@ if TYPE_CHECKING:
InputMediaDocument,
InputMediaPhoto,
InputMediaVideo,
InputPollOption,
LabeledPrice,
LinkPreviewOptions,
Location,
@@ -408,6 +409,7 @@ class User(TelegramObject):
link_preview_options: ODVInput["LinkPreviewOptions"] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
disable_web_page_preview: Optional[bool] = None,
@@ -451,6 +453,7 @@ class User(TelegramObject):
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def delete_message(
@@ -530,6 +533,8 @@ class User(TelegramObject):
has_spoiler: Optional[bool] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
show_caption_above_media: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -574,6 +579,8 @@ class User(TelegramObject):
api_kwargs=api_kwargs,
has_spoiler=has_spoiler,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
show_caption_above_media=show_caption_above_media,
)
async def send_media_group(
@@ -586,6 +593,7 @@ class User(TelegramObject):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -630,6 +638,7 @@ class User(TelegramObject):
parse_mode=parse_mode,
caption_entities=caption_entities,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def send_audio(
@@ -648,6 +657,7 @@ class User(TelegramObject):
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -695,6 +705,7 @@ class User(TelegramObject):
api_kwargs=api_kwargs,
thumbnail=thumbnail,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def send_chat_action(
@@ -749,6 +760,7 @@ class User(TelegramObject):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -792,6 +804,7 @@ class User(TelegramObject):
protect_content=protect_content,
message_thread_id=message_thread_id,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def send_dice(
@@ -803,6 +816,7 @@ class User(TelegramObject):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -841,6 +855,7 @@ class User(TelegramObject):
protect_content=protect_content,
message_thread_id=message_thread_id,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def send_document(
@@ -857,6 +872,7 @@ class User(TelegramObject):
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -902,6 +918,7 @@ class User(TelegramObject):
protect_content=protect_content,
message_thread_id=message_thread_id,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def send_game(
@@ -913,6 +930,7 @@ class User(TelegramObject):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -951,6 +969,7 @@ class User(TelegramObject):
protect_content=protect_content,
message_thread_id=message_thread_id,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def send_invoice(
@@ -958,7 +977,7 @@ class User(TelegramObject):
title: str,
description: str,
payload: str,
provider_token: str,
provider_token: Optional[str],
currency: str,
prices: Sequence["LabeledPrice"],
start_parameter: Optional[str] = None,
@@ -981,6 +1000,7 @@ class User(TelegramObject):
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1048,6 +1068,7 @@ class User(TelegramObject):
suggested_tip_amounts=suggested_tip_amounts,
protect_content=protect_content,
message_thread_id=message_thread_id,
message_effect_id=message_effect_id,
)
async def send_location(
@@ -1064,6 +1085,7 @@ class User(TelegramObject):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1109,6 +1131,7 @@ class User(TelegramObject):
protect_content=protect_content,
message_thread_id=message_thread_id,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def send_animation(
@@ -1128,6 +1151,8 @@ class User(TelegramObject):
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
show_caption_above_media: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1176,6 +1201,8 @@ class User(TelegramObject):
has_spoiler=has_spoiler,
thumbnail=thumbnail,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
show_caption_above_media=show_caption_above_media,
)
async def send_sticker(
@@ -1188,6 +1215,7 @@ class User(TelegramObject):
emoji: Optional[str] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1227,6 +1255,7 @@ class User(TelegramObject):
message_thread_id=message_thread_id,
emoji=emoji,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def send_video(
@@ -1247,6 +1276,8 @@ class User(TelegramObject):
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
show_caption_above_media: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1296,6 +1327,8 @@ class User(TelegramObject):
message_thread_id=message_thread_id,
has_spoiler=has_spoiler,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
show_caption_above_media=show_caption_above_media,
)
async def send_venue(
@@ -1314,6 +1347,7 @@ class User(TelegramObject):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1361,6 +1395,7 @@ class User(TelegramObject):
protect_content=protect_content,
message_thread_id=message_thread_id,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def send_video_note(
@@ -1375,6 +1410,7 @@ class User(TelegramObject):
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1418,6 +1454,7 @@ class User(TelegramObject):
message_thread_id=message_thread_id,
thumbnail=thumbnail,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def send_voice(
@@ -1433,6 +1470,7 @@ class User(TelegramObject):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1477,12 +1515,13 @@ class User(TelegramObject):
protect_content=protect_content,
message_thread_id=message_thread_id,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def send_poll(
self,
question: str,
options: Sequence[str],
options: Sequence[Union[str, "InputPollOption"]],
is_anonymous: Optional[bool] = None,
type: Optional[str] = None,
allows_multiple_answers: Optional[bool] = None,
@@ -1499,6 +1538,9 @@ class User(TelegramObject):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
question_parse_mode: ODVInput[str] = DEFAULT_NONE,
question_entities: Optional[Sequence["MessageEntity"]] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1548,6 +1590,9 @@ class User(TelegramObject):
protect_content=protect_content,
message_thread_id=message_thread_id,
business_connection_id=business_connection_id,
question_parse_mode=question_parse_mode,
question_entities=question_entities,
message_effect_id=message_effect_id,
)
async def send_copy(
@@ -1562,6 +1607,7 @@ class User(TelegramObject):
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
show_caption_above_media: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1603,6 +1649,7 @@ class User(TelegramObject):
api_kwargs=api_kwargs,
protect_content=protect_content,
message_thread_id=message_thread_id,
show_caption_above_media=show_caption_above_media,
)
async def copy_message(
@@ -1617,6 +1664,7 @@ class User(TelegramObject):
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
show_caption_above_media: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1658,6 +1706,7 @@ class User(TelegramObject):
api_kwargs=api_kwargs,
protect_content=protect_content,
message_thread_id=message_thread_id,
show_caption_above_media=show_caption_above_media,
)
async def send_copies(
@@ -2096,3 +2145,35 @@ class User(TelegramObject):
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)
async def refund_star_payment(
self,
telegram_payment_charge_id: str,
*,
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: Optional[JSONDict] = None,
) -> bool:
"""Shortcut for::
await bot.refund_star_payment(user_id=update.effective_user.id, *args, **kwargs)
For the documentation of the arguments, please see
:meth:`telegram.Bot.refund_star_payment`.
.. versionadded:: 21.3
Returns:
:obj:`bool`: On success, :obj:`True` is returned.
"""
return await self.get_bot().refund_star_payment(
user_id=self.id,
telegram_payment_charge_id=telegram_payment_charge_id,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)
+1 -1
View File
@@ -194,7 +194,7 @@ def extract_tzinfo_from_defaults(bot: "Bot") -> Union[dtm.tzinfo, None]:
If the bot has no default values, :obj:`None` is returned.
"""
# We don't use `ininstance(bot, ExtBot)` here so that this works
# in `python-telegram-bot-raw` as well
# without the job-queue extra dependencies as well
if hasattr(bot, "defaults") and bot.defaults:
return bot.defaults.tzinfo
return None
+71
View File
@@ -0,0 +1,71 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2024
# 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 auxiliary functionality for parsing MessageEntity objects.
Warning:
Contents of this module are intended to be used internally by the library and *not* by the
user. Changes to this module are not considered breaking changes and may not be documented in
the changelog.
"""
from typing import Dict, Optional, Sequence
from telegram._messageentity import MessageEntity
def parse_message_entity(text: str, entity: MessageEntity) -> str:
"""Returns the text from a given :class:`telegram.MessageEntity`.
Args:
text (:obj:`str`): The text to extract the entity from.
entity (:class:`telegram.MessageEntity`): The entity to extract the text from.
Returns:
:obj:`str`: The text of the given entity.
"""
entity_text = text.encode("utf-16-le")
entity_text = entity_text[entity.offset * 2 : (entity.offset + entity.length) * 2]
return entity_text.decode("utf-16-le")
def parse_message_entities(
text: str, entities: Sequence[MessageEntity], types: Optional[Sequence[str]] = None
) -> Dict[MessageEntity, str]:
"""
Returns a :obj:`dict` that maps :class:`telegram.MessageEntity` to :obj:`str`.
It contains entities filtered by their ``type`` attribute as
the key, and the text that each entity belongs to as the value of the :obj:`dict`.
Args:
text (:obj:`str`): The text to extract the entity from.
entities (List[:class:`telegram.MessageEntity`]): The entities to extract the text from.
types (List[:obj:`str`], optional): List of ``MessageEntity`` types as strings. If the
``type`` attribute of an entity is contained in this list, it will be returned.
Defaults to :attr:`telegram.MessageEntity.ALL_TYPES`.
Returns:
Dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
the text that belongs to them, calculated based on UTF-16 codepoints.
"""
if types is None:
types = MessageEntity.ALL_TYPES
return {
entity: parse_message_entity(text, entity) for entity in entities if entity.type in types
}
+1 -1
View File
@@ -60,7 +60,7 @@ class StringEnum(str, _enum.Enum):
# Apply the __repr__ modification and __str__ fix to IntEnum
class IntEnum(_enum.IntEnum):
class IntEnum(_enum.IntEnum): # pylint: disable=invalid-slots
"""Helper class for int enums where ``str(member)`` prints the value, but ``repr(member)``
gives ``EnumName.MEMBER_NAME``.
"""
+12 -3
View File
@@ -26,19 +26,28 @@ Warning:
the changelog.
"""
import warnings
from typing import Type
from typing import Type, Union
from telegram.warnings import PTBUserWarning
def warn(message: str, category: Type[Warning] = PTBUserWarning, stacklevel: int = 0) -> None:
def warn(
message: Union[str, PTBUserWarning],
category: Type[Warning] = PTBUserWarning,
stacklevel: int = 0,
) -> None:
"""
Helper function used as a shortcut for warning with default values.
.. versionadded:: 20.0
Args:
message (:obj:`str`): Specify the warnings message to pass to ``warnings.warn()``.
message (:obj:`str` | :obj:`PTBUserWarning`): Specify the warnings message to pass to
``warnings.warn()``.
.. versionchanged:: 21.2
Now also accepts a :obj:`PTBUserWarning` instance.
category (:obj:`Type[Warning]`, optional): Specify the Warning class to pass to
``warnings.warn()``. Defaults to :class:`telegram.warnings.PTBUserWarning`.
stacklevel (:obj:`int`, optional): Specify the stacklevel to pass to ``warnings.warn()``.
+16 -10
View File
@@ -23,10 +23,10 @@ inside warnings.py.
.. versionadded:: 20.2
"""
from typing import Any, Callable, Type
from typing import Any, Callable, Type, Union
from telegram._utils.warnings import warn
from telegram.warnings import PTBDeprecationWarning
from telegram.warnings import PTBDeprecationWarning, PTBUserWarning
def build_deprecation_warning_message(
@@ -54,8 +54,9 @@ def warn_about_deprecated_arg_return_new_arg(
deprecated_arg_name: str,
new_arg_name: str,
bot_api_version: str,
ptb_version: str,
stacklevel: int = 2,
warn_callback: Callable[[str, Type[Warning], int], None] = warn,
warn_callback: Callable[[Union[str, PTBUserWarning], Type[Warning], int], None] = warn,
) -> Any:
"""A helper function for the transition in API when argument is renamed.
@@ -80,10 +81,12 @@ def warn_about_deprecated_arg_return_new_arg(
if deprecated_arg:
warn_callback(
f"Bot API {bot_api_version} renamed the argument '{deprecated_arg_name}' to "
f"'{new_arg_name}'.",
PTBDeprecationWarning,
stacklevel + 1,
PTBDeprecationWarning(
ptb_version,
f"Bot API {bot_api_version} renamed the argument '{deprecated_arg_name}' to "
f"'{new_arg_name}'.",
),
stacklevel=stacklevel + 1, # type: ignore[call-arg]
)
return deprecated_arg
@@ -94,6 +97,7 @@ def warn_about_deprecated_attr_in_property(
deprecated_attr_name: str,
new_attr_name: str,
bot_api_version: str,
ptb_version: str,
stacklevel: int = 2,
) -> None:
"""A helper function for the transition in API when attribute is renamed. Call from properties.
@@ -101,8 +105,10 @@ def warn_about_deprecated_attr_in_property(
The properties replace deprecated attributes in classes and issue these deprecation warnings.
"""
warn(
f"Bot API {bot_api_version} renamed the attribute '{deprecated_attr_name}' to "
f"'{new_attr_name}'.",
PTBDeprecationWarning,
PTBDeprecationWarning(
ptb_version,
f"Bot API {bot_api_version} renamed the attribute '{deprecated_attr_name}' to "
f"'{new_attr_name}'.",
),
stacklevel=stacklevel + 1,
)
+1 -1
View File
@@ -51,7 +51,7 @@ class Version(NamedTuple):
__version_info__: Final[Version] = Version(
major=21, minor=1, micro=0, releaselevel="final", serial=0
major=21, minor=3, micro=0, releaselevel="final", serial=0
)
__version__: Final[str] = str(__version_info__)
+144 -34
View File
@@ -29,7 +29,7 @@ those classes.
* Most of the constants in this module are grouped into enums.
"""
# TODO: Remove this when https://github.com/PyCQA/pylint/issues/6887 is resolved.
# pylint: disable=invalid-enum-extension
# pylint: disable=invalid-enum-extension,invalid-slots
__all__ = [
"BOT_API_VERSION",
@@ -37,6 +37,10 @@ __all__ = [
"SUPPORTED_WEBHOOK_PORTS",
"ZERO_DATE",
"AccentColor",
"BackgroundFillLimit",
"BackgroundFillType",
"BackgroundTypeLimit",
"BackgroundTypeType",
"BotCommandLimit",
"BotCommandScopeType",
"BotDescriptionLimit",
@@ -142,7 +146,7 @@ class _AccentColor(NamedTuple):
#: :data:`telegram.__bot_api_version_info__`.
#:
#: .. versionadded:: 20.0
BOT_API_VERSION_INFO: Final[_BotAPIVersion] = _BotAPIVersion(major=7, minor=2)
BOT_API_VERSION_INFO: Final[_BotAPIVersion] = _BotAPIVersion(major=7, minor=4)
#: :obj:`str`: Telegram Bot API
#: version supported by this version of `python-telegram-bot`. Also available as
#: :data:`telegram.__bot_api_version__`.
@@ -164,7 +168,8 @@ ZERO_DATE: Final[datetime.datetime] = datetime.datetime(1970, 1, 1, tzinfo=UTC)
class AccentColor(Enum):
"""This enum contains the available accent colors for :class:`telegram.Chat.accent_color_id`.
"""This enum contains the available accent colors for
:class:`telegram.ChatFullInfo.accent_color_id`.
The members of this enum are named tuples with the following attributes:
- ``identifier`` (:obj:`int`): The identifier of the accent color.
@@ -822,6 +827,46 @@ class ChatLimit(IntEnum):
"""
class BackgroundTypeLimit(IntEnum):
"""This enum contains limitations for :class:`telegram.BackgroundTypeFill`,
:class:`telegram.BackgroundTypeWallpaper` and :class:`telegram.BackgroundTypePattern`.
The enum members of this enumeration are instances of :class:`int` and can be treated as such.
.. versionadded:: 21.2
"""
__slots__ = ()
MAX_DIMMING = 100
""":obj:`int`: Maximum value allowed for:
* :paramref:`~telegram.BackgroundTypeFill.dark_theme_dimming` parameter of
:class:`telegram.BackgroundTypeFill`
* :paramref:`~telegram.BackgroundTypeWallpaper.dark_theme_dimming` parameter of
:class:`telegram.BackgroundTypeWallpaper`
"""
MAX_INTENSITY = 100
""":obj:`int`: Maximum value allowed for :paramref:`~telegram.BackgroundTypePattern.intensity`
parameter of :class:`telegram.BackgroundTypePattern`
"""
class BackgroundFillLimit(IntEnum):
"""This enum contains limitations for :class:`telegram.BackgroundFillGradient`.
The enum members of this enumeration are instances of :class:`int` and can be treated as such.
.. versionadded:: 21.2
"""
__slots__ = ()
MAX_ROTATION_ANGLE = 359
""":obj:`int`: Maximum value allowed for:
:paramref:`~telegram.BackgroundFillGradient.rotation_angle` parameter of
:class:`telegram.BackgroundFillGradient`
"""
class ChatMemberStatus(StringEnum):
"""This enum contains the available states for :class:`telegram.ChatMember`. The enum
members of this enumeration are instances of :class:`str` and can be treated as such.
@@ -1427,6 +1472,21 @@ class LocationLimit(IntEnum):
:meth:`telegram.Bot.send_location`
"""
LIVE_PERIOD_FOREVER = int(hex(0x7FFFFFFF), 16)
""":obj:`int`: Value for live locations that can be edited indefinitely. Passed in:
* :paramref:`~telegram.InlineQueryResultLocation.live_period` parameter of
:class:`telegram.InlineQueryResultLocation`
* :paramref:`~telegram.InputLocationMessageContent.live_period` parameter of
:class:`telegram.InputLocationMessageContent`
* :paramref:`~telegram.Bot.edit_message_live_location.live_period` parameter of
:meth:`telegram.Bot.edit_message_live_location`
* :paramref:`~telegram.Bot.send_location.live_period` parameter of
:meth:`telegram.Bot.send_location`
.. versionadded:: 21.2
"""
MIN_PROXIMITY_ALERT_RADIUS = 1
""":obj:`int`: Minimum value allowed for:
@@ -1570,48 +1630,53 @@ class MessageEntityType(StringEnum):
__slots__ = ()
MENTION = "mention"
""":obj:`str`: Message entities representing a mention."""
HASHTAG = "hashtag"
""":obj:`str`: Message entities representing a hashtag."""
CASHTAG = "cashtag"
""":obj:`str`: Message entities representing a cashtag."""
PHONE_NUMBER = "phone_number"
""":obj:`str`: Message entities representing a phone number."""
BOT_COMMAND = "bot_command"
""":obj:`str`: Message entities representing a bot command."""
URL = "url"
""":obj:`str`: Message entities representing a url."""
EMAIL = "email"
""":obj:`str`: Message entities representing a email."""
BLOCKQUOTE = "blockquote"
""":obj:`str`: Message entities representing a block quotation.
.. versionadded:: 20.8
"""
BOLD = "bold"
""":obj:`str`: Message entities representing bold text."""
ITALIC = "italic"
""":obj:`str`: Message entities representing italic text."""
BOT_COMMAND = "bot_command"
""":obj:`str`: Message entities representing a bot command."""
CASHTAG = "cashtag"
""":obj:`str`: Message entities representing a cashtag."""
CODE = "code"
""":obj:`str`: Message entities representing monowidth string."""
CUSTOM_EMOJI = "custom_emoji"
""":obj:`str`: Message entities representing inline custom emoji stickers.
.. versionadded:: 20.0
"""
EMAIL = "email"
""":obj:`str`: Message entities representing a email."""
EXPANDABLE_BLOCKQUOTE = "expandable_blockquote"
""":obj:`str`: Message entities representing collapsed-by-default block quotation.
.. versionadded:: 21.3
"""
HASHTAG = "hashtag"
""":obj:`str`: Message entities representing a hashtag."""
ITALIC = "italic"
""":obj:`str`: Message entities representing italic text."""
MENTION = "mention"
""":obj:`str`: Message entities representing a mention."""
PHONE_NUMBER = "phone_number"
""":obj:`str`: Message entities representing a phone number."""
PRE = "pre"
""":obj:`str`: Message entities representing monowidth block."""
SPOILER = "spoiler"
""":obj:`str`: Message entities representing spoiler text."""
STRIKETHROUGH = "strikethrough"
""":obj:`str`: Message entities representing strikethrough text."""
TEXT_LINK = "text_link"
""":obj:`str`: Message entities representing clickable text URLs."""
TEXT_MENTION = "text_mention"
""":obj:`str`: Message entities representing text mention for users without usernames."""
UNDERLINE = "underline"
""":obj:`str`: Message entities representing underline text."""
STRIKETHROUGH = "strikethrough"
""":obj:`str`: Message entities representing strikethrough text."""
SPOILER = "spoiler"
""":obj:`str`: Message entities representing spoiler text."""
CUSTOM_EMOJI = "custom_emoji"
""":obj:`str`: Message entities representing inline custom emoji stickers.
.. versionadded:: 20.0
"""
BLOCKQUOTE = "blockquote"
""":obj:`str`: Message entities representing a block quotation.
.. versionadded:: 20.8
"""
URL = "url"
""":obj:`str`: Message entities representing a url."""
class MessageLimit(IntEnum):
@@ -1726,6 +1791,11 @@ class MessageType(StringEnum):
.. versionadded:: 20.8
"""
CHAT_BACKGROUND_SET = "chat_background_set"
""":obj:`str`: Messages with :attr:`telegram.Message.chat_background_set`.
.. versionadded:: 21.2
"""
CONNECTED_WEBSITE = "connected_website"
""":obj:`str`: Messages with :attr:`telegram.Message.connected_website`."""
CONTACT = "contact"
@@ -1736,6 +1806,10 @@ class MessageType(StringEnum):
""":obj:`str`: Messages with :attr:`telegram.Message.dice`."""
DOCUMENT = "document"
""":obj:`str`: Messages with :attr:`telegram.Message.document`."""
EFFECT_ID = "effect_id"
""":obj:`str`: Messages with :attr:`telegram.Message.effect_id`.
.. versionadded:: 21.3"""
FORUM_TOPIC_CREATED = "forum_topic_created"
""":obj:`str`: Messages with :attr:`telegram.Message.forum_topic_created`.
@@ -1895,7 +1969,7 @@ class PollingLimit(IntEnum):
class ProfileAccentColor(Enum):
"""This enum contains the available accent colors for
:class:`telegram.Chat.profile_accent_color_id`.
:class:`telegram.ChatFullInfo.profile_accent_color_id`.
The members of this enum are named tuples with the following attributes:
- ``identifier`` (:obj:`int`): The identifier of the accent color.
@@ -2878,3 +2952,39 @@ class ReactionEmoji(StringEnum):
""":obj:`str`: Woman Shrugging"""
POUTING_FACE = "😡"
""":obj:`str`: Pouting face"""
class BackgroundTypeType(StringEnum):
"""This enum contains the available types of :class:`telegram.BackgroundType`. The enum
members of this enumeration are instances of :class:`str` and can be treated as such.
.. versionadded:: 21.2
"""
__slots__ = ()
FILL = "fill"
""":obj:`str`: A :class:`telegram.BackgroundType` with fill background."""
WALLPAPER = "wallpaper"
""":obj:`str`: A :class:`telegram.BackgroundType` with wallpaper background."""
PATTERN = "pattern"
""":obj:`str`: A :class:`telegram.BackgroundType` with pattern background."""
CHAT_THEME = "chat_theme"
""":obj:`str`: A :class:`telegram.BackgroundType` with chat_theme background."""
class BackgroundFillType(StringEnum):
"""This enum contains the available types of :class:`telegram.BackgroundFill`. The enum
members of this enumeration are instances of :class:`str` and can be treated as such.
.. versionadded:: 21.2
"""
__slots__ = ()
SOLID = "solid"
""":obj:`str`: A :class:`telegram.BackgroundFill` with solid fill."""
GRADIENT = "gradient"
""":obj:`str`: A :class:`telegram.BackgroundFill` with gradient fill."""
FREEFORM_GRADIENT = "freeform_gradient"
""":obj:`str`: A :class:`telegram.BackgroundFill` with freeform_gradient fill."""
+1 -1
View File
@@ -208,7 +208,7 @@ class AIORateLimiter(BaseRateLimiter[int]):
callback: Callable[..., Coroutine[Any, Any, Union[bool, JSONDict, List[JSONDict]]]],
args: Any,
kwargs: Dict[str, Any],
endpoint: str,
endpoint: str, # noqa: ARG002
data: Dict[str, Any],
rate_limit_args: Optional[int],
) -> Union[bool, JSONDict, List[JSONDict]]:
+143 -83
View File
@@ -365,6 +365,7 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
self.__update_persistence_event = asyncio.Event()
self.__update_persistence_lock = asyncio.Lock()
self.__create_task_tasks: Set[asyncio.Task] = set() # Used for awaiting tasks upon exit
self.__stop_running_marker = asyncio.Event()
async def __aenter__(self: _AppType) -> _AppType: # noqa: PYI019
"""|async_context_manager| :meth:`initializes <initialize>` the App.
@@ -516,6 +517,7 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
await self._add_ch_to_persistence(handler)
self._initialized = True
self.__stop_running_marker.clear()
async def _add_ch_to_persistence(self, handler: "ConversationHandler") -> None:
self._conversation_handler_conversations.update(
@@ -670,14 +672,26 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
raise RuntimeError("This Application is not running!")
self._running = False
self.__stop_running_marker.clear()
_LOGGER.info("Application is stopping. This might take a moment.")
# Stop listening for new updates and handle all pending ones
await self.update_queue.put(_STOP_SIGNAL)
_LOGGER.debug("Waiting for update_queue to join")
await self.update_queue.join()
if self.__update_fetcher_task:
await self.__update_fetcher_task
if self.__update_fetcher_task.done():
try:
self.__update_fetcher_task.result()
except BaseException as exc:
_LOGGER.critical(
"Fetching updates was aborted due to %r. Suppressing "
"exception to ensure graceful shutdown.",
exc,
exc_info=True,
)
else:
await self.update_queue.put(_STOP_SIGNAL)
_LOGGER.debug("Waiting for update_queue to join")
await self.update_queue.join()
await self.__update_fetcher_task
_LOGGER.debug("Application stopped fetching of updates.")
if self._job_queue:
@@ -703,17 +717,36 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
shutdown of the application, i.e. the methods listed in :attr:`run_polling` and
:attr:`run_webhook` will still be executed.
This method can also be called within :meth:`post_init`. This allows for a graceful,
early shutdown of the application if some condition is met (e.g., a database connection
could not be established).
Note:
If the application is not running, this method does nothing.
If the application is not running and this method is not called within
:meth:`post_init`, this method does nothing.
Warning:
This method is designed to for use in combination with :meth:`run_polling` or
:meth:`run_webhook`. Using this method in combination with a custom logic for starting
and stopping the application is not guaranteed to work as expected. Use at your own
risk.
.. versionadded:: 20.5
.. versionchanged:: 21.2
Added support for calling within :meth:`post_init`.
"""
if self.running:
# This works because `__run` is using `loop.run_forever()`. If that changes, this
# method needs to be adapted.
asyncio.get_running_loop().stop()
else:
_LOGGER.debug("Application is not running, stop_running() does nothing.")
self.__stop_running_marker.set()
if not self._initialized:
_LOGGER.debug(
"Application is not running and not initialized. `stop_running()` likely has "
"no effect."
)
def run_polling(
self,
@@ -733,9 +766,7 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
polling updates from Telegram using :meth:`telegram.ext.Updater.start_polling` and
a graceful shutdown of the app on exit.
The app will shut down when :exc:`KeyboardInterrupt` or :exc:`SystemExit` is raised.
On unix, the app will also shut down on receiving the signals specified by
:paramref:`stop_signals`.
|app_run_shutdown| :paramref:`stop_signals`.
The order of execution by :meth:`run_polling` is roughly as follows:
@@ -826,9 +857,11 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
if (read_timeout, write_timeout, connect_timeout, pool_timeout) != ((DEFAULT_NONE,) * 4):
warn(
"Setting timeouts via `Application.run_polling` is deprecated. "
"Please use `ApplicationBuilder.get_updates_*_timeout` instead.",
PTBDeprecationWarning,
PTBDeprecationWarning(
"20.6",
"Setting timeouts via `Application.run_polling` is deprecated. "
"Please use `ApplicationBuilder.get_updates_*_timeout` instead.",
),
stacklevel=2,
)
@@ -874,9 +907,7 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
listening for updates from Telegram using :meth:`telegram.ext.Updater.start_webhook` and
a graceful shutdown of the app on exit.
The app will shut down when :exc:`KeyboardInterrupt` or :exc:`SystemExit` is raised.
On unix, the app will also shut down on receiving the signals specified by
:paramref:`stop_signals`.
|app_run_shutdown| :paramref:`stop_signals`.
If :paramref:`cert`
and :paramref:`key` are not provided, the webhook will be started directly on
@@ -1038,25 +1069,28 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
loop.run_until_complete(self.initialize())
if self.post_init:
loop.run_until_complete(self.post_init(self))
if self.__stop_running_marker.is_set():
_LOGGER.info("Application received stop signal via `stop_running`. Shutting down.")
return
loop.run_until_complete(updater_coroutine) # one of updater.start_webhook/polling
loop.run_until_complete(self.start())
loop.run_forever()
except (KeyboardInterrupt, SystemExit):
_LOGGER.debug("Application received stop signal. Shutting down.")
except Exception as exc:
# In case the coroutine wasn't awaited, we don't need to bother the user with a warning
updater_coroutine.close()
raise exc
finally:
# We arrive here either by catching the exceptions above or if the loop gets stopped
# In case the coroutine wasn't awaited, we don't need to bother the user with a warning
updater_coroutine.close()
try:
# Mypy doesn't know that we already check if updater is None
if self.updater.running: # type: ignore[union-attr]
loop.run_until_complete(self.updater.stop()) # type: ignore[union-attr]
if self.running:
loop.run_until_complete(self.stop())
if self.post_stop:
loop.run_until_complete(self.post_stop(self))
# post_stop should be called only if stop was called!
if self.post_stop:
loop.run_until_complete(self.post_stop(self))
loop.run_until_complete(self.shutdown())
if self.post_shutdown:
loop.run_until_complete(self.post_shutdown(self))
@@ -1151,9 +1185,11 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
# Generator-based coroutines are not supported in Python 3.12+
if sys.version_info < (3, 12) and isinstance(coroutine, Generator):
warn(
"Generator-based coroutines are deprecated in create_task and will not work"
" in Python 3.12+",
category=PTBDeprecationWarning,
PTBDeprecationWarning(
"20.4",
"Generator-based coroutines are deprecated in create_task and will not"
" work in Python 3.12+",
),
)
return await asyncio.create_task(coroutine)
# If user uses generator in python 3.12+, Exception will happen and we cannot do
@@ -1185,45 +1221,44 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
finally:
self._mark_for_persistence_update(update=update)
async def _update_fetcher(self) -> None:
async def __update_fetcher(self) -> None:
# Continuously fetch updates from the queue. Exit only once the signal object is found.
while True:
try:
update = await self.update_queue.get()
update = await self.update_queue.get()
if update is _STOP_SIGNAL:
_LOGGER.debug("Dropping pending updates")
while not self.update_queue.empty():
self.update_queue.task_done()
if update is _STOP_SIGNAL:
# For the _STOP_SIGNAL
self.update_queue.task_done()
return
# For the _STOP_SIGNAL
self.update_queue.task_done()
return
_LOGGER.debug("Processing update %s", update)
_LOGGER.debug("Processing update %s", update)
if self._update_processor.max_concurrent_updates > 1:
# We don't await the below because it has to be run concurrently
self.create_task(
self.__process_update_wrapper(update),
update=update,
name=f"Application:{self.bot.id}:process_concurrent_update",
)
else:
await self.__process_update_wrapper(update)
except asyncio.CancelledError:
# This may happen if the application is manually run via application.start() and
# then a KeyboardInterrupt is sent. We must prevent this loop to die since
# application.stop() will wait for it's clean shutdown.
_LOGGER.warning(
"Fetching updates got a asyncio.CancelledError. Ignoring as this task may only"
"be closed via `Application.stop`."
if self._update_processor.max_concurrent_updates > 1:
# We don't await the below because it has to be run concurrently
self.create_task(
self.__process_update_wrapper(update),
update=update,
name=f"Application:{self.bot.id}:process_concurrent_update",
)
else:
await self.__process_update_wrapper(update)
async def _update_fetcher(self) -> None:
try:
await self.__update_fetcher()
finally:
while not self.update_queue.empty():
_LOGGER.debug("Dropping pending update: %s", self.update_queue.get_nowait())
with contextlib.suppress(ValueError):
# Since we're shutting down here, it's not too bad if we call task_done
# on an empty queue
self.update_queue.task_done()
async def __process_update_wrapper(self, update: object) -> None:
await self._update_processor.process_update(update, self.process_update(update))
self.update_queue.task_done()
try:
await self._update_processor.process_update(update, self.process_update(update))
finally:
self.update_queue.task_done()
async def process_update(self, update: object) -> None:
"""Processes a single update and marks the update to be updated by the persistence later.
@@ -1252,30 +1287,43 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
try:
for handler in handlers:
check = handler.check_update(update) # Should the handler handle this update?
if not (check is None or check is False): # if yes,
if not context: # build a context if not already built
context = self.context_types.context.from_update(update, self)
await context.refresh_data()
coroutine: Coroutine = handler.handle_update(update, self, check, context)
if check is None or check is False:
continue
if not handler.block or ( # if handler is running with block=False,
handler.block is DEFAULT_TRUE
and isinstance(self.bot, ExtBot)
and self.bot.defaults
and not self.bot.defaults.block
):
self.create_task(
coroutine,
update=update,
name=(
f"Application:{self.bot.id}:process_update_non_blocking"
f":{handler}"
if not context: # build a context if not already built
try:
context = self.context_types.context.from_update(update, self)
except Exception as exc:
_LOGGER.critical(
(
"Error while building CallbackContext for update %s. "
"Update will not be processed."
),
update,
exc_info=exc,
)
else:
any_blocking = True
await coroutine
break # Only a max of 1 handler per group is handled
return
await context.refresh_data()
coroutine: Coroutine = handler.handle_update(update, self, check, context)
if not handler.block or ( # if handler is running with block=False,
handler.block is DEFAULT_TRUE
and isinstance(self.bot, ExtBot)
and self.bot.defaults
and not self.bot.defaults.block
):
self.create_task(
coroutine,
update=update,
name=(
f"Application:{self.bot.id}:process_update_non_blocking"
f":{handler}"
),
)
else:
any_blocking = True
await coroutine
break # Only a max of 1 handler per group is handled
# Stop processing with any other handler.
except ApplicationHandlerStop:
@@ -1809,13 +1857,25 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
callback,
block,
) in self.error_handlers.items():
context = self.context_types.context.from_error(
update=update,
error=error,
application=self,
job=job,
coroutine=coroutine,
)
try:
context = self.context_types.context.from_error(
update=update,
error=error,
application=self,
job=job,
coroutine=coroutine,
)
except Exception as exc:
_LOGGER.critical(
(
"Error while building CallbackContext for exception %s. "
"Exception will not be processed by error handlers."
),
error,
exc_info=exc,
)
return False
if not block or ( # If error handler has `block=False`, create a Task to run cb
block is DEFAULT_TRUE
and isinstance(self.bot, ExtBot)
+17 -7
View File
@@ -528,9 +528,11 @@ class ApplicationBuilder(Generic[BT, CCT, UD, CD, BD, JQ]):
:class:`ApplicationBuilder`: The same builder with the updated argument.
"""
warn(
"`ApplicationBuilder.proxy_url` is deprecated since version "
"20.7. Use `ApplicationBuilder.proxy` instead.",
PTBDeprecationWarning,
PTBDeprecationWarning(
"20.7",
"`ApplicationBuilder.proxy_url` is deprecated. Use `ApplicationBuilder.proxy` "
"instead.",
),
stacklevel=2,
)
return self.proxy(proxy_url)
@@ -760,9 +762,11 @@ class ApplicationBuilder(Generic[BT, CCT, UD, CD, BD, JQ]):
:class:`ApplicationBuilder`: The same builder with the updated argument.
"""
warn(
"`ApplicationBuilder.get_updates_proxy_url` is deprecated since version "
"20.7. Use `ApplicationBuilder.get_updates_proxy` instead.",
PTBDeprecationWarning,
PTBDeprecationWarning(
"20.7",
"`ApplicationBuilder.get_updates_proxy_url` is deprecated. Use "
"`ApplicationBuilder.get_updates_proxy` instead.",
),
stacklevel=2,
)
return self.get_updates_proxy(get_updates_proxy_url)
@@ -1334,7 +1338,13 @@ class ApplicationBuilder(Generic[BT, CCT, UD, CD, BD, JQ]):
Tip:
This can be used for custom stop logic that requires to await coroutines, e.g.
sending message to a chat before shutting down the bot
sending message to a chat before shutting down the bot.
Hint:
The callback will be called only, if :meth:`Application.stop` was indeed called
successfully. For example, if the application is stopped early by calling
:meth:`Application.stop_running` within :meth:`post_init`, then the set callback will
*not* be called.
Example:
.. code::
+1 -1
View File
@@ -163,7 +163,7 @@ class BasePersistence(Generic[UD, CD, BD], ABC):
return self._update_interval
@update_interval.setter
def update_interval(self, value: object) -> NoReturn:
def update_interval(self, _: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to update_interval after initialization."
)
+1 -1
View File
@@ -165,7 +165,7 @@ class SimpleUpdateProcessor(BaseUpdateProcessor):
async def do_process_update(
self,
update: object,
update: object, # noqa: ARG002
coroutine: "Awaitable[Any]",
) -> None:
"""Immediately awaits the coroutine, i.e. does not apply any additional processing.
+3 -3
View File
@@ -165,7 +165,7 @@ class CallbackContext(Generic[BT, UD, CD, BD]):
return self.application.bot_data
@bot_data.setter
def bot_data(self, value: object) -> NoReturn:
def bot_data(self, _: object) -> NoReturn:
raise AttributeError(
f"You can not assign a new value to bot_data, see {_STORING_DATA_WIKI}"
)
@@ -192,7 +192,7 @@ class CallbackContext(Generic[BT, UD, CD, BD]):
return None
@chat_data.setter
def chat_data(self, value: object) -> NoReturn:
def chat_data(self, _: object) -> NoReturn:
raise AttributeError(
f"You can not assign a new value to chat_data, see {_STORING_DATA_WIKI}"
)
@@ -214,7 +214,7 @@ class CallbackContext(Generic[BT, UD, CD, BD]):
return None
@user_data.setter
def user_data(self, value: object) -> NoReturn:
def user_data(self, _: object) -> NoReturn:
raise AttributeError(
f"You can not assign a new value to user_data, see {_STORING_DATA_WIKI}"
)
+54 -20
View File
@@ -156,9 +156,11 @@ class Defaults:
raise ValueError("`quote` and `do_quote` are mutually exclusive")
if disable_web_page_preview is not None:
warn(
"`Defaults.disable_web_page_preview` is deprecated. Use "
"`Defaults.link_preview_options` instead.",
category=PTBDeprecationWarning,
PTBDeprecationWarning(
"20.8",
"`Defaults.disable_web_page_preview` is deprecated. Use "
"`Defaults.link_preview_options` instead.",
),
stacklevel=2,
)
self._link_preview_options: Optional[LinkPreviewOptions] = LinkPreviewOptions(
@@ -169,8 +171,9 @@ class Defaults:
if quote is not None:
warn(
"`Defaults.quote` is deprecated. Use `Defaults.do_quote` instead.",
category=PTBDeprecationWarning,
PTBDeprecationWarning(
"20.8", "`Defaults.quote` is deprecated. Use `Defaults.do_quote` instead."
),
stacklevel=2,
)
self._do_quote: Optional[bool] = quote
@@ -179,13 +182,14 @@ class Defaults:
# Gather all defaults that actually have a default value
self._api_defaults = {}
for kwarg in (
"parse_mode",
"explanation_parse_mode",
"disable_notification",
"allow_sending_without_reply",
"protect_content",
"link_preview_options",
"disable_notification",
"do_quote",
"explanation_parse_mode",
"link_preview_options",
"parse_mode",
"protect_content",
"question_parse_mode",
):
value = getattr(self, kwarg)
if value is not None:
@@ -235,7 +239,7 @@ class Defaults:
return self._parse_mode
@parse_mode.setter
def parse_mode(self, value: object) -> NoReturn:
def parse_mode(self, _: object) -> NoReturn:
raise AttributeError("You can not assign a new value to parse_mode after initialization.")
@property
@@ -246,7 +250,7 @@ class Defaults:
return self._parse_mode
@explanation_parse_mode.setter
def explanation_parse_mode(self, value: object) -> NoReturn:
def explanation_parse_mode(self, _: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to explanation_parse_mode after initialization."
)
@@ -259,11 +263,41 @@ class Defaults:
return self._parse_mode
@quote_parse_mode.setter
def quote_parse_mode(self, value: object) -> NoReturn:
def quote_parse_mode(self, _: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to quote_parse_mode after initialization."
)
@property
def text_parse_mode(self) -> Optional[str]:
""":obj:`str`: Optional. Alias for :attr:`parse_mode`, used for
the corresponding parameter of :class:`telegram.InputPollOption`.
.. versionadded:: 21.2
"""
return self._parse_mode
@text_parse_mode.setter
def text_parse_mode(self, _: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to text_parse_mode after initialization."
)
@property
def question_parse_mode(self) -> Optional[str]:
""":obj:`str`: Optional. Alias for :attr:`parse_mode`, used for
the corresponding parameter of :meth:`telegram.Bot.send_poll`.
.. versionadded:: 21.2
"""
return self._parse_mode
@question_parse_mode.setter
def question_parse_mode(self, _: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to question_parse_mode after initialization."
)
@property
def disable_notification(self) -> Optional[bool]:
""":obj:`bool`: Optional. Sends the message silently. Users will
@@ -272,7 +306,7 @@ class Defaults:
return self._disable_notification
@disable_notification.setter
def disable_notification(self, value: object) -> NoReturn:
def disable_notification(self, _: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to disable_notification after initialization."
)
@@ -289,7 +323,7 @@ class Defaults:
return self._link_preview_options.is_disabled if self._link_preview_options else None
@disable_web_page_preview.setter
def disable_web_page_preview(self, value: object) -> NoReturn:
def disable_web_page_preview(self, _: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to disable_web_page_preview after initialization."
)
@@ -302,7 +336,7 @@ class Defaults:
return self._allow_sending_without_reply
@allow_sending_without_reply.setter
def allow_sending_without_reply(self, value: object) -> NoReturn:
def allow_sending_without_reply(self, _: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to allow_sending_without_reply after initialization."
)
@@ -318,7 +352,7 @@ class Defaults:
return self._do_quote if self._do_quote is not None else None
@quote.setter
def quote(self, value: object) -> NoReturn:
def quote(self, _: object) -> NoReturn:
raise AttributeError("You can not assign a new value to quote after initialization.")
@property
@@ -329,7 +363,7 @@ class Defaults:
return self._tzinfo
@tzinfo.setter
def tzinfo(self, value: object) -> NoReturn:
def tzinfo(self, _: object) -> NoReturn:
raise AttributeError("You can not assign a new value to tzinfo after initialization.")
@property
@@ -341,7 +375,7 @@ class Defaults:
return self._block
@block.setter
def block(self, value: object) -> NoReturn:
def block(self, _: object) -> NoReturn:
raise AttributeError("You can not assign a new value to block after initialization.")
@property
@@ -354,7 +388,7 @@ class Defaults:
return self._protect_content
@protect_content.setter
def protect_content(self, value: object) -> NoReturn:
def protect_content(self, _: object) -> NoReturn:
raise AttributeError(
"You can't assign a new value to protect_content after initialization."
)
+103 -10
View File
@@ -50,8 +50,8 @@ from telegram import (
BotShortDescription,
BusinessConnection,
CallbackQuery,
Chat,
ChatAdministratorRights,
ChatFullInfo,
ChatInviteLink,
ChatMember,
ChatPermissions,
@@ -64,6 +64,7 @@ from telegram import (
InlineKeyboardMarkup,
InlineQueryResultsButton,
InputMedia,
InputPollOption,
LinkPreviewOptions,
Location,
MaskPosition,
@@ -113,7 +114,7 @@ if TYPE_CHECKING:
)
from telegram.ext import BaseRateLimiter, Defaults
HandledTypes = TypeVar("HandledTypes", bound=Union[Message, CallbackQuery, Chat])
HandledTypes = TypeVar("HandledTypes", bound=Union[Message, CallbackQuery, ChatFullInfo])
KT = TypeVar("KT", bound=ReplyMarkup)
@@ -262,7 +263,10 @@ class ExtBot(Bot, Generic[RLARGS]):
@classmethod
def _warn(
cls, message: str, category: Type[Warning] = PTBUserWarning, stacklevel: int = 0
cls,
message: Union[str, PTBUserWarning],
category: Type[Warning] = PTBUserWarning,
stacklevel: int = 0,
) -> None:
"""We override this method to add one more level to the stacklevel, so that the warning
points to the user's code, not to the PTB code.
@@ -436,6 +440,7 @@ class ExtBot(Bot, Generic[RLARGS]):
# 3) set the correct parse_mode for all InputMedia objects
# 4) handle the LinkPreviewOptions case (see below)
# 5) handle the ReplyParameters case (see below)
# 6) handle text_parse_mode in InputPollOption
for key, val in data.items():
# 1)
if isinstance(val, DefaultValue):
@@ -487,6 +492,21 @@ class ExtBot(Bot, Generic[RLARGS]):
data[key] = new_value
# 6)
elif isinstance(val, Sequence) and all(
isinstance(obj, InputPollOption) for obj in val
):
new_val = []
for option in val:
if not isinstance(option.text_parse_mode, DefaultValue):
new_val.append(option)
else:
new_option = copy(option)
with new_option._unfrozen():
new_option.text_parse_mode = self.defaults.text_parse_mode
new_val.append(new_option)
data[key] = new_val
def _replace_keyboard(self, reply_markup: Optional[KT]) -> Optional[KT]:
# If the reply_markup is an inline keyboard and we allow arbitrary callback data, let the
# CallbackDataCache build a new keyboard with the data replaced. Otherwise return the input
@@ -554,7 +574,7 @@ class ExtBot(Bot, Generic[RLARGS]):
self.callback_data_cache.process_message(message=obj)
return obj # type: ignore[return-value]
if isinstance(obj, Chat) and obj.pinned_message:
if isinstance(obj, ChatFullInfo) and obj.pinned_message:
self.callback_data_cache.process_message(obj.pinned_message)
return obj
@@ -573,6 +593,7 @@ class ExtBot(Bot, Generic[RLARGS]):
link_preview_options: ODVInput["LinkPreviewOptions"] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -604,6 +625,7 @@ class ExtBot(Bot, Generic[RLARGS]):
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
if isinstance(result, Message):
self._insert_callback_data(result)
@@ -778,6 +800,7 @@ class ExtBot(Bot, Generic[RLARGS]):
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
show_caption_above_media: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -808,6 +831,7 @@ class ExtBot(Bot, Generic[RLARGS]):
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
show_caption_above_media=show_caption_above_media,
)
async def copy_messages(
@@ -853,7 +877,7 @@ class ExtBot(Bot, Generic[RLARGS]):
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
rate_limit_args: Optional[RLARGS] = None,
) -> Chat:
) -> ChatFullInfo:
# We override this method to call self._insert_callback_data
result = await super().get_chat(
chat_id=chat_id,
@@ -1126,7 +1150,7 @@ class ExtBot(Bot, Generic[RLARGS]):
title: str,
description: str,
payload: str,
provider_token: str,
provider_token: Optional[str],
currency: str,
prices: Sequence["LabeledPrice"],
max_tip_amount: Optional[int] = None,
@@ -1185,7 +1209,6 @@ class ExtBot(Bot, Generic[RLARGS]):
name: str,
title: str,
stickers: Sequence["InputSticker"],
sticker_format: Optional[str] = None,
sticker_type: Optional[str] = None,
needs_repainting: Optional[bool] = None,
*,
@@ -1201,7 +1224,6 @@ class ExtBot(Bot, Generic[RLARGS]):
name=name,
title=title,
stickers=stickers,
sticker_format=sticker_format,
sticker_type=sticker_type,
needs_repainting=needs_repainting,
read_timeout=read_timeout,
@@ -1488,6 +1510,7 @@ class ExtBot(Bot, Generic[RLARGS]):
reply_markup: Optional["InlineKeyboardMarkup"] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
show_caption_above_media: Optional[bool] = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -1509,6 +1532,7 @@ class ExtBot(Bot, Generic[RLARGS]):
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
show_caption_above_media=show_caption_above_media,
)
async def edit_message_live_location(
@@ -1522,6 +1546,7 @@ class ExtBot(Bot, Generic[RLARGS]):
horizontal_accuracy: Optional[float] = None,
heading: Optional[int] = None,
proximity_alert_radius: Optional[int] = None,
live_period: Optional[int] = None,
*,
location: Optional[Location] = None,
read_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -1541,6 +1566,7 @@ class ExtBot(Bot, Generic[RLARGS]):
horizontal_accuracy=horizontal_accuracy,
heading=heading,
proximity_alert_radius=proximity_alert_radius,
live_period=live_period,
location=location,
read_timeout=read_timeout,
write_timeout=write_timeout,
@@ -2359,6 +2385,8 @@ class ExtBot(Bot, Generic[RLARGS]):
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
show_caption_above_media: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2395,6 +2423,8 @@ class ExtBot(Bot, Generic[RLARGS]):
business_connection_id=business_connection_id,
pool_timeout=pool_timeout,
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
message_effect_id=message_effect_id,
show_caption_above_media=show_caption_above_media,
)
async def send_audio(
@@ -2414,6 +2444,7 @@ class ExtBot(Bot, Generic[RLARGS]):
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2449,6 +2480,7 @@ class ExtBot(Bot, Generic[RLARGS]):
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
message_effect_id=message_effect_id,
)
async def send_chat_action(
@@ -2490,6 +2522,7 @@ class ExtBot(Bot, Generic[RLARGS]):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2521,6 +2554,7 @@ class ExtBot(Bot, Generic[RLARGS]):
pool_timeout=pool_timeout,
business_connection_id=business_connection_id,
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
message_effect_id=message_effect_id,
)
async def send_dice(
@@ -2533,6 +2567,7 @@ class ExtBot(Bot, Generic[RLARGS]):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2559,6 +2594,7 @@ class ExtBot(Bot, Generic[RLARGS]):
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
message_effect_id=message_effect_id,
)
async def send_document(
@@ -2576,6 +2612,7 @@ class ExtBot(Bot, Generic[RLARGS]):
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2609,6 +2646,7 @@ class ExtBot(Bot, Generic[RLARGS]):
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
message_effect_id=message_effect_id,
)
async def send_game(
@@ -2621,6 +2659,7 @@ class ExtBot(Bot, Generic[RLARGS]):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2647,6 +2686,7 @@ class ExtBot(Bot, Generic[RLARGS]):
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
message_effect_id=message_effect_id,
)
async def send_invoice(
@@ -2655,7 +2695,7 @@ class ExtBot(Bot, Generic[RLARGS]):
title: str,
description: str,
payload: str,
provider_token: str,
provider_token: Optional[str],
currency: str,
prices: Sequence["LabeledPrice"],
start_parameter: Optional[str] = None,
@@ -2678,6 +2718,7 @@ class ExtBot(Bot, Generic[RLARGS]):
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2723,6 +2764,7 @@ class ExtBot(Bot, Generic[RLARGS]):
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
message_effect_id=message_effect_id,
)
async def send_location(
@@ -2740,6 +2782,7 @@ class ExtBot(Bot, Generic[RLARGS]):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2773,6 +2816,7 @@ class ExtBot(Bot, Generic[RLARGS]):
business_connection_id=business_connection_id,
pool_timeout=pool_timeout,
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
message_effect_id=message_effect_id,
)
async def send_media_group(
@@ -2786,6 +2830,7 @@ class ExtBot(Bot, Generic[RLARGS]):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2817,6 +2862,7 @@ class ExtBot(Bot, Generic[RLARGS]):
business_connection_id=business_connection_id,
parse_mode=parse_mode,
caption_entities=caption_entities,
message_effect_id=message_effect_id,
)
async def send_message(
@@ -2832,6 +2878,7 @@ class ExtBot(Bot, Generic[RLARGS]):
link_preview_options: ODVInput["LinkPreviewOptions"] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
disable_web_page_preview: Optional[bool] = None,
reply_to_message_id: Optional[int] = None,
@@ -2863,6 +2910,7 @@ class ExtBot(Bot, Generic[RLARGS]):
pool_timeout=pool_timeout,
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
link_preview_options=link_preview_options,
message_effect_id=message_effect_id,
)
async def send_photo(
@@ -2879,6 +2927,8 @@ class ExtBot(Bot, Generic[RLARGS]):
has_spoiler: Optional[bool] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
show_caption_above_media: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2911,13 +2961,15 @@ class ExtBot(Bot, Generic[RLARGS]):
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
message_effect_id=message_effect_id,
show_caption_above_media=show_caption_above_media,
)
async def send_poll(
self,
chat_id: Union[int, str],
question: str,
options: Sequence[str],
options: Sequence[Union[str, "InputPollOption"]],
is_anonymous: Optional[bool] = None,
type: Optional[str] = None, # pylint: disable=redefined-builtin
allows_multiple_answers: Optional[bool] = None,
@@ -2934,6 +2986,9 @@ class ExtBot(Bot, Generic[RLARGS]):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
question_parse_mode: ODVInput[str] = DEFAULT_NONE,
question_entities: Optional[Sequence["MessageEntity"]] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2971,6 +3026,9 @@ class ExtBot(Bot, Generic[RLARGS]):
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
question_parse_mode=question_parse_mode,
question_entities=question_entities,
message_effect_id=message_effect_id,
)
async def send_sticker(
@@ -2984,6 +3042,7 @@ class ExtBot(Bot, Generic[RLARGS]):
emoji: Optional[str] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -3011,6 +3070,7 @@ class ExtBot(Bot, Generic[RLARGS]):
pool_timeout=pool_timeout,
emoji=emoji,
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
message_effect_id=message_effect_id,
)
async def send_venue(
@@ -3030,6 +3090,7 @@ class ExtBot(Bot, Generic[RLARGS]):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -3065,6 +3126,7 @@ class ExtBot(Bot, Generic[RLARGS]):
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
message_effect_id=message_effect_id,
)
async def send_video(
@@ -3086,6 +3148,8 @@ class ExtBot(Bot, Generic[RLARGS]):
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
show_caption_above_media: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -3123,6 +3187,8 @@ class ExtBot(Bot, Generic[RLARGS]):
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
message_effect_id=message_effect_id,
show_caption_above_media=show_caption_above_media,
)
async def send_video_note(
@@ -3138,6 +3204,7 @@ class ExtBot(Bot, Generic[RLARGS]):
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -3169,6 +3236,7 @@ class ExtBot(Bot, Generic[RLARGS]):
pool_timeout=pool_timeout,
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def send_voice(
@@ -3185,6 +3253,7 @@ class ExtBot(Bot, Generic[RLARGS]):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -3217,6 +3286,7 @@ class ExtBot(Bot, Generic[RLARGS]):
pool_timeout=pool_timeout,
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
)
async def set_chat_administrator_custom_title(
@@ -4087,6 +4157,28 @@ class ExtBot(Bot, Generic[RLARGS]):
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
)
async def refund_star_payment(
self,
user_id: int,
telegram_payment_charge_id: str,
*,
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: Optional[JSONDict] = None,
rate_limit_args: Optional[RLARGS] = None,
) -> bool:
return await super().refund_star_payment(
user_id=user_id,
telegram_payment_charge_id=telegram_payment_charge_id,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=self._merge_api_rl_kwargs(api_kwargs, rate_limit_args),
)
# updated camelCase aliases
getMe = get_me
sendMessage = send_message
@@ -4208,3 +4300,4 @@ class ExtBot(Bot, Generic[RLARGS]):
setMessageReaction = set_message_reaction
getBusinessConnection = get_business_connection
replaceStickerInSet = replace_sticker_in_set
refundStarPayment = refund_star_payment
@@ -159,8 +159,8 @@ class CallbackQueryHandler(BaseHandler[Update, CCT]):
def collect_additional_context(
self,
context: CCT,
update: Update,
application: "Application[Any, CCT, Any, Any, Any, Any]",
update: Update, # noqa: ARG002
application: "Application[Any, CCT, Any, Any, Any, Any]", # noqa: ARG002
check_result: Union[bool, Match[str]],
) -> None:
"""Add the result of ``re.match(pattern, update.callback_query.data)`` to
+26 -11
View File
@@ -21,8 +21,9 @@ from typing import Final, Optional, TypeVar
from telegram import Update
from telegram._utils.defaultvalue import DEFAULT_TRUE
from telegram._utils.types import DVType
from telegram._utils.types import SCT, DVType
from telegram.ext._handlers.basehandler import BaseHandler
from telegram.ext._utils._update_parsing import parse_chat_id
from telegram.ext._utils.types import CCT, HandlerCallback
RT = TypeVar("RT")
@@ -58,6 +59,9 @@ class ChatMemberHandler(BaseHandler[Update, CCT]):
:meth:`telegram.ext.Application.process_update`. Defaults to :obj:`True`.
.. seealso:: :wiki:`Concurrency`
chat_id (:obj:`int` | Collection[:obj:`int`], optional): Filters chat member updates from
specified chat ID(s) only.
.. versionadded:: 21.3
Attributes:
callback (:term:`coroutine function`): The callback function for this handler.
@@ -70,7 +74,10 @@ class ChatMemberHandler(BaseHandler[Update, CCT]):
"""
__slots__ = ("chat_member_types",)
__slots__ = (
"_chat_ids",
"chat_member_types",
)
MY_CHAT_MEMBER: Final[int] = -1
""":obj:`int`: Used as a constant to handle only :attr:`telegram.Update.my_chat_member`."""
CHAT_MEMBER: Final[int] = 0
@@ -84,10 +91,12 @@ class ChatMemberHandler(BaseHandler[Update, CCT]):
callback: HandlerCallback[Update, CCT, RT],
chat_member_types: int = MY_CHAT_MEMBER,
block: DVType[bool] = DEFAULT_TRUE,
chat_id: Optional[SCT[int]] = None,
):
super().__init__(callback, block=block)
self.chat_member_types: Optional[int] = chat_member_types
self._chat_ids = parse_chat_id(chat_id)
def check_update(self, update: object) -> bool:
"""Determines whether an update should be passed to this handler's :attr:`callback`.
@@ -99,12 +108,18 @@ class ChatMemberHandler(BaseHandler[Update, CCT]):
:obj:`bool`
"""
if isinstance(update, Update):
if not (update.my_chat_member or update.chat_member):
return False
if self.chat_member_types == self.ANY_CHAT_MEMBER:
return True
if self.chat_member_types == self.CHAT_MEMBER:
return bool(update.chat_member)
return bool(update.my_chat_member)
return False
if not isinstance(update, Update):
return False
if not (update.my_chat_member or update.chat_member):
return False
if (
self._chat_ids
and update.effective_chat
and update.effective_chat.id not in self._chat_ids
):
return False
if self.chat_member_types == self.ANY_CHAT_MEMBER:
return True
if self.chat_member_types == self.CHAT_MEMBER:
return bool(update.chat_member)
return bool(update.my_chat_member)
@@ -109,8 +109,8 @@ class ChosenInlineResultHandler(BaseHandler[Update, CCT]):
def collect_additional_context(
self,
context: CCT,
update: Update,
application: "Application[Any, CCT, Any, Any, Any, Any]",
update: Update, # noqa: ARG002
application: "Application[Any, CCT, Any, Any, Any, Any]", # noqa: ARG002
check_result: Union[bool, Match[str]],
) -> None:
"""This function adds the matched regex pattern result to
+2 -3
View File
@@ -152,7 +152,6 @@ class CommandHandler(BaseHandler[Update, CCT]):
Returns:
:obj:`bool`: Whether the args are valid for this handler.
"""
# pylint: disable=too-many-boolean-expressions
return bool(
(self.has_args is None)
or (self.has_args is True and args)
@@ -205,8 +204,8 @@ class CommandHandler(BaseHandler[Update, CCT]):
def collect_additional_context(
self,
context: CCT,
update: Update,
application: "Application[Any, CCT, Any, Any, Any, Any]",
update: Update, # noqa: ARG002
application: "Application[Any, CCT, Any, Any, Any, Any]", # noqa: ARG002
check_result: Optional[Union[bool, Tuple[List[str], Optional[bool]]]],
) -> None:
"""Add text after the command to :attr:`CallbackContext.args` as list, split on single
+11 -11
View File
@@ -473,7 +473,7 @@ class ConversationHandler(BaseHandler[Update, CCT]):
return self._entry_points
@entry_points.setter
def entry_points(self, value: object) -> NoReturn:
def entry_points(self, _: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to entry_points after initialization."
)
@@ -487,7 +487,7 @@ class ConversationHandler(BaseHandler[Update, CCT]):
return self._states
@states.setter
def states(self, value: object) -> NoReturn:
def states(self, _: object) -> NoReturn:
raise AttributeError("You can not assign a new value to states after initialization.")
@property
@@ -499,7 +499,7 @@ class ConversationHandler(BaseHandler[Update, CCT]):
return self._fallbacks
@fallbacks.setter
def fallbacks(self, value: object) -> NoReturn:
def fallbacks(self, _: object) -> NoReturn:
raise AttributeError("You can not assign a new value to fallbacks after initialization.")
@property
@@ -508,7 +508,7 @@ class ConversationHandler(BaseHandler[Update, CCT]):
return self._allow_reentry
@allow_reentry.setter
def allow_reentry(self, value: object) -> NoReturn:
def allow_reentry(self, _: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to allow_reentry after initialization."
)
@@ -519,7 +519,7 @@ class ConversationHandler(BaseHandler[Update, CCT]):
return self._per_user
@per_user.setter
def per_user(self, value: object) -> NoReturn:
def per_user(self, _: object) -> NoReturn:
raise AttributeError("You can not assign a new value to per_user after initialization.")
@property
@@ -528,7 +528,7 @@ class ConversationHandler(BaseHandler[Update, CCT]):
return self._per_chat
@per_chat.setter
def per_chat(self, value: object) -> NoReturn:
def per_chat(self, _: object) -> NoReturn:
raise AttributeError("You can not assign a new value to per_chat after initialization.")
@property
@@ -537,7 +537,7 @@ class ConversationHandler(BaseHandler[Update, CCT]):
return self._per_message
@per_message.setter
def per_message(self, value: object) -> NoReturn:
def per_message(self, _: object) -> NoReturn:
raise AttributeError("You can not assign a new value to per_message after initialization.")
@property
@@ -551,7 +551,7 @@ class ConversationHandler(BaseHandler[Update, CCT]):
return self._conversation_timeout
@conversation_timeout.setter
def conversation_timeout(self, value: object) -> NoReturn:
def conversation_timeout(self, _: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to conversation_timeout after initialization."
)
@@ -562,7 +562,7 @@ class ConversationHandler(BaseHandler[Update, CCT]):
return self._name
@name.setter
def name(self, value: object) -> NoReturn:
def name(self, _: object) -> NoReturn:
raise AttributeError("You can not assign a new value to name after initialization.")
@property
@@ -574,7 +574,7 @@ class ConversationHandler(BaseHandler[Update, CCT]):
return self._persistent
@persistent.setter
def persistent(self, value: object) -> NoReturn:
def persistent(self, _: object) -> NoReturn:
raise AttributeError("You can not assign a new value to persistent after initialization.")
@property
@@ -586,7 +586,7 @@ class ConversationHandler(BaseHandler[Update, CCT]):
return self._map_to_parent
@map_to_parent.setter
def map_to_parent(self, value: object) -> NoReturn:
def map_to_parent(self, _: object) -> NoReturn:
raise AttributeError(
"You can not assign a new value to map_to_parent after initialization."
)
+2 -2
View File
@@ -130,8 +130,8 @@ class InlineQueryHandler(BaseHandler[Update, CCT]):
def collect_additional_context(
self,
context: CCT,
update: Update,
application: "Application[Any, CCT, Any, Any, Any, Any]",
update: Update, # noqa: ARG002
application: "Application[Any, CCT, Any, Any, Any, Any]", # noqa: ARG002
check_result: Optional[Union[bool, Match[str]]],
) -> None:
"""Add the result of ``re.match(pattern, update.inline_query.query)`` to
+2 -2
View File
@@ -102,8 +102,8 @@ class MessageHandler(BaseHandler[Update, CCT]):
def collect_additional_context(
self,
context: CCT,
update: Update,
application: "Application[Any, CCT, Any, Any, Any, Any]",
update: Update, # noqa: ARG002
application: "Application[Any, CCT, Any, Any, Any, Any]", # noqa: ARG002
check_result: Optional[Union[bool, Dict[str, object]]],
) -> None:
"""Adds possible output of data filters to the :class:`CallbackContext`."""
+2 -2
View File
@@ -171,8 +171,8 @@ class PrefixHandler(BaseHandler[Update, CCT]):
def collect_additional_context(
self,
context: CCT,
update: Update,
application: "Application[Any, CCT, Any, Any, Any, Any]",
update: Update, # noqa: ARG002
application: "Application[Any, CCT, Any, Any, Any, Any]", # noqa: ARG002
check_result: Optional[Union[bool, Tuple[List[str], Optional[bool]]]],
) -> None:
"""Add text after the command to :attr:`CallbackContext.args` as list, split on single
@@ -49,7 +49,7 @@ class StringCommandHandler(BaseHandler[str, CCT]):
called when :meth:`check_update` has determined that an update should be processed by
this handler. Callback signature::
async def callback(update: Update, context: CallbackContext)
async def callback(update: str, context: CallbackContext)
The return value of the callback is usually ignored except for the special case of
:class:`telegram.ext.ConversationHandler`.
@@ -98,8 +98,8 @@ class StringCommandHandler(BaseHandler[str, CCT]):
def collect_additional_context(
self,
context: CCT,
update: str,
application: "Application[Any, CCT, Any, Any, Any, Any]",
update: str, # noqa: ARG002
application: "Application[Any, CCT, Any, Any, Any, Any]", # noqa: ARG002
check_result: Optional[List[str]],
) -> None:
"""Add text after the command to :attr:`CallbackContext.args` as list, split on single

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