Compare commits

...

34 Commits

Author SHA1 Message Date
Bibo-Joshi 151123745e Bump Version to v21.7 (#4557) 2024-11-04 21:29:59 +01:00
Bibo-Joshi 0eb11ff3e9 Documentation Improvements (#4536, #4556)
Co-authored-by: Abubakar Alaya <ecode5814@gmail.com>
2024-11-04 20:38:41 +01:00
Bibo-Joshi dab75fb963 Add Message.reply_paid_media (#4551) 2024-11-04 20:33:56 +01:00
Bibo-Joshi 62f89758d7 Bot API 7.11 (#4546) 2024-11-04 20:11:10 +01:00
Bibo-Joshi 7a8f4412b2 Update Issue Templates to Use Issue Types (#4553) 2024-11-04 19:08:04 +01:00
Bibo-Joshi 032a859149 Update Automation to Label Changes (#4552) 2024-11-03 21:43:40 +01:00
Bibo-Joshi 507d6bc0e3 Improve Exception Handling in File.download_* (#4542) 2024-11-03 16:35:16 +01:00
dependabot[bot] bd6a60bb30 Bump srvaroa/labeler from 1.11.0 to 1.11.1 (#4549)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-02 18:04:50 +01:00
Bibo-Joshi 3c8f6ed42b Fix Linkcheck Workflow (#4545) 2024-11-01 22:17:14 +01:00
Bibo-Joshi 6540f288f5 Use sphinx-build-compatibility to Keep Sphinx Compatibility (#4492) 2024-10-31 08:27:58 +01:00
Pablo Martínez 5ab82a9c2b Drop Support for Python 3.8 (#4398)
Co-authored-by: poolitzer <github@poolitzer.eu>
Co-authored-by: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com>
2024-10-24 20:48:49 +02:00
Bibo-Joshi 847b97f86e Use Stable Python 3.13 Release in Test Suite (#4535) 2024-10-24 20:03:16 +02:00
Siloé Garcez efacc3dd1b Allow Sequence in Application.add_handlers (#4531) 2024-10-23 22:14:03 +02:00
dependabot[bot] 2ce687c8f1 Bump sphinx from 8.0.2 to 8.1.3 (#4532)
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>
2024-10-21 19:40:12 +02:00
dependabot[bot] a39a59ee9b Bump sphinxcontrib-mermaid from 0.9.2 to 1.0.0 (#4529)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-21 19:12:44 +02:00
dependabot[bot] 06854633ab Bump srvaroa/labeler from 1.10.1 to 1.11.0 (#4509)
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-10-02 03:00:45 +02:00
dependabot[bot] 9a8b208ef7 Bump Bibo-Joshi/pyright-type-completeness from 1.0.0 to 1.0.1 (#4510)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-02 02:57:34 +02:00
Bibo-Joshi 2f06902518 Improve Test Instability Caused by Message Fixtures (#4507) 2024-10-01 07:16:29 +02:00
Bibo-Joshi 2bc65560eb Stabilize Some Flaky Tests (#4500) 2024-09-25 18:53:26 +02:00
Bibo-Joshi 79e589b39e Reduce Creation of HTTP Clients in Tests (#4493) 2024-09-25 17:17:55 +02:00
Bibo-Joshi bd3cdbcdbd Update pytest-xdist Usage (#4491) 2024-09-22 19:49:48 +02:00
Bibo-Joshi 9709c03b35 Fix Failing Tests by Making Them Independent (#4494) 2024-09-21 18:49:33 +02:00
Bibo-Joshi 3409f51107 Introduce Codecov's Test Analysis (#4487) 2024-09-21 17:15:22 +02:00
Bibo-Joshi 2eae2830f3 Maintenance Work on Bot Tests (#4489)
Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com>
2024-09-21 11:34:25 +02:00
Bibo-Joshi 28d19c3b9a Introduce conftest.py for File Related Tests (#4488)
Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com>
2024-09-21 11:33:52 +02:00
Bibo-Joshi e314e78d06 Bump Version to v21.6 (#4486) 2024-09-19 20:17:08 +02:00
Harshil 67a97ae5a7 API 7.10 (#4461, #4460, #4463, #4464)
Co-authored-by: aelkheir <90580077+aelkheir@users.noreply.github.com>
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
2024-09-17 18:09:19 +02:00
dependabot[bot] 9248c539d0 Bump pytest from 8.3.2 to 8.3.3 (#4475)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-14 08:17:31 +02:00
Bibo-Joshi 6b5e46cc08 Improve Type Completeness (#4466) 2024-09-14 08:16:39 +02:00
Harshil b3155b2e55 Update Python 3.13 Test Suite to RC2 (#4471) 2024-09-13 19:32:22 +02:00
Bibo-Joshi ec909e62cf Enforce the offline_bot Fixture in Test*WithoutRequest (#4465) 2024-09-13 19:10:09 +02:00
Bibo-Joshi 1223e851c3 Add Parameter httpx_kwargs to HTTPXRequest (#4451) 2024-09-11 22:34:18 +02:00
Bibo-Joshi 0b352b043e Make Tests for telegram.ext Independent of Networking (#4454) 2024-09-09 07:32:32 +02:00
Bibo-Joshi b9d2efdec5 Rename Testing Base Classes (#4453) 2024-09-03 05:24:25 +02:00
312 changed files with 5086 additions and 3584 deletions
+2 -2
View File
@@ -1,7 +1,7 @@
name: Bug Report
description: Create a report to help us improve
title: "[BUG]"
labels: ["bug :bug:"]
labels: ["📋 triage"]
type: '🐛 bug'
body:
- type: markdown
+2 -2
View File
@@ -1,7 +1,7 @@
name: Feature Request
description: Suggest an idea for this project
title: "[FEATURE]"
labels: ["enhancement"]
labels: ["📋 triage"]
type: '💡 feature'
body:
- type: textarea
+1 -1
View File
@@ -1,7 +1,7 @@
name: Question
description: Get help with errors or general questions
title: "[QUESTION]"
labels: ["question"]
type: '❔ question'
body:
- type: markdown
+2 -2
View File
@@ -3,7 +3,7 @@
version: 1
labels:
- label: "dependencies"
- label: "⚙️ dependencies"
authors: ["dependabot[bot]", "pre-commit-ci[bot]"]
- label: "code quality"
- label: "🛠 code-quality"
authors: ["pre-commit-ci[bot]"]
+4 -1
View File
@@ -3,6 +3,9 @@ on:
schedule:
# First day of month at 05:46 in every 2nd month
- cron: '46 5 1 */2 *'
pull_request:
paths:
- .github/workflows/docs-linkcheck.yml
jobs:
test-sphinx-build:
@@ -10,7 +13,7 @@ jobs:
runs-on: ${{matrix.os}}
strategy:
matrix:
python-version: [3.10]
python-version: ['3.10']
os: [ubuntu-latest]
fail-fast: False
steps:
+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.1
- uses: srvaroa/labeler@v1.11.1
# Config file at .github/labeler.yml
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+1 -1
View File
@@ -13,7 +13,7 @@ jobs:
days-before-stale: 3
days-before-close: 2
days-before-pr-stale: -1
stale-issue-label: 'stale'
stale-issue-label: '📋 stale'
only-labels: 'question'
stale-issue-message: ''
close-issue-message: 'This issue has been automatically closed due to inactivity. Feel free to comment in order to reopen or ask again in our Telegram support group at https://t.me/pythontelegrambotgroup.'
+1 -1
View File
@@ -14,7 +14,7 @@ jobs:
name: test-type-completeness
runs-on: ubuntu-latest
steps:
- uses: Bibo-Joshi/pyright-type-completeness@1.0.0
- uses: Bibo-Joshi/pyright-type-completeness@1.0.1
with:
package-name: telegram
python-version: 3.12
@@ -0,0 +1,33 @@
name: Check Type Completeness Monthly Run
on:
schedule:
# Run first friday of the month at 03:17 - odd time to spread load on GitHub Actions
- cron: '17 3 1-7 * 5'
jobs:
test-type-completeness:
name: test-type-completeness
runs-on: ubuntu-latest
steps:
- uses: Bibo-Joshi/pyright-type-completeness@1.0.1
id: pyright-type-completeness
with:
package-name: telegram
python-version: 3.12
pyright-version: ~=1.1.367
- name: Check Output
uses: jannekem/run-python-script-action@v1
env:
TYPE_COMPLETENESS: ${{ steps.pyright-type-completeness.outputs.base-completeness-score }}
with:
script: |
import os
completeness = float(os.getenv("TYPE_COMPLETENESS"))
if completeness >= 1:
exit(0)
text = f"Type Completeness Decreased to {completeness}. ❌"
error(text)
set_summary(text)
exit(1)
+17 -15
View File
@@ -20,7 +20,7 @@ jobs:
runs-on: ${{matrix.os}}
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13.0-rc.1']
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
os: [ubuntu-latest, windows-latest, macos-latest]
fail-fast: False
steps:
@@ -37,7 +37,7 @@ jobs:
python -W ignore -m pip install -U pytest-cov
python -W ignore -m pip install .
python -W ignore -m pip install -r requirements-unit-tests.txt
python -W ignore -m pip install pytest-xdist[psutil]
python -W ignore -m pip install pytest-xdist
- name: Test with pytest
# We run 4 different suites here
@@ -57,21 +57,17 @@ jobs:
# - without socks support
# - without http2 support
TO_TEST="test_no_passport.py or test_datetime.py or test_defaults.py or test_jobqueue.py or test_applicationbuilder.py or test_ratelimiter.py or test_updater.py or test_callbackdatacache.py or test_request.py"
pytest -v --cov -k "${TO_TEST}"
# Rerun only failed tests (--lf), and don't run any tests if none failed (--lfnf=none)
pytest -v --cov --cov-append -k "${TO_TEST}" --lf --lfnf=none --junit-xml=.test_report_no_optionals.xml
# No tests were selected, convert returned status code to 0
opt_dep_status=$(( $? == 5 ? 0 : $? ))
pytest -v --cov -k "${TO_TEST}" --junit-xml=.test_report_no_optionals_junit.xml
opt_dep_status=$?
# Test the rest
export TEST_WITH_OPT_DEPS='true'
pip install .[all]
# `-n auto --dist loadfile` uses pytest-xdist to run each test file on a different CPU
# worker. Increasing number of workers has little effect on test duration, but it seems
# to increase flakyness, specially on python 3.7 with --dist=loadgroup.
pytest -v --cov --cov-append -n auto --dist loadfile
pytest -v --cov --cov-append -n auto --dist loadfile --lf --lfnf=none --junit-xml=.test_report_optionals.xml
main_status=$(( $? == 5 ? 0 : $? ))
# `-n auto --dist worksteal` uses pytest-xdist to run tests on multiple CPU
# workers. Increasing number of workers has little effect on test duration, but it seems
# to increase flakyness.
pytest -v --cov --cov-append -n auto --dist worksteal --junit-xml=.test_report_optionals_junit.xml
main_status=$?
# exit with non-zero status if any of the two pytest runs failed
exit $(( ${opt_dep_status} || ${main_status} ))
env:
@@ -87,8 +83,8 @@ jobs:
if: always() # always run, even if tests fail
with:
paths: |
.test_report_no_optionals.xml
.test_report_optionals.xml
.test_report_no_optionals_junit.xml
.test_report_optionals_junit.xml
- name: Submit coverage
uses: codecov/codecov-action@v4
@@ -97,3 +93,9 @@ jobs:
name: ${{ matrix.os }}-${{ matrix.python-version }}
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }}
- name: Upload test results to Codecov
uses: codecov/test-results-action@v1
if: ${{ !cancelled() }}
with:
files: .test_report_no_optionals_junit.xml,.test_report_optionals_junit.xml
token: ${{ secrets.CODECOV_TOKEN }}
+1 -1
View File
@@ -72,7 +72,7 @@ repos:
hooks:
- id: pyupgrade
args:
- --py38-plus
- --py39-plus
- repo: https://github.com/pycqa/isort
rev: 5.13.2
hooks:
+2
View File
@@ -23,6 +23,7 @@ The following wonderful people contributed directly or indirectly to this projec
- `Abdelrahman <https://github.com/aelkheir>`_
- `Abshar <https://github.com/abxhr>`_
- `Abubakar Alaya <https://github.com/Ecode2>`_
- `Alateas <https://github.com/alateas>`_
- `Ales Dokshanin <https://github.com/alesdokshanin>`_
- `Alexandre <https://github.com/xTudoS>`_
@@ -115,6 +116,7 @@ The following wonderful people contributed directly or indirectly to this projec
- `Sascha <https://github.com/saschalalala>`_
- `Shelomentsev D <https://github.com/shelomentsevd>`_
- `Shivam Saini <https://github.com/shivamsn97>`_
- `Siloé Garcez <https://github.com/roast-lord>`_
- `Simon Schürrle <https://github.com/SitiSchu>`_
- `sooyhwang <https://github.com/sooyhwang>`_
- `syntx <https://github.com/syntx>`_
+81
View File
@@ -4,6 +4,87 @@
Changelog
=========
Version 21.7
============
*Released 2024-11-04*
This is the technical changelog for version 21.7. More elaborate release notes can be found in the news channel `@pythontelegrambotchannel <https://t.me/pythontelegrambotchannel>`_.
Major Changes
-------------
- Full Support for Bot API 7.11 (:pr:`4546` closes :issue:`4543`)
- Add ``Message.reply_paid_media`` (:pr:`4551`)
- Drop Support for Python 3.8 (:pr:`4398` by `elpekenin <https://github.com/elpekenin>`_)
Minor Changes
-------------
- Allow ``Sequence`` in ``Application.add_handlers`` (:pr:`4531` by `roast-lord <https://github.com/roast-lord>`_ closes :issue:`4530`)
- Improve Exception Handling in ``File.download_*`` (:pr:`4542`)
- Use Stable Python 3.13 Release in Test Suite (:pr:`4535`)
Documentation Improvements
--------------------------
- Documentation Improvements (:pr:`4536` by `Ecode2 <https://github.com/Ecode2>`_, :pr:`4556`)
- Fix Linkcheck Workflow (:pr:`4545`)
- Use ``sphinx-build-compatibility`` to Keep Sphinx Compatibility (:pr:`4492`)
Internal Changes
----------------
- Improve Test Instability Caused by ``Message`` Fixtures (:pr:`4507`)
- Stabilize Some Flaky Tests (:pr:`4500`)
- Reduce Creation of HTTP Clients in Tests (:pr:`4493`)
- Update ``pytest-xdist`` Usage (:pr:`4491`)
- Fix Failing Tests by Making Them Independent (:pr:`4494`)
- Introduce Codecov's Test Analysis (:pr:`4487`)
- Maintenance Work on ``Bot`` Tests (:pr:`4489`)
- Introduce ``conftest.py`` for File Related Tests (:pr:`4488`)
- Update Issue Templates to Use Issue Types (:pr:`4553`)
- Update Automation to Label Changes (:pr:`4552`)
Dependency Updates
------------------
- Bump ``srvaroa/labeler`` from 1.11.0 to 1.11.1 (:pr:`4549`)
- Bump ``sphinx`` from 8.0.2 to 8.1.3 (:pr:`4532`)
- Bump ``sphinxcontrib-mermaid`` from 0.9.2 to 1.0.0 (:pr:`4529`)
- Bump ``srvaroa/labeler`` from 1.10.1 to 1.11.0 (:pr:`4509`)
- Bump ``Bibo-Joshi/pyright-type-completeness`` from 1.0.0 to 1.0.1 (:pr:`4510`)
Version 21.6
============
*Released 2024-09-19*
This is the technical changelog for version 21.6. More elaborate release notes can be found in the news channel `@pythontelegrambotchannel <https://t.me/pythontelegrambotchannel>`_.
New Features
------------
- Full Support for Bot API 7.10 (:pr:`4461` closes :issue:`4459`, :pr:`4460`, :pr:`4463` by `aelkheir <https://github.com/aelkheir>`_, :pr:`4464`)
- Add Parameter ``httpx_kwargs`` to ``HTTPXRequest`` (:pr:`4451` closes :issue:`4424`)
Minor Changes
-------------
- Improve Type Completeness (:pr:`4466`)
Internal Changes
----------------
- Update Python 3.13 Test Suite to RC2 (:pr:`4471`)
- Enforce the ``offline_bot`` Fixture in ``Test*WithoutRequest`` (:pr:`4465`)
- Make Tests for ``telegram.ext`` Independent of Networking (:pr:`4454`)
- Rename Testing Base Classes (:pr:`4453`)
Dependency Updates
------------------
- Bump ``pytest`` from 8.3.2 to 8.3.3 (:pr:`4475`)
Version 21.5
============
+6 -6
View File
@@ -11,7 +11,7 @@
:target: https://pypi.org/project/python-telegram-bot/
:alt: Supported Python versions
.. image:: https://img.shields.io/badge/Bot%20API-7.9-blue?logo=telegram
.. image:: https://img.shields.io/badge/Bot%20API-7.11-blue?logo=telegram
:target: https://core.telegram.org/bots/api-changelog
:alt: Supported Bot API version
@@ -70,7 +70,7 @@ Introduction
This library provides a pure Python, asynchronous interface for the
`Telegram Bot API <https://core.telegram.org/bots/api>`_.
It's compatible with Python versions **3.8+**.
It's compatible with Python versions **3.9+**.
In addition to the pure API implementation, this library features several convenience methods and shortcuts as well as a number of high-level classes to
make the development of bots easy and straightforward. These classes are contained in the
@@ -81,7 +81,7 @@ After installing_ the library, be sure to check out the section on `working with
Telegram API support
~~~~~~~~~~~~~~~~~~~~
All types and methods of the Telegram Bot API **7.9** are natively supported by this library.
All types and methods of the Telegram Bot API **7.11** are natively supported by this library.
In addition, Bot API functionality not yet natively included can still be used as described `in our wiki <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Bot-API-Forward-Compatibility>`_.
Notable Features
@@ -121,7 +121,7 @@ To enable you to verify that a release file that you downloaded was indeed provi
Starting with v21.4, all releases are signed via `sigstore <https://www.sigstore.dev>`_.
The corresponding signature files are uploaded to the `GitHub releases page`_.
To verify the signature, please install the `sigstore Python client <https://pypi.org/project/sigstore/>`_ and follow the instructions for `verifying signatures from GitHub Actions <https://github.com/sigstore/sigstore-python#signatures-from-github-actions>`_. As input for the ``--repository`` parameter, please use the value ``python-telegram-bot/python-telegram-bot``.
To verify the signature, please install the `sigstore Python client <https://pypi.org/project/sigstore/>`_ and follow the instructions for `verifying signatures from GitHub Actions <https://github.com/sigstore/sigstore-python?tab=readme-ov-file>`_. As input for the ``--repository`` parameter, please use the value ``python-telegram-bot/python-telegram-bot``.
Earlier releases are signed with a GPG key.
The signatures are uploaded to both the `GitHub releases page`_ and the `PyPI project <https://pypi.org/project/python-telegram-bot/>`_ and end with a suffix ``.asc``.
@@ -230,6 +230,6 @@ License
-------
You may copy, distribute and modify the software provided that modifications are described and licensed for free under `LGPL-3 <https://www.gnu.org/licenses/lgpl-3.0.html>`_.
Derivatives works (including modifications or anything statically linked to the library) can only be redistributed under LGPL-3, but applications that use the library don't have to be.
Derivative works (including modifications or anything statically linked to the library) can only be redistributed under LGPL-3, but applications that use the library don't have to be.
.. _`GitHub releases page`: https://github.com/python-telegram-bot/python-telegram-bot/releases>
.. _`GitHub releases page`: https://github.com/python-telegram-bot/python-telegram-bot/releases
+2 -1
View File
@@ -20,7 +20,8 @@ import inspect
import re
import typing
from collections import defaultdict
from typing import Any, Iterator, Union
from collections.abc import Iterator
from typing import Any, Union
import telegram
import telegram.ext
+1 -2
View File
@@ -16,7 +16,6 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
import inspect
from typing import List
keyword_args = [
"Keyword Arguments:",
@@ -85,7 +84,7 @@ get_updates_read_timeout_addition = [
]
def find_insert_pos_for_kwargs(lines: List[str]) -> int:
def find_insert_pos_for_kwargs(lines: list[str]) -> int:
"""Finds the correct position to insert the keyword arguments and returns the index."""
for idx, value in reversed(list(enumerate(lines))): # reversed since :returns: is at the end
if value.startswith("Returns"):
+1 -2
View File
@@ -21,7 +21,6 @@ https://github.com/sphinx-doc/sphinx/issues/1556 is closed
"""
import subprocess
from pathlib import Path
from typing import Dict, Tuple
from sphinx.util import logging
@@ -32,7 +31,7 @@ sphinx_logger = logging.getLogger(__name__)
# must be a module-level variable so that it can be written to by the `autodoc-process-docstring`
# event handler in `sphinx_hooks.py`
LINE_NUMBERS: Dict[str, Tuple[Path, int, int]] = {}
LINE_NUMBERS: dict[str, tuple[Path, int, int]] = {}
def _git_branch() -> str:
+5 -3
View File
@@ -1,7 +1,9 @@
sphinx==8.0.2
sphinx==8.1.3
furo==2024.8.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
sphinxcontrib-mermaid==1.0.0
sphinx-copybutton==0.5.2
sphinx-inline-tabs==2023.4.21
sphinx-inline-tabs==2023.4.21
# Temporary. See #4387
sphinx-build-compatibility @ git+https://github.com/readthedocs/sphinx-build-compatibility.git@58aabc5f207c6c2421f23d3578adc0b14af57047
+5 -1
View File
@@ -30,7 +30,7 @@ version = telegram.__version__
release = telegram.__version__
# If your documentation needs a minimal Sphinx version, state it here.
needs_sphinx = "8.0.2"
needs_sphinx = "8.1.3"
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
@@ -48,6 +48,10 @@ extensions = [
"sphinx_search.extension",
]
# Temporary. See #4387
if os.environ.get("READTHEDOCS", "") == "True":
extensions.append("sphinx_build_compatibility.extension")
# For shorter links to Wiki in docstrings
extlinks = {
"wiki": ("https://github.com/python-telegram-bot/python-telegram-bot/wiki/%s", "%s"),
+2
View File
@@ -29,6 +29,7 @@ Available Types
telegram.chat
telegram.chatadministratorrights
telegram.chatbackground
telegram.copytextbutton
telegram.backgroundtype
telegram.backgroundtypefill
telegram.backgroundtypewallpaper
@@ -120,6 +121,7 @@ Available Types
telegram.paidmediainfo
telegram.paidmediaphoto
telegram.paidmediapreview
telegram.paidmediapurchased
telegram.paidmediavideo
telegram.photosize
telegram.poll
+6
View File
@@ -0,0 +1,6 @@
CopyTextButton
==============
.. autoclass:: telegram.CopyTextButton
:members:
:show-inheritance:
@@ -18,6 +18,7 @@ Handlers
telegram.ext.inlinequeryhandler
telegram.ext.messagehandler
telegram.ext.messagereactionhandler
telegram.ext.paidmediapurchasedhandler
telegram.ext.pollanswerhandler
telegram.ext.pollhandler
telegram.ext.precheckoutqueryhandler
@@ -0,0 +1,6 @@
PaidMediaPurchasedHandler
=========================
.. autoclass:: telegram.ext.PaidMediaPurchasedHandler
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
PaidMediaPurchased
==================
.. autoclass:: telegram.PaidMediaPurchased
:members:
:show-inheritance:
+1
View File
@@ -28,4 +28,5 @@ Your bot can accept payments from Telegram users. Please see the `introduction t
telegram.transactionpartnerfragment
telegram.transactionpartnerother
telegram.transactionpartnertelegramads
telegram.transactionpartnertelegramapi
telegram.transactionpartneruser
@@ -4,4 +4,4 @@ TransactionPartnerFragment
.. autoclass:: telegram.TransactionPartnerFragment
:members:
:show-inheritance:
:inherited-members: TelegramObject
:inherited-members: TransactionPartner
@@ -4,4 +4,4 @@ TransactionPartnerOther
.. autoclass:: telegram.TransactionPartnerOther
:members:
:show-inheritance:
:inherited-members: TelegramObject
:inherited-members: TransactionPartner
@@ -4,4 +4,4 @@ TransactionPartnerTelegramAds
.. autoclass:: telegram.TransactionPartnerTelegramAds
:members:
:show-inheritance:
:inherited-members: TelegramObject
:inherited-members: TransactionPartner
@@ -0,0 +1,7 @@
TransactionPartnerTelegramApi
=============================
.. autoclass:: telegram.TransactionPartnerTelegramApi
:members:
:show-inheritance:
:inherited-members: TransactionPartner
@@ -4,4 +4,4 @@ TransactionPartnerUser
.. autoclass:: telegram.TransactionPartnerUser
:members:
:show-inheritance:
:inherited-members: TelegramObject
:inherited-members: TransactionPartner
+2
View File
@@ -93,3 +93,5 @@
.. |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>`__
.. |allow_paid_broadcast| replace:: Pass True to allow up to :tg-const:`telegram.constants.FloodLimit.PAID_MESSAGES_PER_SECOND` messages per second, ignoring `broadcasting limits <https://core.telegram.org/bots/faq#how-can-i-message-all-of-my-bot-39s-subscribers-at-once>`__ for a fee of 0.1 Telegram Stars per message. The relevant Stars will be withdrawn from the bot's balance.
+4 -4
View File
@@ -12,7 +12,7 @@ To use arbitrary callback data, you must install PTB via
`pip install "python-telegram-bot[callback-data]"`
"""
import logging
from typing import List, Tuple, cast
from typing import cast
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
from telegram.ext import (
@@ -36,7 +36,7 @@ logger = logging.getLogger(__name__)
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"""Sends a message with 5 inline buttons attached."""
number_list: List[int] = []
number_list: list[int] = []
await update.message.reply_text("Please choose:", reply_markup=build_keyboard(number_list))
@@ -55,7 +55,7 @@ async def clear(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
await update.effective_message.reply_text("All clear!")
def build_keyboard(current_list: List[int]) -> InlineKeyboardMarkup:
def build_keyboard(current_list: list[int]) -> InlineKeyboardMarkup:
"""Helper function to build the next inline keyboard."""
return InlineKeyboardMarkup.from_column(
[InlineKeyboardButton(str(i), callback_data=(i, current_list)) for i in range(1, 6)]
@@ -69,7 +69,7 @@ async def list_button(update: Update, context: ContextTypes.DEFAULT_TYPE) -> Non
# Get the data from the callback_data.
# If you're using a type checker like MyPy, you'll have to use typing.cast
# to make the checker get the expected type of the callback_data
number, number_list = cast(Tuple[int, List[int]], query.data)
number, number_list = cast(tuple[int, list[int]], query.data)
# append the number to the list
number_list.append(number)
+2 -2
View File
@@ -12,7 +12,7 @@ bot.
"""
import logging
from typing import Optional, Tuple
from typing import Optional
from telegram import Chat, ChatMember, ChatMemberUpdated, Update
from telegram.constants import ParseMode
@@ -37,7 +37,7 @@ logging.getLogger("httpx").setLevel(logging.WARNING)
logger = logging.getLogger(__name__)
def extract_status_change(chat_member_update: ChatMemberUpdated) -> Optional[Tuple[bool, bool]]:
def extract_status_change(chat_member_update: ChatMemberUpdated) -> Optional[tuple[bool, bool]]:
"""Takes a ChatMemberUpdated instance and extracts whether the 'old_chat_member' was a member
of the chat and whether the 'new_chat_member' is a member of the chat. Returns None, if
the status didn't change.
+3 -3
View File
@@ -12,7 +12,7 @@ bot.
import logging
from collections import defaultdict
from typing import DefaultDict, Optional, Set
from typing import Optional
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
from telegram.constants import ParseMode
@@ -40,7 +40,7 @@ class ChatData:
"""Custom class for chat_data. Here we store data per message."""
def __init__(self) -> None:
self.clicks_per_message: DefaultDict[int, int] = defaultdict(int)
self.clicks_per_message: defaultdict[int, int] = defaultdict(int)
# The [ExtBot, dict, ChatData, dict] is for type checkers like mypy
@@ -57,7 +57,7 @@ class CustomContext(CallbackContext[ExtBot, dict, ChatData, dict]):
self._message_id: Optional[int] = None
@property
def bot_user_ids(self) -> Set[int]:
def bot_user_ids(self) -> set[int]:
"""Custom shortcut to access a value stored in the bot_data dict"""
return self.bot_data.setdefault("user_ids", set())
+1 -2
View File
@@ -15,7 +15,6 @@ bot.
"""
import logging
from typing import Dict
from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, Update
from telegram.ext import (
@@ -46,7 +45,7 @@ reply_keyboard = [
markup = ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True)
def facts_to_str(user_data: Dict[str, str]) -> str:
def facts_to_str(user_data: dict[str, str]) -> str:
"""Helper function for formatting the gathered user info."""
facts = [f"{key} - {value}" for key, value in user_data.items()]
return "\n".join(facts).join(["\n", "\n"])
+5 -5
View File
@@ -15,7 +15,7 @@ bot.
"""
import logging
from typing import Any, Dict, Tuple
from typing import Any
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
from telegram.ext import (
@@ -66,7 +66,7 @@ END = ConversationHandler.END
# Helper
def _name_switcher(level: str) -> Tuple[str, str]:
def _name_switcher(level: str) -> tuple[str, str]:
if level == PARENTS:
return "Father", "Mother"
return "Brother", "Sister"
@@ -122,7 +122,7 @@ async def adding_self(update: Update, context: ContextTypes.DEFAULT_TYPE) -> str
async def show_data(update: Update, context: ContextTypes.DEFAULT_TYPE) -> str:
"""Pretty print gathered data."""
def pretty_print(data: Dict[str, Any], level: str) -> str:
def pretty_print(data: dict[str, Any], level: str) -> str:
people = data.get(level)
if not people:
return "\nNo information yet."
@@ -371,8 +371,8 @@ def main() -> None:
entry_points=[CommandHandler("start", start)],
states={
SHOWING: [CallbackQueryHandler(start, pattern="^" + str(END) + "$")],
SELECTING_ACTION: selection_handlers,
SELECTING_LEVEL: selection_handlers,
SELECTING_ACTION: selection_handlers, # type: ignore[dict-item]
SELECTING_LEVEL: selection_handlers, # type: ignore[dict-item]
DESCRIBING_SELF: [description_conv],
STOPPING: [CommandHandler("start", start)],
},
+1 -2
View File
@@ -15,7 +15,6 @@ bot.
"""
import logging
from typing import Dict
from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, Update
from telegram.ext import (
@@ -47,7 +46,7 @@ reply_keyboard = [
markup = ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True)
def facts_to_str(user_data: Dict[str, str]) -> str:
def facts_to_str(user_data: dict[str, str]) -> str:
"""Helper function for formatting the gathered user info."""
facts = [f"{key} - {value}" for key, value in user_data.items()]
return "\n".join(facts).join(["\n", "\n"])
+2 -3
View File
@@ -8,7 +8,7 @@ dynamic = ["version"]
name = "python-telegram-bot"
description = "We have made you a wrapper you can't refuse"
readme = "README.rst"
requires-python = ">=3.8"
requires-python = ">=3.9"
license = "LGPL-3.0-only"
license-files = { paths = ["LICENSE", "LICENSE.dual", "LICENSE.lesser"] }
authors = [
@@ -31,7 +31,6 @@ classifiers = [
"Topic :: Internet",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
@@ -192,7 +191,7 @@ disallow_untyped_defs = true
disallow_incomplete_defs = true
disallow_untyped_decorators = true
show_error_codes = true
python_version = "3.8"
python_version = "3.9"
# For some files, it's easier to just disable strict-optional all together instead of
# cluttering the code with `# type: ignore`s or stuff like
+1 -1
View File
@@ -4,7 +4,7 @@
build
# For the test suite
pytest==8.3.2
pytest==8.3.3
# needed because pytest doesn't come with native support for coroutines as tests
pytest-asyncio==0.21.2
+13 -1
View File
@@ -81,6 +81,7 @@ __all__ = (
"ChatShared",
"ChosenInlineResult",
"Contact",
"CopyTextButton",
"Credentials",
"DataCredentials",
"Dice",
@@ -180,6 +181,7 @@ __all__ = (
"PaidMediaInfo",
"PaidMediaPhoto",
"PaidMediaPreview",
"PaidMediaPurchased",
"PaidMediaVideo",
"PassportData",
"PassportElementError",
@@ -234,6 +236,7 @@ __all__ = (
"TransactionPartnerFragment",
"TransactionPartnerOther",
"TransactionPartnerTelegramAds",
"TransactionPartnerTelegramApi",
"TransactionPartnerUser",
"Update",
"User",
@@ -329,6 +332,7 @@ from ._chatmember import (
from ._chatmemberupdated import ChatMemberUpdated
from ._chatpermissions import ChatPermissions
from ._choseninlineresult import ChosenInlineResult
from ._copytextbutton import CopyTextButton
from ._dice import Dice
from ._files.animation import Animation
from ._files.audio import Audio
@@ -419,7 +423,14 @@ from ._messageorigin import (
MessageOriginUser,
)
from ._messagereactionupdated import MessageReactionCountUpdated, MessageReactionUpdated
from ._paidmedia import PaidMedia, PaidMediaInfo, PaidMediaPhoto, PaidMediaPreview, PaidMediaVideo
from ._paidmedia import (
PaidMedia,
PaidMediaInfo,
PaidMediaPhoto,
PaidMediaPreview,
PaidMediaPurchased,
PaidMediaVideo,
)
from ._passport.credentials import (
Credentials,
DataCredentials,
@@ -463,6 +474,7 @@ from ._payment.stars import (
TransactionPartnerFragment,
TransactionPartnerOther,
TransactionPartnerTelegramAds,
TransactionPartnerTelegramApi,
TransactionPartnerUser,
)
from ._payment.successfulpayment import SuccessfulPayment
+157 -69
View File
@@ -23,21 +23,15 @@ import asyncio
import contextlib
import copy
import pickle
from collections.abc import Sequence
from datetime import datetime
from types import TracebackType
from typing import (
TYPE_CHECKING,
Any,
AsyncContextManager,
Callable,
Dict,
List,
NoReturn,
Optional,
Sequence,
Set,
Tuple,
Type,
TypeVar,
Union,
cast,
@@ -130,7 +124,7 @@ if TYPE_CHECKING:
BT = TypeVar("BT", bound="Bot")
class Bot(TelegramObject, AsyncContextManager["Bot"]):
class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]):
"""This object represents a Telegram Bot.
Instances of this class can be used as asyncio context managers, where
@@ -263,7 +257,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
self._private_key: Optional[bytes] = None
self._initialized: bool = False
self._request: Tuple[BaseRequest, BaseRequest] = (
self._request: tuple[BaseRequest, BaseRequest] = (
HTTPXRequest() if get_updates_request is None else get_updates_request,
HTTPXRequest() if request is None else request,
)
@@ -332,7 +326,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
async def __aexit__(
self,
exc_type: Optional[Type[BaseException]],
exc_type: Optional[type[BaseException]],
exc_val: Optional[BaseException],
exc_tb: Optional[TracebackType],
) -> None:
@@ -352,7 +346,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
"""
raise pickle.PicklingError("Bot objects cannot be pickled!")
def __deepcopy__(self, memodict: Dict[int, object]) -> NoReturn:
def __deepcopy__(self, memodict: dict[int, object]) -> NoReturn:
"""Customizes how :func:`copy.deepcopy` processes objects of this type. Bots can not
be deepcopied and this method will always raise an exception.
@@ -528,7 +522,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
def _warn(
cls,
message: Union[str, PTBUserWarning],
category: Type[Warning] = PTBUserWarning,
category: type[Warning] = PTBUserWarning,
stacklevel: int = 0,
) -> None:
"""Convenience method to issue a warning. This method is here mostly to make it easier
@@ -539,7 +533,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
def _parse_file_input(
self,
file_input: Union[FileInput, "TelegramObject"],
tg_type: Optional[Type["TelegramObject"]] = None,
tg_type: Optional[type["TelegramObject"]] = None,
filename: Optional[str] = None,
attach: bool = False,
) -> Union[str, "InputFile", Any]:
@@ -551,7 +545,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
local_mode=self._local_mode,
)
def _insert_defaults(self, data: Dict[str, object]) -> None:
def _insert_defaults(self, data: dict[str, object]) -> None:
"""This method is here to make ext.Defaults work. Because we need to be able to tell
e.g. `send_message(chat_id, text)` from `send_message(chat_id, text, parse_mode=None)`, the
default values for `parse_mode` etc are not `None` but `DEFAULT_NONE`. While this *could*
@@ -605,7 +599,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Any:
# We know that the return type is Union[bool, JSONDict, List[JSONDict]], but it's hard
# We know that the return type is Union[bool, JSONDict, list[JSONDict]], but it's hard
# to tell mypy which methods expects which of these return values and `Any` saves us a
# lot of `type: ignore` comments
if data is None:
@@ -638,7 +632,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
) -> Union[bool, JSONDict, List[JSONDict]]:
) -> Union[bool, JSONDict, list[JSONDict]]:
# This also converts datetimes into timestamps.
# We don't do this earlier so that _insert_defaults (see above) has a chance to convert
# to the default timezone in case this is called by ExtBot
@@ -678,6 +672,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -714,33 +709,22 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
allow_sending_without_reply=allow_sending_without_reply,
)
data["disable_notification"] = disable_notification
data["protect_content"] = protect_content
data["parse_mode"] = parse_mode
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
if reply_markup is not None:
data["reply_markup"] = reply_markup
if message_thread_id is not None:
data["message_thread_id"] = message_thread_id
if caption is not None:
data["caption"] = caption
if caption_entities is not None:
data["caption_entities"] = caption_entities
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
data.update(
{
"allow_paid_broadcast": allow_paid_broadcast,
"business_connection_id": business_connection_id,
"caption": caption,
"caption_entities": caption_entities,
"disable_notification": disable_notification,
"link_preview_options": link_preview_options,
"message_thread_id": message_thread_id,
"message_effect_id": message_effect_id,
"parse_mode": parse_mode,
"protect_content": protect_content,
"reply_markup": reply_markup,
"reply_parameters": reply_parameters,
}
)
result = await self._post(
endpoint,
@@ -798,7 +782,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
self,
endpoint: str,
api_kwargs: Optional[JSONDict] = None,
return_type: Optional[Type[TelegramObject]] = None,
return_type: Optional[type[TelegramObject]] = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -931,6 +915,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -982,6 +967,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast|
.. versionadded:: 21.7
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -1040,6 +1028,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
link_preview_options=link_preview_options,
reply_parameters=reply_parameters,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
@@ -1226,7 +1215,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple[MessageId, ...]:
) -> tuple[MessageId, ...]:
"""
Use this method to forward messages of any kind. If some of the specified messages can't be
found or forwarded, they are skipped. Service messages and messages with protected content
@@ -1248,7 +1237,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_thread_id (:obj:`int`, optional): |message_thread_id_arg|
Returns:
Tuple[:class:`telegram.Message`]: On success, a tuple of ``MessageId`` of sent messages
tuple[:class:`telegram.Message`]: On success, a tuple of ``MessageId`` of sent messages
is returned.
Raises:
@@ -1289,6 +1278,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
show_caption_above_media: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1356,6 +1346,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast|
.. versionadded:: 21.7
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
.. versionadded:: 21.3
@@ -1419,6 +1412,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def send_audio(
@@ -1439,6 +1433,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -1514,6 +1509,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast|
.. versionadded:: 21.7
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -1576,6 +1574,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def send_document(
@@ -1594,6 +1593,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -1668,6 +1668,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast|
.. versionadded:: 21.7
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -1726,6 +1729,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def send_sticker(
@@ -1740,6 +1744,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -1794,6 +1799,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast|
.. versionadded:: 21.7
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -1844,6 +1852,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def send_video(
@@ -1866,6 +1875,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
show_caption_above_media: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1950,6 +1960,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast|
.. versionadded:: 21.7
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
.. versionadded:: 21.3
@@ -2018,6 +2031,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def send_video_note(
@@ -2034,6 +2048,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -2103,6 +2118,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast|
.. versionadded:: 21.7
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -2161,6 +2179,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def send_animation(
@@ -2182,6 +2201,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
show_caption_above_media: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2260,6 +2280,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast|
.. versionadded:: 21.7
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
.. versionadded:: 21.3
@@ -2327,6 +2350,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def send_voice(
@@ -2344,6 +2368,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -2415,6 +2440,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast|
.. versionadded:: 21.7
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -2474,6 +2502,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def send_media_group(
@@ -2488,6 +2517,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -2499,7 +2529,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
caption: Optional[str] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
) -> Tuple[Message, ...]:
) -> tuple[Message, ...]:
"""Use this method to send a group of photos, videos, documents or audios as an album.
Documents and audio files can be only grouped in an album with messages of the same type.
@@ -2541,6 +2571,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast|
.. versionadded:: 21.7
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -2581,7 +2614,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
.. versionadded:: 20.0
Returns:
Tuple[:class:`telegram.Message`]: An array of the sent Messages.
tuple[:class:`telegram.Message`]: An array of the sent Messages.
Raises:
:class:`telegram.error.TelegramError`
@@ -2635,6 +2668,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
"reply_parameters": reply_parameters,
"business_connection_id": business_connection_id,
"message_effect_id": message_effect_id,
"allow_paid_broadcast": allow_paid_broadcast,
}
result = await self._post(
@@ -2665,6 +2699,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -2724,6 +2759,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast|
.. versionadded:: 21.7
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -2794,6 +2832,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def edit_message_live_location(
@@ -2976,6 +3015,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -3031,6 +3071,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast|
.. versionadded:: 21.7
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -3112,6 +3155,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def send_contact(
@@ -3128,6 +3172,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -3173,6 +3218,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast|
.. versionadded:: 21.7
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -3245,6 +3293,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def send_game(
@@ -3258,6 +3307,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -3293,6 +3343,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast|
.. versionadded:: 21.7
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -3340,6 +3393,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def send_chat_action(
@@ -3403,7 +3457,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
],
next_offset: Optional[str] = None,
current_offset: Optional[str] = None,
) -> Tuple[Sequence["InlineQueryResult"], Optional[str]]:
) -> tuple[Sequence["InlineQueryResult"], Optional[str]]:
"""
Builds the effective results from the results input.
We make this a stand-alone method so tg.ext.ExtBot can wrap it.
@@ -3526,7 +3580,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
Args:
inline_query_id (:obj:`str`): Unique identifier for the answered query.
results (List[:class:`telegram.InlineQueryResult`] | Callable): A list of results for
results (list[:class:`telegram.InlineQueryResult`] | Callable): A list of results for
the inline query. In case :paramref:`current_offset` is passed,
:paramref:`results` may also be
a callable that accepts the current page index starting from 0. It must return
@@ -4154,7 +4208,8 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
api_kwargs: Optional[JSONDict] = None,
) -> Union[Message, bool]:
"""
Use this method to edit animation, audio, document, photo, or video messages. If a message
Use this method to edit animation, audio, document, photo, or video messages, or to add
media to text messages. If a message
is part of a message album, then it can be edited only to an audio for audio albums, only
to a document for document albums and to a photo or a video otherwise. When an inline
message is edited, a new file can't be uploaded; use a previously uploaded file via its
@@ -4280,7 +4335,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple[Update, ...]:
) -> tuple[Update, ...]:
"""Use this method to receive incoming updates using long polling.
Note:
@@ -4325,7 +4380,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
|sequenceargs|
Returns:
Tuple[:class:`telegram.Update`]
tuple[:class:`telegram.Update`]
Raises:
:class:`telegram.error.TelegramError`
@@ -4362,7 +4417,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
# waiting for the server to return and there's no way of knowing the connection had been
# dropped in real time.
result = cast(
List[JSONDict],
list[JSONDict],
await self._post(
"getUpdates",
data,
@@ -4626,7 +4681,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple[ChatMember, ...]:
) -> tuple[ChatMember, ...]:
"""
Use this method to get a list of administrators in a chat.
@@ -4637,7 +4692,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
chat_id (:obj:`int` | :obj:`str`): |chat_id_channel|
Returns:
Tuple[:class:`telegram.ChatMember`]: On success, returns a tuple of ``ChatMember``
tuple[:class:`telegram.ChatMember`]: On success, returns a tuple of ``ChatMember``
objects that contains information about all chat administrators except
other bots. If the chat is a group or a supergroup and no administrators were
appointed, only the creator will be returned.
@@ -4901,7 +4956,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple[GameHighScore, ...]:
) -> tuple[GameHighScore, ...]:
"""
Use this method to get data for high score tables. Will return the score of the specified
user and several of their neighbors in a game.
@@ -4924,7 +4979,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
:paramref:`message_id` are not specified. Identifier of the inline message.
Returns:
Tuple[:class:`telegram.GameHighScore`]
tuple[:class:`telegram.GameHighScore`]
Raises:
:class:`telegram.error.TelegramError`
@@ -4979,6 +5034,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -5096,6 +5152,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast|
.. versionadded:: 21.7
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -5165,6 +5224,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def answer_shipping_query(
@@ -6304,7 +6364,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple[Sticker, ...]:
) -> tuple[Sticker, ...]:
"""
Use this method to get information about emoji stickers by their identifiers.
@@ -6320,7 +6380,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|sequenceargs|
Returns:
Tuple[:class:`telegram.Sticker`]
tuple[:class:`telegram.Sticker`]
Raises:
:class:`telegram.error.TelegramError`
@@ -7005,6 +7065,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
question_parse_mode: ODVInput[str] = DEFAULT_NONE,
question_entities: Optional[Sequence["MessageEntity"]] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -7102,6 +7163,9 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast|
.. versionadded:: 21.7
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -7168,6 +7232,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def stop_poll(
@@ -7231,6 +7296,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -7280,6 +7346,9 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
message_effect_id (:obj:`str`, optional): |message_effect_id|
.. versionadded:: 21.3
allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast|
.. versionadded:: 21.7
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -7328,6 +7397,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def get_my_default_administrator_rights(
@@ -7427,7 +7497,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple[BotCommand, ...]:
) -> tuple[BotCommand, ...]:
"""
Use this method to get the current list of the bot's commands for the given scope and user
language.
@@ -7449,7 +7519,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
.. versionadded:: 13.7
Returns:
Tuple[:class:`telegram.BotCommand`]: On success, the commands set for the bot. An empty
tuple[:class:`telegram.BotCommand`]: On success, the commands set for the bot. An empty
tuple is returned if commands are not set.
Raises:
@@ -7472,7 +7542,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
async def set_my_commands(
self,
commands: Sequence[Union[BotCommand, Tuple[str, str]]],
commands: Sequence[Union[BotCommand, tuple[str, str]]],
scope: Optional[BotCommandScope] = None,
language_code: Optional[str] = None,
*,
@@ -7658,6 +7728,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
show_caption_above_media: Optional[bool] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -7705,6 +7776,9 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
.. versionadded:: 21.3
allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast|
.. versionadded:: 21.7
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -7763,6 +7837,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
"message_thread_id": message_thread_id,
"reply_parameters": reply_parameters,
"show_caption_above_media": show_caption_above_media,
"allow_paid_broadcast": allow_paid_broadcast,
}
result = await self._post(
@@ -7791,7 +7866,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple["MessageId", ...]:
) -> tuple["MessageId", ...]:
"""
Use this method to copy messages of any kind. If some of the specified messages can't be
found or copied, they are skipped. Service messages, paid media messages, giveaway
@@ -7819,7 +7894,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
their captions.
Returns:
Tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
of the sent messages is returned.
Raises:
@@ -8072,14 +8147,14 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple[Sticker, ...]:
) -> tuple[Sticker, ...]:
"""Use this method to get custom emoji stickers, which can be used as a forum topic
icon by any user. Requires no parameters.
.. versionadded:: 20.0
Returns:
Tuple[:class:`telegram.Sticker`]
tuple[:class:`telegram.Sticker`]
Raises:
:class:`telegram.error.TelegramError`
@@ -8968,7 +9043,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
Raises:
:class:`telegram.error.TelegramError`
"""
allowed_reactions: Set[str] = set(ReactionEmoji)
allowed_reactions: set[str] = set(ReactionEmoji)
parsed_reaction = (
[
(
@@ -9193,6 +9268,8 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
reply_parameters: Optional["ReplyParameters"] = None,
reply_markup: Optional[ReplyMarkup] = None,
business_connection_id: Optional[str] = None,
payload: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -9211,9 +9288,15 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
Telegram Star proceeds from this media will be credited to the chat's balance.
Otherwise, they will be credited to the bot's balance.
star_count (:obj:`int`): The number of Telegram Stars that must be paid to buy access
to the media.
to the media; :tg-const:`telegram.constants.InvoiceLimit.MIN_STAR_COUNT` -
:tg-const:`telegram.constants.InvoiceLimit.MAX_STAR_COUNT`.
media (Sequence[:class:`telegram.InputPaidMedia`]): A list describing the media to be
sent; up to :tg-const:`telegram.constants.MediaGroupLimit.MAX_MEDIA_LENGTH` items.
payload (:obj:`str`, optional): Bot-defined paid media payload,
0-:tg-const:`telegram.constants.InvoiceLimit.MAX_PAYLOAD_LENGTH` bytes. This will
not be displayed to the user, use it for your internal processes.
.. versionadded:: 21.6
caption (:obj:`str`, optional): Caption of the media to be sent,
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters.
parse_mode (:obj:`str`, optional): |parse_mode|
@@ -9230,6 +9313,9 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
business_connection_id (:obj:`str`, optional): |business_id_str|
.. versionadded:: 21.5
allow_paid_broadcast (:obj:`bool`, optional): |allow_paid_broadcast|
.. versionadded:: 21.7
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
@@ -9252,6 +9338,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
"star_count": star_count,
"media": media,
"show_caption_above_media": show_caption_above_media,
"payload": payload,
}
return await self._send_message(
@@ -9272,6 +9359,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,
allow_paid_broadcast=allow_paid_broadcast,
)
async def create_chat_subscription_invite_link(
+3 -3
View File
@@ -18,7 +18,7 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
# pylint: disable=redefined-builtin
"""This module contains objects representing Telegram bot command scopes."""
from typing import TYPE_CHECKING, Dict, Final, Optional, Type, Union
from typing import TYPE_CHECKING, Final, Optional, Union
from telegram import constants
from telegram._telegramobject import TelegramObject
@@ -91,7 +91,7 @@ class BotCommandScope(TelegramObject):
care of selecting the correct subclass.
Args:
data (Dict[:obj:`str`, ...]): The JSON data.
data (dict[:obj:`str`, ...]): The JSON data.
bot (:class:`telegram.Bot`, optional): The bot associated with this object. Defaults to
:obj:`None`, in which case shortcut methods will not be available.
@@ -107,7 +107,7 @@ class BotCommandScope(TelegramObject):
if not data:
return None
_class_mapping: Dict[str, Type[BotCommandScope]] = {
_class_mapping: dict[str, type[BotCommandScope]] = {
cls.DEFAULT: BotCommandScopeDefault,
cls.ALL_PRIVATE_CHATS: BotCommandScopeAllPrivateChats,
cls.ALL_GROUP_CHATS: BotCommandScopeAllGroupChats,
+11 -10
View File
@@ -19,8 +19,9 @@
# along with this program. If not, see [http://www.gnu.org/licenses/]
"""This module contains the Telegram Business related classes."""
from collections.abc import Sequence
from datetime import datetime
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from typing import TYPE_CHECKING, Optional
from telegram._chat import Chat
from telegram._files.location import Location
@@ -145,7 +146,7 @@ class BusinessMessagesDeleted(TelegramObject):
business_connection_id (:obj:`str`): Unique identifier of the business connection.
chat (:class:`telegram.Chat`): Information about a chat in the business account. The bot
may not have access to the chat or the corresponding user.
message_ids (Tuple[:obj:`int`]): A list of identifiers of the deleted messages in the
message_ids (tuple[:obj:`int`]): A list of identifiers of the deleted messages in the
chat of the business account.
"""
@@ -166,7 +167,7 @@ class BusinessMessagesDeleted(TelegramObject):
super().__init__(api_kwargs=api_kwargs)
self.business_connection_id: str = business_connection_id
self.chat: Chat = chat
self.message_ids: Tuple[int, ...] = parse_sequence_arg(message_ids)
self.message_ids: tuple[int, ...] = parse_sequence_arg(message_ids)
self._id_attrs = (
self.business_connection_id,
@@ -359,37 +360,37 @@ class BusinessOpeningHoursInterval(TelegramObject):
self.opening_minute: int = opening_minute
self.closing_minute: int = closing_minute
self._opening_time: Optional[Tuple[int, int, int]] = None
self._closing_time: Optional[Tuple[int, int, int]] = None
self._opening_time: Optional[tuple[int, int, int]] = None
self._closing_time: Optional[tuple[int, int, int]] = None
self._id_attrs = (self.opening_minute, self.closing_minute)
self._freeze()
def _parse_minute(self, minute: int) -> Tuple[int, int, int]:
def _parse_minute(self, minute: int) -> tuple[int, int, int]:
return (minute // 1440, minute % 1440 // 60, minute % 1440 % 60)
@property
def opening_time(self) -> Tuple[int, int, int]:
def opening_time(self) -> tuple[int, int, int]:
"""Convenience attribute. A :obj:`tuple` parsed from :attr:`opening_minute`. It contains
the `weekday`, `hour` and `minute` in the same ranges as :attr:`datetime.datetime.weekday`,
:attr:`datetime.datetime.hour` and :attr:`datetime.datetime.minute`
Returns:
Tuple[:obj:`int`, :obj:`int`, :obj:`int`]:
tuple[:obj:`int`, :obj:`int`, :obj:`int`]:
"""
if self._opening_time is None:
self._opening_time = self._parse_minute(self.opening_minute)
return self._opening_time
@property
def closing_time(self) -> Tuple[int, int, int]:
def closing_time(self) -> tuple[int, int, int]:
"""Convenience attribute. A :obj:`tuple` parsed from :attr:`closing_minute`. It contains
the `weekday`, `hour` and `minute` in the same ranges as :attr:`datetime.datetime.weekday`,
:attr:`datetime.datetime.hour` and :attr:`datetime.datetime.minute`
Returns:
Tuple[:obj:`int`, :obj:`int`, :obj:`int`]:
tuple[:obj:`int`, :obj:`int`, :obj:`int`]:
"""
if self._closing_time is None:
self._closing_time = self._parse_minute(self.closing_minute)
+6 -3
View File
@@ -18,7 +18,8 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
# pylint: disable=redefined-builtin
"""This module contains an object that represents a Telegram CallbackQuery"""
from typing import TYPE_CHECKING, Final, Optional, Sequence, Tuple, Union
from collections.abc import Sequence
from typing import TYPE_CHECKING, Final, Optional, Union
from telegram import constants
from telegram._files.location import Location
@@ -676,7 +677,7 @@ class CallbackQuery(TelegramObject):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple["GameHighScore", ...]:
) -> tuple["GameHighScore", ...]:
"""Shortcut for either::
await update.callback_query.message.get_game_high_score(*args, **kwargs)
@@ -695,7 +696,7 @@ class CallbackQuery(TelegramObject):
Raises :exc:`TypeError` if :attr:`message` is not accessible.
Returns:
Tuple[:class:`telegram.GameHighScore`]
tuple[:class:`telegram.GameHighScore`]
Raises:
:exc:`TypeError` if :attr:`message` is not accessible.
@@ -833,6 +834,7 @@ class CallbackQuery(TelegramObject):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
show_caption_above_media: Optional[bool] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -880,6 +882,7 @@ class CallbackQuery(TelegramObject):
message_thread_id=message_thread_id,
reply_parameters=reply_parameters,
show_caption_above_media=show_caption_above_media,
allow_paid_broadcast=allow_paid_broadcast,
)
MAX_ANSWER_TEXT_LENGTH: Final[int] = (
+56 -13
View File
@@ -18,9 +18,10 @@
# 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 Chat."""
from collections.abc import Sequence
from datetime import datetime
from html import escape
from typing import TYPE_CHECKING, Final, Optional, Sequence, Tuple, Union
from typing import TYPE_CHECKING, Final, Optional, Union
from telegram import constants
from telegram._chatpermissions import ChatPermissions
@@ -296,7 +297,7 @@ class _ChatBase(TelegramObject):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple["ChatMember", ...]:
) -> tuple["ChatMember", ...]:
"""Shortcut for::
await bot.get_chat_administrators(update.effective_chat.id, *args, **kwargs)
@@ -305,7 +306,7 @@ class _ChatBase(TelegramObject):
:meth:`telegram.Bot.get_chat_administrators`.
Returns:
Tuple[:class:`telegram.ChatMember`]: A tuple of administrators in a chat. An Array of
tuple[:class:`telegram.ChatMember`]: A tuple of administrators in a chat. An Array of
:class:`telegram.ChatMember` objects that contains information about all
chat administrators except other bots. If the chat is a group or a supergroup
and no administrators were appointed, only the creator will be returned.
@@ -1011,6 +1012,7 @@ class _ChatBase(TelegramObject):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1052,6 +1054,7 @@ class _ChatBase(TelegramObject):
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def delete_message(
@@ -1129,6 +1132,7 @@ class _ChatBase(TelegramObject):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1140,7 +1144,7 @@ class _ChatBase(TelegramObject):
caption: Optional[str] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
) -> Tuple["Message", ...]:
) -> tuple["Message", ...]:
"""Shortcut for::
await bot.send_media_group(update.effective_chat.id, *args, **kwargs)
@@ -1148,7 +1152,7 @@ class _ChatBase(TelegramObject):
For the documentation of the arguments, please see :meth:`telegram.Bot.send_media_group`.
Returns:
Tuple[:class:`telegram.Message`]: On success, a tuple of :class:`~telegram.Message`
tuple[:class:`telegram.Message`]: On success, a tuple of :class:`~telegram.Message`
instances that were sent is returned.
"""
@@ -1171,6 +1175,7 @@ class _ChatBase(TelegramObject):
reply_parameters=reply_parameters,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def send_chat_action(
@@ -1224,6 +1229,7 @@ class _ChatBase(TelegramObject):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
show_caption_above_media: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
@@ -1267,6 +1273,7 @@ class _ChatBase(TelegramObject):
has_spoiler=has_spoiler,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
show_caption_above_media=show_caption_above_media,
)
@@ -1283,6 +1290,7 @@ class _ChatBase(TelegramObject):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1324,6 +1332,7 @@ class _ChatBase(TelegramObject):
message_thread_id=message_thread_id,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def send_audio(
@@ -1343,6 +1352,7 @@ class _ChatBase(TelegramObject):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1388,6 +1398,7 @@ class _ChatBase(TelegramObject):
thumbnail=thumbnail,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def send_document(
@@ -1405,6 +1416,7 @@ class _ChatBase(TelegramObject):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1448,6 +1460,7 @@ class _ChatBase(TelegramObject):
message_thread_id=message_thread_id,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def send_dice(
@@ -1460,6 +1473,7 @@ class _ChatBase(TelegramObject):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1496,6 +1510,7 @@ class _ChatBase(TelegramObject):
message_thread_id=message_thread_id,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def send_game(
@@ -1508,6 +1523,7 @@ class _ChatBase(TelegramObject):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1544,6 +1560,7 @@ class _ChatBase(TelegramObject):
message_thread_id=message_thread_id,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def send_invoice(
@@ -1575,6 +1592,7 @@ class _ChatBase(TelegramObject):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1640,6 +1658,7 @@ class _ChatBase(TelegramObject):
message_thread_id=message_thread_id,
reply_parameters=reply_parameters,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def send_location(
@@ -1657,6 +1676,7 @@ class _ChatBase(TelegramObject):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1700,6 +1720,7 @@ class _ChatBase(TelegramObject):
message_thread_id=message_thread_id,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def send_animation(
@@ -1720,6 +1741,7 @@ class _ChatBase(TelegramObject):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
show_caption_above_media: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
@@ -1767,6 +1789,7 @@ class _ChatBase(TelegramObject):
thumbnail=thumbnail,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
show_caption_above_media=show_caption_above_media,
)
@@ -1781,6 +1804,7 @@ class _ChatBase(TelegramObject):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1818,6 +1842,7 @@ class _ChatBase(TelegramObject):
emoji=emoji,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def send_venue(
@@ -1837,6 +1862,7 @@ class _ChatBase(TelegramObject):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1882,6 +1908,7 @@ class _ChatBase(TelegramObject):
message_thread_id=message_thread_id,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def send_video(
@@ -1903,6 +1930,7 @@ class _ChatBase(TelegramObject):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
show_caption_above_media: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
@@ -1951,6 +1979,7 @@ class _ChatBase(TelegramObject):
has_spoiler=has_spoiler,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
show_caption_above_media=show_caption_above_media,
)
@@ -1967,6 +1996,7 @@ class _ChatBase(TelegramObject):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2008,6 +2038,7 @@ class _ChatBase(TelegramObject):
message_thread_id=message_thread_id,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def send_voice(
@@ -2024,6 +2055,7 @@ class _ChatBase(TelegramObject):
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2066,6 +2098,7 @@ class _ChatBase(TelegramObject):
message_thread_id=message_thread_id,
business_connection_id=business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def send_poll(
@@ -2091,6 +2124,7 @@ class _ChatBase(TelegramObject):
question_parse_mode: ODVInput[str] = DEFAULT_NONE,
question_entities: Optional[Sequence["MessageEntity"]] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2128,6 +2162,7 @@ class _ChatBase(TelegramObject):
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
explanation=explanation,
explanation_parse_mode=explanation_parse_mode,
open_period=open_period,
@@ -2155,6 +2190,7 @@ class _ChatBase(TelegramObject):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
show_caption_above_media: Optional[bool] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2196,6 +2232,7 @@ class _ChatBase(TelegramObject):
protect_content=protect_content,
message_thread_id=message_thread_id,
show_caption_above_media=show_caption_above_media,
allow_paid_broadcast=allow_paid_broadcast,
)
async def copy_message(
@@ -2211,6 +2248,7 @@ class _ChatBase(TelegramObject):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
show_caption_above_media: Optional[bool] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2252,6 +2290,7 @@ class _ChatBase(TelegramObject):
protect_content=protect_content,
message_thread_id=message_thread_id,
show_caption_above_media=show_caption_above_media,
allow_paid_broadcast=allow_paid_broadcast,
)
async def send_copies(
@@ -2268,7 +2307,7 @@ class _ChatBase(TelegramObject):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple["MessageId", ...]:
) -> tuple["MessageId", ...]:
"""Shortcut for::
await bot.copy_messages(chat_id=update.effective_chat.id, *args, **kwargs)
@@ -2280,7 +2319,7 @@ class _ChatBase(TelegramObject):
.. versionadded:: 20.8
Returns:
Tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
of the sent messages is returned.
"""
@@ -2313,7 +2352,7 @@ class _ChatBase(TelegramObject):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple["MessageId", ...]:
) -> tuple["MessageId", ...]:
"""Shortcut for::
await bot.copy_messages(from_chat_id=update.effective_chat.id, *args, **kwargs)
@@ -2325,7 +2364,7 @@ class _ChatBase(TelegramObject):
.. versionadded:: 20.8
Returns:
Tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
of the sent messages is returned.
"""
@@ -2442,7 +2481,7 @@ class _ChatBase(TelegramObject):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple["MessageId", ...]:
) -> tuple["MessageId", ...]:
"""Shortcut for::
await bot.forward_messages(chat_id=update.effective_chat.id, *args, **kwargs)
@@ -2454,7 +2493,7 @@ class _ChatBase(TelegramObject):
.. versionadded:: 20.8
Returns:
Tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
of sent messages is returned.
"""
@@ -2485,7 +2524,7 @@ class _ChatBase(TelegramObject):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple["MessageId", ...]:
) -> tuple["MessageId", ...]:
"""Shortcut for::
await bot.forward_messages(from_chat_id=update.effective_chat.id, *args, **kwargs)
@@ -2497,7 +2536,7 @@ class _ChatBase(TelegramObject):
.. versionadded:: 20.8
Returns:
Tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
of sent messages is returned.
"""
@@ -3350,6 +3389,8 @@ class _ChatBase(TelegramObject):
reply_parameters: Optional["ReplyParameters"] = None,
reply_markup: Optional[ReplyMarkup] = None,
business_connection_id: Optional[str] = None,
payload: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
@@ -3391,6 +3432,8 @@ class _ChatBase(TelegramObject):
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
payload=payload,
allow_paid_broadcast=allow_paid_broadcast,
)
+5 -4
View File
@@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains objects related to chat backgrounds."""
from typing import TYPE_CHECKING, Dict, Final, Optional, Sequence, Tuple, Type
from collections.abc import Sequence
from typing import TYPE_CHECKING, Final, Optional
from telegram import constants
from telegram._files.document import Document
@@ -87,7 +88,7 @@ class BackgroundFill(TelegramObject):
if not data:
return None
_class_mapping: Dict[str, Type[BackgroundFill]] = {
_class_mapping: dict[str, type[BackgroundFill]] = {
cls.SOLID: BackgroundFillSolid,
cls.GRADIENT: BackgroundFillGradient,
cls.FREEFORM_GRADIENT: BackgroundFillFreeformGradient,
@@ -212,7 +213,7 @@ class BackgroundFillFreeformGradient(BackgroundFill):
super().__init__(type=self.FREEFORM_GRADIENT, api_kwargs=api_kwargs)
with self._unfrozen():
self.colors: Tuple[int, ...] = parse_sequence_arg(colors)
self.colors: tuple[int, ...] = parse_sequence_arg(colors)
self._id_attrs = (self.colors,)
@@ -278,7 +279,7 @@ class BackgroundType(TelegramObject):
if not data:
return None
_class_mapping: Dict[str, Type[BackgroundType]] = {
_class_mapping: dict[str, type[BackgroundType]] = {
cls.FILL: BackgroundTypeFill,
cls.WALLPAPER: BackgroundTypeWallpaper,
cls.PATTERN: BackgroundTypePattern,
+22 -8
View File
@@ -18,8 +18,9 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the classes that represent Telegram ChatBoosts."""
from collections.abc import Sequence
from datetime import datetime
from typing import TYPE_CHECKING, Dict, Final, Optional, Sequence, Tuple, Type
from typing import TYPE_CHECKING, Final, Optional
from telegram import constants
from telegram._chat import Chat
@@ -119,7 +120,7 @@ class ChatBoostSource(TelegramObject):
if not data:
return None
_class_mapping: Dict[str, Type[ChatBoostSource]] = {
_class_mapping: dict[str, type[ChatBoostSource]] = {
cls.PREMIUM: ChatBoostSourcePremium,
cls.GIFT_CODE: ChatBoostSourceGiftCode,
cls.GIVEAWAY: ChatBoostSourceGiveaway,
@@ -187,15 +188,22 @@ class ChatBoostSourceGiftCode(ChatBoostSource):
class ChatBoostSourceGiveaway(ChatBoostSource):
"""
The boost was obtained by the creation of a Telegram Premium giveaway. This boosts the chat 4
times for the duration of the corresponding Telegram Premium subscription.
The boost was obtained by the creation of a Telegram Premium giveaway or a Telegram Star.
This boosts the chat 4 times for the duration of the corresponding Telegram Premium
subscription for Telegram Premium giveaways and :attr:`prize_star_count` / 500 times for
one year for Telegram Star giveaways.
.. versionadded:: 20.8
Args:
giveaway_message_id (:obj:`int`): Identifier of a message in the chat with the giveaway;
the message could have been deleted already. May be 0 if the message isn't sent yet.
user (:class:`telegram.User`, optional): User that won the prize in the giveaway if any.
user (:class:`telegram.User`, optional): User that won the prize in the giveaway if any;
for Telegram Premium giveaways only.
prize_star_count (:obj:`int`, optional): The number of Telegram Stars to be split between
giveaway winners; for Telegram Star giveaways only.
.. versionadded:: 21.6
is_unclaimed (:obj:`bool`, optional): :obj:`True`, if the giveaway was completed, but
there was no user to win the prize.
@@ -205,17 +213,22 @@ class ChatBoostSourceGiveaway(ChatBoostSource):
giveaway_message_id (:obj:`int`): Identifier of a message in the chat with the giveaway;
the message could have been deleted already. May be 0 if the message isn't sent yet.
user (:class:`telegram.User`): Optional. User that won the prize in the giveaway if any.
prize_star_count (:obj:`int`): Optional. The number of Telegram Stars to be split between
giveaway winners; for Telegram Star giveaways only.
.. versionadded:: 21.6
is_unclaimed (:obj:`bool`): Optional. :obj:`True`, if the giveaway was completed, but
there was no user to win the prize.
"""
__slots__ = ("giveaway_message_id", "is_unclaimed", "user")
__slots__ = ("giveaway_message_id", "is_unclaimed", "prize_star_count", "user")
def __init__(
self,
giveaway_message_id: int,
user: Optional[User] = None,
is_unclaimed: Optional[bool] = None,
prize_star_count: Optional[int] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
@@ -224,6 +237,7 @@ class ChatBoostSourceGiveaway(ChatBoostSource):
with self._unfrozen():
self.giveaway_message_id: int = giveaway_message_id
self.user: Optional[User] = user
self.prize_star_count: Optional[int] = prize_star_count
self.is_unclaimed: Optional[bool] = is_unclaimed
@@ -418,7 +432,7 @@ class UserChatBoosts(TelegramObject):
user.
Attributes:
boosts (Tuple[:class:`telegram.ChatBoost`]): List of boosts added to the chat by the user.
boosts (tuple[:class:`telegram.ChatBoost`]): List of boosts added to the chat by the user.
"""
__slots__ = ("boosts",)
@@ -431,7 +445,7 @@ class UserChatBoosts(TelegramObject):
):
super().__init__(api_kwargs=api_kwargs)
self.boosts: Tuple[ChatBoost, ...] = parse_sequence_arg(boosts)
self.boosts: tuple[ChatBoost, ...] = parse_sequence_arg(boosts)
self._id_attrs = (self.boosts,)
self._freeze()
+6 -5
View File
@@ -18,8 +18,9 @@
# 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 collections.abc import Sequence
from datetime import datetime
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from typing import TYPE_CHECKING, Optional
from telegram._birthdate import Birthdate
from telegram._chat import Chat, _ChatBase
@@ -224,7 +225,7 @@ class ChatFullInfo(_ChatBase):
.. versionadded:: 20.0
photo (:class:`telegram.ChatPhoto`): Optional. Chat photo.
active_usernames (Tuple[:obj:`str`]): Optional. If set, the list of all `active chat
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.
@@ -252,7 +253,7 @@ class ChatFullInfo(_ChatBase):
of the user.
.. versionadded:: 21.1
available_reactions (Tuple[:class:`telegram.ReactionType`]): Optional. List of available
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.
@@ -483,14 +484,14 @@ class ChatFullInfo(_ChatBase):
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.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(
self.available_reactions: Optional[tuple[ReactionType, ...]] = parse_sequence_arg(
available_reactions
)
self.accent_color_id: Optional[int] = accent_color_id
+2 -2
View File
@@ -19,7 +19,7 @@
"""This module contains an object that represents a Telegram ChatMember."""
import datetime
from typing import TYPE_CHECKING, Dict, Final, Optional, Type
from typing import TYPE_CHECKING, Final, Optional
from telegram import constants
from telegram._telegramobject import TelegramObject
@@ -114,7 +114,7 @@ class ChatMember(TelegramObject):
if not data:
return None
_class_mapping: Dict[str, Type[ChatMember]] = {
_class_mapping: dict[str, type[ChatMember]] = {
cls.OWNER: ChatMemberOwner,
cls.ADMINISTRATOR: ChatMemberAdministrator,
cls.MEMBER: ChatMemberMember,
+5 -5
View File
@@ -18,7 +18,7 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram ChatMemberUpdated."""
import datetime
from typing import TYPE_CHECKING, Dict, Optional, Tuple, Union
from typing import TYPE_CHECKING, Optional, Union
from telegram._chat import Chat
from telegram._chatinvitelink import ChatInviteLink
@@ -162,7 +162,7 @@ class ChatMemberUpdated(TelegramObject):
return super().de_json(data=data, bot=bot)
def _get_attribute_difference(self, attribute: str) -> Tuple[object, object]:
def _get_attribute_difference(self, attribute: str) -> tuple[object, object]:
try:
old = self.old_chat_member[attribute]
except KeyError:
@@ -177,9 +177,9 @@ class ChatMemberUpdated(TelegramObject):
def difference(
self,
) -> Dict[
) -> dict[
str,
Tuple[
tuple[
Union[str, bool, datetime.datetime, User], Union[str, bool, datetime.datetime, User]
],
]:
@@ -198,7 +198,7 @@ class ChatMemberUpdated(TelegramObject):
.. versionadded:: 13.5
Returns:
Dict[:obj:`str`, Tuple[:class:`object`, :class:`object`]]: A dictionary mapping
dict[:obj:`str`, tuple[:class:`object`, :class:`object`]]: A dictionary mapping
attribute names to tuples of the form ``(old_value, new_value)``
"""
# we first get the names of the attributes that have changed
+55
View File
@@ -0,0 +1,55 @@
#!/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 an object that represents a Telegram CopyTextButton."""
from typing import Optional
from telegram._telegramobject import TelegramObject
from telegram._utils.types import JSONDict
class CopyTextButton(TelegramObject):
"""
This object represents an inline keyboard button that copies specified text to the clipboard.
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.7
Args:
text (:obj:`str`): The text to be copied to the clipboard;
:tg-const:`telegram.constants.InlineKeyboardButtonLimit.MIN_COPY_TEXT`-
:tg-const:`telegram.constants.InlineKeyboardButtonLimit.MAX_COPY_TEXT` characters
Attributes:
text (:obj:`str`): The text to be copied to the clipboard;
:tg-const:`telegram.constants.InlineKeyboardButtonLimit.MIN_COPY_TEXT`-
:tg-const:`telegram.constants.InlineKeyboardButtonLimit.MAX_COPY_TEXT` characters
"""
__slots__ = ("text",)
def __init__(self, text: str, *, api_kwargs: Optional[JSONDict] = None):
super().__init__(api_kwargs=api_kwargs)
self.text: str = text
self._id_attrs = (self.text,)
self._freeze()
+3 -3
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 Dice."""
from typing import Final, List, Optional
from typing import Final, Optional
from telegram import constants
from telegram._telegramobject import TelegramObject
@@ -114,8 +114,8 @@ class Dice(TelegramObject):
.. versionadded:: 13.4
"""
ALL_EMOJI: Final[List[str]] = list(constants.DiceEmoji)
"""List[:obj:`str`]: A list of all available dice emoji."""
ALL_EMOJI: Final[list[str]] = list(constants.DiceEmoji)
"""list[:obj:`str`]: A list of all available dice emoji."""
MIN_VALUE: Final[int] = constants.DiceLimit.MIN_VALUE
""":const:`telegram.constants.DiceLimit.MIN_VALUE`
+2 -2
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/].
"""Common base class for media objects with thumbnails"""
from typing import TYPE_CHECKING, Optional, Type, TypeVar
from typing import TYPE_CHECKING, Optional, TypeVar
from telegram._files._basemedium import _BaseMedium
from telegram._files.photosize import PhotoSize
@@ -82,7 +82,7 @@ class _BaseThumbedMedium(_BaseMedium):
@classmethod
def de_json(
cls: Type[ThumbedMT_co], data: Optional[JSONDict], bot: Optional["Bot"] = None
cls: type[ThumbedMT_co], data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional[ThumbedMT_co]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
+36 -6
View File
@@ -128,9 +128,8 @@ class File(TelegramObject):
) -> Path:
"""
Download this file. By default, the file is saved in the current working directory with
:attr:`file_path` as file name. If the file has no filename, the file ID will be used as
filename. If :paramref:`custom_path` is supplied as a :obj:`str` or :obj:`pathlib.Path`,
it will be saved to that path.
:attr:`file_path` as file name. If :paramref:`custom_path` is supplied as a :obj:`str` or
:obj:`pathlib.Path`, it will be saved to that path.
Note:
If :paramref:`custom_path` isn't provided and :attr:`file_path` is the path of a
@@ -152,6 +151,11 @@ class File(TelegramObject):
* This method was previously called ``download``. It was split into
:meth:`download_to_drive` and :meth:`download_to_memory`.
.. versionchanged:: 21.7
Raises :exc:`RuntimeError` if :attr:`file_path` is not set. Note that files without
a :attr:`file_path` could never be downloaded, as this attribute is mandatory for that
operation.
Args:
custom_path (:class:`pathlib.Path` | :obj:`str` , optional): The path where the file
will be saved to. If not specified, will be saved in the current working directory
@@ -175,7 +179,13 @@ class File(TelegramObject):
Returns:
:class:`pathlib.Path`: Returns the Path object the file was downloaded to.
Raises:
RuntimeError: If :attr:`file_path` is not set.
"""
if not self.file_path:
raise RuntimeError("No `file_path` available for this file. Can not download.")
local_file = is_local_file(self.file_path)
url = None if local_file else self._get_encoded_url()
@@ -198,10 +208,8 @@ class File(TelegramObject):
filename = Path(custom_path)
elif local_file:
return Path(self.file_path)
elif self.file_path:
filename = Path(Path(self.file_path).name)
else:
filename = Path.cwd() / self.file_id
filename = Path(Path(self.file_path).name)
buf = await self.get_bot().request.retrieve(
url,
@@ -237,6 +245,11 @@ class File(TelegramObject):
.. versionadded:: 20.0
.. versionchanged:: 21.7
Raises :exc:`RuntimeError` if :attr:`file_path` is not set. Note that files without
a :attr:`file_path` could never be downloaded, as this attribute is mandatory for that
operation.
Args:
out (:obj:`io.BufferedIOBase`): A file-like object. Must be opened for writing in
binary mode.
@@ -254,7 +267,13 @@ class File(TelegramObject):
pool_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to
:paramref:`telegram.request.BaseRequest.post.pool_timeout`. Defaults to
:attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.
Raises:
RuntimeError: If :attr:`file_path` is not set.
"""
if not self.file_path:
raise RuntimeError("No `file_path` available for this file. Can not download.")
local_file = is_local_file(self.file_path)
url = None if local_file else self._get_encoded_url()
path = Path(self.file_path) if local_file else None
@@ -283,6 +302,11 @@ class File(TelegramObject):
) -> bytearray:
"""Download this file and return it as a bytearray.
.. versionchanged:: 21.7
Raises :exc:`RuntimeError` if :attr:`file_path` is not set. Note that files without
a :attr:`file_path` could never be downloaded, as this attribute is mandatory for that
operation.
Args:
buf (:obj:`bytearray`, optional): Extend the given bytearray with the downloaded data.
@@ -312,7 +336,13 @@ class File(TelegramObject):
:obj:`bytearray`: The same object as :paramref:`buf` if it was specified. Otherwise a
newly allocated :obj:`bytearray`.
Raises:
RuntimeError: If :attr:`file_path` is not set.
"""
if not self.file_path:
raise RuntimeError("No `file_path` available for this file. Can not download.")
if buf is None:
buf = bytearray()
+3 -3
View File
@@ -56,8 +56,8 @@ class InputFile:
read_file_handle (:obj:`bool`, optional): If :obj:`True` and :paramref:`obj` is a file
handle, the data will be read from the file handle on initialization of this object.
If :obj:`False`, the file handle will be passed on to the
`networking backend <telegram.request.BaseRequest.do_request>`_ which will have to
handle the reading. Defaults to :obj:`True`.
:attr:`networking backend <telegram.request.BaseRequest.do_request>` which will have
to handle the reading. Defaults to :obj:`True`.
Tip:
If you upload extremely large files, you may want to set this to :obj:`False` to
@@ -130,7 +130,7 @@ class InputFile:
Content may now be a file handle.
Returns:
Tuple[:obj:`str`, :obj:`bytes` | :class:`IO`, :obj:`str`]:
tuple[:obj:`str`, :obj:`bytes` | :class:`IO`, :obj:`str`]:
"""
return self.filename, self.input_file_content, self.mimetype
+9 -8
View File
@@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""Base class for Telegram InputMedia Objects."""
from typing import Final, Optional, Sequence, Tuple, Union
from collections.abc import Sequence
from typing import Final, Optional, Union
from telegram import constants
from telegram._files.animation import Animation
@@ -74,7 +75,7 @@ class InputMedia(TelegramObject):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after entities
parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@@ -99,7 +100,7 @@ class InputMedia(TelegramObject):
self.type: str = enum.get_member(constants.InputMediaType, media_type, media_type)
self.media: Union[str, InputFile, Animation, Audio, Document, PhotoSize, Video] = media
self.caption: Optional[str] = caption
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.caption_entities: tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.parse_mode: ODVInput[str] = parse_mode
self._freeze()
@@ -321,7 +322,7 @@ class InputMediaAnimation(InputMedia):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. The parse mode to use for text formatting.
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@@ -436,7 +437,7 @@ class InputMediaPhoto(InputMedia):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@@ -546,7 +547,7 @@ class InputMediaVideo(InputMedia):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@@ -676,7 +677,7 @@ class InputMediaAudio(InputMedia):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@@ -779,7 +780,7 @@ class InputMediaDocument(InputMedia):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
+6 -5
View File
@@ -18,7 +18,8 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram InputSticker."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple, Union
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional, Union
from telegram._files.sticker import MaskPosition
from telegram._telegramobject import TelegramObject
@@ -67,13 +68,13 @@ class InputSticker(TelegramObject):
Attributes:
sticker (:obj:`str` | :class:`telegram.InputFile`): The added sticker.
emoji_list (Tuple[:obj:`str`]): Tuple of
emoji_list (tuple[:obj:`str`]): Tuple of
:tg-const:`telegram.constants.StickerLimit.MIN_STICKER_EMOJI` -
:tg-const:`telegram.constants.StickerLimit.MAX_STICKER_EMOJI` emoji associated with the
sticker.
mask_position (:class:`telegram.MaskPosition`): Optional. Position where the mask should be
placed on faces. For ":tg-const:`telegram.constants.StickerType.MASK`" stickers only.
keywords (Tuple[:obj:`str`]): Optional. Tuple of
keywords (tuple[:obj:`str`]): Optional. Tuple of
0-:tg-const:`telegram.constants.StickerLimit.MAX_SEARCH_KEYWORDS` search keywords
for the sticker with the total length of up to
:tg-const:`telegram.constants.StickerLimit.MAX_KEYWORD_LENGTH` characters. For
@@ -110,9 +111,9 @@ class InputSticker(TelegramObject):
local_mode=True,
attach=True,
)
self.emoji_list: Tuple[str, ...] = parse_sequence_arg(emoji_list)
self.emoji_list: tuple[str, ...] = parse_sequence_arg(emoji_list)
self.format: str = format
self.mask_position: Optional[MaskPosition] = mask_position
self.keywords: Tuple[str, ...] = parse_sequence_arg(keywords)
self.keywords: tuple[str, ...] = parse_sequence_arg(keywords)
self._freeze()
+4 -3
View File
@@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains objects that represent stickers."""
from typing import TYPE_CHECKING, Final, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Final, Optional
from telegram import constants
from telegram._files._basethumbedmedium import _BaseThumbedMedium
@@ -259,7 +260,7 @@ class StickerSet(TelegramObject):
Attributes:
name (:obj:`str`): Sticker set name.
title (:obj:`str`): Sticker set title.
stickers (Tuple[:class:`telegram.Sticker`]): List of all set stickers.
stickers (tuple[:class:`telegram.Sticker`]): List of all set stickers.
.. versionchanged:: 20.0
|tupleclassattrs|
@@ -296,7 +297,7 @@ class StickerSet(TelegramObject):
super().__init__(api_kwargs=api_kwargs)
self.name: str = name
self.title: str = title
self.stickers: Tuple[Sticker, ...] = parse_sequence_arg(stickers)
self.stickers: tuple[Sticker, ...] = parse_sequence_arg(stickers)
self.sticker_type: str = sticker_type
# Optional
self.thumbnail: Optional[PhotoSize] = thumbnail
+9 -8
View File
@@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram Game."""
from typing import TYPE_CHECKING, Dict, List, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._files.animation import Animation
from telegram._files.photosize import PhotoSize
@@ -65,7 +66,7 @@ class Game(TelegramObject):
Attributes:
title (:obj:`str`): Title of the game.
description (:obj:`str`): Description of the game.
photo (Tuple[:class:`telegram.PhotoSize`]): Photo that will be displayed in the game
photo (tuple[:class:`telegram.PhotoSize`]): Photo that will be displayed in the game
message in chats.
.. versionchanged:: 20.0
@@ -76,7 +77,7 @@ class Game(TelegramObject):
when the bot calls :meth:`telegram.Bot.set_game_score`, or manually edited
using :meth:`telegram.Bot.edit_message_text`.
0-:tg-const:`telegram.constants.MessageLimit.MAX_TEXT_LENGTH` characters.
text_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. Special entities that
text_entities (tuple[:class:`telegram.MessageEntity`]): Optional. Special entities that
appear in text, such as usernames, URLs, bot commands, etc.
This tuple is empty if the message does not contain text entities.
@@ -112,10 +113,10 @@ class Game(TelegramObject):
# Required
self.title: str = title
self.description: str = description
self.photo: Tuple[PhotoSize, ...] = parse_sequence_arg(photo)
self.photo: tuple[PhotoSize, ...] = parse_sequence_arg(photo)
# Optionals
self.text: Optional[str] = text
self.text_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(text_entities)
self.text_entities: tuple[MessageEntity, ...] = parse_sequence_arg(text_entities)
self.animation: Optional[Animation] = animation
self._id_attrs = (self.title, self.description, self.photo)
@@ -163,7 +164,7 @@ class Game(TelegramObject):
return entity_text.decode(TextEncoding.UTF_16_LE)
def parse_text_entities(self, types: Optional[List[str]] = None) -> Dict[MessageEntity, str]:
def parse_text_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 message filtered by their
@@ -176,13 +177,13 @@ class Game(TelegramObject):
See :attr:`parse_text_entity` for more info.
Args:
types (List[:obj:`str`], optional): List of :class:`telegram.MessageEntity` types as
types (list[:obj:`str`], optional): List of :class:`telegram.MessageEntity` types as
strings. If the :attr:`~telegram.MessageEntity.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
dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
the text that belongs to them, calculated based on UTF-16 codepoints.
"""
+62 -13
View File
@@ -18,7 +18,8 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an objects that are related to Telegram giveaways."""
import datetime
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._chat import Chat
from telegram._telegramobject import TelegramObject
@@ -41,7 +42,7 @@ class Giveaway(TelegramObject):
.. versionadded:: 20.8
Args:
chats (Tuple[:class:`telegram.Chat`]): The list of chats which the user must join to
chats (tuple[:class:`telegram.Chat`]): The list of chats which the user must join to
participate in the giveaway.
winners_selection_date (:class:`datetime.datetime`): The date when the giveaway winner will
be selected. |datetime_localization|
@@ -56,8 +57,13 @@ class Giveaway(TelegramObject):
country codes indicating the countries from which eligible users for the giveaway must
come. If empty, then all users can participate in the giveaway. Users with a phone
number that was bought on Fragment can always participate in giveaways.
prize_star_count (:obj:`int`, optional): The number of Telegram Stars to be split between
giveaway winners; for Telegram Star giveaways only.
.. versionadded:: 21.6
premium_subscription_month_count (:obj:`int`, optional): The number of months the Telegram
Premium subscription won from the giveaway will be active for.
Premium subscription won from the giveaway will be active for; for Telegram Premium
giveaways only.
Attributes:
chats (Sequence[:class:`telegram.Chat`]): The list of chats which the user must join to
@@ -71,12 +77,17 @@ class Giveaway(TelegramObject):
has_public_winners (:obj:`True`): Optional. :obj:`True`, if the list of giveaway winners
will be visible to everyone
prize_description (:obj:`str`): Optional. Description of additional giveaway prize
country_codes (Tuple[:obj:`str`]): Optional. A tuple of two-letter ISO 3166-1 alpha-2
country_codes (tuple[:obj:`str`]): Optional. A tuple of two-letter ISO 3166-1 alpha-2
country codes indicating the countries from which eligible users for the giveaway must
come. If empty, then all users can participate in the giveaway. Users with a phone
number that was bought on Fragment can always participate in giveaways.
prize_star_count (:obj:`int`): Optional. The number of Telegram Stars to be split between
giveaway winners; for Telegram Star giveaways only.
.. versionadded:: 21.6
premium_subscription_month_count (:obj:`int`): Optional. The number of months the Telegram
Premium subscription won from the giveaway will be active for.
Premium subscription won from the giveaway will be active for; for Telegram Premium
giveaways only.
"""
__slots__ = (
@@ -86,6 +97,7 @@ class Giveaway(TelegramObject):
"only_new_members",
"premium_subscription_month_count",
"prize_description",
"prize_star_count",
"winner_count",
"winners_selection_date",
)
@@ -100,19 +112,21 @@ class Giveaway(TelegramObject):
prize_description: Optional[str] = None,
country_codes: Optional[Sequence[str]] = None,
premium_subscription_month_count: Optional[int] = None,
prize_star_count: Optional[int] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(api_kwargs=api_kwargs)
self.chats: Tuple[Chat, ...] = tuple(chats)
self.chats: tuple[Chat, ...] = tuple(chats)
self.winners_selection_date: datetime.datetime = winners_selection_date
self.winner_count: int = winner_count
self.only_new_members: Optional[bool] = only_new_members
self.has_public_winners: Optional[bool] = has_public_winners
self.prize_description: Optional[str] = prize_description
self.country_codes: Tuple[str, ...] = parse_sequence_arg(country_codes)
self.country_codes: tuple[str, ...] = parse_sequence_arg(country_codes)
self.premium_subscription_month_count: Optional[int] = premium_subscription_month_count
self.prize_star_count: Optional[int] = prize_star_count
self._id_attrs = (
self.chats,
@@ -145,13 +159,28 @@ class Giveaway(TelegramObject):
class GiveawayCreated(TelegramObject):
"""This object represents a service message about the creation of a scheduled giveaway.
Currently holds no information.
Args:
prize_star_count (:obj:`int`, optional): The number of Telegram Stars to be
split between giveaway winners; for Telegram Star giveaways only.
.. versionadded:: 21.6
Attributes:
prize_star_count (:obj:`int`): Optional. The number of Telegram Stars to be
split between giveaway winners; for Telegram Star giveaways only.
.. versionadded:: 21.6
"""
__slots__ = ()
__slots__ = ("prize_star_count",)
def __init__(self, *, api_kwargs: Optional[JSONDict] = None):
def __init__(
self, prize_star_count: Optional[int] = None, *, api_kwargs: Optional[JSONDict] = None
):
super().__init__(api_kwargs=api_kwargs)
self.prize_star_count: Optional[int] = prize_star_count
self._freeze()
@@ -173,6 +202,10 @@ class GiveawayWinners(TelegramObject):
winner_count (:obj:`int`): Total number of winners in the giveaway
winners (Sequence[:class:`telegram.User`]): List of up to
:tg-const:`telegram.constants.GiveawayLimit.MAX_WINNERS` winners of the giveaway
prize_star_count (:obj:`int`, optional): The number of Telegram Stars to be split between
giveaway winners; for Telegram Star giveaways only.
.. versionadded:: 21.6
additional_chat_count (:obj:`int`, optional): The number of other chats the user had to
join in order to be eligible for the giveaway
premium_subscription_month_count (:obj:`int`, optional): The number of months the Telegram
@@ -190,10 +223,14 @@ class GiveawayWinners(TelegramObject):
winners_selection_date (:class:`datetime.datetime`): Point in time when winners of the
giveaway were selected. |datetime_localization|
winner_count (:obj:`int`): Total number of winners in the giveaway
winners (Tuple[:class:`telegram.User`]): tuple of up to
winners (tuple[:class:`telegram.User`]): tuple of up to
:tg-const:`telegram.constants.GiveawayLimit.MAX_WINNERS` winners of the giveaway
additional_chat_count (:obj:`int`): Optional. The number of other chats the user had to
join in order to be eligible for the giveaway
prize_star_count (:obj:`int`): Optional. The number of Telegram Stars to be split between
giveaway winners; for Telegram Star giveaways only.
.. versionadded:: 21.6
premium_subscription_month_count (:obj:`int`): Optional. The number of months the Telegram
Premium subscription won from the giveaway will be active for
unclaimed_prize_count (:obj:`int`): Optional. Number of undistributed prizes
@@ -211,6 +248,7 @@ class GiveawayWinners(TelegramObject):
"only_new_members",
"premium_subscription_month_count",
"prize_description",
"prize_star_count",
"unclaimed_prize_count",
"was_refunded",
"winner_count",
@@ -231,6 +269,7 @@ class GiveawayWinners(TelegramObject):
only_new_members: Optional[bool] = None,
was_refunded: Optional[bool] = None,
prize_description: Optional[str] = None,
prize_star_count: Optional[int] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
@@ -240,13 +279,14 @@ class GiveawayWinners(TelegramObject):
self.giveaway_message_id: int = giveaway_message_id
self.winners_selection_date: datetime.datetime = winners_selection_date
self.winner_count: int = winner_count
self.winners: Tuple[User, ...] = tuple(winners)
self.winners: tuple[User, ...] = tuple(winners)
self.additional_chat_count: Optional[int] = additional_chat_count
self.premium_subscription_month_count: Optional[int] = premium_subscription_month_count
self.unclaimed_prize_count: Optional[int] = unclaimed_prize_count
self.only_new_members: Optional[bool] = only_new_members
self.was_refunded: Optional[bool] = was_refunded
self.prize_description: Optional[str] = prize_description
self.prize_star_count: Optional[int] = prize_star_count
self._id_attrs = (
self.chat,
@@ -295,21 +335,29 @@ class GiveawayCompleted(TelegramObject):
unclaimed_prize_count (:obj:`int`, optional): Number of undistributed prizes
giveaway_message (:class:`telegram.Message`, optional): Message with the giveaway that was
completed, if it wasn't deleted
is_star_giveaway (:obj:`bool`, optional): :obj:`True`, if the giveaway is a Telegram Star
giveaway. Otherwise, currently, the giveaway is a Telegram Premium giveaway.
.. versionadded:: 21.6
Attributes:
winner_count (:obj:`int`): Number of winners in the giveaway
unclaimed_prize_count (:obj:`int`): Optional. Number of undistributed prizes
giveaway_message (:class:`telegram.Message`): Optional. Message with the giveaway that was
completed, if it wasn't deleted
is_star_giveaway (:obj:`bool`): Optional. :obj:`True`, if the giveaway is a Telegram Star
giveaway. Otherwise, currently, the giveaway is a Telegram Premium giveaway.
.. versionadded:: 21.6
"""
__slots__ = ("giveaway_message", "unclaimed_prize_count", "winner_count")
__slots__ = ("giveaway_message", "is_star_giveaway", "unclaimed_prize_count", "winner_count")
def __init__(
self,
winner_count: int,
unclaimed_prize_count: Optional[int] = None,
giveaway_message: Optional["Message"] = None,
is_star_giveaway: Optional[bool] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
@@ -318,6 +366,7 @@ class GiveawayCompleted(TelegramObject):
self.winner_count: int = winner_count
self.unclaimed_prize_count: Optional[int] = unclaimed_prize_count
self.giveaway_message: Optional[Message] = giveaway_message
self.is_star_giveaway: Optional[bool] = is_star_giveaway
self._id_attrs = (
self.winner_count,
+13
View File
@@ -21,6 +21,7 @@
from typing import TYPE_CHECKING, Final, Optional, Union
from telegram import constants
from telegram._copytextbutton import CopyTextButton
from telegram._games.callbackgame import CallbackGame
from telegram._loginurl import LoginUrl
from telegram._switchinlinequerychosenchat import SwitchInlineQueryChosenChat
@@ -123,6 +124,10 @@ class InlineKeyboardButton(TelegramObject):
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.
copy_text (:class:`telegram.CopyTextButton`, optional): Description of the button that
copies the specified text to the clipboard.
.. versionadded:: 21.7
callback_game (:class:`telegram.CallbackGame`, optional): Description of the game that will
be launched when the user presses the button
@@ -192,6 +197,10 @@ class InlineKeyboardButton(TelegramObject):
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.
copy_text (:class:`telegram.CopyTextButton`): Optional. Description of the button that
copies the specified text to the clipboard.
.. versionadded:: 21.7
callback_game (:class:`telegram.CallbackGame`): Optional. Description of the game that will
be launched when the user presses the button.
@@ -224,6 +233,7 @@ class InlineKeyboardButton(TelegramObject):
__slots__ = (
"callback_data",
"callback_game",
"copy_text",
"login_url",
"pay",
"switch_inline_query",
@@ -246,6 +256,7 @@ class InlineKeyboardButton(TelegramObject):
login_url: Optional[LoginUrl] = None,
web_app: Optional[WebAppInfo] = None,
switch_inline_query_chosen_chat: Optional[SwitchInlineQueryChosenChat] = None,
copy_text: Optional[CopyTextButton] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
@@ -265,6 +276,7 @@ class InlineKeyboardButton(TelegramObject):
self.switch_inline_query_chosen_chat: Optional[SwitchInlineQueryChosenChat] = (
switch_inline_query_chosen_chat
)
self.copy_text: Optional[CopyTextButton] = copy_text
self._id_attrs = ()
self._set_id_attrs()
@@ -299,6 +311,7 @@ class InlineKeyboardButton(TelegramObject):
data["switch_inline_query_chosen_chat"] = SwitchInlineQueryChosenChat.de_json(
data.get("switch_inline_query_chosen_chat"), bot
)
data["copy_text"] = CopyTextButton.de_json(data.get("copy_text"), bot)
return super().de_json(data=data, bot=bot)
+4 -3
View File
@@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram InlineKeyboardMarkup."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardbutton import InlineKeyboardButton
from telegram._telegramobject import TelegramObject
@@ -57,7 +58,7 @@ class InlineKeyboardMarkup(TelegramObject):
|sequenceclassargs|
Attributes:
inline_keyboard (Tuple[Tuple[:class:`telegram.InlineKeyboardButton`]]): Tuple of
inline_keyboard (tuple[tuple[:class:`telegram.InlineKeyboardButton`]]): Tuple of
button rows, each represented by a tuple of :class:`~telegram.InlineKeyboardButton`
objects.
@@ -81,7 +82,7 @@ class InlineKeyboardMarkup(TelegramObject):
"InlineKeyboardButtons"
)
# Required
self.inline_keyboard: Tuple[Tuple[InlineKeyboardButton, ...], ...] = tuple(
self.inline_keyboard: tuple[tuple[InlineKeyboardButton, ...], ...] = tuple(
tuple(row) for row in inline_keyboard
)
+2 -1
View File
@@ -19,7 +19,8 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram InlineQuery."""
from typing import TYPE_CHECKING, Callable, Final, Optional, Sequence, Union
from collections.abc import Sequence
from typing import TYPE_CHECKING, Callable, Final, Optional, Union
from telegram import constants
from telegram._files.location import Location
+4 -3
View File
@@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the classes that represent Telegram InlineQueryResultAudio."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@@ -73,7 +74,7 @@ class InlineQueryResultAudio(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after entities
parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@@ -124,6 +125,6 @@ class InlineQueryResultAudio(InlineQueryResult):
self.audio_duration: Optional[int] = audio_duration
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
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
@@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the classes that represent Telegram InlineQueryResultCachedAudio."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@@ -68,7 +69,7 @@ class InlineQueryResultCachedAudio(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after entities
parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@@ -110,6 +111,6 @@ class InlineQueryResultCachedAudio(InlineQueryResult):
# Optionals
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
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
@@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the classes that represent Telegram InlineQueryResultCachedDocument."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@@ -72,7 +73,7 @@ class InlineQueryResultCachedDocument(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@@ -120,6 +121,6 @@ class InlineQueryResultCachedDocument(InlineQueryResult):
self.description: Optional[str] = description
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
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
@@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the classes that represent Telegram InlineQueryResultCachedGif."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@@ -74,7 +75,7 @@ class InlineQueryResultCachedGif(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@@ -124,7 +125,7 @@ class InlineQueryResultCachedGif(InlineQueryResult):
self.title: Optional[str] = title
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
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
@@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the classes that represent Telegram InlineQueryResultMpeg4Gif."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@@ -74,7 +75,7 @@ class InlineQueryResultCachedMpeg4Gif(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@@ -124,7 +125,7 @@ class InlineQueryResultCachedMpeg4Gif(InlineQueryResult):
self.title: Optional[str] = title
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
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
@@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the classes that represent Telegram InlineQueryResultPhoto"""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@@ -76,7 +77,7 @@ class InlineQueryResultCachedPhoto(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after
entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@@ -129,7 +130,7 @@ class InlineQueryResultCachedPhoto(InlineQueryResult):
self.description: Optional[str] = description
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
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
@@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the classes that represent Telegram InlineQueryResultCachedVideo."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@@ -72,7 +73,7 @@ class InlineQueryResultCachedVideo(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after
entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@@ -125,7 +126,7 @@ class InlineQueryResultCachedVideo(InlineQueryResult):
self.description: Optional[str] = description
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
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
@@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the classes that represent Telegram InlineQueryResultCachedVoice."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@@ -70,7 +71,7 @@ class InlineQueryResultCachedVoice(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after entities
parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |caption_entities|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |caption_entities|
.. versionchanged:: 20.0
@@ -115,6 +116,6 @@ class InlineQueryResultCachedVoice(InlineQueryResult):
# Optionals
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
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
@@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the classes that represent Telegram InlineQueryResultDocument"""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@@ -86,7 +87,7 @@ class InlineQueryResultDocument(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@@ -155,7 +156,7 @@ class InlineQueryResultDocument(InlineQueryResult):
# Optionals
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.caption_entities: tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.description: Optional[str] = description
self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup
self.input_message_content: Optional[InputMessageContent] = input_message_content
+4 -3
View File
@@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the classes that represent Telegram InlineQueryResultGif."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@@ -102,7 +103,7 @@ class InlineQueryResultGif(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@@ -166,7 +167,7 @@ class InlineQueryResultGif(InlineQueryResult):
self.title: Optional[str] = title
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
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.thumbnail_mime_type: Optional[str] = thumbnail_mime_type
@@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the classes that represent Telegram InlineQueryResultMpeg4Gif."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@@ -104,7 +105,7 @@ class InlineQueryResultMpeg4Gif(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |caption_entities|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |caption_entities|
.. versionchanged:: 20.0
@@ -168,7 +169,7 @@ class InlineQueryResultMpeg4Gif(InlineQueryResult):
self.title: Optional[str] = title
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
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.thumbnail_mime_type: Optional[str] = thumbnail_mime_type
+4 -3
View File
@@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the classes that represent Telegram InlineQueryResultPhoto."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@@ -92,7 +93,7 @@ class InlineQueryResultPhoto(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after
entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@@ -154,7 +155,7 @@ class InlineQueryResultPhoto(InlineQueryResult):
self.description: Optional[str] = description
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
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
+4 -3
View File
@@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the classes that represent Telegram InlineQueryResultVideo."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@@ -99,7 +100,7 @@ class InlineQueryResultVideo(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after entities
parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional.
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional.
|captionentitiesattr|
.. versionchanged:: 20.0
@@ -171,7 +172,7 @@ class InlineQueryResultVideo(InlineQueryResult):
# Optional
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.caption_entities: tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.video_width: Optional[int] = video_width
self.video_height: Optional[int] = video_height
self.video_duration: Optional[int] = video_duration
+4 -3
View File
@@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the classes that represent Telegram InlineQueryResultVoice."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@@ -72,7 +73,7 @@ class InlineQueryResultVoice(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after entities
parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@@ -121,6 +122,6 @@ class InlineQueryResultVoice(InlineQueryResult):
self.voice_duration: Optional[int] = voice_duration
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
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
@@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains a class that represents a Telegram InputInvoiceMessageContent."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inputmessagecontent import InputMessageContent
from telegram._payment.labeledprice import LabeledPrice
@@ -122,7 +123,7 @@ class InputInvoiceMessageContent(InputMessageContent):
currency (:obj:`str`): Three-letter ISO 4217 currency code, see more on
`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
prices (tuple[:class:`telegram.LabeledPrice`]): Price breakdown, a list of
components (e.g. product price, tax, discount, delivery cost, delivery tax, bonus,
etc.). Must contain exactly one item for payments in |tg_stars|.
@@ -135,7 +136,7 @@ class InputInvoiceMessageContent(InputMessageContent):
`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``. Not supported for payments in |tg_stars|.
suggested_tip_amounts (Tuple[:obj:`int`]): Optional. An array of suggested
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
positive, passed in a strictly increased order and must not exceed
@@ -226,10 +227,10 @@ class InputInvoiceMessageContent(InputMessageContent):
self.payload: str = payload
self.provider_token: Optional[str] = provider_token
self.currency: str = currency
self.prices: Tuple[LabeledPrice, ...] = parse_sequence_arg(prices)
self.prices: tuple[LabeledPrice, ...] = parse_sequence_arg(prices)
# Optionals
self.max_tip_amount: Optional[int] = max_tip_amount
self.suggested_tip_amounts: Tuple[int, ...] = parse_sequence_arg(suggested_tip_amounts)
self.suggested_tip_amounts: tuple[int, ...] = parse_sequence_arg(suggested_tip_amounts)
self.provider_data: Optional[str] = provider_data
self.photo_url: Optional[str] = photo_url
self.photo_size: Optional[int] = photo_size
+4 -3
View File
@@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the classes that represent Telegram InputTextMessageContent."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inputmessagecontent import InputMessageContent
from telegram._messageentity import MessageEntity
@@ -75,7 +76,7 @@ class InputTextMessageContent(InputMessageContent):
:tg-const:`telegram.constants.MessageLimit.MAX_TEXT_LENGTH` characters after entities
parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@@ -107,7 +108,7 @@ class InputTextMessageContent(InputMessageContent):
self.message_text: str = message_text
# Optionals
self.parse_mode: ODVInput[str] = parse_mode
self.entities: Tuple[MessageEntity, ...] = parse_sequence_arg(entities)
self.entities: tuple[MessageEntity, ...] = parse_sequence_arg(entities)
self.link_preview_options: ODVInput[LinkPreviewOptions] = parse_lpo_and_dwpp(
disable_web_page_preview, link_preview_options
)
+3 -3
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 objects related to Telegram menu buttons."""
from typing import TYPE_CHECKING, Dict, Final, Optional, Type
from typing import TYPE_CHECKING, Final, Optional
from telegram import constants
from telegram._telegramobject import TelegramObject
@@ -76,7 +76,7 @@ class MenuButton(TelegramObject):
care of selecting the correct subclass.
Args:
data (Dict[:obj:`str`, ...]): The JSON data.
data (dict[:obj:`str`, ...]): The JSON data.
bot (:class:`telegram.Bot`, optional): The bot associated with this object. Defaults to
:obj:`None`, in which case shortcut methods will not be available.
@@ -95,7 +95,7 @@ class MenuButton(TelegramObject):
if not data and cls is MenuButton:
return None
_class_mapping: Dict[str, Type[MenuButton]] = {
_class_mapping: dict[str, type[MenuButton]] = {
cls.COMMANDS: MenuButtonCommands,
cls.WEB_APP: MenuButtonWebApp,
cls.DEFAULT: MenuButtonDefault,
+153 -30
View File
@@ -21,8 +21,9 @@
import datetime
import re
from collections.abc import Sequence
from html import escape
from typing import TYPE_CHECKING, Dict, List, Optional, Sequence, Tuple, TypedDict, Union
from typing import TYPE_CHECKING, Optional, TypedDict, Union
from telegram._chat import Chat
from telegram._chatbackground import ChatBackground
@@ -104,6 +105,7 @@ if TYPE_CHECKING:
InputMediaDocument,
InputMediaPhoto,
InputMediaVideo,
InputPaidMedia,
InputPollOption,
LabeledPrice,
MessageId,
@@ -279,7 +281,10 @@ class Message(MaybeInaccessibleMessage):
and notice that some positional arguments changed position as a result.
Args:
message_id (:obj:`int`): Unique message identifier inside this chat.
message_id (:obj:`int`): Unique message identifier inside this chat. In specific instances
(e.g., message containing a video sent to a big chat), the server might automatically
schedule a message instead of sending it immediately. In such cases, this field will be
``0`` and the relevant message will be unusable until it is actually sent.
from_user (:class:`telegram.User`, optional): Sender of the message; may be empty for
messages sent to channels. For backward compatibility, if the message was sent on
behalf of a chat, the field contains a fake sender user in non-channel chats.
@@ -589,7 +594,10 @@ class Message(MaybeInaccessibleMessage):
.. versionadded:: 21.4
Attributes:
message_id (:obj:`int`): Unique message identifier inside this chat.
message_id (:obj:`int`): Unique message identifier inside this chat. In specific instances
(e.g., message containing a video sent to a big chat), the server might automatically
schedule a message instead of sending it immediately. In such cases, this field will be
``0`` and the relevant message will be unusable until it is actually sent.
from_user (:class:`telegram.User`): Optional. Sender of the message; may be empty for
messages sent to channels. For backward compatibility, if the message was sent on
behalf of a chat, the field contains a fake sender user in non-channel chats.
@@ -629,7 +637,7 @@ class Message(MaybeInaccessibleMessage):
message belongs to.
text (:obj:`str`): Optional. For text messages, the actual UTF-8 text of the message,
0-:tg-const:`telegram.constants.MessageLimit.MAX_TEXT_LENGTH` characters.
entities (Tuple[:class:`telegram.MessageEntity`]): Optional. For text messages, special
entities (tuple[:class:`telegram.MessageEntity`]): Optional. For text messages, special
entities like usernames, URLs, bot commands, etc. that appear in the text. See
:attr:`parse_entity` and :attr:`parse_entities` methods for how to use properly.
This list is empty if the message does not contain entities.
@@ -648,7 +656,7 @@ class Message(MaybeInaccessibleMessage):
..versionadded:: 21.3
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. For messages with a
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`
methods for how to use properly. This list is empty if the message does not contain
@@ -675,7 +683,7 @@ class Message(MaybeInaccessibleMessage):
.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
game (:class:`telegram.Game`): Optional. Message is a game, information about the game.
:ref:`More about games >> <games-tree>`.
photo (Tuple[:class:`telegram.PhotoSize`]): Optional. Message is a photo, available
photo (tuple[:class:`telegram.PhotoSize`]): Optional. Message is a photo, available
sizes of the photo. This list is empty if the message does not contain a photo.
.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
@@ -703,7 +711,7 @@ class Message(MaybeInaccessibleMessage):
about the video message.
.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
new_chat_members (Tuple[:class:`telegram.User`]): Optional. New members that were added
new_chat_members (tuple[:class:`telegram.User`]): Optional. New members that were added
to the group or supergroup and information about them (the bot itself may be one of
these members). This list is empty if the message does not contain new chat members.
@@ -722,7 +730,7 @@ class Message(MaybeInaccessibleMessage):
left_chat_member (:class:`telegram.User`): Optional. A member was removed from the group,
information about them (this member may be the bot itself).
new_chat_title (:obj:`str`): Optional. A chat title was changed to this value.
new_chat_photo (Tuple[:class:`telegram.PhotoSize`]): A chat photo was changed to
new_chat_photo (tuple[:class:`telegram.PhotoSize`]): A chat photo was changed to
this value. This list is empty if the message does not contain a new chat photo.
.. versionchanged:: 20.0
@@ -1118,12 +1126,12 @@ class Message(MaybeInaccessibleMessage):
self.edit_date: Optional[datetime.datetime] = edit_date
self.has_protected_content: Optional[bool] = has_protected_content
self.text: Optional[str] = text
self.entities: Tuple[MessageEntity, ...] = parse_sequence_arg(entities)
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.entities: tuple[MessageEntity, ...] = parse_sequence_arg(entities)
self.caption_entities: tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.audio: Optional[Audio] = audio
self.game: Optional[Game] = game
self.document: Optional[Document] = document
self.photo: Tuple[PhotoSize, ...] = parse_sequence_arg(photo)
self.photo: tuple[PhotoSize, ...] = parse_sequence_arg(photo)
self.sticker: Optional[Sticker] = sticker
self.video: Optional[Video] = video
self.voice: Optional[Voice] = voice
@@ -1132,10 +1140,10 @@ class Message(MaybeInaccessibleMessage):
self.contact: Optional[Contact] = contact
self.location: Optional[Location] = location
self.venue: Optional[Venue] = venue
self.new_chat_members: Tuple[User, ...] = parse_sequence_arg(new_chat_members)
self.new_chat_members: tuple[User, ...] = parse_sequence_arg(new_chat_members)
self.left_chat_member: Optional[User] = left_chat_member
self.new_chat_title: Optional[str] = new_chat_title
self.new_chat_photo: Tuple[PhotoSize, ...] = parse_sequence_arg(new_chat_photo)
self.new_chat_photo: tuple[PhotoSize, ...] = parse_sequence_arg(new_chat_photo)
self.delete_chat_photo: Optional[bool] = bool(delete_chat_photo)
self.group_chat_created: Optional[bool] = bool(group_chat_created)
self.supergroup_chat_created: Optional[bool] = bool(supergroup_chat_created)
@@ -1406,7 +1414,7 @@ class Message(MaybeInaccessibleMessage):
* :class:`telegram.Invoice`
* :class:`telegram.Location`
* :class:`telegram.PassportData`
* List[:class:`telegram.PhotoSize`]
* list[:class:`telegram.PhotoSize`]
* :class:`telegram.PaidMediaInfo`
* :class:`telegram.Poll`
* :class:`telegram.Sticker`
@@ -1478,7 +1486,7 @@ class Message(MaybeInaccessibleMessage):
def compute_quote_position_and_entities(
self, quote: str, index: Optional[int] = None
) -> Tuple[int, Optional[Tuple[MessageEntity, ...]]]:
) -> tuple[int, Optional[tuple[MessageEntity, ...]]]:
"""
Use this function to compute position and entities of a quote in the message text or
caption. Useful for filling the parameters
@@ -1504,7 +1512,7 @@ class Message(MaybeInaccessibleMessage):
message. If not specified, the first occurrence is used.
Returns:
Tuple[:obj:`int`, :obj:`None` | Tuple[:class:`~telegram.MessageEntity`, ...]]: On
tuple[:obj:`int`, :obj:`None` | tuple[:class:`~telegram.MessageEntity`, ...]]: On
success, a tuple containing information about quote position and entities is returned.
Raises:
@@ -1647,7 +1655,7 @@ class Message(MaybeInaccessibleMessage):
quote: Optional[bool],
reply_to_message_id: Optional[int],
reply_parameters: Optional["ReplyParameters"],
) -> Tuple[Union[str, int], ReplyParameters]:
) -> tuple[Union[str, int], ReplyParameters]:
if quote and do_quote:
raise ValueError("The arguments `quote` and `do_quote` are mutually exclusive")
@@ -1714,6 +1722,7 @@ class Message(MaybeInaccessibleMessage):
link_preview_options: ODVInput["LinkPreviewOptions"] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1779,6 +1788,7 @@ class Message(MaybeInaccessibleMessage):
api_kwargs=api_kwargs,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def reply_markdown(
@@ -1792,6 +1802,7 @@ class Message(MaybeInaccessibleMessage):
link_preview_options: ODVInput["LinkPreviewOptions"] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1863,6 +1874,7 @@ class Message(MaybeInaccessibleMessage):
api_kwargs=api_kwargs,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def reply_markdown_v2(
@@ -1876,6 +1888,7 @@ class Message(MaybeInaccessibleMessage):
link_preview_options: ODVInput["LinkPreviewOptions"] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -1943,6 +1956,7 @@ class Message(MaybeInaccessibleMessage):
api_kwargs=api_kwargs,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def reply_html(
@@ -1956,6 +1970,7 @@ class Message(MaybeInaccessibleMessage):
link_preview_options: ODVInput["LinkPreviewOptions"] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2023,6 +2038,7 @@ class Message(MaybeInaccessibleMessage):
api_kwargs=api_kwargs,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def reply_media_group(
@@ -2035,6 +2051,7 @@ class Message(MaybeInaccessibleMessage):
message_thread_id: ODVInput[int] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2048,7 +2065,7 @@ class Message(MaybeInaccessibleMessage):
caption: Optional[str] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
) -> Tuple["Message", ...]:
) -> tuple["Message", ...]:
"""Shortcut for::
await bot.send_media_group(
@@ -2075,7 +2092,7 @@ class Message(MaybeInaccessibleMessage):
.. versionadded:: 20.8
Returns:
Tuple[:class:`telegram.Message`]: An array of the sent Messages.
tuple[:class:`telegram.Message`]: An array of the sent Messages.
Raises:
:class:`telegram.error.TelegramError`
@@ -2102,6 +2119,7 @@ class Message(MaybeInaccessibleMessage):
caption_entities=caption_entities,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def reply_photo(
@@ -2117,6 +2135,7 @@ class Message(MaybeInaccessibleMessage):
has_spoiler: Optional[bool] = None,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
show_caption_above_media: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
@@ -2184,6 +2203,7 @@ class Message(MaybeInaccessibleMessage):
has_spoiler=has_spoiler,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
show_caption_above_media=show_caption_above_media,
)
@@ -2203,6 +2223,7 @@ class Message(MaybeInaccessibleMessage):
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2272,6 +2293,7 @@ class Message(MaybeInaccessibleMessage):
thumbnail=thumbnail,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def reply_document(
@@ -2288,6 +2310,7 @@ class Message(MaybeInaccessibleMessage):
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2355,6 +2378,7 @@ class Message(MaybeInaccessibleMessage):
thumbnail=thumbnail,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def reply_animation(
@@ -2374,6 +2398,7 @@ class Message(MaybeInaccessibleMessage):
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
show_caption_above_media: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
@@ -2445,6 +2470,7 @@ class Message(MaybeInaccessibleMessage):
thumbnail=thumbnail,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
show_caption_above_media=show_caption_above_media,
)
@@ -2458,6 +2484,7 @@ class Message(MaybeInaccessibleMessage):
emoji: Optional[str] = None,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2519,6 +2546,7 @@ class Message(MaybeInaccessibleMessage):
emoji=emoji,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def reply_video(
@@ -2539,6 +2567,7 @@ class Message(MaybeInaccessibleMessage):
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
show_caption_above_media: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
@@ -2611,6 +2640,7 @@ class Message(MaybeInaccessibleMessage):
thumbnail=thumbnail,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
show_caption_above_media=show_caption_above_media,
)
@@ -2626,6 +2656,7 @@ class Message(MaybeInaccessibleMessage):
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2691,6 +2722,7 @@ class Message(MaybeInaccessibleMessage):
thumbnail=thumbnail,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def reply_voice(
@@ -2706,6 +2738,7 @@ class Message(MaybeInaccessibleMessage):
message_thread_id: ODVInput[int] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2772,6 +2805,7 @@ class Message(MaybeInaccessibleMessage):
message_thread_id=message_thread_id,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def reply_location(
@@ -2788,6 +2822,7 @@ class Message(MaybeInaccessibleMessage):
message_thread_id: ODVInput[int] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2855,6 +2890,7 @@ class Message(MaybeInaccessibleMessage):
message_thread_id=message_thread_id,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def reply_venue(
@@ -2873,6 +2909,7 @@ class Message(MaybeInaccessibleMessage):
message_thread_id: ODVInput[int] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -2942,6 +2979,7 @@ class Message(MaybeInaccessibleMessage):
message_thread_id=message_thread_id,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def reply_contact(
@@ -2956,6 +2994,7 @@ class Message(MaybeInaccessibleMessage):
message_thread_id: ODVInput[int] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -3021,6 +3060,7 @@ class Message(MaybeInaccessibleMessage):
message_thread_id=message_thread_id,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def reply_poll(
@@ -3045,6 +3085,7 @@ class Message(MaybeInaccessibleMessage):
question_parse_mode: ODVInput[str] = DEFAULT_NONE,
question_entities: Optional[Sequence["MessageEntity"]] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -3118,6 +3159,7 @@ class Message(MaybeInaccessibleMessage):
question_parse_mode=question_parse_mode,
question_entities=question_entities,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def reply_dice(
@@ -3129,6 +3171,7 @@ class Message(MaybeInaccessibleMessage):
message_thread_id: ODVInput[int] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -3189,6 +3232,7 @@ class Message(MaybeInaccessibleMessage):
message_thread_id=message_thread_id,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def reply_chat_action(
@@ -3244,6 +3288,7 @@ class Message(MaybeInaccessibleMessage):
message_thread_id: ODVInput[int] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -3306,6 +3351,7 @@ class Message(MaybeInaccessibleMessage):
message_thread_id=message_thread_id,
business_connection_id=self.business_connection_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def reply_invoice(
@@ -3337,6 +3383,7 @@ class Message(MaybeInaccessibleMessage):
message_thread_id: ODVInput[int] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
message_effect_id: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -3427,6 +3474,7 @@ class Message(MaybeInaccessibleMessage):
protect_content=protect_content,
message_thread_id=message_thread_id,
message_effect_id=message_effect_id,
allow_paid_broadcast=allow_paid_broadcast,
)
async def forward(
@@ -3491,6 +3539,7 @@ class Message(MaybeInaccessibleMessage):
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
show_caption_above_media: Optional[bool] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -3536,6 +3585,7 @@ class Message(MaybeInaccessibleMessage):
protect_content=protect_content,
message_thread_id=message_thread_id,
show_caption_above_media=show_caption_above_media,
allow_paid_broadcast=allow_paid_broadcast,
)
async def reply_copy(
@@ -3551,6 +3601,7 @@ class Message(MaybeInaccessibleMessage):
message_thread_id: ODVInput[int] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
show_caption_above_media: Optional[bool] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
@@ -3615,6 +3666,78 @@ class Message(MaybeInaccessibleMessage):
protect_content=protect_content,
message_thread_id=message_thread_id,
show_caption_above_media=show_caption_above_media,
allow_paid_broadcast=allow_paid_broadcast,
)
async def reply_paid_media(
self,
star_count: int,
media: Sequence["InputPaidMedia"],
caption: Optional[str] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
show_caption_above_media: Optional[bool] = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
protect_content: ODVInput[bool] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
reply_markup: Optional[ReplyMarkup] = None,
payload: Optional[str] = None,
allow_paid_broadcast: Optional[bool] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
do_quote: Optional[Union[bool, _ReplyKwargs]] = None,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> "Message":
"""Shortcut for::
await bot.send_paid_media(
chat_id=message.chat.id,
business_connection_id=message.business_connection_id,
*args,
**kwargs
)
For the documentation of the arguments, please see :meth:`telegram.Bot.send_paid_media`.
.. versionadded:: 21.7
Keyword Args:
do_quote (:obj:`bool` | :obj:`dict`, optional): |do_quote|
Mutually exclusive with :paramref:`quote`.
Returns:
:class:`telegram.Message`: On success, the sent message is returned.
"""
chat_id, effective_reply_parameters = await self._parse_quote_arguments(
do_quote, None, reply_to_message_id, reply_parameters
)
return await self.get_bot().send_paid_media(
chat_id=chat_id,
caption=caption,
star_count=star_count,
media=media,
payload=payload,
business_connection_id=self.business_connection_id,
parse_mode=parse_mode,
caption_entities=caption_entities,
disable_notification=disable_notification,
reply_parameters=effective_reply_parameters,
allow_sending_without_reply=allow_sending_without_reply,
reply_markup=reply_markup,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
protect_content=protect_content,
show_caption_above_media=show_caption_above_media,
allow_paid_broadcast=allow_paid_broadcast,
)
async def edit_text(
@@ -3989,7 +4112,7 @@ class Message(MaybeInaccessibleMessage):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple["GameHighScore", ...]:
) -> tuple["GameHighScore", ...]:
"""Shortcut for::
await bot.get_game_high_scores(
@@ -4005,7 +4128,7 @@ class Message(MaybeInaccessibleMessage):
behaviour is undocumented and might be changed by Telegram.
Returns:
Tuple[:class:`telegram.GameHighScore`]
tuple[:class:`telegram.GameHighScore`]
"""
return await self.get_bot().get_game_high_scores(
chat_id=self.chat_id,
@@ -4431,7 +4554,7 @@ class Message(MaybeInaccessibleMessage):
return parse_message_entity(self.caption, entity)
def parse_entities(self, types: Optional[List[str]] = None) -> Dict[MessageEntity, str]:
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 message filtered by their
@@ -4444,21 +4567,21 @@ class Message(MaybeInaccessibleMessage):
See :attr:`parse_entity` for more info.
Args:
types (List[:obj:`str`], optional): List of :class:`telegram.MessageEntity` types as
types (list[:obj:`str`], optional): List of :class:`telegram.MessageEntity` types as
strings. If the ``type`` attribute of an entity is contained in this list, it will
be returned. Defaults to a list of all types. All types can be found as constants
in :class:`telegram.MessageEntity`.
Returns:
Dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
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.entities, types=types)
def parse_caption_entities(
self, types: Optional[List[str]] = None
) -> Dict[MessageEntity, str]:
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 message's caption filtered by their
@@ -4471,13 +4594,13 @@ class Message(MaybeInaccessibleMessage):
codepoints. See :attr:`parse_entity` for more info.
Args:
types (List[:obj:`str`], optional): List of :class:`telegram.MessageEntity` types as
types (list[:obj:`str`], optional): List of :class:`telegram.MessageEntity` types as
strings. If the ``type`` attribute of an entity is contained in this list, it will
be returned. Defaults to a list of all types. All types can be found as constants
in :class:`telegram.MessageEntity`.
Returns:
Dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
the text that belongs to them, calculated based on UTF-16 codepoints.
"""
@@ -4487,7 +4610,7 @@ class Message(MaybeInaccessibleMessage):
def _parse_html(
cls,
message_text: Optional[str],
entities: Dict[MessageEntity, str],
entities: dict[MessageEntity, str],
urled: bool = False,
offset: int = 0,
) -> Optional[str]:
@@ -4676,7 +4799,7 @@ class Message(MaybeInaccessibleMessage):
def _parse_markdown(
cls,
message_text: Optional[str],
entities: Dict[MessageEntity, str],
entities: dict[MessageEntity, str],
urled: bool = False,
version: MarkdownVersion = 1,
offset: int = 0,
+21 -18
View File
@@ -20,7 +20,8 @@
import copy
import itertools
from typing import TYPE_CHECKING, Dict, Final, List, Optional, Sequence, Tuple, Union
from collections.abc import Sequence
from typing import TYPE_CHECKING, Final, Optional, Union
from telegram import constants
from telegram._telegramobject import TelegramObject
@@ -44,10 +45,11 @@ class MessageEntity(TelegramObject):
considered equal, if their :attr:`type`, :attr:`offset` and :attr:`length` are equal.
Args:
type (:obj:`str`): Type of the entity. Can be :attr:`MENTION` (@username),
:attr:`HASHTAG` (#hashtag), :attr:`CASHTAG` ($USD), :attr:`BOT_COMMAND`
(/start@jobs_bot), :attr:`URL` (https://telegram.org),
:attr:`EMAIL` (do-not-reply@telegram.org), :attr:`PHONE_NUMBER` (+1-212-555-0123),
type (:obj:`str`): Type of the entity. Can be :attr:`MENTION` (``@username``),
:attr:`HASHTAG` (``#hashtag`` or ``#hashtag@chatusername``), :attr:`CASHTAG` (``$USD``
or ``USD@chatusername``), :attr:`BOT_COMMAND` (``/start@jobs_bot``), :attr:`URL`
(``https://telegram.org``), :attr:`EMAIL` (``do-not-reply@telegram.org``),
:attr:`PHONE_NUMBER` (``+1-212-555-0123``),
:attr:`BOLD` (**bold text**), :attr:`ITALIC` (*italic text*), :attr:`UNDERLINE`
(underlined text), :attr:`STRIKETHROUGH`, :attr:`SPOILER` (spoiler message),
:attr:`BLOCKQUOTE` (block quotation), :attr:`CODE` (monowidth string), :attr:`PRE`
@@ -73,10 +75,11 @@ class MessageEntity(TelegramObject):
.. versionadded:: 20.0
Attributes:
type (:obj:`str`): Type of the entity. Can be :attr:`MENTION` (@username),
:attr:`HASHTAG` (#hashtag), :attr:`CASHTAG` ($USD), :attr:`BOT_COMMAND`
(/start@jobs_bot), :attr:`URL` (https://telegram.org),
:attr:`EMAIL` (do-not-reply@telegram.org), :attr:`PHONE_NUMBER` (+1-212-555-0123),
type (:obj:`str`): Type of the entity. Can be :attr:`MENTION` (``@username``),
:attr:`HASHTAG` (``#hashtag`` or ``#hashtag@chatusername``), :attr:`CASHTAG` (``$USD``
or ``USD@chatusername``), :attr:`BOT_COMMAND` (``/start@jobs_bot``), :attr:`URL`
(``https://telegram.org``), :attr:`EMAIL` (``do-not-reply@telegram.org``),
:attr:`PHONE_NUMBER` (``+1-212-555-0123``),
:attr:`BOLD` (**bold text**), :attr:`ITALIC` (*italic text*), :attr:`UNDERLINE`
(underlined text), :attr:`STRIKETHROUGH`, :attr:`SPOILER` (spoiler message),
:attr:`BLOCKQUOTE` (block quotation), :attr:`CODE` (monowidth string), :attr:`PRE`
@@ -200,7 +203,7 @@ class MessageEntity(TelegramObject):
accumulated_length = 0
# calculate the length of each slice text[:position] in utf-16 accordingly,
# store the position translations
position_translation: Dict[int, int] = {}
position_translation: dict[int, int] = {}
for i, position in enumerate(positions):
last_position = positions[i - 1] if i > 0 else 0
text_slice = text[last_position:position]
@@ -286,8 +289,8 @@ class MessageEntity(TelegramObject):
@classmethod
def concatenate(
cls,
*args: Union[Tuple[str, _SEM], Tuple[str, _SEM, bool]],
) -> Tuple[str, _SEM]:
*args: Union[tuple[str, _SEM], tuple[str, _SEM, bool]],
) -> tuple[str, _SEM]:
"""Utility functionality for concatenating two text along with their formatting entities.
Tip:
@@ -332,8 +335,8 @@ class MessageEntity(TelegramObject):
.. versionadded:: 21.5
Args:
*args (Tuple[:obj:`str`, Sequence[:class:`telegram.MessageEntity`]] | \
Tuple[:obj:`str`, Sequence[:class:`telegram.MessageEntity`], :obj:`bool`]):
*args (tuple[:obj:`str`, Sequence[:class:`telegram.MessageEntity`]] | \
tuple[:obj:`str`, Sequence[:class:`telegram.MessageEntity`], :obj:`bool`]):
Arbitrary number of tuples containing the text and its entities to concatenate.
If the last element of the tuple is a :obj:`bool`, it is used to determine whether
to adjust the entities to UTF-16 via
@@ -341,11 +344,11 @@ class MessageEntity(TelegramObject):
default.
Returns:
Tuple[:obj:`str`, Sequence[:class:`telegram.MessageEntity`]]: The concatenated text
tuple[:obj:`str`, Sequence[:class:`telegram.MessageEntity`]]: The concatenated text
and its entities
"""
output_text = ""
output_entities: List[MessageEntity] = []
output_entities: list[MessageEntity] = []
for arg in args:
text, entities = arg[0], arg[1]
@@ -357,8 +360,8 @@ class MessageEntity(TelegramObject):
return output_text, output_entities
ALL_TYPES: Final[List[str]] = list(constants.MessageEntityType)
"""List[:obj:`str`]: A list of all available message entity types."""
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`
+8 -2
View File
@@ -31,10 +31,16 @@ class MessageId(TelegramObject):
considered equal, if their :attr:`message_id` is equal.
Args:
message_id (:obj:`int`): Unique message identifier.
message_id (:obj:`int`): Unique message identifier. In specific instances
(e.g., message containing a video sent to a big chat), the server might automatically
schedule a message instead of sending it immediately. In such cases, this field will be
``0`` and the relevant message will be unusable until it is actually sent.
Attributes:
message_id (:obj:`int`): Unique message identifier.
message_id (:obj:`int`): Unique message identifier. In specific instances
(e.g., message containing a video sent to a big chat), the server might automatically
schedule a message instead of sending it immediately. In such cases, this field will be
``0`` and the relevant message will be unusable until it is actually sent.
"""
__slots__ = ("message_id",)
+2 -2
View File
@@ -18,7 +18,7 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the classes that represent Telegram MessageOigin."""
import datetime
from typing import TYPE_CHECKING, Dict, Final, Optional, Type
from typing import TYPE_CHECKING, Final, Optional
from telegram import constants
from telegram._chat import Chat
@@ -105,7 +105,7 @@ class MessageOrigin(TelegramObject):
if not data:
return None
_class_mapping: Dict[str, Type[MessageOrigin]] = {
_class_mapping: dict[str, type[MessageOrigin]] = {
cls.USER: MessageOriginUser,
cls.HIDDEN_USER: MessageOriginHiddenUser,
cls.CHAT: MessageOriginChat,
+8 -7
View File
@@ -17,8 +17,9 @@
# 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 MessageReaction Update."""
from collections.abc import Sequence
from datetime import datetime
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from typing import TYPE_CHECKING, Optional
from telegram._chat import Chat
from telegram._reaction import ReactionCount, ReactionType
@@ -54,7 +55,7 @@ class MessageReactionCountUpdated(TelegramObject):
message_id (:obj:`int`): Unique message identifier inside the chat.
date (:class:`datetime.datetime`): Date of the change in Unix time
|datetime_localization|
reactions (Tuple[:class:`telegram.ReactionCount`]): List of reactions that are present on
reactions (tuple[:class:`telegram.ReactionCount`]): List of reactions that are present on
the message
"""
@@ -79,7 +80,7 @@ class MessageReactionCountUpdated(TelegramObject):
self.chat: Chat = chat
self.message_id: int = message_id
self.date: datetime = date
self.reactions: Tuple[ReactionCount, ...] = parse_sequence_arg(reactions)
self.reactions: tuple[ReactionCount, ...] = parse_sequence_arg(reactions)
self._id_attrs = (self.chat, self.message_id, self.date, self.reactions)
self._freeze()
@@ -132,9 +133,9 @@ class MessageReactionUpdated(TelegramObject):
message_id (:obj:`int`): Unique message identifier inside the chat.
date (:class:`datetime.datetime`): Date of the change in Unix time.
|datetime_localization|
old_reaction (Tuple[:class:`telegram.ReactionType`]): Previous list of reaction types
old_reaction (tuple[:class:`telegram.ReactionType`]): Previous list of reaction types
that were set by the user.
new_reaction (Tuple[:class:`telegram.ReactionType`]): New list of reaction types that
new_reaction (tuple[:class:`telegram.ReactionType`]): New list of reaction types that
were set by the user.
user (:class:`telegram.User`): Optional. The user that changed the reaction, if the user
isn't anonymous.
@@ -169,8 +170,8 @@ class MessageReactionUpdated(TelegramObject):
self.chat: Chat = chat
self.message_id: int = message_id
self.date: datetime = date
self.old_reaction: Tuple[ReactionType, ...] = parse_sequence_arg(old_reaction)
self.new_reaction: Tuple[ReactionType, ...] = parse_sequence_arg(new_reaction)
self.old_reaction: tuple[ReactionType, ...] = parse_sequence_arg(old_reaction)
self.new_reaction: tuple[ReactionType, ...] = parse_sequence_arg(new_reaction)
# Optional
self.user: Optional[User] = user
+58 -7
View File
@@ -18,12 +18,14 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains objects that represent paid media in Telegram."""
from typing import TYPE_CHECKING, Dict, Final, Optional, Sequence, Tuple, Type
from collections.abc import Sequence
from typing import TYPE_CHECKING, Final, Optional
from telegram import constants
from telegram._files.photosize import PhotoSize
from telegram._files.video import Video
from telegram._telegramobject import TelegramObject
from telegram._user import User
from telegram._utils import enum
from telegram._utils.argumentparsing import parse_sequence_arg
from telegram._utils.types import JSONDict
@@ -80,7 +82,7 @@ class PaidMedia(TelegramObject):
care of selecting the correct subclass.
Args:
data (Dict[:obj:`str`, ...]): The JSON data.
data (dict[:obj:`str`, ...]): The JSON data.
bot (:class:`telegram.Bot`, optional): The bot associated with this object.
Returns:
@@ -95,7 +97,7 @@ class PaidMedia(TelegramObject):
if not data and cls is PaidMedia:
return None
_class_mapping: Dict[str, Type[PaidMedia]] = {
_class_mapping: dict[str, type[PaidMedia]] = {
cls.PREVIEW: PaidMediaPreview,
cls.PHOTO: PaidMediaPhoto,
cls.VIDEO: PaidMediaVideo,
@@ -164,7 +166,7 @@ class PaidMediaPhoto(PaidMedia):
Attributes:
type (:obj:`str`): Type of the paid media, always :tg-const:`telegram.PaidMedia.PHOTO`.
photo (Tuple[:class:`telegram.PhotoSize`]): The photo.
photo (tuple[:class:`telegram.PhotoSize`]): The photo.
"""
__slots__ = ("photo",)
@@ -178,7 +180,7 @@ class PaidMediaPhoto(PaidMedia):
super().__init__(type=PaidMedia.PHOTO, api_kwargs=api_kwargs)
with self._unfrozen():
self.photo: Tuple[PhotoSize, ...] = parse_sequence_arg(photo)
self.photo: tuple[PhotoSize, ...] = parse_sequence_arg(photo)
self._id_attrs = (self.type, self.photo)
@@ -258,7 +260,7 @@ class PaidMediaInfo(TelegramObject):
Attributes:
star_count (:obj:`int`): The number of Telegram Stars that must be paid to buy access to
the media.
paid_media (Tuple[:class:`telegram.PaidMedia`]): Information about the paid media.
paid_media (tuple[:class:`telegram.PaidMedia`]): Information about the paid media.
"""
__slots__ = ("paid_media", "star_count")
@@ -272,7 +274,7 @@ class PaidMediaInfo(TelegramObject):
) -> None:
super().__init__(api_kwargs=api_kwargs)
self.star_count: int = star_count
self.paid_media: Tuple[PaidMedia, ...] = parse_sequence_arg(paid_media)
self.paid_media: tuple[PaidMedia, ...] = parse_sequence_arg(paid_media)
self._id_attrs = (self.star_count, self.paid_media)
self._freeze()
@@ -288,3 +290,52 @@ class PaidMediaInfo(TelegramObject):
data["paid_media"] = PaidMedia.de_list(data.get("paid_media"), bot=bot)
return super().de_json(data=data, bot=bot)
class PaidMediaPurchased(TelegramObject):
"""This object contains information about a paid media purchase.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`from_user` and :attr:`paid_media_payload` are equal.
Note:
In Python :keyword:`from` is a reserved word. Use :paramref:`from_user` instead.
.. versionadded:: 21.6
Args:
from_user (:class:`telegram.User`): User who purchased the media.
paid_media_payload (:obj:`str`): Bot-specified paid media payload.
Attributes:
from_user (:class:`telegram.User`): User who purchased the media.
paid_media_payload (:obj:`str`): Bot-specified paid media payload.
"""
__slots__ = ("from_user", "paid_media_payload")
def __init__(
self,
from_user: "User",
paid_media_payload: str,
*,
api_kwargs: Optional[JSONDict] = None,
) -> None:
super().__init__(api_kwargs=api_kwargs)
self.from_user: User = from_user
self.paid_media_payload: str = paid_media_payload
self._id_attrs = (self.from_user, self.paid_media_payload)
self._freeze()
@classmethod
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["PaidMediaPurchased"]:
data = cls._parse_data(data)
if not data:
return None
data["from_user"] = User.de_json(data=data.pop("from"), bot=bot)
return super().de_json(data=data, bot=bot)
+8 -7
View File
@@ -19,7 +19,8 @@
# pylint: disable=missing-module-docstring, redefined-builtin
import json
from base64 import b64decode
from typing import TYPE_CHECKING, Optional, Sequence, Tuple, no_type_check
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional, no_type_check
try:
from cryptography.hazmat.backends import default_backend
@@ -390,11 +391,11 @@ class SecureValue(TelegramObject):
selfie (:class:`telegram.FileCredentials`, optional): Credentials for encrypted selfie
of the user with a document. Can be available for "passport", "driver_license",
"identity_card" and "internal_passport".
translation (List[:class:`telegram.FileCredentials`], optional): Credentials for an
translation (list[:class:`telegram.FileCredentials`], optional): Credentials for an
encrypted translation of the document. Available for "passport", "driver_license",
"identity_card", "internal_passport", "utility_bill", "bank_statement",
"rental_agreement", "passport_registration" and "temporary_registration".
files (List[:class:`telegram.FileCredentials`], optional): Credentials for encrypted
files (list[:class:`telegram.FileCredentials`], optional): Credentials for encrypted
files. Available for "utility_bill", "bank_statement", "rental_agreement",
"passport_registration" and "temporary_registration" types.
@@ -410,7 +411,7 @@ class SecureValue(TelegramObject):
selfie (:class:`telegram.FileCredentials`): Optional. Credentials for encrypted selfie
of the user with a document. Can be available for "passport", "driver_license",
"identity_card" and "internal_passport".
translation (Tuple[:class:`telegram.FileCredentials`]): Optional. Credentials for an
translation (tuple[:class:`telegram.FileCredentials`]): Optional. Credentials for an
encrypted translation of the document. Available for "passport", "driver_license",
"identity_card", "internal_passport", "utility_bill", "bank_statement",
"rental_agreement", "passport_registration" and "temporary_registration".
@@ -418,7 +419,7 @@ class SecureValue(TelegramObject):
.. versionchanged:: 20.0
|tupleclassattrs|
files (Tuple[:class:`telegram.FileCredentials`]): Optional. Credentials for encrypted
files (tuple[:class:`telegram.FileCredentials`]): Optional. Credentials for encrypted
files. Available for "utility_bill", "bank_statement", "rental_agreement",
"passport_registration" and "temporary_registration" types.
@@ -447,8 +448,8 @@ class SecureValue(TelegramObject):
self.front_side: Optional[FileCredentials] = front_side
self.reverse_side: Optional[FileCredentials] = reverse_side
self.selfie: Optional[FileCredentials] = selfie
self.files: Tuple[FileCredentials, ...] = parse_sequence_arg(files)
self.translation: Tuple[FileCredentials, ...] = parse_sequence_arg(translation)
self.files: tuple[FileCredentials, ...] = parse_sequence_arg(files)
self.translation: tuple[FileCredentials, ...] = parse_sequence_arg(translation)
self._freeze()
@@ -18,7 +18,8 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram EncryptedPassportElement."""
from base64 import b64decode
from typing import TYPE_CHECKING, Optional, Sequence, Tuple, Union
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional, Union
from telegram._passport.credentials import decrypt_json
from telegram._passport.data import IdDocumentData, PersonalDetails, ResidentialAddress
@@ -100,7 +101,7 @@ class EncryptedPassportElement(TelegramObject):
"phone_number" type.
email (:obj:`str`): Optional. User's verified email address; available only for "email"
type.
files (Tuple[:class:`telegram.PassportFile`]): Optional. Array of encrypted/decrypted
files (tuple[:class:`telegram.PassportFile`]): Optional. Array of encrypted/decrypted
files with documents provided by the user; available only for "utility_bill",
"bank_statement", "rental_agreement", "passport_registration" and
"temporary_registration" types.
@@ -119,7 +120,7 @@ class EncryptedPassportElement(TelegramObject):
selfie (:class:`telegram.PassportFile`): Optional. Encrypted/decrypted file with the
selfie of the user holding a document, provided by the user; available if requested for
"passport", "driver_license", "identity_card" and "internal_passport".
translation (Tuple[:class:`telegram.PassportFile`]): Optional. Array of
translation (tuple[:class:`telegram.PassportFile`]): Optional. Array of
encrypted/decrypted files with translated versions of documents provided by the user;
available if requested for "passport", "driver_license", "identity_card",
"internal_passport", "utility_bill", "bank_statement", "rental_agreement",
@@ -172,11 +173,11 @@ class EncryptedPassportElement(TelegramObject):
self.data: Optional[Union[PersonalDetails, IdDocumentData, ResidentialAddress]] = data
self.phone_number: Optional[str] = phone_number
self.email: Optional[str] = email
self.files: Tuple[PassportFile, ...] = parse_sequence_arg(files)
self.files: tuple[PassportFile, ...] = parse_sequence_arg(files)
self.front_side: Optional[PassportFile] = front_side
self.reverse_side: Optional[PassportFile] = reverse_side
self.selfie: Optional[PassportFile] = selfie
self.translation: Tuple[PassportFile, ...] = parse_sequence_arg(translation)
self.translation: tuple[PassportFile, ...] = parse_sequence_arg(translation)
self.hash: str = hash
self._id_attrs = (
@@ -218,7 +219,7 @@ class EncryptedPassportElement(TelegramObject):
passport credentials.
Args:
data (Dict[:obj:`str`, ...]): The JSON data.
data (dict[:obj:`str`, ...]): The JSON data.
bot (:class:`telegram.Bot` | :obj:`None`): The bot associated with these object.
May be :obj:`None`, in which case shortcut methods will not be available.
+7 -6
View File
@@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""Contains information about Telegram Passport data shared with the bot by the user."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._passport.credentials import EncryptedCredentials
from telegram._passport.encryptedpassportelement import EncryptedPassportElement
@@ -49,7 +50,7 @@ class PassportData(TelegramObject):
credentials (:class:`telegram.EncryptedCredentials`)): Encrypted credentials.
Attributes:
data (Tuple[:class:`telegram.EncryptedPassportElement`]): Array with encrypted
data (tuple[:class:`telegram.EncryptedPassportElement`]): Array with encrypted
information about documents and other Telegram Passport elements that was shared with
the bot.
@@ -72,10 +73,10 @@ class PassportData(TelegramObject):
):
super().__init__(api_kwargs=api_kwargs)
self.data: Tuple[EncryptedPassportElement, ...] = parse_sequence_arg(data)
self.data: tuple[EncryptedPassportElement, ...] = parse_sequence_arg(data)
self.credentials: EncryptedCredentials = credentials
self._decrypted_data: Optional[Tuple[EncryptedPassportElement]] = None
self._decrypted_data: Optional[tuple[EncryptedPassportElement]] = None
self._id_attrs = tuple([x.type for x in data] + [credentials.hash])
self._freeze()
@@ -96,9 +97,9 @@ class PassportData(TelegramObject):
return super().de_json(data=data, bot=bot)
@property
def decrypted_data(self) -> Tuple[EncryptedPassportElement, ...]:
def decrypted_data(self) -> tuple[EncryptedPassportElement, ...]:
"""
Tuple[:class:`telegram.EncryptedPassportElement`]: Lazily decrypt and return information
tuple[:class:`telegram.EncryptedPassportElement`]: Lazily decrypt and return information
about documents and other Telegram Passport elements which were shared with the bot.
.. versionchanged:: 20.0
+9 -9
View File
@@ -19,7 +19,7 @@
# pylint: disable=redefined-builtin
"""This module contains the classes that represent Telegram PassportElementError."""
from typing import List, Optional
from typing import Optional
from telegram._telegramobject import TelegramObject
from telegram._utils.types import JSONDict
@@ -168,7 +168,7 @@ class PassportElementErrorFiles(PassportElementError):
type (:obj:`str`): The section of the user's Telegram Passport which has the issue, one of
``"utility_bill"``, ``"bank_statement"``, ``"rental_agreement"``,
``"passport_registration"``, ``"temporary_registration"``.
file_hashes (List[:obj:`str`]): List of base64-encoded file hashes.
file_hashes (list[:obj:`str`]): List of base64-encoded file hashes.
message (:obj:`str`): Error message.
Attributes:
@@ -184,7 +184,7 @@ class PassportElementErrorFiles(PassportElementError):
def __init__(
self,
type: str,
file_hashes: List[str],
file_hashes: list[str],
message: str,
*,
api_kwargs: Optional[JSONDict] = None,
@@ -192,7 +192,7 @@ class PassportElementErrorFiles(PassportElementError):
# Required
super().__init__("files", type, message, api_kwargs=api_kwargs)
with self._unfrozen():
self._file_hashes: List[str] = file_hashes
self._file_hashes: list[str] = file_hashes
self._id_attrs = (self.source, self.type, self.message, *tuple(file_hashes))
@@ -203,7 +203,7 @@ class PassportElementErrorFiles(PassportElementError):
return data
@property
def file_hashes(self) -> List[str]:
def file_hashes(self) -> list[str]:
"""List of base64-encoded file hashes.
.. deprecated:: 20.6
@@ -386,7 +386,7 @@ class PassportElementErrorTranslationFiles(PassportElementError):
one of ``"passport"``, ``"driver_license"``, ``"identity_card"``,
``"internal_passport"``, ``"utility_bill"``, ``"bank_statement"``,
``"rental_agreement"``, ``"passport_registration"``, ``"temporary_registration"``.
file_hashes (List[:obj:`str`]): List of base64-encoded file hashes.
file_hashes (list[:obj:`str`]): List of base64-encoded file hashes.
message (:obj:`str`): Error message.
Attributes:
@@ -403,7 +403,7 @@ class PassportElementErrorTranslationFiles(PassportElementError):
def __init__(
self,
type: str,
file_hashes: List[str],
file_hashes: list[str],
message: str,
*,
api_kwargs: Optional[JSONDict] = None,
@@ -411,7 +411,7 @@ class PassportElementErrorTranslationFiles(PassportElementError):
# Required
super().__init__("translation_files", type, message, api_kwargs=api_kwargs)
with self._unfrozen():
self._file_hashes: List[str] = file_hashes
self._file_hashes: list[str] = file_hashes
self._id_attrs = (self.source, self.type, self.message, *tuple(file_hashes))
@@ -422,7 +422,7 @@ class PassportElementErrorTranslationFiles(PassportElementError):
return data
@property
def file_hashes(self) -> List[str]:
def file_hashes(self) -> list[str]:
"""List of base64-encoded file hashes.
.. deprecated:: 20.6
+7 -7
View File
@@ -18,7 +18,7 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Encrypted PassportFile."""
from typing import TYPE_CHECKING, List, Optional, Tuple
from typing import TYPE_CHECKING, Optional
from telegram._telegramobject import TelegramObject
from telegram._utils.defaultvalue import DEFAULT_NONE
@@ -124,7 +124,7 @@ class PassportFile(TelegramObject):
passport credentials.
Args:
data (Dict[:obj:`str`, ...]): The JSON data.
data (dict[:obj:`str`, ...]): The JSON data.
bot (:class:`telegram.Bot` | :obj:`None`): The bot associated with these object.
May be :obj:`None`, in which case shortcut methods will not be available.
@@ -151,10 +151,10 @@ class PassportFile(TelegramObject):
@classmethod
def de_list_decrypted(
cls,
data: Optional[List[JSONDict]],
data: Optional[list[JSONDict]],
bot: Optional["Bot"],
credentials: List["FileCredentials"],
) -> Tuple[Optional["PassportFile"], ...]:
credentials: list["FileCredentials"],
) -> tuple[Optional["PassportFile"], ...]:
"""Variant of :meth:`telegram.TelegramObject.de_list` that also takes into account
passport credentials.
@@ -164,7 +164,7 @@ class PassportFile(TelegramObject):
* Filters out any :obj:`None` values
Args:
data (List[Dict[:obj:`str`, ...]]): The JSON data.
data (list[dict[:obj:`str`, ...]]): The JSON data.
bot (:class:`telegram.Bot` | :obj:`None`): The bot associated with these object.
May be :obj:`None`, in which case shortcut methods will not be available.
@@ -176,7 +176,7 @@ class PassportFile(TelegramObject):
credentials (:class:`telegram.FileCredentials`): The credentials
Returns:
Tuple[:class:`telegram.PassportFile`]:
tuple[:class:`telegram.PassportFile`]:
"""
if not data:
+4 -3
View File
@@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram ShippingOption."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._telegramobject import TelegramObject
from telegram._utils.argumentparsing import parse_sequence_arg
@@ -47,7 +48,7 @@ class ShippingOption(TelegramObject):
Attributes:
id (:obj:`str`): Shipping option identifier.
title (:obj:`str`): Option title.
prices (Tuple[:class:`telegram.LabeledPrice`]): List of price portions.
prices (tuple[:class:`telegram.LabeledPrice`]): List of price portions.
.. versionchanged:: 20.0
|tupleclassattrs|
@@ -68,7 +69,7 @@ class ShippingOption(TelegramObject):
self.id: str = id
self.title: str = title
self.prices: Tuple[LabeledPrice, ...] = parse_sequence_arg(prices)
self.prices: tuple[LabeledPrice, ...] = parse_sequence_arg(prices)
self._id_attrs = (self.id,)
+2 -1
View File
@@ -18,7 +18,8 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram ShippingQuery."""
from typing import TYPE_CHECKING, Optional, Sequence
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._payment.shippingaddress import ShippingAddress
from telegram._telegramobject import TelegramObject
+55 -17
View File
@@ -19,8 +19,9 @@
# pylint: disable=redefined-builtin
"""This module contains the classes for Telegram Stars transactions."""
from collections.abc import Sequence
from datetime import datetime
from typing import TYPE_CHECKING, Dict, Final, Optional, Sequence, Tuple, Type
from typing import TYPE_CHECKING, Final, Optional
from telegram import constants
from telegram._paidmedia import PaidMedia
@@ -79,7 +80,7 @@ class RevenueWithdrawalState(TelegramObject):
care of selecting the correct subclass.
Args:
data (Dict[:obj:`str`, ...]): The JSON data.
data (dict[:obj:`str`, ...]): The JSON data.
bot (:class:`telegram.Bot`): The bot associated with this object.
Returns:
@@ -91,7 +92,7 @@ class RevenueWithdrawalState(TelegramObject):
if not data:
return None
_class_mapping: Dict[str, Type[RevenueWithdrawalState]] = {
_class_mapping: dict[str, type[RevenueWithdrawalState]] = {
cls.PENDING: RevenueWithdrawalStatePending,
cls.SUCCEEDED: RevenueWithdrawalStateSucceeded,
cls.FAILED: RevenueWithdrawalStateFailed,
@@ -217,12 +218,14 @@ class TransactionPartner(TelegramObject):
FRAGMENT: Final[str] = constants.TransactionPartnerType.FRAGMENT
""":const:`telegram.constants.TransactionPartnerType.FRAGMENT`"""
USER: Final[str] = constants.TransactionPartnerType.USER
""":const:`telegram.constants.TransactionPartnerType.USER`"""
OTHER: Final[str] = constants.TransactionPartnerType.OTHER
""":const:`telegram.constants.TransactionPartnerType.OTHER`"""
TELEGRAM_ADS: Final[str] = constants.TransactionPartnerType.TELEGRAM_ADS
""":const:`telegram.constants.TransactionPartnerType.TELEGRAM_ADS`"""
TELEGRAM_API: Final[str] = constants.TransactionPartnerType.TELEGRAM_API
""":const:`telegram.constants.TransactionPartnerType.TELEGRAM_API`"""
USER: Final[str] = constants.TransactionPartnerType.USER
""":const:`telegram.constants.TransactionPartnerType.USER`"""
def __init__(self, type: str, *, api_kwargs: Optional[JSONDict] = None) -> None:
super().__init__(api_kwargs=api_kwargs)
@@ -239,7 +242,7 @@ class TransactionPartner(TelegramObject):
care of selecting the correct subclass.
Args:
data (Dict[:obj:`str`, ...]): The JSON data.
data (dict[:obj:`str`, ...]): The JSON data.
bot (:class:`telegram.Bot`): The bot associated with this object.
Returns:
@@ -254,11 +257,12 @@ class TransactionPartner(TelegramObject):
if not data and cls is TransactionPartner:
return None
_class_mapping: Dict[str, Type[TransactionPartner]] = {
_class_mapping: dict[str, type[TransactionPartner]] = {
cls.FRAGMENT: TransactionPartnerFragment,
cls.USER: TransactionPartnerUser,
cls.OTHER: TransactionPartnerOther,
cls.TELEGRAM_ADS: TransactionPartnerTelegramAds,
cls.TELEGRAM_API: TransactionPartnerTelegramApi,
cls.OTHER: TransactionPartnerOther,
}
if cls is TransactionPartner and data.get("type") in _class_mapping:
@@ -328,29 +332,33 @@ class TransactionPartnerUser(TransactionPartner):
media bought by the user.
.. versionadded:: 21.5
paid_media_payload (:obj:`str`, optional): Optional. Bot-specified paid media payload.
.. versionadded:: 21.6
Attributes:
type (:obj:`str`): The type of the transaction partner,
always :tg-const:`telegram.TransactionPartner.USER`.
user (:class:`telegram.User`): Information about the user.
invoice_payload (:obj:`str`): Optional. Bot-specified invoice payload.
paid_media (Tuple[:class:`telegram.PaidMedia`]): Optional. Information about the paid
paid_media (tuple[:class:`telegram.PaidMedia`]): Optional. Information about the paid
media bought by the user.
.. versionadded:: 21.5
paid_media_payload (:obj:`str`): Optional. Optional. Bot-specified paid media payload.
.. versionadded:: 21.6
"""
__slots__ = (
"invoice_payload",
"paid_media",
"user",
)
__slots__ = ("invoice_payload", "paid_media", "paid_media_payload", "user")
def __init__(
self,
user: "User",
invoice_payload: Optional[str] = None,
paid_media: Optional[Sequence[PaidMedia]] = None,
paid_media_payload: Optional[str] = None,
*,
api_kwargs: Optional[JSONDict] = None,
) -> None:
@@ -359,7 +367,8 @@ class TransactionPartnerUser(TransactionPartner):
with self._unfrozen():
self.user: User = user
self.invoice_payload: Optional[str] = invoice_payload
self.paid_media: Optional[Tuple[PaidMedia, ...]] = parse_sequence_arg(paid_media)
self.paid_media: Optional[tuple[PaidMedia, ...]] = parse_sequence_arg(paid_media)
self.paid_media_payload: Optional[str] = paid_media_payload
self._id_attrs = (
self.type,
self.user,
@@ -415,6 +424,35 @@ class TransactionPartnerTelegramAds(TransactionPartner):
self._freeze()
class TransactionPartnerTelegramApi(TransactionPartner):
"""Describes a transaction with payment for
`paid broadcasting <https://core.telegram.org/bots/api#paid-broadcasts>`_.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`request_count` is equal.
.. versionadded:: 21.7
Args:
request_count (:obj:`int`): The number of successful requests that exceeded regular limits
and were therefore billed.
Attributes:
type (:obj:`str`): The type of the transaction partner,
always :tg-const:`telegram.TransactionPartner.TELEGRAM_API`.
request_count (:obj:`int`): The number of successful requests that exceeded regular limits
and were therefore billed.
"""
__slots__ = ("request_count",)
def __init__(self, request_count: int, *, api_kwargs: Optional[JSONDict] = None) -> None:
super().__init__(type=TransactionPartner.TELEGRAM_API, api_kwargs=api_kwargs)
with self._unfrozen():
self.request_count: int = request_count
self._id_attrs = (self.request_count,)
class StarTransaction(TelegramObject):
"""Describes a Telegram Star transaction.
@@ -511,7 +549,7 @@ class StarTransactions(TelegramObject):
transactions (Sequence[:class:`telegram.StarTransaction`]): The list of transactions.
Attributes:
transactions (Tuple[:class:`telegram.StarTransaction`]): The list of transactions.
transactions (tuple[:class:`telegram.StarTransaction`]): The list of transactions.
"""
__slots__ = ("transactions",)
@@ -520,7 +558,7 @@ class StarTransactions(TelegramObject):
self, transactions: Sequence[StarTransaction], *, api_kwargs: Optional[JSONDict] = None
):
super().__init__(api_kwargs=api_kwargs)
self.transactions: Tuple[StarTransaction, ...] = parse_sequence_arg(transactions)
self.transactions: tuple[StarTransaction, ...] = parse_sequence_arg(transactions)
self._id_attrs = (self.transactions,)
self._freeze()
+24 -23
View File
@@ -18,7 +18,8 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram Poll."""
import datetime
from typing import TYPE_CHECKING, Dict, Final, List, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Final, Optional
from telegram import constants
from telegram._chat import Chat
@@ -83,7 +84,7 @@ class InputPollOption(TelegramObject):
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.text_entities: tuple[MessageEntity, ...] = parse_sequence_arg(text_entities)
self._id_attrs = (self.text,)
@@ -127,7 +128,7 @@ 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 (Tuple[:class:`telegram.MessageEntity`]): Special entities
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.
@@ -149,7 +150,7 @@ class PollOption(TelegramObject):
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.text_entities: tuple[MessageEntity, ...] = parse_sequence_arg(text_entities)
self._id_attrs = (self.text, self.voter_count)
@@ -189,7 +190,7 @@ class PollOption(TelegramObject):
"""
return parse_message_entity(self.text, entity)
def parse_entities(self, types: Optional[List[str]] = None) -> Dict[MessageEntity, str]:
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
@@ -203,12 +204,12 @@ class PollOption(TelegramObject):
.. versionadded:: 21.2
Args:
types (List[:obj:`str`], optional): List of ``MessageEntity`` types as strings. If the
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
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)
@@ -260,7 +261,7 @@ class PollAnswer(TelegramObject):
Attributes:
poll_id (:obj:`str`): Unique poll identifier.
option_ids (Tuple[:obj:`int`]): Identifiers of answer options, chosen by the user. May
option_ids (tuple[:obj:`int`]): Identifiers of answer options, chosen by the user. May
be empty if the user retracted their vote.
.. versionchanged:: 20.0
@@ -292,7 +293,7 @@ class PollAnswer(TelegramObject):
super().__init__(api_kwargs=api_kwargs)
self.poll_id: str = poll_id
self.voter_chat: Optional[Chat] = voter_chat
self.option_ids: Tuple[int, ...] = parse_sequence_arg(option_ids)
self.option_ids: tuple[int, ...] = parse_sequence_arg(option_ids)
self.user: Optional[User] = user
self._id_attrs = (
@@ -374,7 +375,7 @@ class Poll(TelegramObject):
id (:obj:`str`): Unique poll identifier.
question (:obj:`str`): Poll question, :tg-const:`telegram.Poll.MIN_QUESTION_LENGTH`-
:tg-const:`telegram.Poll.MAX_QUESTION_LENGTH` characters.
options (Tuple[:class:`~telegram.PollOption`]): List of poll options.
options (tuple[:class:`~telegram.PollOption`]): List of poll options.
.. versionchanged:: 20.0
|tupleclassattrs|
@@ -389,7 +390,7 @@ class Poll(TelegramObject):
explanation (:obj:`str`): Optional. Text that is shown when a user chooses an incorrect
answer or taps on the lamp icon in a quiz-style poll,
0-:tg-const:`telegram.Poll.MAX_EXPLANATION_LENGTH` characters.
explanation_entities (Tuple[:class:`telegram.MessageEntity`]): Special entities
explanation_entities (tuple[:class:`telegram.MessageEntity`]): Special entities
like usernames, URLs, bot commands, etc. that appear in the :attr:`explanation`.
This list is empty if the message does not contain explanation entities.
@@ -405,7 +406,7 @@ class Poll(TelegramObject):
.. versionchanged:: 20.3
|datetime_localization|
question_entities (Tuple[:class:`telegram.MessageEntity`]): Special entities
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.
@@ -453,7 +454,7 @@ class Poll(TelegramObject):
super().__init__(api_kwargs=api_kwargs)
self.id: str = id
self.question: str = question
self.options: Tuple[PollOption, ...] = parse_sequence_arg(options)
self.options: tuple[PollOption, ...] = parse_sequence_arg(options)
self.total_voter_count: int = total_voter_count
self.is_closed: bool = is_closed
self.is_anonymous: bool = is_anonymous
@@ -461,12 +462,12 @@ class Poll(TelegramObject):
self.allows_multiple_answers: bool = allows_multiple_answers
self.correct_option_id: Optional[int] = correct_option_id
self.explanation: Optional[str] = explanation
self.explanation_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(
self.explanation_entities: tuple[MessageEntity, ...] = parse_sequence_arg(
explanation_entities
)
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.question_entities: tuple[MessageEntity, ...] = parse_sequence_arg(question_entities)
self._id_attrs = (self.id,)
@@ -516,8 +517,8 @@ class Poll(TelegramObject):
return parse_message_entity(self.explanation, entity)
def parse_explanation_entities(
self, types: Optional[List[str]] = None
) -> Dict[MessageEntity, str]:
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 explanation filtered by their ``type`` attribute as
@@ -529,12 +530,12 @@ class Poll(TelegramObject):
UTF-16 codepoints. See :attr:`parse_explanation_entity` for more info.
Args:
types (List[:obj:`str`], optional): List of ``MessageEntity`` types as strings. If the
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
dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
the text that belongs to them, calculated based on UTF-16 codepoints.
Raises:
@@ -567,8 +568,8 @@ class Poll(TelegramObject):
return parse_message_entity(self.question, entity)
def parse_question_entities(
self, types: Optional[List[str]] = None
) -> Dict[MessageEntity, str]:
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
@@ -582,12 +583,12 @@ class Poll(TelegramObject):
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
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
dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
the text that belongs to them, calculated based on UTF-16 codepoints.
"""
+2 -2
View File
@@ -18,7 +18,7 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains objects that represents a Telegram ReactionType."""
from typing import TYPE_CHECKING, Dict, Final, Literal, Optional, Type, Union
from typing import TYPE_CHECKING, Final, Literal, Optional, Union
from telegram import constants
from telegram._telegramobject import TelegramObject
@@ -89,7 +89,7 @@ class ReactionType(TelegramObject):
if not data and cls is ReactionType:
return None
_class_mapping: Dict[str, Type[ReactionType]] = {
_class_mapping: dict[str, type[ReactionType]] = {
cls.EMOJI: ReactionTypeEmoji,
cls.CUSTOM_EMOJI: ReactionTypeCustomEmoji,
cls.PAID: ReactionTypePaid,
+8 -7
View File
@@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This modules contains objects that represents Telegram Replies"""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple, Union
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional, Union
from telegram._chat import Chat
from telegram._dice import Dice
@@ -124,7 +125,7 @@ class ExternalReplyInfo(TelegramObject):
file.
document (:class:`telegram.Document`): Optional. Message is a general file, information
about the file.
photo (Tuple[:class:`telegram.PhotoSize`]): Optional. Message is a photo, available sizes
photo (tuple[:class:`telegram.PhotoSize`]): Optional. Message is a photo, available sizes
of the photo.
sticker (:class:`telegram.Sticker`): Optional. Message is a sticker, information about the
sticker.
@@ -224,7 +225,7 @@ class ExternalReplyInfo(TelegramObject):
self.animation: Optional[Animation] = animation
self.audio: Optional[Audio] = audio
self.document: Optional[Document] = document
self.photo: Optional[Tuple[PhotoSize, ...]] = parse_sequence_arg(photo)
self.photo: Optional[tuple[PhotoSize, ...]] = parse_sequence_arg(photo)
self.sticker: Optional[Sticker] = sticker
self.story: Optional[Story] = story
self.video: Optional[Video] = video
@@ -311,7 +312,7 @@ class TextQuote(TelegramObject):
message.
position (:obj:`int`): Approximate quote position in the original message in UTF-16 code
units as specified by the sender.
entities (Tuple[:class:`telegram.MessageEntity`]): Optional. Special entities that appear
entities (tuple[:class:`telegram.MessageEntity`]): Optional. Special entities that appear
in the quote. Currently, only bold, italic, underline, strikethrough, spoiler, and
custom_emoji entities are kept in quotes.
is_manual (:obj:`bool`): Optional. :obj:`True`, if the quote was chosen manually by the
@@ -338,7 +339,7 @@ class TextQuote(TelegramObject):
self.text: str = text
self.position: int = position
self.entities: Optional[Tuple[MessageEntity, ...]] = parse_sequence_arg(entities)
self.entities: Optional[tuple[MessageEntity, ...]] = parse_sequence_arg(entities)
self.is_manual: Optional[bool] = is_manual
self._id_attrs = (
@@ -411,7 +412,7 @@ class ReplyParameters(TelegramObject):
quote_parse_mode (:obj:`str`): Optional. Mode for parsing entities in the quote. See
:wiki:`formatting options <Code-snippets#message-formatting-bold-italic-code->` for
more details.
quote_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. A JSON-serialized list
quote_entities (tuple[:class:`telegram.MessageEntity`]): Optional. A JSON-serialized list
of special entities that appear in the quote. It can be specified instead of
:paramref:`quote_parse_mode`.
quote_position (:obj:`int`): Optional. Position of the quote in the original message in
@@ -447,7 +448,7 @@ class ReplyParameters(TelegramObject):
self.allow_sending_without_reply: ODVInput[bool] = allow_sending_without_reply
self.quote: Optional[str] = quote
self.quote_parse_mode: ODVInput[str] = quote_parse_mode
self.quote_entities: Optional[Tuple[MessageEntity, ...]] = parse_sequence_arg(
self.quote_entities: Optional[tuple[MessageEntity, ...]] = parse_sequence_arg(
quote_entities
)
self.quote_position: Optional[int] = quote_position
+4 -3
View File
@@ -18,7 +18,8 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram ReplyKeyboardMarkup."""
from typing import Final, Optional, Sequence, Tuple, Union
from collections.abc import Sequence
from typing import Final, Optional, Union
from telegram import constants
from telegram._keyboardbutton import KeyboardButton
@@ -85,7 +86,7 @@ class ReplyKeyboardMarkup(TelegramObject):
.. versionadded:: 20.0
Attributes:
keyboard (Tuple[Tuple[:class:`telegram.KeyboardButton`]]): Array of button rows,
keyboard (tuple[tuple[:class:`telegram.KeyboardButton`]]): Array of button rows,
each represented by an Array of :class:`telegram.KeyboardButton` objects.
resize_keyboard (:obj:`bool`): Optional. Requests clients to resize the keyboard vertically
for optimal fit (e.g., make the keyboard smaller if there are just two rows of
@@ -148,7 +149,7 @@ class ReplyKeyboardMarkup(TelegramObject):
)
# Required
self.keyboard: Tuple[Tuple[KeyboardButton, ...], ...] = tuple(
self.keyboard: tuple[tuple[KeyboardButton, ...], ...] = tuple(
tuple(KeyboardButton(button) if isinstance(button, str) else button for button in row)
for row in keyboard
)
+8 -7
View File
@@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains two objects used for request chats/users service messages."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._files.photosize import PhotoSize
from telegram._telegramobject import TelegramObject
@@ -59,7 +60,7 @@ class UsersShared(TelegramObject):
Attributes:
request_id (:obj:`int`): Identifier of the request.
users (Tuple[:class:`telegram.SharedUser`]): Information about users shared with the
users (tuple[:class:`telegram.SharedUser`]): Information about users shared with the
bot.
.. versionadded:: 21.1
@@ -76,7 +77,7 @@ class UsersShared(TelegramObject):
):
super().__init__(api_kwargs=api_kwargs)
self.request_id: int = request_id
self.users: Tuple[SharedUser, ...] = parse_sequence_arg(users)
self.users: tuple[SharedUser, ...] = parse_sequence_arg(users)
self._id_attrs = (self.request_id, self.users)
@@ -144,7 +145,7 @@ class ChatShared(TelegramObject):
the bot and available.
.. versionadded:: 21.1
photo (Tuple[:class:`telegram.PhotoSize`]): Optional. Available sizes of the chat photo,
photo (tuple[:class:`telegram.PhotoSize`]): Optional. Available sizes of the chat photo,
if the photo was requested by the bot
.. versionadded:: 21.1
@@ -167,7 +168,7 @@ class ChatShared(TelegramObject):
self.chat_id: int = chat_id
self.title: Optional[str] = title
self.username: Optional[str] = username
self.photo: Optional[Tuple[PhotoSize, ...]] = parse_sequence_arg(photo)
self.photo: Optional[tuple[PhotoSize, ...]] = parse_sequence_arg(photo)
self._id_attrs = (self.request_id, self.chat_id)
@@ -226,7 +227,7 @@ class SharedUser(TelegramObject):
bot.
username (:obj:`str`): Optional. Username of the user, if the username was requested by the
bot.
photo (Tuple[:class:`telegram.PhotoSize`]): Available sizes of the chat photo, if
photo (tuple[:class:`telegram.PhotoSize`]): Available sizes of the chat photo, if
the photo was requested by the bot. This list is empty if the photo was not requsted.
"""
@@ -247,7 +248,7 @@ class SharedUser(TelegramObject):
self.first_name: Optional[str] = first_name
self.last_name: Optional[str] = last_name
self.username: Optional[str] = username
self.photo: Optional[Tuple[PhotoSize, ...]] = parse_sequence_arg(photo)
self.photo: Optional[tuple[PhotoSize, ...]] = parse_sequence_arg(photo)
self._id_attrs = (self.user_id,)
+20 -35
View File
@@ -21,27 +21,12 @@ import contextlib
import datetime
import inspect
import json
from collections.abc import Sized
from collections.abc import Iterator, Mapping, Sized
from contextlib import contextmanager
from copy import deepcopy
from itertools import chain
from types import MappingProxyType
from typing import (
TYPE_CHECKING,
Any,
ClassVar,
Dict,
Iterator,
List,
Mapping,
Optional,
Set,
Tuple,
Type,
TypeVar,
Union,
cast,
)
from typing import TYPE_CHECKING, Any, ClassVar, Optional, TypeVar, Union, cast
from telegram._utils.datetime import to_timestamp
from telegram._utils.defaultvalue import DefaultValue
@@ -80,7 +65,7 @@ class TelegramObject:
:obj:`list` are now of type :obj:`tuple`.
Arguments:
api_kwargs (Dict[:obj:`str`, any], optional): |toapikwargsarg|
api_kwargs (dict[:obj:`str`, any], optional): |toapikwargsarg|
.. versionadded:: 20.0
@@ -95,11 +80,11 @@ class TelegramObject:
# Used to cache the names of the parameters of the __init__ method of the class
# Must be a private attribute to avoid name clashes between subclasses
__INIT_PARAMS: ClassVar[Set[str]] = set()
__INIT_PARAMS: ClassVar[set[str]] = set()
# Used to check if __INIT_PARAMS has been set for the current class. Unfortunately, we can't
# just check if `__INIT_PARAMS is None`, since subclasses use the parent class' __INIT_PARAMS
# unless it's overridden
__INIT_PARAMS_CHECK: Optional[Type["TelegramObject"]] = None
__INIT_PARAMS_CHECK: Optional[type["TelegramObject"]] = None
def __init__(self, *, api_kwargs: Optional[JSONDict] = None) -> None:
# Setting _frozen to `False` here means that classes without arguments still need to
@@ -107,7 +92,7 @@ class TelegramObject:
# `with self._unfrozen()` in the `__init__` of subclasses and we have fewer empty
# classes than classes with arguments.
self._frozen: bool = False
self._id_attrs: Tuple[object, ...] = ()
self._id_attrs: tuple[object, ...] = ()
self._bot: Optional[Bot] = None
# We don't do anything with api_kwargs here - see docstring of _apply_api_kwargs
self.api_kwargs: Mapping[str, Any] = MappingProxyType(api_kwargs or {})
@@ -263,7 +248,7 @@ class TelegramObject:
f"`{item}`."
) from exc
def __getstate__(self) -> Dict[str, Union[str, object]]:
def __getstate__(self) -> dict[str, Union[str, object]]:
"""
Overrides :meth:`object.__getstate__` to customize the pickling process of objects of this
type.
@@ -271,7 +256,7 @@ class TelegramObject:
:meth:`set_bot` (if any), as it can't be pickled.
Returns:
state (Dict[:obj:`str`, :obj:`object`]): The state of the object.
state (dict[:obj:`str`, :obj:`object`]): The state of the object.
"""
out = self._get_attrs(
include_private=True, recursive=False, remove_bot=True, convert_default_vault=False
@@ -281,7 +266,7 @@ class TelegramObject:
out["api_kwargs"] = dict(self.api_kwargs)
return out
def __setstate__(self, state: Dict[str, object]) -> None:
def __setstate__(self, state: dict[str, object]) -> None:
"""
Overrides :meth:`object.__setstate__` to customize the unpickling process of objects of
this type. Modifies the object in-place.
@@ -305,7 +290,7 @@ class TelegramObject:
self._bot = None
# get api_kwargs first because we may need to add entries to it (see try-except below)
api_kwargs = cast(Dict[str, object], state.pop("api_kwargs", {}))
api_kwargs = cast(dict[str, object], state.pop("api_kwargs", {}))
# get _frozen before the loop to avoid setting it to True in the loop
frozen = state.pop("_frozen", False)
@@ -341,7 +326,7 @@ class TelegramObject:
if frozen:
self._freeze()
def __deepcopy__(self: Tele_co, memodict: Dict[int, object]) -> Tele_co:
def __deepcopy__(self: Tele_co, memodict: dict[int, object]) -> Tele_co:
"""
Customizes how :func:`copy.deepcopy` processes objects of this type.
The only difference to the default implementation is that the :class:`telegram.Bot`
@@ -401,7 +386,7 @@ class TelegramObject:
@classmethod
def _de_json(
cls: Type[Tele_co],
cls: type[Tele_co],
data: Optional[JSONDict],
bot: Optional["Bot"],
api_kwargs: Optional[JSONDict] = None,
@@ -433,12 +418,12 @@ class TelegramObject:
@classmethod
def de_json(
cls: Type[Tele_co], data: Optional[JSONDict], bot: Optional["Bot"] = None
cls: type[Tele_co], data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional[Tele_co]:
"""Converts JSON data to a Telegram object.
Args:
data (Dict[:obj:`str`, ...]): The JSON data.
data (dict[:obj:`str`, ...]): The JSON data.
bot (:class:`telegram.Bot`, optional): The bot associated with this object. Defaults to
:obj:`None`, in which case shortcut methods will not be available.
@@ -453,8 +438,8 @@ class TelegramObject:
@classmethod
def de_list(
cls: Type[Tele_co], data: Optional[List[JSONDict]], bot: Optional["Bot"] = None
) -> Tuple[Tele_co, ...]:
cls: type[Tele_co], data: Optional[list[JSONDict]], bot: Optional["Bot"] = None
) -> tuple[Tele_co, ...]:
"""Converts a list of JSON objects to a tuple of Telegram objects.
.. versionchanged:: 20.0
@@ -463,7 +448,7 @@ class TelegramObject:
* Filters out any :obj:`None` values.
Args:
data (List[Dict[:obj:`str`, ...]]): The JSON data.
data (list[dict[:obj:`str`, ...]]): The JSON data.
bot (:class:`telegram.Bot`, optional): The bot associated with these object. Defaults
to :obj:`None`, in which case shortcut methods will not be available.
@@ -552,7 +537,7 @@ class TelegramObject:
recursive: bool = False,
remove_bot: bool = False,
convert_default_vault: bool = True,
) -> Dict[str, Union[str, object]]:
) -> dict[str, Union[str, object]]:
"""This method is used for obtaining the attributes of the object.
Args:
@@ -625,7 +610,7 @@ class TelegramObject:
# Now we should convert TGObjects to dicts inside objects such as sequences, and convert
# datetimes to timestamps. This mostly eliminates the need for subclasses to override
# `to_dict`
pop_keys: Set[str] = set()
pop_keys: set[str] = set()
for key, value in out.items():
if isinstance(value, (tuple, list)):
if not value:
@@ -637,7 +622,7 @@ class TelegramObject:
for item in value:
if hasattr(item, "to_dict"):
val.append(item.to_dict(recursive=recursive))
# This branch is useful for e.g. Tuple[Tuple[PhotoSize|KeyboardButton]]
# This branch is useful for e.g. tuple[tuple[PhotoSize|KeyboardButton]]
elif isinstance(item, (tuple, list)):
val.append(
[

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