Compare commits

..

52 Commits

Author SHA1 Message Date
Bibo-Joshi 8c692d1008 Bump Version to v21.5 (#4449) 2024-09-01 15:25:34 +02:00
Bibo-Joshi 970d2ab085 Documentation Improvements (#4400, #4448)
Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com>
Co-authored-by: Palaptin <100526200+Palaptin@users.noreply.github.com>
2024-09-01 14:12:41 +02:00
dependabot[bot] 60b439ff42 Update cachetools requirement from <5.5.0,>=5.3.3 to >=5.3.3,<5.6.0 (#4437)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
2024-09-01 10:35:11 +02:00
Bibo-Joshi b17b0d248d Improve PyPI Automation (#4375) 2024-09-01 09:34:20 +02:00
Bibo-Joshi e0f36867cc Add MessageEntity.shift_entities and MessageEntity.concatenate (#4376) 2024-09-01 09:33:12 +02:00
Poolitzer 01f689373c Bot API 7.9 (#4429)
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com>
2024-09-01 09:32:42 +02:00
Bibo-Joshi 1e05381133 Update Test Suite to New Test Channel Setup (#4435) 2024-08-26 20:16:35 +02:00
Martin Hjelmare a05362c79a Remove Surplus Logging from Updater Network Loop (#4432) 2024-08-19 16:40:28 +02:00
Palaptin fbf07bf126 Improve Fixture Usage in test_message.py (#4431) 2024-08-19 16:14:01 +02:00
Harshil 3017bf00a4 Update Python 3.13 Test Suite to RC1 (#4415) 2024-08-13 17:58:08 +02:00
dependabot[bot] 374875c786 Bump sphinx from 7.4.7 to 8.0.2 and furo from 2024.7.18 to 2024.8.6 (#4412)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com>
2024-08-13 17:57:26 +02:00
Harshil 8f9db63f4f Bump ruff and Add New Rules (#4416)
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
2024-08-07 21:56:46 +02:00
Harshil 1787586902 Bugfix for "Available In" Admonitions (#4413) 2024-08-03 22:47:38 +02:00
dependabot[bot] 9c50a38512 Bump test-summary/action from 2.3 to 2.4 (#4410)
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: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com>
2024-08-03 17:27:39 +02:00
Bibo-Joshi 3a49372591 Add Parameter read_file_handle to InputFile (#4388) 2024-08-02 22:28:38 +02:00
dependabot[bot] e637d1733c Bump pytest from 8.2.2 to 8.3.2 (#4403)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-02 14:01:31 +02:00
dependabot[bot] b89f5d6126 Bump dependabot/fetch-metadata from 2.1.0 to 2.2.0 (#4411)
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: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com>
2024-08-02 14:00:26 +02:00
Bibo-Joshi 6578c76068 API 7.8 (#4408) 2024-08-02 13:43:27 +02:00
Bibo-Joshi a967dbe37a Document Return Types of RequestData Members (#4396) 2024-08-02 13:41:39 +02:00
dependabot[bot] af76a8485f Update cachetools requirement from ~=5.3.3 to >=5.3.3,<5.5.0 (#4390)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
2024-07-24 21:03:54 +02:00
MOHD YUSUF 8a205b10c0 Add Introductory Paragraphs to Telegram Types Subsections (#4389)
Co-authored-by: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com>
2024-07-24 21:02:53 +02:00
dependabot[bot] 6d70c56159 Bump sphinx from 7.3.7 to 7.4.7 (#4395)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-21 21:23:21 +02:00
Pablo Martínez 0913b859d7 Add Internal Constants for Encodings (#4378) 2024-07-21 21:13:30 +02:00
Bibo-Joshi c3f17bb18e Start Adapting to RTD Addons (#4386) 2024-07-21 21:12:30 +02:00
dependabot[bot] 006a290b7b Bump furo from 2024.5.6 to 2024.7.18 (#4392)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-21 21:05:01 +02:00
Jãїиãм 422993b8ab Add Parameter game_pattern to CallbackQueryHandler (#4353) 2024-07-13 21:26:44 +02:00
Bibo-Joshi 2ac4e009d0 Bump version to v21.4 (#4371) 2024-07-12 17:40:42 +02:00
Bibo-Joshi efe1392e73 Automate PyPI Releases (#4364) 2024-07-12 16:44:41 +02:00
Bibo-Joshi 0a673e8f7e Documentation Improvements (#4303)
Co-authored-by: poolitzer <github@poolitzer.eu>
2024-07-12 16:33:42 +02:00
Bibo-Joshi 86c8cae40d Restructure Readme (#4362) 2024-07-10 20:36:47 +02:00
Bibo-Joshi f737702544 Use a Composite Action for Testing Type Completeness (#4367) 2024-07-10 17:33:04 +02:00
Bibo-Joshi 06f1da576e Stabilize Some Concurrency Usages in Test Suite (#4360) 2024-07-10 17:11:22 +02:00
Bibo-Joshi 7a470d57c8 Add a Test Case for MenuButton (#4363) 2024-07-10 17:10:33 +02:00
Poolitzer 1714bfd8f6 Deprecate Inclusion of successful_payment in Message.effective_attachment (#4365) 2024-07-09 23:33:57 +02:00
Poolitzer 71e4015e22 API 7.7 (#4356)
Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com>
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
2024-07-09 10:35:18 +02:00
Harshil 52237cf00c Add filters.PAID_MEDIA (#4357) 2024-07-07 22:23:31 +02:00
Harshil dba7866aab API 7.6 (#4333, #4341, #4342, #4334, #4335, #4344, #4348, #4351)
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
2024-07-07 13:08:52 +02:00
Bibo-Joshi 98bed6f01a Log Received Data on Deserialization Errors (#4304) 2024-07-06 16:09:04 +02:00
Antares 42d7c8c477 Add MessageEntity.adjust_message_entities_to_utf_16 Utility Function (#4323)
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com>
2024-07-06 16:08:29 +02:00
Poolitzer 8018e5ff3f Extend SuccessfulPayment Test (#4349) 2024-07-05 23:03:54 +02:00
Harshil c39839b026 Small Fixes for test_stars.py (#4347) 2024-07-05 18:44:41 +02:00
Harshil 4213c12c5b Use Python 3.13 Beta 3 in Test Suite (#4336)
Co-authored-by: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com>
2024-07-03 19:04:45 +02:00
pre-commit-ci[bot] 97226b1ae3 Bump pre-commit Hooks to Latest Versions (#4337)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com>
2024-07-03 18:29:09 +02:00
Harshil 146ec54a00 API 7.5 (#4312, #4311, #4315, #4328, #4316)
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
2024-07-01 21:45:37 +02:00
Bibo-Joshi df8aae0a38 Fix Link-Check Workflow (#4332) 2024-07-01 20:43:54 +02:00
Bibo-Joshi 4ccc80f9c1 Make Argument bot of TelegramObject.de_json Optional (#4320) 2024-07-01 19:59:54 +02:00
Harshil cfc75bb08b Bump ruff and Add New Rules (#4329) 2024-06-30 18:22:12 +02:00
Palaptin 51ef571a07 Add Lower Bound for flaky Dependency (#4322) 2024-06-23 20:15:37 +02:00
Harshil 9ce0f49882 Add Support for Python 3.13 Beta (#4253)
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
2024-06-18 22:25:02 +02:00
dependabot[bot] 5b1e7399a4 Bump pytest from 8.2.1 to 8.2.2 (#4294)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
2024-06-18 22:20:47 +02:00
Harshil a83046e1ec Add mise-en-place to .gitignore (#4300) 2024-06-17 19:32:47 +02:00
Bibo-Joshi 44e8292838 Drop python-telegram-bot-raw And Switch to pyproject.toml Based Packaging (#4288) 2024-06-15 10:29:19 +02:00
231 changed files with 6037 additions and 1477 deletions
+4 -9
View File
@@ -26,7 +26,7 @@ Setting things up
.. code-block:: bash
$ pip install -r requirements-all.txt
$ pip install -r requirements-dev-all.txt
5. Install pre-commit hooks:
@@ -194,7 +194,7 @@ Feel free to copy (parts of) the checklist to the PR description to remind you o
- Added or updated documentation for the changed class(es) and/or method(s)
- Added the new method(s) to ``_extbot.py``
- Added or updated ``bot_methods.rst``
- Updated the Bot API version number in all places: ``README.rst`` and ``README_RAW.rst`` (including the badge), as well as ``telegram.constants.BOT_API_VERSION_INFO``
- Updated the Bot API version number in all places: ``README.rst`` (including the badge) and ``telegram.constants.BOT_API_VERSION_INFO``
- Added logic for arbitrary callback data in :class:`telegram.ext.ExtBot` for new methods that either accept a ``reply_markup`` in some form or have a return type that is/contains :class:`~telegram.Message`
Documenting
@@ -210,13 +210,8 @@ doc strings don't have a separate documentation site they generate, instead, the
User facing documentation
-------------------------
We use `sphinx`_ to generate static HTML docs. To build them, first make sure you're running Python 3.9 or above and have the required dependencies:
.. code-block:: bash
$ pip install -r docs/requirements-docs.txt
then run the following from the PTB root directory:
We use `sphinx`_ to generate static HTML docs. To build them, first make sure you're running Python 3.10 or above and have the required dependencies installed as explained above.
Then, run the following from the PTB root directory:
.. code-block:: bash
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
- name: Fetch Dependabot metadata
id: dependabot-metadata
uses: dependabot/fetch-metadata@v2.1.0
uses: dependabot/fetch-metadata@v2.2.0
- uses: actions/checkout@v4
with:
+2 -2
View File
@@ -10,7 +10,7 @@ jobs:
runs-on: ${{matrix.os}}
strategy:
matrix:
python-version: [3.9]
python-version: [3.10]
os: [ubuntu-latest]
fail-fast: False
steps:
@@ -22,6 +22,6 @@ jobs:
- name: Install dependencies
run: |
python -W ignore -m pip install --upgrade pip
python -W ignore -m pip install -r requirements-all.txt
python -W ignore -m pip install -r requirements-dev-all.txt
- name: Check Links
run: sphinx-build docs/source docs/build/html -W --keep-going -j auto -b linkcheck
+2 -2
View File
@@ -14,7 +14,7 @@ jobs:
runs-on: ${{matrix.os}}
strategy:
matrix:
python-version: [3.9]
python-version: ['3.10']
os: [ubuntu-latest]
fail-fast: False
steps:
@@ -28,7 +28,7 @@ jobs:
- name: Install dependencies
run: |
python -W ignore -m pip install --upgrade pip
python -W ignore -m pip install -r requirements-all.txt
python -W ignore -m pip install -r requirements-dev-all.txt
- name: Test autogeneration of admonitions
run: pytest -v --tb=short tests/docs/admonition_inserter.py
- name: Build docs
@@ -1,19 +0,0 @@
name: Warning maintainers
on:
pull_request_target:
paths:
- requirements.txt
- requirements-opts.txt
- .pre-commit-config.yaml
permissions:
pull-requests: write
jobs:
job:
runs-on: ubuntu-latest
name: about pre-commit and dependency change
steps:
- name: running the check
uses: Poolitzer/notifier-action@master
with:
notify-message: Hey! Looks like you edited the (optional) requirements or the pre-commit hooks. I'm just a friendly reminder to keep the additional dependencies for the hooks in sync with the requirements :)
repo-token: ${{ secrets.GITHUB_TOKEN }}
-18
View File
@@ -1,18 +0,0 @@
name: Warning maintainers
on:
pull_request_target:
paths:
- README.rst
- README_RAW.rst
permissions:
pull-requests: write
jobs:
job:
runs-on: ubuntu-latest
name: about readme change
steps:
- name: running the check
uses: Poolitzer/notifier-action@master
with:
notify-message: Hey! Looks like you edited README.rst or README_RAW.rst. I'm just a friendly reminder to apply relevant changes to both of those files :)
repo-token: ${{ secrets.GITHUB_TOKEN }}
+129
View File
@@ -0,0 +1,129 @@
name: Publish to PyPI
on:
# manually trigger the workflow
workflow_dispatch:
jobs:
build:
name: Build Distribution
runs-on: ubuntu-latest
outputs:
TAG: ${{ steps.get_tag.outputs.TAG }}
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: Install pypa/build
run: >-
python3 -m pip install build --user
- name: Build a binary wheel and a source tarball
run: python3 -m build
- name: Store the distribution packages
uses: actions/upload-artifact@v4
with:
name: python-package-distributions
path: dist/
- name: Get Tag Name
id: get_tag
run: |
pip install .
TAG=$(python -c "from telegram import __version__; print(f'v{__version__}')")
echo "TAG=$TAG" >> $GITHUB_OUTPUT
publish-to-pypi:
name: Publish to PyPI
needs:
- build
runs-on: ubuntu-latest
environment:
name: release_pypi
url: https://pypi.org/p/python-telegram-bot
permissions:
id-token: write # IMPORTANT: mandatory for trusted publishing
steps:
- name: Download all the dists
uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
compute-signatures:
name: Compute SHA1 Sums and Sign with Sigstore
runs-on: ubuntu-latest
needs:
- publish-to-pypi
permissions:
id-token: write # IMPORTANT: mandatory for sigstore
steps:
- name: Download all the dists
uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/
- name: Compute SHA1 Sums
run: |
# Compute SHA1 sum of the distribution packages and save it to a file with the same name,
# but with .sha1 extension
for file in dist/*; do
sha1sum $file > $file.sha1
done
- name: Sign the dists with Sigstore
uses: sigstore/gh-action-sigstore-python@v3.0.0
with:
inputs: >-
./dist/*.tar.gz
./dist/*.whl
- name: Store the distribution packages and signatures
uses: actions/upload-artifact@v4
with:
name: python-package-distributions-and-signatures
path: dist/
github-release:
name: Upload to GitHub Release
needs:
- build
- compute-signatures
runs-on: ubuntu-latest
permissions:
contents: write # IMPORTANT: mandatory for making GitHub Releases
steps:
- name: Download all the dists
uses: actions/download-artifact@v4
with:
name: python-package-distributions-and-signatures
path: dist/
- name: Create GitHub Release
env:
GITHUB_TOKEN: ${{ github.token }}
TAG: ${{ needs.build.outputs.TAG }}
# Create a tag and a GitHub Release. The description can be changed later, as for now
# we don't define it through this workflow.
run: >-
gh release create
'${{ env.TAG }}'
--repo '${{ github.repository }}'
--generate-notes
- name: Upload artifact signatures to GitHub Release
env:
GITHUB_TOKEN: ${{ github.token }}
TAG: ${{ needs.build.outputs.TAG }}
# Upload to GitHub Release using the `gh` CLI.
# `dist/` contains the built packages, and the
# sigstore-produced signatures and certificates.
run: >-
gh release upload
'${{ env.TAG }}' dist/**
--repo '${{ github.repository }}'
+132
View File
@@ -0,0 +1,132 @@
name: Publish to Test PyPI
on:
# manually trigger the workflow
workflow_dispatch:
jobs:
build:
name: Build Distribution
runs-on: ubuntu-latest
outputs:
TAG: ${{ steps.get_tag.outputs.TAG }}
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: Install pypa/build
run: >-
python3 -m pip install build --user
- name: Build a binary wheel and a source tarball
run: python3 -m build
- name: Store the distribution packages
uses: actions/upload-artifact@v4
with:
name: python-package-distributions
path: dist/
- name: Get Tag Name
id: get_tag
run: |
pip install .
TAG=$(python -c "from telegram import __version__; print(f'v{__version__}')")
echo "TAG=$TAG" >> $GITHUB_OUTPUT
publish-to-test-pypi:
name: Publish to Test PyPI
needs:
- build
runs-on: ubuntu-latest
environment:
name: release_test_pypi
url: https://test.pypi.org/p/python-telegram-bot
permissions:
id-token: write # IMPORTANT: mandatory for trusted publishing
steps:
- name: Download all the dists
uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/
- name: Publish to Test PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/
compute-signatures:
name: Compute SHA1 Sums and Sign with Sigstore
runs-on: ubuntu-latest
needs:
- publish-to-test-pypi
permissions:
id-token: write # IMPORTANT: mandatory for sigstore
steps:
- name: Download all the dists
uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/
- name: Compute SHA1 Sums
run: |
# Compute SHA1 sum of the distribution packages and save it to a file with the same name,
# but with .sha1 extension
for file in dist/*; do
sha1sum $file > $file.sha1
done
- name: Sign the dists with Sigstore
uses: sigstore/gh-action-sigstore-python@v3.0.0
with:
inputs: >-
./dist/*.tar.gz
./dist/*.whl
- name: Store the distribution packages and signatures
uses: actions/upload-artifact@v4
with:
name: python-package-distributions-and-signatures
path: dist/
github-test-release:
name: Upload to GitHub Release Draft
needs:
- build
- compute-signatures
runs-on: ubuntu-latest
permissions:
contents: write # IMPORTANT: mandatory for making GitHub Releases
steps:
- name: Download all the dists
uses: actions/download-artifact@v4
with:
name: python-package-distributions-and-signatures
path: dist/
- name: Create GitHub Release
env:
GITHUB_TOKEN: ${{ github.token }}
TAG: ${{ needs.build.outputs.TAG }}
# Create a GitHub Release *draft*. The description can be changed later, as for now
# we don't define it through this workflow.
run: >-
gh release create
'${{ env.TAG }}'
--repo '${{ github.repository }}'
--generate-notes
--draft
- name: Upload artifact signatures to GitHub Release
env:
GITHUB_TOKEN: ${{ github.token }}
TAG: ${{ needs.build.outputs.TAG }}
# Upload to GitHub Release using the `gh` CLI.
# `dist/` contains the built packages, and the
# sigstore-produced signatures and certificates.
run: >-
gh release upload
'${{ env.TAG }}' dist/**
--repo '${{ github.repository }}'
+3 -4
View File
@@ -29,9 +29,8 @@ jobs:
- name: Install dependencies
run: |
python -W ignore -m pip install --upgrade pip
python -W ignore -m pip install -r requirements.txt
python -W ignore -m pip install -r requirements-opts.txt
python -W ignore -m pip install -r requirements-dev.txt
python -W ignore -m pip install .[all]
python -W ignore -m pip install -r requirements-unit-tests.txt
- name: Compare to official api
run: |
pytest -v tests/test_official/test_official.py --junit-xml=.test_report_official.xml
@@ -42,7 +41,7 @@ jobs:
- name: Test Summary
id: test_summary
uses: test-summary/action@v2.3
uses: test-summary/action@v2.4
if: always() # always run, even if tests fail
with:
paths: .test_report_official.xml
+6 -64
View File
@@ -3,8 +3,8 @@ on:
pull_request:
paths:
- telegram/**
- requirements.txt
- requirements-opts.txt
- pyproject.toml
- .github/workflows/type_completeness.yml
push:
branches:
- master
@@ -14,66 +14,8 @@ jobs:
name: test-type-completeness
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: git fetch --depth=1 # https://github.com/actions/checkout/issues/329#issuecomment-674881489
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
- uses: Bibo-Joshi/pyright-type-completeness@1.0.0
with:
python-version: 3.9
cache: 'pip'
cache-dependency-path: '**/requirements*.txt'
- name: Install Pyright
run: |
python -W ignore -m pip install pyright~=1.1.316
- name: Get PR Completeness
# Must run before base completeness, as base completeness will checkout the base branch
# And we can't go back to the PR branch after that in case the PR is coming from a fork
run: |
pip install . -U
pyright --verifytypes telegram --ignoreexternal --outputjson > pr.json || true
pyright --verifytypes telegram --ignoreexternal > pr.readable || true
- name: Get Base Completeness
run: |
git checkout ${{ github.base_ref }}
pip install . -U
pyright --verifytypes telegram --ignoreexternal --outputjson > base.json || true
- name: Compare Completeness
uses: jannekem/run-python-script-action@v1
with:
script: |
import json
import os
from pathlib import Path
base = float(
json.load(open("base.json", "rb"))["typeCompleteness"]["completenessScore"]
)
pr = float(
json.load(open("pr.json", "rb"))["typeCompleteness"]["completenessScore"]
)
base_text = f"This PR changes type completeness from {round(base, 3)} to {round(pr, 3)}."
if base == 0:
text = f"Something is broken in the workflow. Reported type completeness is 0. 💥"
set_summary(text)
print(Path("pr.readable").read_text(encoding="utf-8"))
error(text)
exit(1)
if pr < (base - 0.001):
text = f"{base_text} ❌"
set_summary(text)
print(Path("pr.readable").read_text(encoding="utf-8"))
error(text)
exit(1)
elif pr > (base + 0.001):
text = f"{base_text} ✨"
set_summary(text)
if pr < 1:
print(Path("pr.readable").read_text(encoding="utf-8"))
print(text)
else:
text = f"{base_text} This is less than 0.1 percentage points. ✅"
set_summary(text)
print(Path("pr.readable").read_text(encoding="utf-8"))
print(text)
package-name: telegram
python-version: 3.12
pyright-version: ~=1.1.367
+8 -8
View File
@@ -4,9 +4,9 @@ on:
paths:
- telegram/**
- tests/**
- requirements.txt
- requirements-opts.txt
- requirements-dev.txt
- .github/workflows/unit_tests.yml
- pyproject.toml
- requirements-unit-tests.txt
push:
branches:
- master
@@ -20,7 +20,7 @@ jobs:
runs-on: ${{matrix.os}}
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13.0-rc.1']
os: [ubuntu-latest, windows-latest, macos-latest]
fail-fast: False
steps:
@@ -35,8 +35,8 @@ jobs:
run: |
python -W ignore -m pip install --upgrade pip
python -W ignore -m pip install -U pytest-cov
python -W ignore -m pip install -r requirements.txt
python -W ignore -m pip install -r requirements-dev.txt
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]
- name: Test with pytest
@@ -65,7 +65,7 @@ jobs:
# Test the rest
export TEST_WITH_OPT_DEPS='true'
pip install -r requirements-opts.txt
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.
@@ -83,7 +83,7 @@ jobs:
- name: Test Summary
id: test_summary
uses: test-summary/action@v2.3
uses: test-summary/action@v2.4
if: always() # always run, even if tests fail
with:
paths: |
+3
View File
@@ -92,3 +92,6 @@ telegram.jpg
# virtual env
venv*
# environment manager:
.mise.toml
+10 -10
View File
@@ -1,4 +1,4 @@
# Make sure that the additional_dependencies here match requirements(-opts).txt
# Make sure that the additional_dependencies here match pyproject.toml
ci:
autofix_prs: false
@@ -7,7 +7,7 @@ ci:
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: 'v0.4.3'
rev: 'v0.5.6'
hooks:
- id: ruff
name: ruff
@@ -15,7 +15,7 @@ repos:
- httpx~=0.27
- tornado~=6.4
- APScheduler~=3.10.4
- cachetools~=5.3.3
- cachetools>=5.3.3,<5.5.0
- aiolimiter~=1.1.0
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 24.4.2
@@ -25,11 +25,11 @@ repos:
- --diff
- --check
- repo: https://github.com/PyCQA/flake8
rev: 7.0.0
rev: 7.1.0
hooks:
- id: flake8
- repo: https://github.com/PyCQA/pylint
rev: v3.1.0
rev: v3.2.4
hooks:
- id: pylint
files: ^(?!(tests|docs)).*\.py$
@@ -37,11 +37,11 @@ repos:
- httpx~=0.27
- tornado~=6.4
- APScheduler~=3.10.4
- cachetools~=5.3.3
- cachetools>=5.3.3,<5.5.0
- aiolimiter~=1.1.0
- . # this basically does `pip install -e .`
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.10.0
rev: v1.10.1
hooks:
- id: mypy
name: mypy-ptb
@@ -53,7 +53,7 @@ repos:
- httpx~=0.27
- tornado~=6.4
- APScheduler~=3.10.4
- cachetools~=5.3.3
- cachetools>=5.3.3,<5.5.0
- aiolimiter~=1.1.0
- . # this basically does `pip install -e .`
- id: mypy
@@ -65,10 +65,10 @@ repos:
additional_dependencies:
- tornado~=6.4
- APScheduler~=3.10.4
- cachetools~=5.3.3
- cachetools>=5.3.3,<5.5.0
- . # this basically does `pip install -e .`
- repo: https://github.com/asottile/pyupgrade
rev: v3.15.2
rev: v3.16.0
hooks:
- id: pyupgrade
args:
+3
View File
@@ -60,6 +60,7 @@ The following wonderful people contributed directly or indirectly to this projec
- `Hugo Damer <https://github.com/HakimusGIT>`_
- `ihoru <https://github.com/ihoru>`_
- `Iulian Onofrei <https://github.com/revolter>`_
- `Jainam Oswal <https://github.com/jainamoswal>`_
- `Jasmin Bom <https://github.com/jsmnbom>`_
- `JASON0916 <https://github.com/JASON0916>`_
- `jeffffc <https://github.com/jeffffc>`_
@@ -86,6 +87,7 @@ The following wonderful people contributed directly or indirectly to this projec
- `Miguel C. R. <https://github.com/MiguelX413>`_
- `miles <https://github.com/miles170>`_
- `Mischa Krüger <https://github.com/Makman2>`_
- `Mohd Yusuf <https://github.com/mohdyusuf2312>`_
- `naveenvhegde <https://github.com/naveenvhegde>`_
- `neurrone <https://github.com/neurrone>`_
- `NikitaPirate <https://github.com/NikitaPirate>`_
@@ -96,6 +98,7 @@ The following wonderful people contributed directly or indirectly to this projec
- `Oleg Sushchenko <https://github.com/feuillemorte>`_
- `Or Bin <https://github.com/OrBin>`_
- `overquota <https://github.com/overquota>`_
- `Pablo Martinez <https://github.com/elpekenin>`_
- `Paradox <https://github.com/paradox70>`_
- `Patrick Hofmann <https://github.com/PH89>`_
- `Paul Larsen <https://github.com/PaulSonOfLars>`_
+104
View File
@@ -4,6 +4,110 @@
Changelog
=========
Version 21.5
============
*Released 2024-09-01*
This is the technical changelog for version 21.5. More elaborate release notes can be found in the news channel `@pythontelegrambotchannel <https://t.me/pythontelegrambotchannel>`_.
Major Changes
-------------
- Full Support for Bot API 7.9 (:pr:`4429`)
- Full Support for Bot API 7.8 (:pr:`4408`)
New Features
------------
- Add ``MessageEntity.shift_entities`` and ``MessageEntity.concatenate`` (:pr:`4376` closes :issue:`4372`)
- Add Parameter ``game_pattern`` to ``CallbackQueryHandler`` (:pr:`4353` by `jainamoswal <https://github.com/jainamoswal>`_ closes :issue:`4269`)
- Add Parameter ``read_file_handle`` to ``InputFile`` (:pr:`4388` closes :issue:`4339`)
Documentation Improvements
--------------------------
- Bugfix for "Available In" Admonitions (:pr:`4413`)
- Documentation Improvements (:pr:`4400` closes :issue:`4446`, :pr:`4448` by `Palaptin <https://github.com/Palaptin>`_)
- Document Return Types of ``RequestData`` Members (:pr:`4396`)
- Add Introductory Paragraphs to Telegram Types Subsections (:pr:`4389` by `mohdyusuf2312 <https://github.com/mohdyusuf2312>`_ closes :issue:`4380`)
- Start Adapting to RTD Addons (:pr:`4386`)
Minor and Internal Changes
---------------------------
- Remove Surplus Logging from ``Updater`` Network Loop (:pr:`4432` by `MartinHjelmare <https://github.com/MartinHjelmare>`_)
- Add Internal Constants for Encodings (:pr:`4378` by `elpekenin <https://github.com/elpekenin>`_)
- Improve PyPI Automation (:pr:`4375` closes :issue:`4373`)
- Update Test Suite to New Test Channel Setup (:pr:`4435`)
- Improve Fixture Usage in ``test_message.py`` (:pr:`4431` by `Palaptin <https://github.com/Palaptin>`_)
- Update Python 3.13 Test Suite to RC1 (:pr:`4415`)
- Bump ``ruff`` and Add New Rules (:pr:`4416`)
Dependency Updates
------------------
- Update ``cachetools`` requirement from <5.5.0,>=5.3.3 to >=5.3.3,<5.6.0 (:pr:`4437`)
- Bump ``sphinx`` from 7.4.7 to 8.0.2 and ``furo`` from 2024.7.18 to 2024.8.6 (:pr:`4412`)
- Bump ``test-summary/action`` from 2.3 to 2.4 (:pr:`4410`)
- Bump ``pytest`` from 8.2.2 to 8.3.2 (:pr:`4403`)
- Bump ``dependabot/fetch-metadata`` from 2.1.0 to 2.2.0 (:pr:`4411`)
- Update ``cachetools`` requirement from ~=5.3.3 to >=5.3.3,<5.5.0 (:pr:`4390`)
- Bump ``sphinx`` from 7.3.7 to 7.4.7 (:pr:`4395`)
- Bump ``furo`` from 2024.5.6 to 2024.7.18 (:pr:`4392`)
Version 21.4
============
*Released 2024-07-12*
This is the technical changelog for version 21.4. More elaborate release notes can be found in the news channel `@pythontelegrambotchannel <https://t.me/pythontelegrambotchannel>`_.
Major Changes
-------------
- Full Support for Bot API 7.5 (:pr:`4328`, :pr:`4316`, :pr:`4315`, :pr:`4312` closes :issue:`4310`, :pr:`4311`)
- Full Support for Bot API 7.6 (:pr:`4333` closes :issue:`4331`, :pr:`4344`, :pr:`4341`, :pr:`4334`, :pr:`4335`, :pr:`4351`, :pr:`4342`, :pr:`4348`)
- Full Support for Bot API 7.7 (:pr:`4356` closes :issue:`4355`)
- Drop ``python-telegram-bot-raw`` And Switch to ``pyproject.toml`` Based Packaging (:pr:`4288` closes :issue:`4129` and :issue:`4296`)
- Deprecate Inclusion of ``successful_payment`` in ``Message.effective_attachment`` (:pr:`4365` closes :issue:`4350`)
New Features
------------
- Add Support for Python 3.13 Beta (:pr:`4253`)
- Add ``filters.PAID_MEDIA`` (:pr:`4357`)
- Log Received Data on Deserialization Errors (:pr:`4304`)
- Add ``MessageEntity.adjust_message_entities_to_utf_16`` Utility Function (:pr:`4323` by `Antares0982 <https://github.com/Antares0982>`_ closes :issue:`4319`)
- Make Argument ``bot`` of ``TelegramObject.de_json`` Optional (:pr:`4320`)
Documentation Improvements
--------------------------
- Documentation Improvements (:pr:`4303` closes :issue:`4301`)
- Restructure Readme (:pr:`4362`)
- Fix Link-Check Workflow (:pr:`4332`)
Internal Changes
----------------
- Automate PyPI Releases (:pr:`4364` closes :issue:`4318`)
- Add ``mise-en-place`` to ``.gitignore`` (:pr:`4300`)
- Use a Composite Action for Testing Type Completeness (:pr:`4367`)
- Stabilize Some Concurrency Usages in Test Suite (:pr:`4360`)
- Add a Test Case for ``MenuButton`` (:pr:`4363`)
- Extend ``SuccessfulPayment`` Test (:pr:`4349`)
- Small Fixes for ``test_stars.py`` (:pr:`4347`)
- Use Python 3.13 Beta 3 in Test Suite (:pr:`4336`)
Dependency Updates
------------------
- Bump ``ruff`` and Add New Rules (:pr:`4329`)
- Bump ``pre-commit`` Hooks to Latest Versions (:pr:`4337`)
- Add Lower Bound for ``flaky`` Dependency (:pr:`4322` by `Palaptin <https://github.com/Palaptin>`_)
- Bump ``pytest`` from 8.2.1 to 8.2.2 (:pr:`4294`)
Version 21.3
============
*Released 2024-06-07*
-1
View File
@@ -1 +0,0 @@
include LICENSE LICENSE.lesser requirements.txt requirements-opts.txt README_RAW.rst telegram/py.typed
+48 -23
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.4-blue?logo=telegram
.. image:: https://img.shields.io/badge/Bot%20API-7.9-blue?logo=telegram
:target: https://core.telegram.org/bots/api-changelog
:alt: Supported Bot API version
@@ -66,23 +66,36 @@ We have a vibrant community of developers helping each other in our `Telegram gr
*Stay tuned for library updates and new releases on our* `Telegram Channel <https://telegram.me/pythontelegrambotchannel>`_.
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+**.
In addition to the pure API implementation, this library features a number of high-level classes to
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
``telegram.ext`` submodule.
Telegram API support
====================
After installing_ the library, be sure to check out the section on `working with PTB`_.
All types and methods of the Telegram Bot API **7.4** are supported.
Telegram API support
~~~~~~~~~~~~~~~~~~~~
All types and methods of the Telegram Bot API **7.9** 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
~~~~~~~~~~~~~~~~
- `Fully asynchronous <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Concurrency>`_
- Convenient shortcut methods, e.g. `Message.reply_text <https://docs.python-telegram-bot.org/en/stable/telegram.message.html#telegram.Message.reply_text>`_
- `Fully annotated with static type hints <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Type-Checking>`_
- `Customizable and extendable interface <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Architecture>`_
- Seamless integration with `webhooks <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Webhooks>`_ and `polling <https://docs.python-telegram-bot.org/en/stable/telegram.ext.application.html#telegram.ext.Application.run_polling>`_
- `Comprehensive documentation and examples <#working-with-ptb>`_
Installing
==========
----------
You can install or upgrade ``python-telegram-bot`` via
@@ -98,22 +111,27 @@ You can also install ``python-telegram-bot`` from source, though this is usually
$ git clone https://github.com/python-telegram-bot/python-telegram-bot
$ cd python-telegram-bot
$ python setup.py install
$ pip install build
$ python -m build
Verifying Releases
------------------
~~~~~~~~~~~~~~~~~~
We sign all the releases with a GPG key.
The signatures are uploaded to both the `GitHub releases page <https://github.com/python-telegram-bot/python-telegram-bot/releases>`_ and the `PyPI project <https://pypi.org/project/python-telegram-bot/>`_ and end with a suffix ``.asc``.
To enable you to verify that a release file that you downloaded was indeed provided by the ``python-telegram-bot`` team, we have taken the following measures.
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``.
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``.
Please find the public keys `here <https://github.com/python-telegram-bot/python-telegram-bot/tree/master/public_keys>`_.
The keys are named in the format ``<first_version>-<last_version>.gpg`` or ``<first_version>-current.gpg`` if the key is currently being used for new releases.
The keys are named in the format ``<first_version>-<last_version>.gpg``.
In addition, the GitHub release page also contains the sha1 hashes of the release files in the files with the suffix ``.sha1``.
This allows you to verify that a release file that you downloaded was indeed provided by the ``python-telegram-bot`` team.
Dependencies & Their Versions
-----------------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``python-telegram-bot`` tries to use as few 3rd party dependencies as possible.
However, for some features using a 3rd party library is more sane than implementing the functionality again.
@@ -139,7 +157,7 @@ PTB can be installed with optional dependencies:
* ``pip install "python-telegram-bot[http2]"`` installs `httpx[http2] <https://www.python-httpx.org/#dependencies>`_. Use this, if you want to use HTTP/2.
* ``pip install "python-telegram-bot[rate-limiter]"`` installs `aiolimiter~=1.1.0 <https://aiolimiter.readthedocs.io/en/stable/>`_. Use this, if you want to use ``telegram.ext.AIORateLimiter``.
* ``pip install "python-telegram-bot[webhooks]"`` installs the `tornado~=6.4 <https://www.tornadoweb.org/en/stable/>`_ library. Use this, if you want to use ``telegram.ext.Updater.start_webhook``/``telegram.ext.Application.run_webhook``.
* ``pip install "python-telegram-bot[callback-data]"`` installs the `cachetools~=5.3.3 <https://cachetools.readthedocs.io/en/latest/>`_ library. Use this, if you want to use `arbitrary callback_data <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Arbitrary-callback_data>`_.
* ``pip install "python-telegram-bot[callback-data]"`` installs the `cachetools>=5.3.3,<5.6.0 <https://cachetools.readthedocs.io/en/latest/>`_ library. Use this, if you want to use `arbitrary callback_data <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Arbitrary-callback_data>`_.
* ``pip install "python-telegram-bot[job-queue]"`` installs the `APScheduler~=3.10.4 <https://apscheduler.readthedocs.io/en/3.x/>`_ library and enforces `pytz>=2018.6 <https://pypi.org/project/pytz/>`_, where ``pytz`` is a dependency of ``APScheduler``. Use this, if you want to use the ``telegram.ext.JobQueue``.
To install multiple optional dependencies, separate them by commas, e.g. ``pip install "python-telegram-bot[socks,webhooks]"``.
@@ -149,14 +167,19 @@ Additionally, two shortcuts are provided:
* ``pip install "python-telegram-bot[all]"`` installs all optional dependencies.
* ``pip install "python-telegram-bot[ext]"`` installs all optional dependencies that are related to ``telegram.ext``, i.e. ``[rate-limiter, webhooks, callback-data, job-queue]``.
Working with PTB
----------------
Once you have installed the library, you can begin working with it - so let's get started!
Quick Start
===========
~~~~~~~~~~~
Our Wiki contains an `Introduction to the API <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Introduction-to-the-API>`_ explaining how the pure Bot API can be accessed via ``python-telegram-bot``.
Moreover, the `Tutorial: Your first Bot <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Extensions---Your-first-Bot>`_ gives an introduction on how chatbots can be easily programmed with the help of the ``telegram.ext`` module.
Resources
=========
~~~~~~~~~
- The `package documentation <https://docs.python-telegram-bot.org/>`_ is the technical reference for ``python-telegram-bot``.
It contains descriptions of all available classes, modules, methods and arguments as well as the `changelog <https://docs.python-telegram-bot.org/changelog.html>`_.
@@ -167,7 +190,7 @@ Resources
- The `official Telegram Bot API documentation <https://core.telegram.org/bots/api>`_ is of course always worth a read.
Getting help
============
~~~~~~~~~~~~
If the resources mentioned above don't answer your questions or simply overwhelm you, there are several ways of getting help.
@@ -178,7 +201,7 @@ If the resources mentioned above don't answer your questions or simply overwhelm
3. You can even ask for help on Stack Overflow using the `python-telegram-bot tag <https://stackoverflow.com/questions/tagged/python-telegram-bot>`_.
Concurrency
===========
~~~~~~~~~~~
Since v20.0, ``python-telegram-bot`` is built on top of Pythons ``asyncio`` module.
Because ``asyncio`` is in general single-threaded, ``python-telegram-bot`` does currently not aim to be thread-safe.
@@ -191,20 +214,22 @@ Noteworthy parts of ``python-telegram-bots`` API that are likely to cause issues
* all classes in the ``telegram.ext.filters`` module that allow to add/remove allowed users/chats at runtime
Contributing
============
------------
Contributions of all sizes are welcome.
Please review our `contribution guidelines <https://github.com/python-telegram-bot/python-telegram-bot/blob/master/.github/CONTRIBUTING.rst>`_ to get started.
You can also help by `reporting bugs or feature requests <https://github.com/python-telegram-bot/python-telegram-bot/issues/new/choose>`_.
Donating
========
--------
Occasionally we are asked if we accept donations to support the development.
While we appreciate the thought, maintaining PTB is our hobby, and we have almost no running costs for it. We therefore have nothing set up to accept donations.
If you still want to donate, we kindly ask you to donate to another open source project/initiative of your choice instead.
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.
.. _`GitHub releases page`: https://github.com/python-telegram-bot/python-telegram-bot/releases>
-213
View File
@@ -1,213 +0,0 @@
.. image:: https://github.com/python-telegram-bot/logos/blob/master/logo-text/png/ptb-raw-logo-text_768.png?raw=true
:align: center
:target: https://python-telegram-bot.org
:alt: python-telegram-bot-raw Logo
.. image:: https://img.shields.io/pypi/v/python-telegram-bot-raw.svg
:target: https://pypi.org/project/python-telegram-bot-raw/
:alt: PyPi Package Version
.. image:: https://img.shields.io/pypi/pyversions/python-telegram-bot-raw.svg
:target: https://pypi.org/project/python-telegram-bot-raw/
:alt: Supported Python versions
.. image:: https://img.shields.io/badge/Bot%20API-7.4-blue?logo=telegram
:target: https://core.telegram.org/bots/api-changelog
:alt: Supported Bot API version
.. image:: https://img.shields.io/pypi/dm/python-telegram-bot-raw
:target: https://pypistats.org/packages/python-telegram-bot-raw
:alt: PyPi Package Monthly Download
.. image:: https://readthedocs.org/projects/python-telegram-bot/badge/?version=stable
:target: https://docs.python-telegram-bot.org/
:alt: Documentation Status
.. image:: https://img.shields.io/pypi/l/python-telegram-bot-raw.svg
:target: https://www.gnu.org/licenses/lgpl-3.0.html
:alt: LGPLv3 License
.. image:: https://github.com/python-telegram-bot/python-telegram-bot/actions/workflows/unit_tests.yml/badge.svg?branch=master
:target: https://github.com/python-telegram-bot/python-telegram-bot/
:alt: Github Actions workflow
.. image:: https://codecov.io/gh/python-telegram-bot/python-telegram-bot/branch/master/graph/badge.svg
:target: https://app.codecov.io/gh/python-telegram-bot/python-telegram-bot
:alt: Code coverage
.. image:: https://isitmaintained.com/badge/resolution/python-telegram-bot/python-telegram-bot.svg
:target: https://isitmaintained.com/project/python-telegram-bot/python-telegram-bot
:alt: Median time to resolve an issue
.. image:: https://api.codacy.com/project/badge/Grade/99d901eaa09b44b4819aec05c330c968
:target: https://app.codacy.com/gh/python-telegram-bot/python-telegram-bot/dashboard
:alt: Code quality: Codacy
.. image:: https://results.pre-commit.ci/badge/github/python-telegram-bot/python-telegram-bot/master.svg
:target: https://results.pre-commit.ci/latest/github/python-telegram-bot/python-telegram-bot/master
:alt: pre-commit.ci status
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/psf/black
:alt: Code Style: Black
.. image:: https://img.shields.io/badge/Telegram-Channel-blue.svg?logo=telegram
:target: https://t.me/pythontelegrambotchannel
:alt: Telegram Channel
.. image:: https://img.shields.io/badge/Telegram-Group-blue.svg?logo=telegram
:target: https://telegram.me/pythontelegrambotgroup
:alt: Telegram Group
⚠️ Deprecation Notice
=====================
The ``python-telegram-bot-raw`` library will no longer be updated after 21.3.
Please instead use the ``python-telegram-bot`` `library <https://pypi.org/python-telegram-bot>`_.
The change requires no changes in your code and requires no additional dependencies.
For additional information, please see this `channel post <https://t.me/pythontelegrambotchannel/145>`_.
----
We have made you a wrapper you can't refuse
We have a vibrant community of developers helping each other in our `Telegram group <https://telegram.me/pythontelegrambotgroup>`_. Join us!
*Stay tuned for library updates and new releases on our* `Telegram Channel <https://telegram.me/pythontelegrambotchannel>`_.
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+**.
``python-telegram-bot-raw`` is part of the `python-telegram-bot <https://python-telegram-bot.org>`_ ecosystem and provides the pure API functionality extracted from PTB. It therefore does not have independent release schedules, changelogs or documentation.
Note
----
Installing both ``python-telegram-bot`` and ``python-telegram-bot-raw`` in conjunction will result in undesired side-effects, so only install *one* of both.
Telegram API support
====================
All types and methods of the Telegram Bot API **7.4** are supported.
Installing
==========
You can install or upgrade ``python-telegram-bot`` via
.. code:: shell
$ pip install python-telegram-bot-raw --upgrade
To install a pre-release, use the ``--pre`` `flag <https://pip.pypa.io/en/stable/cli/pip_install/#cmdoption-pre>`_ in addition.
You can also install ``python-telegram-bot-raw`` from source, though this is usually not necessary.
.. code:: shell
$ git clone https://github.com/python-telegram-bot/python-telegram-bot
$ cd python-telegram-bot
$ python setup_raw.py install
Note
----
Installing the ``.tar.gz`` archive available on PyPi directly via ``pip`` will *not* work as expected, as ``pip`` does not recognize that it should use ``setup_raw.py`` instead of ``setup.py``.
Verifying Releases
------------------
We sign all the releases with a GPG key.
The signatures are uploaded to both the `GitHub releases page <https://github.com/python-telegram-bot/python-telegram-bot/releases>`_ and the `PyPI project <https://pypi.org/project/python-telegram-bot/>`_ and end with a suffix ``.asc``.
Please find the public keys `here <https://github.com/python-telegram-bot/python-telegram-bot/tree/master/public_keys>`_.
The keys are named in the format ``<first_version>-<last_version>.gpg`` or ``<first_version>-current.gpg`` if the key is currently being used for new releases.
In addition, the GitHub release page also contains the sha1 hashes of the release files in the files with the suffix ``.sha1``.
This allows you to verify that a release file that you downloaded was indeed provided by the ``python-telegram-bot`` team.
Dependencies & Their Versions
-----------------------------
``python-telegram-bot`` tries to use as few 3rd party dependencies as possible.
However, for some features using a 3rd party library is more sane than implementing the functionality again.
As these features are *optional*, the corresponding 3rd party dependencies are not installed by default.
Instead, they are listed as optional dependencies.
This allows to avoid unnecessary dependency conflicts for users who don't need the optional features.
The only required dependency is `httpx ~= 0.27 <https://www.python-httpx.org>`_ for
``telegram.request.HTTPXRequest``, the default networking backend.
``python-telegram-bot`` is most useful when used along with additional libraries.
To minimize dependency conflicts, we try to be liberal in terms of version requirements on the (optional) dependencies.
On the other hand, we have to ensure stability of ``python-telegram-bot``, which is why we do apply version bounds.
If you encounter dependency conflicts due to these bounds, feel free to reach out.
Optional Dependencies
#####################
PTB can be installed with optional dependencies:
* ``pip install "python-telegram-bot-raw[passport]"`` installs the `cryptography>=39.0.1 <https://cryptography.io/en/stable>`_ library. Use this, if you want to use Telegram Passport related functionality.
* ``pip install "python-telegram-bot-raw[socks]"`` installs `httpx[socks] <https://www.python-httpx.org/#dependencies>`_. Use this, if you want to work behind a Socks5 server.
* ``pip install "python-telegram-bot-raw[http2]"`` installs `httpx[http2] <https://www.python-httpx.org/#dependencies>`_. Use this, if you want to use HTTP/2.
To install multiple optional dependencies, separate them by commas, e.g. ``pip install "python-telegram-bot-raw[passport,socks]"``.
Additionally, the shortcut ``pip install "python-telegram-bot-raw[all]"`` installs all optional dependencies.
Quick Start
===========
Our Wiki contains an `Introduction to the API <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Introduction-to-the-API>`_ explaining how the pure Bot API can be accessed via ``python-telegram-bot``.
Resources
=========
- The `package documentation <https://docs.python-telegram-bot.org/>`_ is the technical reference for ``python-telegram-bot``.
It contains descriptions of all available classes, modules, methods and arguments as well as the `changelog <https://docs.python-telegram-bot.org/changelog.html>`_.
- The `wiki <https://github.com/python-telegram-bot/python-telegram-bot/wiki/>`_ is home to number of more elaborate introductions of the different features of ``python-telegram-bot`` and other useful resources that go beyond the technical documentation.
- Our `examples section <https://docs.python-telegram-bot.org/examples.html>`_ contains several examples that showcase the different features of both the Bot API and ``python-telegram-bot``.
Even if it is not your approach for learning, please take a look at ``echobot.py``. It is the de facto base for most of the bots out there.
The code for these examples is released to the public domain, so you can start by grabbing the code and building on top of it.
- The `official Telegram Bot API documentation <https://core.telegram.org/bots/api>`_ is of course always worth a read.
Getting help
============
If the resources mentioned above don't answer your questions or simply overwhelm you, there are several ways of getting help.
1. We have a vibrant community of developers helping each other in our `Telegram group <https://telegram.me/pythontelegrambotgroup>`_. Join us! Asking a question here is often the quickest way to get a pointer in the right direction.
2. Ask questions by opening `a discussion <https://github.com/python-telegram-bot/python-telegram-bot/discussions/new>`_.
3. You can even ask for help on Stack Overflow using the `python-telegram-bot tag <https://stackoverflow.com/questions/tagged/python-telegram-bot>`_.
Concurrency
===========
Since v20.0, ``python-telegram-bot`` is built on top of Pythons ``asyncio`` module.
Because ``asyncio`` is in general single-threaded, ``python-telegram-bot`` does currently not aim to be thread-safe.
Contributing
============
Contributions of all sizes are welcome.
Please review our `contribution guidelines <https://github.com/python-telegram-bot/python-telegram-bot/blob/master/.github/CONTRIBUTING.rst>`_ to get started.
You can also help by `reporting bugs or feature requests <https://github.com/python-telegram-bot/python-telegram-bot/issues/new/choose>`_.
Donating
========
Occasionally we are asked if we accept donations to support the development.
While we appreciate the thought, maintaining PTB is our hobby, and we have almost no running costs for it. We therefore have nothing set up to accept donations.
If you still want to donate, we kindly ask you to donate to another open source project/initiative of your choice instead.
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.
+4 -3
View File
@@ -140,7 +140,7 @@ class AdmonitionInserter:
r"^\s*(?P<attr_name>[a-z_]+)" # Any number of spaces, named group for attribute
r"\s?\(" # Optional whitespace, opening parenthesis
r".*" # Any number of characters (that could denote a built-in type)
r":class:`.+`" # Marker of a classref, class name in backticks
r":(class|obj):`.+`" # Marker of a classref, class name in backticks
r".*\):" # Any number of characters, closing parenthesis, colon.
# The ^ colon above along with parenthesis is important because it makes sure that
# the class is mentioned in the attribute description, not in free text.
@@ -149,11 +149,11 @@ class AdmonitionInserter:
)
# for properties: there is no attr name in docstring. Just check if there's a class name.
prop_docstring_pattern = re.compile(r":class:`.+`.*:")
prop_docstring_pattern = re.compile(r":(class|obj):`.+`.*:")
# pattern for iterating over potentially many class names in docstring for one attribute.
# Tilde is optional (sometimes it is in the docstring, sometimes not).
single_class_name_pattern = re.compile(r":class:`~?(?P<class_name>[\w.]*)`")
single_class_name_pattern = re.compile(r":(class|obj):`~?(?P<class_name>[\w.]*)`")
classes_to_inspect = inspect.getmembers(telegram, inspect.isclass) + inspect.getmembers(
telegram.ext, inspect.isclass
@@ -366,6 +366,7 @@ class AdmonitionInserter:
# to ".. admonition: Examples":
".. admonition:: Examples",
".. version",
"Args:",
# The space after ":param" is important because docstring can contain
# ":paramref:" in its plain text in the beginning of a line (e.g. ExtBot):
":param ",
+2 -3
View File
@@ -16,6 +16,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/].
import collections.abc
import contextlib
import inspect
import re
import typing
@@ -153,13 +154,11 @@ def autodoc_process_docstring(
if isinstance(obj, telegram.ext.filters.BaseFilter):
obj = obj.__class__
try:
with contextlib.suppress(Exception):
source_lines, start_line = inspect.getsourcelines(obj)
end_line = start_line + len(source_lines)
file = Path(inspect.getsourcefile(obj)).relative_to(FILE_ROOT)
LINE_NUMBERS[name] = (file, start_line, end_line)
except Exception:
pass
# Since we don't document the `__init__`, we call this manually to have it available for
# attributes -- see the note above
+2 -1
View File
@@ -88,7 +88,6 @@ class TGConstXRefRole(PyXRefRole):
refnode.rawsource,
CONSTANTS_ROLE,
)
return title, target
except Exception as exc:
sphinx_logger.exception(
"%s:%d: WARNING: Did not convert reference %s due to an exception.",
@@ -98,3 +97,5 @@ class TGConstXRefRole(PyXRefRole):
exc_info=exc,
)
return title, target
else:
return title, target
+3 -3
View File
@@ -1,7 +1,7 @@
sphinx==7.3.7
furo==2024.5.6
sphinx==8.0.2
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
sphinx-copybutton==0.5.2
sphinx-inline-tabs==2023.4.21
sphinx-inline-tabs==2023.4.21
+10 -2
View File
@@ -1,3 +1,4 @@
import os
import re
import sys
from pathlib import Path
@@ -29,7 +30,7 @@ version = telegram.__version__
release = telegram.__version__
# If your documentation needs a minimal Sphinx version, state it here.
needs_sphinx = "6.1.3"
needs_sphinx = "8.0.2"
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
@@ -251,7 +252,14 @@ htmlhelp_basename = "python-telegram-bot-doc"
# The base URL which points to the root of the HTML documentation. It is used to indicate the
# location of document using The Canonical Link Relation. Default: ''.
html_baseurl = "https://docs.python-telegram-bot.org"
# Set canonical URL from the Read the Docs Domain
html_baseurl = os.environ.get("READTHEDOCS_CANONICAL_URL", "")
# Tell Jinja2 templates the build is running on Read the Docs
html_context = {}
if os.environ.get("READTHEDOCS", "") == "True":
html_context["READTHEDOCS"] = True
# -- Options for LaTeX output ---------------------------------------------
+4
View File
@@ -33,6 +33,8 @@
- Used for sending media grouped together
* - :meth:`~telegram.Bot.send_message`
- Used for sending text messages
* - :meth:`~telegram.Bot.send_paid_media`
- Used for sending paid media to channels
* - :meth:`~telegram.Bot.send_photo`
- Used for sending photos
* - :meth:`~telegram.Bot.send_poll`
@@ -369,6 +371,8 @@
- Used for getting basic info about a file
* - :meth:`~telegram.Bot.get_me`
- Used for getting basic information about the bot
* - :meth:`~telegram.Bot.get_star_transactions`
- Used for obtaining the bot's Telegram Stars transactions
* - :meth:`~telegram.Bot.refund_star_payment`
- Used for refunding a payment in Telegram Stars
+12
View File
@@ -3,6 +3,18 @@
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
.. raw:: html
<div style="display: none">
Hidden Headline
===============
This is just here to get furo to display the right sidebar.
.. raw:: html
</div>
.. include:: ../../README.rst
.. The toctrees are hidden such that they don't render on the start page but still include the contents into the documentation.
+9
View File
@@ -88,6 +88,9 @@ Available Types
telegram.inputmediadocument
telegram.inputmediaphoto
telegram.inputmediavideo
telegram.inputpaidmedia
telegram.inputpaidmediaphoto
telegram.inputpaidmediavideo
telegram.inputpolloption
telegram.inputsticker
telegram.keyboardbutton
@@ -113,6 +116,11 @@ Available Types
telegram.messageoriginuser
telegram.messagereactioncountupdated
telegram.messagereactionupdated
telegram.paidmedia
telegram.paidmediainfo
telegram.paidmediaphoto
telegram.paidmediapreview
telegram.paidmediavideo
telegram.photosize
telegram.poll
telegram.pollanswer
@@ -122,6 +130,7 @@ Available Types
telegram.reactiontype
telegram.reactiontypecustomemoji
telegram.reactiontypeemoji
telegram.reactiontypepaid
telegram.replykeyboardmarkup
telegram.replykeyboardremove
telegram.replyparameters
+15
View File
@@ -1,6 +1,21 @@
.. _games-tree:
Games
-----
Your bot can offer users **HTML5 games** to play solo or to compete against each other in groups and one-on-one chats. Create games via `@BotFather <https://telegram.me/BotFather>`_ using the ``/newgame`` command. Please note that this kind of power requires responsibility: you will need to accept the terms for each game that your bots will be offering.
* Games are a new type of content on Telegram, represented by the :class:`telegram.Game` and :class:`telegram.InlineQueryResultGame` objects.
* Once you've created a game via `BotFather <https://t.me/botfather>`_, you can send games to chats as regular messages using the :meth:`~telegram.Bot.sendGame` method, or use :ref:`inline mode <inline-tree>` with :class:`telegram.InlineQueryResultGame`.
* If you send the game message without any buttons, it will automatically have a 'Play ``GameName``' button. When this button is pressed, your bot gets a :class:`telegram.CallbackQuery` with the ``game_short_name`` of the requested game. You provide the correct URL for this particular user and the app opens the game in the in-app browser.
* You can manually add multiple buttons to your game message. Please note that the first button in the first row **must always** launch the game, using the field ``callback_game`` in :class:`telegram.InlineKeyboardButton`. You can add extra buttons according to taste: e.g., for a description of the rules, or to open the game's official community.
* To make your game more attractive, you can upload a GIF animation that demonstrates the game to the users via `BotFather <https://t.me/botfather>`_ (see `Lumberjack <https://t.me/gamebot?game=lumberjack>`_ for example).
* A game message will also display high scores for the current chat. Use :meth:`~telegram.Bot.setGameScore` to post high scores to the chat with the game, add the :paramref:`~telegram.Bot.set_game_score.disable_edit_message` parameter to disable automatic update of the message with the current scoreboard.
* Use :meth:`~telegram.Bot.getGameHighScores` to get data for in-game high score tables.
* You can also add an extra sharing button for users to share their best score to different chats.
* For examples of what can be done using this new stuff, check the `@gamebot <https://t.me/gamebot>`_ and `@gamee <https://t.me/gamee>`_ bots.
.. toctree::
:titlesonly:
+8
View File
@@ -1,6 +1,14 @@
.. _inline-tree:
Inline Mode
-----------
The following methods and objects allow your bot to work in `inline mode <https://core.telegram.org/bots/inline>`_.
Please see Telegrams `Introduction to Inline bots <https://core.telegram.org/bots/inline>`_ for more details.
To enable this option, send the ``/setinline`` command to `@BotFather <https://t.me/botfather>`_ and provide the placeholder text that the user will see in the input field after typing your bot's name.
.. toctree::
:titlesonly:
+6
View File
@@ -0,0 +1,6 @@
InputPaidMedia
==============
.. autoclass:: telegram.InputPaidMedia
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
InputPaidMediaPhoto
===================
.. autoclass:: telegram.InputPaidMediaPhoto
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
InputPaidMediaVideo
===================
.. autoclass:: telegram.InputPaidMediaVideo
:members:
:show-inheritance:
+6
View File
@@ -0,0 +1,6 @@
PaidMedia
=========
.. autoclass:: telegram.PaidMedia
:members:
:show-inheritance:
+6
View File
@@ -0,0 +1,6 @@
PaidMediaInfo
=============
.. autoclass:: telegram.PaidMediaInfo
:members:
:show-inheritance:
+6
View File
@@ -0,0 +1,6 @@
PaidMediaPhoto
==============
.. autoclass:: telegram.PaidMediaPhoto
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
PaidMediaPreview
================
.. autoclass:: telegram.PaidMediaPreview
:members:
:show-inheritance:
+6
View File
@@ -0,0 +1,6 @@
PaidMediaVideo
==============
.. autoclass:: telegram.PaidMediaVideo
:members:
:show-inheritance:
+3
View File
@@ -1,6 +1,9 @@
Passport
--------
Passport is a unified authorization method for services that require personal identification. Users can upload their documents once, then instantly share their data with services that require real-world ID (finance, ICOs, etc.). Please see the `manual <https://core.telegram.org/passport>`_ for details.
.. toctree::
:titlesonly:
+17
View File
@@ -1,6 +1,11 @@
.. _payments-tree:
Payments
--------
Your bot can accept payments from Telegram users. Please see the `introduction to payments <https://core.telegram.org/bots/payments>`_ for more details on the process and how to set up payments for your bot.
.. toctree::
:titlesonly:
@@ -8,7 +13,19 @@ Payments
telegram.labeledprice
telegram.orderinfo
telegram.precheckoutquery
telegram.refundedpayment
telegram.revenuewithdrawalstate
telegram.revenuewithdrawalstatefailed
telegram.revenuewithdrawalstatepending
telegram.revenuewithdrawalstatesucceeded
telegram.shippingaddress
telegram.shippingoption
telegram.shippingquery
telegram.startransaction
telegram.startransactions
telegram.successfulpayment
telegram.transactionpartner
telegram.transactionpartnerfragment
telegram.transactionpartnerother
telegram.transactionpartnertelegramads
telegram.transactionpartneruser
@@ -0,0 +1,6 @@
ReactionTypePaid
================
.. autoclass:: telegram.ReactionTypePaid
:members:
:show-inheritance:
+6
View File
@@ -0,0 +1,6 @@
RefundedPayment
===============
.. autoclass:: telegram.RefundedPayment
:members:
:show-inheritance:
@@ -0,0 +1,7 @@
RevenueWithdrawalState
======================
.. autoclass:: telegram.RevenueWithdrawalState
:members:
:show-inheritance:
:inherited-members: TelegramObject
@@ -0,0 +1,7 @@
RevenueWithdrawalStateFailed
=============================
.. autoclass:: telegram.RevenueWithdrawalStateFailed
:members:
:show-inheritance:
:inherited-members: TelegramObject
@@ -0,0 +1,7 @@
RevenueWithdrawalStatePending
=============================
.. autoclass:: telegram.RevenueWithdrawalStatePending
:members:
:show-inheritance:
:inherited-members: TelegramObject
@@ -0,0 +1,7 @@
RevenueWithdrawalStateSucceeded
===============================
.. autoclass:: telegram.RevenueWithdrawalStateSucceeded
:members:
:show-inheritance:
:inherited-members: TelegramObject
+7
View File
@@ -0,0 +1,7 @@
StarTransaction
===============
.. autoclass:: telegram.StarTransaction
:members:
:show-inheritance:
:inherited-members: TelegramObject
@@ -0,0 +1,8 @@
StarTransactions
================
.. autoclass:: telegram.StarTransactions
:members:
:show-inheritance:
:inherited-members: TelegramObject
+2
View File
@@ -1,6 +1,8 @@
Stickers
--------
The following methods and objects allow your bot to handle stickers and sticker sets.
.. toctree::
:titlesonly:
@@ -0,0 +1,7 @@
TransactionPartner
==================
.. autoclass:: telegram.TransactionPartner
:members:
:show-inheritance:
:inherited-members: TelegramObject
@@ -0,0 +1,7 @@
TransactionPartnerFragment
==========================
.. autoclass:: telegram.TransactionPartnerFragment
:members:
:show-inheritance:
:inherited-members: TelegramObject
@@ -0,0 +1,7 @@
TransactionPartnerOther
=======================
.. autoclass:: telegram.TransactionPartnerOther
:members:
:show-inheritance:
:inherited-members: TelegramObject
@@ -0,0 +1,7 @@
TransactionPartnerTelegramAds
=============================
.. autoclass:: telegram.TransactionPartnerTelegramAds
:members:
:show-inheritance:
:inherited-members: TelegramObject
@@ -0,0 +1,7 @@
TransactionPartnerUser
======================
.. autoclass:: telegram.TransactionPartnerUser
:members:
:show-inheritance:
:inherited-members: TelegramObject
+7 -1
View File
@@ -16,6 +16,8 @@
.. |editreplymarkup| replace:: It is currently only possible to edit messages without :attr:`telegram.Message.reply_markup` or with inline keyboards.
.. |bcid_edit_time| replace:: Note that business messages that were not sent by the bot and do not contain an inline keyboard can only be edited within *48 hours* from the time they were sent.
.. |toapikwargsbase| replace:: These arguments are also considered by :meth:`~telegram.TelegramObject.to_dict` and :meth:`~telegram.TelegramObject.to_json`, i.e. when passing objects to Telegram. Passing them to Telegram is however not guaranteed to work for all kinds of objects, e.g. this will fail for objects that can not directly be JSON serialized.
.. |toapikwargsarg| replace:: Arbitrary keyword arguments. Can be used to store data for which there are no dedicated attributes. |toapikwargsbase|
@@ -58,10 +60,12 @@
.. |removed_thumb_note| replace:: Removed the deprecated argument and attribute ``thumb``.
.. |removed_thumb_url_note| replace:: Removed the deprecated argument and attribute ``thumb_url``.
.. |removed_thumb_url_note| replace:: Removed the deprecated argument and attribute ``thumb_url`` which made thumbnail_url mandatory.
.. |removed_thumb_wildcard_note| replace:: Removed the deprecated arguments and attributes ``thumb_*``.
.. |thumbnail_url_mandatory| replace:: Removal of the deprecated argument ``thumb_url`` made ``thumbnail_url`` mandatory.
.. |async_context_manager| replace:: Asynchronous context manager which
.. |reply_parameters| replace:: Description of the message to reply to.
@@ -82,6 +86,8 @@
.. |business_id_str| replace:: Unique identifier of the business connection on behalf of which the message will be sent.
.. |business_id_str_edit| replace:: Unique identifier of the business connection on behalf of which the message to be edited was sent
.. |message_effect_id| replace:: Unique identifier of the message effect to be added to the message; for private chats only.
.. |show_cap_above_med| replace:: :obj:`True`, if the caption must be shown above the message media.
+10 -10
View File
@@ -47,9 +47,9 @@ async def msg(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
# Files will be downloaded to current directory
for data in passport_data.decrypted_data: # This is where the data gets decrypted
if data.type == "phone_number":
print("Phone: ", data.phone_number)
logger.info("Phone: %s", data.phone_number)
elif data.type == "email":
print("Email: ", data.email)
logger.info("Email: %s", data.email)
if data.type in (
"personal_details",
"passport",
@@ -58,7 +58,7 @@ async def msg(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"internal_passport",
"address",
):
print(data.type, data.data)
logger.info(data.type, data.data)
if data.type in (
"utility_bill",
"bank_statement",
@@ -66,28 +66,28 @@ async def msg(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"passport_registration",
"temporary_registration",
):
print(data.type, len(data.files), "files")
logger.info(data.type, len(data.files), "files")
for file in data.files:
actual_file = await file.get_file()
print(actual_file)
logger.info(actual_file)
await actual_file.download_to_drive()
if (
data.type in ("passport", "driver_license", "identity_card", "internal_passport")
and data.front_side
):
front_file = await data.front_side.get_file()
print(data.type, front_file)
logger.info(data.type, front_file)
await front_file.download_to_drive()
if data.type in ("driver_license" and "identity_card") and data.reverse_side:
reverse_file = await data.reverse_side.get_file()
print(data.type, reverse_file)
logger.info(data.type, reverse_file)
await reverse_file.download_to_drive()
if (
data.type in ("passport", "driver_license", "identity_card", "internal_passport")
and data.selfie
):
selfie_file = await data.selfie.get_file()
print(data.type, selfie_file)
logger.info(data.type, selfie_file)
await selfie_file.download_to_drive()
if data.translation and data.type in (
"passport",
@@ -100,10 +100,10 @@ async def msg(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"passport_registration",
"temporary_registration",
):
print(data.type, len(data.translation), "translation")
logger.info(data.type, len(data.translation), "translation")
for file in data.translation:
actual_file = await file.get_file()
print(actual_file)
logger.info(actual_file)
await actual_file.download_to_drive()
+122 -8
View File
@@ -1,7 +1,116 @@
# PACKAGING
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
dynamic = ["version"]
name = "python-telegram-bot"
description = "We have made you a wrapper you can't refuse"
readme = "README.rst"
requires-python = ">=3.8"
license = "LGPL-3.0-only"
license-files = { paths = ["LICENSE", "LICENSE.dual", "LICENSE.lesser"] }
authors = [
{ name = "Leandro Toledo", email = "devs@python-telegram-bot.org" }
]
keywords = [
"python",
"telegram",
"bot",
"api",
"wrapper",
]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
"Operating System :: OS Independent",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Communications :: Chat",
"Topic :: Internet",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
]
dependencies = [
"httpx ~= 0.27",
]
[project.urls]
"Homepage" = "https://python-telegram-bot.org"
"Documentation" = "https://docs.python-telegram-bot.org"
"Bug Tracker" = "https://github.com/python-telegram-bot/python-telegram-bot/issues"
"Source Code" = "https://github.com/python-telegram-bot/python-telegram-bot"
"News" = "https://t.me/pythontelegrambotchannel"
"Changelog" = "https://docs.python-telegram-bot.org/en/stable/changelog.html"
"Support" = "https://t.me/pythontelegrambotgroup"
[project.optional-dependencies]
# Make sure to install those as additional_dependencies in the
# pre-commit hooks for pylint & mypy
# Also update the readme accordingly
#
# When dependencies release new versions and tests succeed, we should try to expand the allowed
# versions and only increase the lower bound if necessary
#
# When adding new groups, make sure to update `ext` and `all` accordingly
# Optional dependencies for production
all = [
"python-telegram-bot[ext,http2,passport,socks]",
]
callback-data = [
# Cachetools doesn't have a strict stability policy. Let's be cautious for now.
"cachetools>=5.3.3,<5.6.0",
]
ext = [
"python-telegram-bot[callback-data,job-queue,rate-limiter,webhooks]",
]
http2 = [
"httpx[http2]",
]
job-queue = [
# APS doesn't have a strict stability policy. Let's be cautious for now.
"APScheduler~=3.10.4",
# pytz is required by APS and just needs the lower bound due to #2120
"pytz>=2018.6",
]
passport = [
"cryptography!=3.4,!=3.4.1,!=3.4.2,!=3.4.3,>=39.0.1",
# cffi is a dependency of cryptography and added support for python 3.13 in 1.17.0rc1
"cffi >= 1.17.0rc1; python_version > '3.12'"
]
rate-limiter = [
"aiolimiter~=1.1.0",
]
socks = [
"httpx[socks]",
]
webhooks = [
# tornado is rather stable, but let's not allow the next major release without prior testing
"tornado~=6.4",
]
# HATCH
[tool.hatch.version]
# dynamically evaluates the `__version__` variable in that file
source = "code"
path = "telegram/_version.py"
search-paths = ["telegram"]
[tool.hatch.build]
packages = ["telegram"]
# BLACK:
[tool.black]
line-length = 99
target-version = ['py38', 'py39', 'py310', 'py311']
# ISORT:
[tool.isort] # black config
@@ -11,24 +120,29 @@ line_length = 99
# RUFF:
[tool.ruff]
line-length = 99
target-version = "py38"
show-fixes = true
[tool.ruff.lint]
preview = true
explicit-preview-rules = true
explicit-preview-rules = true # TODO: Drop this when RUF022 and RUF023 are out of preview
ignore = ["PLR2004", "PLR0911", "PLR0912", "PLR0913", "PLR0915", "PERF203"]
select = ["E", "F", "I", "PL", "UP", "RUF", "PTH", "C4", "B", "PIE", "SIM", "RET", "RSE",
"G", "ISC", "PT", "ASYNC", "TCH", "SLOT", "PERF", "PYI", "FLY", "AIR", "RUF022",
"RUF023", "Q", "INP", "W", "YTT", "DTZ", "ARG"]
# Add "FURB" after it's out of preview
"RUF023", "Q", "INP", "W", "YTT", "DTZ", "ARG", "T20", "FURB", "DOC", "TRY",
"D100", "D101", "D102", "D103", "D300", "D418", "D419", "S"]
# Add "A (flake8-builtins)" after we drop pylint
[tool.ruff.lint.per-file-ignores]
"tests/*.py" = ["B018"]
"tests/**.py" = ["RUF012", "ASYNC101", "DTZ", "ARG"]
"docs/**.py" = ["INP001", "ARG"]
"examples/**.py" = ["ARG"]
"tests/**.py" = ["RUF012", "ASYNC230", "DTZ", "ARG", "T201", "ASYNC109", "D", "S", "TRY"]
"telegram/**.py" = ["TRY003"]
"telegram/ext/_applicationbuilder.py" = ["TRY004"]
"telegram/ext/filters.py" = ["D102"]
"docs/**.py" = ["INP001", "ARG", "D", "TRY003", "S"]
"examples/**.py" = ["ARG", "D", "S105", "TRY003"]
[tool.ruff.lint.pydocstyle]
convention = "google"
# PYLINT:
[tool.pylint."messages control"]
-4
View File
@@ -1,4 +0,0 @@
-r requirements.txt
-r requirements-dev.txt
-r requirements-opts.txt
-r docs/requirements-docs.txt
+5
View File
@@ -0,0 +1,5 @@
-e .[all]
# needed for pre-commit hooks in the git commit command
pre-commit
-r requirements-unit-tests.txt
-r docs/requirements-docs.txt
-11
View File
@@ -1,11 +0,0 @@
pre-commit # needed for pre-commit hooks in the git commit command
# For the test suite
setuptools # required for test_meta
pytest==8.2.1
pytest-asyncio==0.21.2 # needed because pytest doesn't come with native support for coroutines as tests
pytest-xdist==3.6.1 # xdist runs tests in parallel
flaky # Used for flaky tests (flaky decorator)
beautifulsoup4 # used in test_official for parsing tg docs
wheel # required for building the wheels for releases
-27
View File
@@ -1,27 +0,0 @@
# Format:
# package_name==version # req-1, req-2, req-3!ext
# `pip install ptb-raw[req-1/2]` will install `package_name`
# `pip install ptb[req-1/2/3]` will also install `package_name`
# Make sure to install those as additional_dependencies in the
# pre-commit hooks for pylint & mypy
# Also update the readme accordingly
# When dependencies release new versions and tests succeed, we should try to expand the allowed
# versions and only increase the lower bound if necessary
httpx[socks] # socks
httpx[http2] # http2
cryptography!=3.4,!=3.4.1,!=3.4.2,!=3.4.3,>=39.0.1 # passport
aiolimiter~=1.1.0 # rate-limiter!ext
# tornado is rather stable, but let's not allow the next mayor release without prior testing
tornado~=6.4 # webhooks!ext
# Cachetools and APS don't have a strict stability policy.
# Let's be cautious for now.
cachetools~=5.3.3 # callback-data!ext
APScheduler~=3.10.4 # job-queue!ext
# pytz is required by APS and just needs the lower bound due to #2120
pytz>=2018.6 # job-queue!ext
+19
View File
@@ -0,0 +1,19 @@
-e .
# required for building the wheels for releases
build
# For the test suite
pytest==8.3.2
# needed because pytest doesn't come with native support for coroutines as tests
pytest-asyncio==0.21.2
# xdist runs tests in parallel
pytest-xdist==3.6.1
# Used for flaky tests (flaky decorator)
flaky>=3.8.1
# used in test_official for parsing tg docs
beautifulsoup4
-10
View File
@@ -1,10 +0,0 @@
# Make sure to install those as additional_dependencies in the
# pre-commit hooks for pylint & mypy
# Also update the readme accordingly
# When dependencies release new versions and tests succeed, we should try to expand the allowed
# versions and only increase the lower bound if necessary
# httpx has no stable release yet, but we've had no stability problems since v20.0a0 either
# Since there have been requests to relax the bound a bit, we allow versions < 1.0.0
httpx ~= 0.27
+1 -4
View File
@@ -1,8 +1,5 @@
[metadata]
license_files = LICENSE, LICENSE.dual, LICENSE.lesser
[flake8]
max-line-length = 99
ignore = W503, W605
extend-ignore = E203, E704
exclude = setup.py, setup_raw.py docs/source/conf.py
exclude = docs/source/conf.py
-131
View File
@@ -1,131 +0,0 @@
#!/usr/bin/env python
"""The setup and build script for the python-telegram-bot library."""
import subprocess
import sys
from collections import defaultdict
from pathlib import Path
from typing import Any, Dict, List, Tuple
from setuptools import find_packages, setup
def get_requirements() -> List[str]:
"""Build the requirements list for this project"""
requirements_list = []
with Path("requirements.txt").open(encoding="utf-8") as reqs:
for install in reqs:
if install.startswith("#"):
continue
requirements_list.append(install.strip())
return requirements_list
def get_packages_requirements(raw: bool = False) -> Tuple[List[str], List[str]]:
"""Build the package & requirements list for this project"""
reqs = get_requirements()
exclude = ["tests*", "docs*"]
if raw:
exclude.append("telegram.ext*")
packs = find_packages(exclude=exclude)
return packs, reqs
def get_optional_requirements(raw: bool = False) -> Dict[str, List[str]]:
"""Build the optional dependencies"""
requirements = defaultdict(list)
with Path("requirements-opts.txt").open(encoding="utf-8") as reqs:
for line in reqs:
effective_line = line.strip()
if not effective_line or effective_line.startswith("#"):
continue
dependency, names = effective_line.split("#")
dependency = dependency.strip()
for name in names.split(","):
effective_name = name.strip()
if effective_name.endswith("!ext"):
if raw:
continue
effective_name = effective_name[:-4]
requirements["ext"].append(dependency)
requirements[effective_name].append(dependency)
requirements["all"].append(dependency)
return requirements
def get_setup_kwargs(raw: bool = False) -> Dict[str, Any]:
"""Builds a dictionary of kwargs for the setup function"""
packages, requirements = get_packages_requirements(raw=raw)
raw_ext = "-raw" if raw else ""
readme = Path(f'README{"_RAW" if raw else ""}.rst')
version_file = Path("telegram/_version.py").read_text(encoding="utf-8")
first_part = version_file.split("# SETUP.PY MARKER")[0]
exec(first_part) # pylint: disable=exec-used
return {
"script_name": f"setup{raw_ext}.py",
"name": f"python-telegram-bot{raw_ext}",
"version": locals()["__version__"],
"author": "Leandro Toledo",
"author_email": "devs@python-telegram-bot.org",
"license": "LGPLv3",
"url": "https://python-telegram-bot.org/",
# Keywords supported by PyPI can be found at
# https://github.com/pypa/warehouse/blob/aafc5185e57e67d43487ce4faa95913dd4573e14/
# warehouse/templates/packaging/detail.html#L20-L58
"project_urls": {
"Documentation": "https://docs.python-telegram-bot.org",
"Bug Tracker": "https://github.com/python-telegram-bot/python-telegram-bot/issues",
"Source Code": "https://github.com/python-telegram-bot/python-telegram-bot",
"News": "https://t.me/pythontelegrambotchannel",
"Changelog": "https://docs.python-telegram-bot.org/en/stable/changelog.html",
},
"download_url": f"https://pypi.org/project/python-telegram-bot{raw_ext}/",
"keywords": "python telegram bot api wrapper",
"description": "We have made you a wrapper you can't refuse",
"long_description": readme.read_text(encoding="utf-8"),
"long_description_content_type": "text/x-rst",
"packages": packages,
"install_requires": requirements,
"extras_require": get_optional_requirements(raw=raw),
"include_package_data": True,
"classifiers": [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
"Operating System :: OS Independent",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Communications :: Chat",
"Topic :: Internet",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
],
"python_requires": ">=3.8",
}
def main() -> None:
# If we're building, build ptb-raw as well
if set(sys.argv[1:]) in [{"bdist_wheel"}, {"sdist"}, {"sdist", "bdist_wheel"}]:
args = ["python", "setup_raw.py"]
args.extend(sys.argv[1:])
subprocess.run(args, check=True, capture_output=True)
setup(**get_setup_kwargs(raw=False))
if __name__ == "__main__":
main()
-8
View File
@@ -1,8 +0,0 @@
#!/usr/bin/env python
"""The setup and build script for the python-telegram-bot-raw library."""
from setuptools import setup
from setup import get_setup_kwargs
setup(**get_setup_kwargs(raw=True))
+48 -31
View File
@@ -142,6 +142,9 @@ __all__ = (
"InputMediaPhoto",
"InputMediaVideo",
"InputMessageContent",
"InputPaidMedia",
"InputPaidMediaPhoto",
"InputPaidMediaVideo",
"InputPollOption",
"InputSticker",
"InputTextMessageContent",
@@ -173,6 +176,11 @@ __all__ = (
"MessageReactionCountUpdated",
"MessageReactionUpdated",
"OrderInfo",
"PaidMedia",
"PaidMediaInfo",
"PaidMediaPhoto",
"PaidMediaPreview",
"PaidMediaVideo",
"PassportData",
"PassportElementError",
"PassportElementErrorDataField",
@@ -196,10 +204,16 @@ __all__ = (
"ReactionType",
"ReactionTypeCustomEmoji",
"ReactionTypeEmoji",
"ReactionTypePaid",
"RefundedPayment",
"ReplyKeyboardMarkup",
"ReplyKeyboardRemove",
"ReplyParameters",
"ResidentialAddress",
"RevenueWithdrawalState",
"RevenueWithdrawalStateFailed",
"RevenueWithdrawalStatePending",
"RevenueWithdrawalStateSucceeded",
"SecureData",
"SecureValue",
"SentWebAppMessage",
@@ -207,6 +221,8 @@ __all__ = (
"ShippingAddress",
"ShippingOption",
"ShippingQuery",
"StarTransaction",
"StarTransactions",
"Sticker",
"StickerSet",
"Story",
@@ -214,6 +230,11 @@ __all__ = (
"SwitchInlineQueryChosenChat",
"TelegramObject",
"TextQuote",
"TransactionPartner",
"TransactionPartnerFragment",
"TransactionPartnerOther",
"TransactionPartnerTelegramAds",
"TransactionPartnerUser",
"Update",
"User",
"UserChatBoosts",
@@ -242,8 +263,6 @@ __all__ = (
"warnings",
)
from pathlib import Path
from . import _version, constants, error, helpers, request, warnings
from ._birthdate import Birthdate
from ._bot import Bot
@@ -325,6 +344,9 @@ from ._files.inputmedia import (
InputMediaDocument,
InputMediaPhoto,
InputMediaVideo,
InputPaidMedia,
InputPaidMediaPhoto,
InputPaidMediaVideo,
)
from ._files.inputsticker import InputSticker
from ._files.location import Location
@@ -397,6 +419,7 @@ from ._messageorigin import (
MessageOriginUser,
)
from ._messagereactionupdated import MessageReactionCountUpdated, MessageReactionUpdated
from ._paidmedia import PaidMedia, PaidMediaInfo, PaidMediaPhoto, PaidMediaPreview, PaidMediaVideo
from ._passport.credentials import (
Credentials,
DataCredentials,
@@ -425,13 +448,33 @@ from ._payment.invoice import Invoice
from ._payment.labeledprice import LabeledPrice
from ._payment.orderinfo import OrderInfo
from ._payment.precheckoutquery import PreCheckoutQuery
from ._payment.refundedpayment import RefundedPayment
from ._payment.shippingaddress import ShippingAddress
from ._payment.shippingoption import ShippingOption
from ._payment.shippingquery import ShippingQuery
from ._payment.stars import (
RevenueWithdrawalState,
RevenueWithdrawalStateFailed,
RevenueWithdrawalStatePending,
RevenueWithdrawalStateSucceeded,
StarTransaction,
StarTransactions,
TransactionPartner,
TransactionPartnerFragment,
TransactionPartnerOther,
TransactionPartnerTelegramAds,
TransactionPartnerUser,
)
from ._payment.successfulpayment import SuccessfulPayment
from ._poll import InputPollOption, Poll, PollAnswer, PollOption
from ._proximityalerttriggered import ProximityAlertTriggered
from ._reaction import ReactionCount, ReactionType, ReactionTypeCustomEmoji, ReactionTypeEmoji
from ._reaction import (
ReactionCount,
ReactionType,
ReactionTypeCustomEmoji,
ReactionTypeEmoji,
ReactionTypePaid,
)
from ._reply import ExternalReplyInfo, ReplyParameters, TextQuote
from ._replykeyboardmarkup import ReplyKeyboardMarkup
from ._replykeyboardremove import ReplyKeyboardRemove
@@ -443,7 +486,6 @@ from ._telegramobject import TelegramObject
from ._update import Update
from ._user import User
from ._userprofilephotos import UserProfilePhotos
from ._utils.warnings import warn
from ._videochat import (
VideoChatEnded,
VideoChatParticipantsInvited,
@@ -472,33 +514,8 @@ __version_info__: _version.Version = _version.__version_info__
#:
#: .. versionchanged:: 20.0
#: This constant was previously named ``bot_api_version``.
__bot_api_version__: str = _version.__bot_api_version__
__bot_api_version__: str = constants.BOT_API_VERSION
#: :class:`typing.NamedTuple`: Shortcut for :const:`telegram.constants.BOT_API_VERSION_INFO`.
#:
#: .. versionadded:: 20.0
__bot_api_version_info__: constants._BotAPIVersion = _version.__bot_api_version_info__
if not (Path(__file__).parent.resolve().absolute() / "ext").exists():
_MESSAGE = (
"Hey. You seem to be using the `python-telegram-bot-raw` library. "
"Please note that this libray has been deprecated and will no longer be updated. "
"Please instead use the `python-telegram-bot` library. The change requires no "
"changes in your code and requires no additional dependencies. For additional "
"information, please see the channel post at "
"https://t.me/pythontelegrambotchannel/145."
)
# DeprecationWarning is ignored by default in Python 3.7 and later by default outside
# __main__ modules. We use both warning categories to increase the chance of the user
# seeing the warning.
warn(
warnings.PTBDeprecationWarning(version="21.3", message=_MESSAGE),
stacklevel=2,
)
warn(
message=_MESSAGE,
category=warnings.PTBUserWarning,
stacklevel=2,
)
__bot_api_version_info__: constants._BotAPIVersion = constants.BOT_API_VERSION_INFO
+1
View File
@@ -17,6 +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/].
# pylint: disable=missing-module-docstring
# ruff: noqa: T201, D100, S603, S607
import subprocess
import sys
from typing import Optional
+406 -81
View File
@@ -18,6 +18,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 Bot."""
import asyncio
import contextlib
import copy
@@ -70,7 +71,7 @@ from telegram._files.chatphoto import ChatPhoto
from telegram._files.contact import Contact
from telegram._files.document import Document
from telegram._files.file import File
from telegram._files.inputmedia import InputMedia
from telegram._files.inputmedia import InputMedia, InputPaidMedia
from telegram._files.location import Location
from telegram._files.photosize import PhotoSize
from telegram._files.sticker import MaskPosition, Sticker, StickerSet
@@ -84,6 +85,7 @@ from telegram._inline.inlinequeryresultsbutton import InlineQueryResultsButton
from telegram._menubutton import MenuButton
from telegram._message import Message
from telegram._messageid import MessageId
from telegram._payment.stars import StarTransactions
from telegram._poll import InputPollOption, Poll
from telegram._reaction import ReactionType, ReactionTypeCustomEmoji, ReactionTypeEmoji
from telegram._reply import ReplyParameters
@@ -323,10 +325,10 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
"""
try:
await self.initialize()
return self
except Exception as exc:
except Exception:
await self.shutdown()
raise exc
raise
return self
async def __aexit__(
self,
@@ -577,13 +579,16 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
with new._unfrozen():
new.parse_mode = DefaultValue.get_value(new.parse_mode)
data[key] = new
elif key == "media" and isinstance(val, Sequence):
elif (
key == "media"
and isinstance(val, Sequence)
and not isinstance(val[0], InputPaidMedia)
):
# Copy objects as not to edit them in-place
copy_list = [copy.copy(media) for media in val]
for media in copy_list:
with media._unfrozen():
media.parse_mode = DefaultValue.get_value(media.parse_mode)
data[key] = copy_list
# 2)
else:
@@ -1301,8 +1306,8 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
Args:
chat_id (:obj:`int` | :obj:`str`): |chat_id_channel|
photo (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | \
:class:`telegram.PhotoSize`): Photo to send.
photo (:obj:`str` | :term:`file object` | :class:`~telegram.InputFile` | :obj:`bytes` \
| :class:`pathlib.Path` | :class:`telegram.PhotoSize`): Photo to send.
|fileinput|
Lastly you can pass an existing :class:`telegram.PhotoSize` object to send.
@@ -1461,9 +1466,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
Args:
chat_id (:obj:`int` | :obj:`str`): |chat_id_channel|
audio (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | \
:class:`telegram.Audio`): Audio file to send.
|fileinput|
audio (:obj:`str` | :term:`file object` | :class:`~telegram.InputFile` | \
:obj:`bytes` | :class:`pathlib.Path` | :class:`telegram.Audio`): Audio file to
send. |fileinput|
Lastly you can pass an existing :class:`telegram.Audio` object to send.
.. versionchanged:: 13.2
@@ -1613,8 +1618,8 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
Args:
chat_id (:obj:`int` | :obj:`str`): |chat_id_channel|
document (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | \
:class:`telegram.Document`): File to send.
document (:obj:`str` | :term:`file object` | :class:`~telegram.InputFile` | \
:obj:`bytes` | :class:`pathlib.Path` | :class:`telegram.Document`): File to send.
|fileinput|
Lastly you can pass an existing :class:`telegram.Document` object to send.
@@ -1751,8 +1756,8 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
Args:
chat_id (:obj:`int` | :obj:`str`): |chat_id_channel|
sticker (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | \
:class:`telegram.Sticker`): Sticker to send.
sticker (:obj:`str` | :term:`file object` | :class:`~telegram.InputFile` | \
:obj:`bytes` | :class:`pathlib.Path` | :class:`telegram.Sticker`): Sticker to send.
|fileinput| Video stickers can only be sent by a ``file_id``. Video and animated
stickers can't be sent via an HTTP URL.
@@ -1891,8 +1896,8 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
Args:
chat_id (:obj:`int` | :obj:`str`): |chat_id_channel|
video (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | \
:class:`telegram.Video`): Video file to send.
video (:obj:`str` | :term:`file object` | :class:`~telegram.InputFile` | :obj:`bytes` \
| :class:`pathlib.Path` | :class:`telegram.Video`): Video file to send.
|fileinput|
Lastly you can pass an existing :class:`telegram.Video` object to send.
@@ -2055,8 +2060,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
Args:
chat_id (:obj:`int` | :obj:`str`): |chat_id_channel|
video_note (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | \
:class:`telegram.VideoNote`): Video note to send.
video_note (:obj:`str` | :term:`file object` | :class:`~telegram.InputFile` | \
:obj:`bytes` | :class:`pathlib.Path` | :class:`telegram.VideoNote`): Video note
to send.
Pass a file_id as String to send a video note that exists on the Telegram
servers (recommended) or upload a new video using multipart/form-data.
|uploadinput|
@@ -2205,9 +2211,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
Args:
chat_id (:obj:`int` | :obj:`str`): |chat_id_channel|
animation (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | \
:class:`telegram.Animation`): Animation to send.
|fileinput|
animation (:obj:`str` | :term:`file object` | :class:`~telegram.InputFile` | \
:obj:`bytes` | :class:`pathlib.Path` | :class:`telegram.Animation`): Animation to
send. |fileinput|
Lastly you can pass an existing :class:`telegram.Animation` object to send.
.. versionchanged:: 13.2
@@ -2367,8 +2373,8 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
Args:
chat_id (:obj:`int` | :obj:`str`): |chat_id_channel|
voice (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | \
:class:`telegram.Voice`): Voice file to send.
voice (:obj:`str` | :term:`file object` | :class:`~telegram.InputFile` | :obj:`bytes` \
| :class:`pathlib.Path` | :class:`telegram.Voice`): Voice file to send.
|fileinput|
Lastly you can pass an existing :class:`telegram.Voice` object to send.
@@ -2802,6 +2808,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
heading: Optional[int] = None,
proximity_alert_radius: Optional[int] = None,
live_period: Optional[int] = None,
business_connection_id: Optional[str] = None,
*,
location: Optional[Location] = None,
read_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -2849,6 +2856,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
remains unchanged
.. versionadded:: 21.2.
business_connection_id (:obj:`str`, optional): |business_id_str_edit|
.. versionadded:: 21.4
Keyword Args:
location (:class:`telegram.Location`, optional): The location to send.
@@ -2888,6 +2898,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
"editMessageLiveLocation",
data,
reply_markup=reply_markup,
business_connection_id=business_connection_id,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
@@ -2901,6 +2912,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_id: Optional[int] = None,
inline_message_id: Optional[str] = None,
reply_markup: Optional["InlineKeyboardMarkup"] = None,
business_connection_id: Optional[str] = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -2920,6 +2932,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
:paramref:`message_id` are not specified. Identifier of the inline message.
reply_markup (:class:`telegram.InlineKeyboardMarkup`, optional): An object for a new
inline keyboard.
business_connection_id (:obj:`str`, optional): |business_id_str_edit|
.. versionadded:: 21.4
Returns:
:class:`telegram.Message`: On success, if edited message is not an inline message, the
@@ -2935,6 +2950,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
"stopMessageLiveLocation",
data,
reply_markup=reply_markup,
business_connection_id=business_connection_id,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
@@ -3945,6 +3961,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
reply_markup: Optional["InlineKeyboardMarkup"] = None,
entities: Optional[Sequence["MessageEntity"]] = None,
link_preview_options: ODVInput["LinkPreviewOptions"] = DEFAULT_NONE,
business_connection_id: Optional[str] = None,
*,
disable_web_page_preview: Optional[bool] = None,
read_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -3957,7 +3974,8 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
Use this method to edit text and game messages.
Note:
|editreplymarkup|.
* |editreplymarkup|
* |bcid_edit_time|
.. seealso:: :attr:`telegram.Game.text`
@@ -3988,6 +4006,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
reply_markup (:class:`telegram.InlineKeyboardMarkup`, optional): An object for an
inline keyboard.
business_connection_id (:obj:`str`, optional): |business_id_str_edit|
.. versionadded:: 21.4
Keyword Args:
disable_web_page_preview (:obj:`bool`, optional): Disables link previews for links in
@@ -4029,6 +4050,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
reply_markup=reply_markup,
parse_mode=parse_mode,
link_preview_options=link_preview_options,
business_connection_id=business_connection_id,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
@@ -4046,6 +4068,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
show_caption_above_media: Optional[bool] = None,
business_connection_id: Optional[str] = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -4057,7 +4080,8 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
Use this method to edit captions of messages.
Note:
|editreplymarkup|
* |editreplymarkup|
* |bcid_edit_time|
Args:
chat_id (:obj:`int` | :obj:`str`, optional): Required if inline_message_id is not
@@ -4080,6 +4104,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
.. versionadded:: 21.3
business_connection_id (:obj:`str`, optional): |business_id_str_edit|
.. versionadded:: 21.4
Returns:
:class:`telegram.Message`: On success, if edited message is not an inline message, the
@@ -4103,6 +4130,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
caption=caption,
parse_mode=parse_mode,
caption_entities=caption_entities,
business_connection_id=business_connection_id,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
@@ -4117,6 +4145,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_id: Optional[int] = None,
inline_message_id: Optional[str] = None,
reply_markup: Optional["InlineKeyboardMarkup"] = None,
business_connection_id: Optional[str] = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -4132,7 +4161,8 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
:attr:`~telegram.File.file_id` or specify a URL.
Note:
|editreplymarkup|
* |editreplymarkup|
* |bcid_edit_time|
.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
@@ -4147,6 +4177,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
specified. Identifier of the inline message.
reply_markup (:class:`telegram.InlineKeyboardMarkup`, optional): An object for an
inline keyboard.
business_connection_id (:obj:`str`, optional): |business_id_str_edit|
.. versionadded:: 21.4
Returns:
:class:`telegram.Message`: On success, if edited message is not an inline message, the
@@ -4166,6 +4199,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
"editMessageMedia",
data,
reply_markup=reply_markup,
business_connection_id=business_connection_id,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
@@ -4179,6 +4213,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_id: Optional[int] = None,
inline_message_id: Optional[str] = None,
reply_markup: Optional["InlineKeyboardMarkup"] = None,
business_connection_id: Optional[str] = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -4191,7 +4226,8 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
(for inline bots).
Note:
|editreplymarkup|
* |editreplymarkup|
* |bcid_edit_time|
Args:
chat_id (:obj:`int` | :obj:`str`, optional): Required if inline_message_id is not
@@ -4202,6 +4238,9 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
specified. Identifier of the inline message.
reply_markup (:class:`telegram.InlineKeyboardMarkup`, optional): An object for an
inline keyboard.
business_connection_id (:obj:`str`, optional): |business_id_str_edit|
.. versionadded:: 21.4
Returns:
:class:`telegram.Message`: On success, if edited message is not an inline message, the
@@ -4221,6 +4260,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
"editMessageReplyMarkup",
data,
reply_markup=reply_markup,
business_connection_id=business_connection_id,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
@@ -4232,7 +4272,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
self,
offset: Optional[int] = None,
limit: Optional[int] = None,
timeout: Optional[int] = None,
timeout: Optional[int] = None, # noqa: ASYNC109
allowed_updates: Optional[Sequence[str]] = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -4339,7 +4379,16 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
else:
self._LOGGER.debug("No new updates found.")
return Update.de_list(result, self)
try:
return Update.de_list(result, self)
except Exception as exc:
# This logging is in place mostly b/c we can't access the raw json data in Updater,
# where the exception is caught and logged again. Still, it might also be beneficial
# for custom usages of `get_updates`.
self._LOGGER.critical(
"Error while parsing updates! Received data was %r", result, exc_info=exc
)
raise
async def set_webhook(
self,
@@ -4379,18 +4428,6 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
If you're having any trouble setting up webhooks, please check out this `guide to
Webhooks`_.
Note:
1. You will not be able to receive updates using :meth:`get_updates` for long as an
outgoing webhook is set up.
2. To use a self-signed certificate, you need to upload your public key certificate
using certificate parameter. Please upload as InputFile, sending a String will not
work.
3. Ports currently supported for Webhooks:
:attr:`telegram.constants.SUPPORTED_WEBHOOK_PORTS`.
If you're having any trouble setting up webhooks, please check out this `guide to
Webhooks`_.
.. seealso:: :meth:`telegram.ext.Application.run_webhook`,
:meth:`telegram.ext.Updater.start_webhook`
@@ -4971,7 +5008,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
payload (:obj:`str`): Bot-defined invoice payload.
:tg-const:`telegram.Invoice.MIN_PAYLOAD_LENGTH`-
:tg-const:`telegram.Invoice.MAX_PAYLOAD_LENGTH` bytes. This will not be
displayed to the user, use for your internal processes.
displayed to the user, use it for your internal processes.
provider_token (:obj:`str`): Payments provider token, obtained via
`@BotFather <https://t.me/BotFather>`_. Pass an empty string for payments in
|tg_stars|.
@@ -4990,15 +5027,16 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
.. versionchanged:: 20.0
|sequenceargs|
max_tip_amount (:obj:`int`, optional): The maximum accepted amount for tips in the
*smallest* units of the currency (integer, **not** float/double). For example, for
a maximum tip of US$ 1.45 pass ``max_tip_amount = 145``. See the exp parameter in
`currencies.json <https://core.telegram.org/bots/payments/currencies.json>`_, it
shows the number of digits past the decimal point for each currency (2 for the
majority of currencies). Defaults to ``0``. Not supported for payment in |tg_stars|
*smallest units* of the currency (integer, **not** float/double). For example, for
a maximum tip of ``US$ 1.45`` pass ``max_tip_amount = 145``. See the ``exp``
parameter in `currencies.json
<https://core.telegram.org/bots/payments/currencies.json>`_, it shows the number of
digits past the decimal point for each currency (2 for the majority of currencies).
Defaults to ``0``. Not supported for payment in |tg_stars|.
.. versionadded:: 13.5
suggested_tip_amounts (Sequence[:obj:`int`], optional): An array of
suggested amounts of tips in the *smallest* units of the currency (integer, **not**
suggested amounts of tips in the *smallest units* of the currency (integer, **not**
float/double). At most :tg-const:`telegram.Invoice.MAX_TIP_AMOUNTS` suggested tip
amounts can be specified. The suggested tip amounts must be positive, passed in a
strictly increased order and must not exceed :paramref:`max_tip_amount`.
@@ -5736,10 +5774,10 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
Args:
chat_id (:obj:`int` | :obj:`str`): |chat_id_channel|
invite_link (:obj:`str` | :obj:`telegram.ChatInviteLink`): The invite link to edit.
invite_link (:obj:`str` | :class:`telegram.ChatInviteLink`): The invite link to edit.
.. versionchanged:: 20.0
Now also accepts :obj:`telegram.ChatInviteLink` instances.
Now also accepts :class:`telegram.ChatInviteLink` instances.
expire_date (:obj:`int` | :obj:`datetime.datetime`, optional): Date when the link will
expire.
For timezone naive :obj:`datetime.datetime` objects, the default timezone of the
@@ -5808,10 +5846,10 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
Args:
chat_id (:obj:`int` | :obj:`str`): |chat_id_channel|
invite_link (:obj:`str` | :obj:`telegram.ChatInviteLink`): The invite link to revoke.
invite_link (:obj:`str` | :class:`telegram.ChatInviteLink`): The invite link to revoke.
.. versionchanged:: 20.0
Now also accepts :obj:`telegram.ChatInviteLink` instances.
Now also accepts :class:`telegram.ChatInviteLink` instances.
Returns:
:class:`telegram.ChatInviteLink`
@@ -6083,6 +6121,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
chat_id: Union[str, int],
message_id: int,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
business_connection_id: Optional[str] = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -6103,6 +6142,10 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
disable_notification (:obj:`bool`, optional): Pass :obj:`True`, if it is not necessary
to send a notification to all chat members about the new pinned message.
Notifications are always disabled in channels and private chats.
business_connection_id (:obj:`str`, optional): Unique identifier of the business
connection on behalf of which the message will be pinned.
.. versionadded:: 21.5
Returns:
:obj:`bool`: On success, :obj:`True` is returned.
@@ -6115,6 +6158,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
"chat_id": chat_id,
"message_id": message_id,
"disable_notification": disable_notification,
"business_connection_id": business_connection_id,
}
return await self._post(
@@ -6131,6 +6175,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
self,
chat_id: Union[str, int],
message_id: Optional[int] = None,
business_connection_id: Optional[str] = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -6147,8 +6192,13 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
Args:
chat_id (:obj:`int` | :obj:`str`): |chat_id_channel|
message_id (:obj:`int`, optional): Identifier of a message to unpin. If not specified,
message_id (:obj:`int`, optional): Identifier of the message to unpin. Required if
:paramref:`business_connection_id` is specified. If not specified,
the most recent pinned message (by sending date) will be unpinned.
business_connection_id (:obj:`str`, optional): Unique identifier of the business
connection on behalf of which the message will be unpinned.
.. versionadded:: 21.5
Returns:
:obj:`bool`: On success, :obj:`True` is returned.
@@ -6157,7 +6207,11 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
:class:`telegram.error.TelegramError`
"""
data: JSONDict = {"chat_id": chat_id, "message_id": message_id}
data: JSONDict = {
"chat_id": chat_id,
"message_id": message_id,
"business_connection_id": business_connection_id,
}
return await self._post(
"unpinChatMessage",
@@ -6306,8 +6360,9 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
Args:
user_id (:obj:`int`): User identifier of sticker file owner.
sticker (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path`):
A file with the sticker in the ``".WEBP"``, ``".PNG"``, ``".TGS"`` or ``".WEBM"``
sticker (:obj:`str` | :term:`file object` | :class:`~telegram.InputFile` | \
:obj:`bytes` | :class:`pathlib.Path`): A file with the sticker in the
``".WEBP"``, ``".PNG"``, ``".TGS"`` or ``".WEBM"``
format. See `here <https://core.telegram.org/stickers>`_ for technical requirements
. |uploadinput|
@@ -6631,8 +6686,9 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
.. versionadded:: 21.1
thumbnail (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path`, \
optional): A **.WEBP** or **.PNG** image with the thumbnail, must
thumbnail (:obj:`str` | :term:`file object` | :class:`~telegram.InputFile` | \
:obj:`bytes` | :class:`pathlib.Path`, optional): A **.WEBP** or **.PNG** image
with the thumbnail, must
be up to :tg-const:`telegram.constants.StickerSetLimit.MAX_STATIC_THUMBNAIL_SIZE`
kilobytes in size and have width and height of exactly
:tg-const:`telegram.constants.StickerSetLimit.STATIC_THUMB_DIMENSIONS` px, or a
@@ -7119,6 +7175,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
chat_id: Union[int, str],
message_id: int,
reply_markup: Optional["InlineKeyboardMarkup"] = None,
business_connection_id: Optional[str] = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -7134,6 +7191,9 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
message_id (:obj:`int`): Identifier of the original message with the poll.
reply_markup (:class:`telegram.InlineKeyboardMarkup`, optional): An object for a new
message inline keyboard.
business_connection_id (:obj:`str`, optional): |business_id_str_edit|
.. versionadded:: 21.4
Returns:
:class:`telegram.Poll`: On success, the stopped Poll is returned.
@@ -7146,6 +7206,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
"chat_id": chat_id,
"message_id": message_id,
"reply_markup": reply_markup,
"business_connection_id": business_connection_id,
}
result = await self._post(
@@ -7330,8 +7391,9 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
.. versionadded:: 20.0
Args:
rights (:obj:`telegram.ChatAdministratorRights`, optional): A
:obj:`telegram.ChatAdministratorRights` object describing new default administrator
rights (:class:`telegram.ChatAdministratorRights`, optional): A
:class:`telegram.ChatAdministratorRights` object describing new default
administrator
rights. If not specified, the default administrator rights will be cleared.
for_channels (:obj:`bool`, optional): Pass :obj:`True` to change the default
administrator rights of the bot in channels. Otherwise, the default administrator
@@ -7341,7 +7403,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
:obj:`bool`: Returns :obj:`True` on success.
Raises:
:obj:`telegram.error.TelegramError`
:exc:`telegram.error.TelegramError`
"""
data: JSONDict = {"rights": rights, "for_channels": for_channels}
@@ -7605,7 +7667,8 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> MessageId:
"""Use this method to copy messages of any kind. Service messages and invoice messages
"""Use this method to copy messages of any kind. Service messages, paid media messages,
giveaway messages, giveaway winners messages, and invoice messages
can't be copied. The method is analogous to the method :meth:`forward_message`, but the
copied message doesn't have a link to the original message.
@@ -7731,11 +7794,12 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
) -> 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, giveaway messages, giveaway winners
messages, and invoice messages can't be copied. A quiz poll can be copied only if the value
of the field correct_option_id is known to the bot. The method is analogous to the method
:meth:`forward_messages`, but the copied messages don't have a link to the original
message. Album grouping is kept for copied messages.
found or copied, they are skipped. Service messages, paid media messages, giveaway
messages, giveaway winners messages, and invoice messages can't be copied. A quiz poll can
be copied only if the value
of the field :attr:`telegram.Poll.correct_option_id` is known to the bot. The method is
analogous to the method :meth:`forward_messages`, but the copied messages don't have a
link to the original message. Album grouping is kept for copied messages.
.. versionadded:: 20.8
@@ -7905,7 +7969,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
payload (:obj:`str`): Bot-defined invoice payload.
:tg-const:`telegram.Invoice.MIN_PAYLOAD_LENGTH`-
:tg-const:`telegram.Invoice.MAX_PAYLOAD_LENGTH` bytes. This will not be
displayed to the user, use for your internal processes.
displayed to the user, use it for your internal processes.
provider_token (:obj:`str`): Payments provider token, obtained via
`@BotFather <https://t.me/BotFather>`_. Pass an empty string for payments in
|tg_stars|.
@@ -7924,14 +7988,14 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
.. versionchanged:: 20.0
|sequenceargs|
max_tip_amount (:obj:`int`, optional): The maximum accepted amount for tips in the
*smallest* units of the currency (integer, **not** float/double). For example, for
a maximum tip of US$ 1.45 pass ``max_tip_amount = 145``. See the exp parameter in
`currencies.json <https://core.telegram.org/bots/payments/currencies.json>`_, it
shows the number of digits past the decimal point for each currency (2 for the
majority of currencies). Defaults to ``0``. Not supported for payments in
|tg_stars|.
*smallest units* of the currency (integer, **not** float/double). For example, for
a maximum tip of ``US$ 1.45`` pass ``max_tip_amount = 145``. See the ``exp``
parameter in `currencies.json
<https://core.telegram.org/bots/payments/currencies.json>`_, it shows the number of
digits past the decimal point for each currency (2 for the majority of currencies).
Defaults to ``0``. Not supported for payments in |tg_stars|.
suggested_tip_amounts (Sequence[:obj:`int`], optional): An array of
suggested amounts of tips in the *smallest* units of the currency (integer, **not**
suggested amounts of tips in the *smallest units* of the currency (integer, **not**
float/double). At most :tg-const:`telegram.Invoice.MAX_TIP_AMOUNTS` suggested tip
amounts can be specified. The suggested tip amounts must be positive, passed in a
strictly increased order and must not exceed :paramref:`max_tip_amount`.
@@ -8105,7 +8169,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
) -> bool:
"""
Use this method to edit name and icon of a topic in a forum supergroup chat. The bot must
be an administrator in the chat for this to work and must have
be an administrator in the chat for this to work and must have the
:paramref:`~telegram.ChatAdministratorRights.can_manage_topics` administrator rights,
unless it is the creator of the topic.
@@ -8373,7 +8437,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
) -> bool:
"""
Use this method to edit the name of the 'General' topic in a forum supergroup chat. The bot
must be an administrator in the chat for this to work and must have
must be an administrator in the chat for this to work and must have the
:attr:`~telegram.ChatAdministratorRights.can_manage_topics` administrator rights.
.. versionadded:: 20.0
@@ -8872,7 +8936,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
"""
Use this method to change the chosen reactions on a message. Service messages can't be
reacted to. Automatically forwarded messages from a channel to its discussion group have
the same available reactions as messages in the channel.
the same available reactions as messages in the channel. Bots can't use paid reactions.
.. versionadded:: 20.8
@@ -8885,7 +8949,8 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
:class:`telegram.ReactionType` | :obj:`str`, optional): A list of reaction
types to set on the message. Currently, as non-premium users, bots can set up to
one reaction per message. A custom emoji reaction can be used if it is either
already present on the message or explicitly allowed by chat administrators.
already present on the message or explicitly allowed by chat administrators. Paid
reactions can't be used by bots.
Tip:
Passed :obj:`str` values will be converted to either
@@ -9002,7 +9067,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
user_id (:obj:`int`): User identifier of the sticker set owner.
name (:obj:`str`): Sticker set name.
old_sticker (:obj:`str`): File identifier of the replaced sticker.
sticker (:obj:`telegram.InputSticker`): An object with information about the added
sticker (:class:`telegram.InputSticker`): An object with information about the added
sticker. If exactly the same sticker had already been added to the set, then the
set remains unchanged.
@@ -9070,6 +9135,258 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
api_kwargs=api_kwargs,
)
async def get_star_transactions(
self,
offset: Optional[int] = None,
limit: Optional[int] = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> StarTransactions:
"""Returns the bot's Telegram Star transactions in chronological order.
.. versionadded:: 21.4
Args:
offset (:obj:`int`, optional): Number of transactions to skip in the response.
limit (:obj:`int`, optional): The maximum number of transactions to be retrieved.
Values between :tg-const:`telegram.constants.StarTransactionsLimit.MIN_LIMIT`-
:tg-const:`telegram.constants.StarTransactionsLimit.MAX_LIMIT` are accepted.
Defaults to :tg-const:`telegram.constants.StarTransactionsLimit.MAX_LIMIT`.
Returns:
:class:`telegram.StarTransactions`: On success.
Raises:
:class:`telegram.error.TelegramError`
"""
data: JSONDict = {"offset": offset, "limit": limit}
return StarTransactions.de_json( # type: ignore[return-value]
await self._post(
"getStarTransactions",
data,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
),
bot=self,
)
async def send_paid_media(
self,
chat_id: Union[str, int],
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,
business_connection_id: Optional[str] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Message:
"""Use this method to send paid media.
.. versionadded:: 21.4
Args:
chat_id (:obj:`int` | :obj:`str`): |chat_id_channel| If the chat is a channel, all
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.
media (Sequence[:class:`telegram.InputPaidMedia`]): A list describing the media to be
sent; up to :tg-const:`telegram.constants.MediaGroupLimit.MAX_MEDIA_LENGTH` items.
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|
caption_entities (Sequence[:class:`telegram.MessageEntity`], optional):
|caption_entities|
show_caption_above_media (:obj:`bool`, optional): Pass |show_cap_above_med|
disable_notification (:obj:`bool`, optional): |disable_notification|
protect_content (:obj:`bool`, optional): |protect_content|
reply_parameters (:class:`telegram.ReplyParameters`, optional): |reply_parameters|
reply_markup (:class:`InlineKeyboardMarkup` | :class:`ReplyKeyboardMarkup` | \
:class:`ReplyKeyboardRemove` | :class:`ForceReply`, optional):
Additional interface options. An object for an inline keyboard, custom reply
keyboard, instructions to remove reply keyboard or to force a reply from the user.
business_connection_id (:obj:`str`, optional): |business_id_str|
.. versionadded:: 21.5
Keyword Args:
allow_sending_without_reply (:obj:`bool`, optional): |allow_sending_without_reply|
Mutually exclusive with :paramref:`reply_parameters`, which this is a convenience
parameter for
reply_to_message_id (:obj:`int`, optional): |reply_to_msg_id|
Mutually exclusive with :paramref:`reply_parameters`, which this is a convenience
parameter for
Returns:
:class:`telegram.Message`: On success, the sent message is returned.
Raises:
:class:`telegram.error.TelegramError`
"""
data: JSONDict = {
"chat_id": chat_id,
"star_count": star_count,
"media": media,
"show_caption_above_media": show_caption_above_media,
}
return await self._send_message(
"sendPaidMedia",
data,
caption=caption,
parse_mode=parse_mode,
caption_entities=caption_entities,
disable_notification=disable_notification,
protect_content=protect_content,
reply_parameters=reply_parameters,
reply_markup=reply_markup,
allow_sending_without_reply=allow_sending_without_reply,
reply_to_message_id=reply_to_message_id,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
)
async def create_chat_subscription_invite_link(
self,
chat_id: Union[str, int],
subscription_period: int,
subscription_price: int,
name: Optional[str] = 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,
) -> ChatInviteLink:
"""
Use this method to create a `subscription invite link <https://telegram.org/blog/\
superchannels-star-reactions-subscriptions#star-subscriptions>`_ for a channel chat.
The bot must have the :attr:`~telegram.ChatPermissions.can_invite_users` administrator
right. The link can be edited using the :meth:`edit_chat_subscription_invite_link` or
revoked using the :meth:`revoke_chat_invite_link`.
.. versionadded:: 21.5
Args:
chat_id (:obj:`int` | :obj:`str`): |chat_id_channel|
subscription_period (:obj:`int`): The number of seconds the subscription will be
active for before the next payment. Currently, it must always be
:tg-const:`telegram.constants.ChatSubscriptionLimit.SUBSCRIPTION_PERIOD` (30 days).
subscription_price (:obj:`int`): The number of Telegram Stars a user must pay initially
and after each subsequent subscription period to be a member of the chat;
:tg-const:`telegram.constants.ChatSubscriptionLimit.MIN_PRICE`-
:tg-const:`telegram.constants.ChatSubscriptionLimit.MAX_PRICE`.
name (:obj:`str`, optional): Invite link name;
0-:tg-const:`telegram.constants.ChatInviteLinkLimit.NAME_LENGTH` characters.
Returns:
:class:`telegram.ChatInviteLink`
Raises:
:class:`telegram.error.TelegramError`
"""
data: JSONDict = {
"chat_id": chat_id,
"subscription_period": subscription_period,
"subscription_price": subscription_price,
"name": name,
}
result = await self._post(
"createChatSubscriptionInviteLink",
data,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)
return ChatInviteLink.de_json(result, self) # type: ignore[return-value]
async def edit_chat_subscription_invite_link(
self,
chat_id: Union[str, int],
invite_link: Union[str, "ChatInviteLink"],
name: Optional[str] = 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,
) -> ChatInviteLink:
"""
Use this method to edit a subscription invite link created by the bot. The bot must have
:attr:`telegram.ChatPermissions.can_invite_users` administrator right.
.. versionadded:: 21.5
Args:
chat_id (:obj:`int` | :obj:`str`): |chat_id_channel|
invite_link (:obj:`str` | :obj:`telegram.ChatInviteLink`): The invite link to edit.
name (:obj:`str`, optional): Invite link name;
0-:tg-const:`telegram.constants.ChatInviteLinkLimit.NAME_LENGTH` characters.
Tip:
Omitting this argument removes the name of the invite link.
Returns:
:class:`telegram.ChatInviteLink`
Raises:
:class:`telegram.error.TelegramError`
"""
link = invite_link.invite_link if isinstance(invite_link, ChatInviteLink) else invite_link
data: JSONDict = {
"chat_id": chat_id,
"invite_link": link,
"name": name,
}
result = await self._post(
"editChatSubscriptionInviteLink",
data,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)
return ChatInviteLink.de_json(result, self) # type: ignore[return-value]
def to_dict(self, recursive: bool = True) -> JSONDict: # noqa: ARG002
"""See :meth:`telegram.TelegramObject.to_dict`."""
data: JSONDict = {"id": self.id, "username": self.username, "first_name": self.first_name}
@@ -9322,3 +9639,11 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
"""Alias for :meth:`replace_sticker_in_set`"""
refundStarPayment = refund_star_payment
"""Alias for :meth:`refund_star_payment`"""
getStarTransactions = get_star_transactions
"""Alias for :meth:`get_star_transactions`"""
sendPaidMedia = send_paid_media
"""Alias for :meth:`send_paid_media`"""
createChatSubscriptionInviteLink = create_chat_subscription_invite_link
"""Alias for :meth:`create_chat_subscription_invite_link`"""
editChatSubscriptionInviteLink = edit_chat_subscription_invite_link
"""Alias for :meth:`edit_chat_subscription_invite_link`"""
+8 -2
View File
@@ -84,13 +84,19 @@ class BotCommandScope(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["BotCommandScope"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["BotCommandScope"]:
"""Converts JSON data to the appropriate :class:`BotCommandScope` object, i.e. takes
care of selecting the correct subclass.
Args:
data (Dict[:obj:`str`, ...]): The JSON data.
bot (:class:`telegram.Bot`): The bot associated with this object.
bot (:class:`telegram.Bot`, optional): The bot associated with this object. Defaults to
:obj:`None`, in which case shortcut methods will not be available.
.. versionchanged:: 21.4
:paramref:`bot` is now optional and defaults to :obj:`None`
Returns:
The Telegram object.
+15 -5
View File
@@ -106,7 +106,9 @@ class BusinessConnection(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["BusinessConnection"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["BusinessConnection"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
@@ -175,7 +177,9 @@ class BusinessMessagesDeleted(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["BusinessMessagesDeleted"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["BusinessMessagesDeleted"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
@@ -232,7 +236,9 @@ class BusinessIntro(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["BusinessIntro"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["BusinessIntro"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
@@ -284,7 +290,9 @@ class BusinessLocation(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["BusinessLocation"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["BusinessLocation"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
@@ -431,7 +439,9 @@ class BusinessOpeningHours(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["BusinessOpeningHours"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["BusinessOpeningHours"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
+16 -2
View File
@@ -93,7 +93,7 @@ class CallbackQuery(TelegramObject):
with the callback button that originated the query.
.. versionchanged:: 20.8
Objects maybe be of type :class:`telegram.MaybeInaccessibleMessage` since Bot API
Objects may be of type :class:`telegram.MaybeInaccessibleMessage` since Bot API
7.0.
data (:obj:`str` | :obj:`object`): Optional. Data associated with the callback button.
Be aware that the message, which originated the query, can contain no callback buttons
@@ -148,7 +148,9 @@ class CallbackQuery(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["CallbackQuery"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["CallbackQuery"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
@@ -260,6 +262,8 @@ class CallbackQuery(TelegramObject):
entities=entities,
chat_id=None,
message_id=None,
# inline messages can not be sent on behalf of a bcid
business_connection_id=None,
)
return await self._get_message().edit_text(
text=text,
@@ -328,6 +332,8 @@ class CallbackQuery(TelegramObject):
chat_id=None,
message_id=None,
show_caption_above_media=show_caption_above_media,
# inline messages can not be sent on behalf of a bcid
business_connection_id=None,
)
return await self._get_message().edit_caption(
caption=caption,
@@ -388,6 +394,8 @@ class CallbackQuery(TelegramObject):
api_kwargs=api_kwargs,
chat_id=None,
message_id=None,
# inline messages can not be sent on behalf of a bcid
business_connection_id=None,
)
return await self._get_message().edit_reply_markup(
reply_markup=reply_markup,
@@ -445,6 +453,8 @@ class CallbackQuery(TelegramObject):
api_kwargs=api_kwargs,
chat_id=None,
message_id=None,
# inline messages can not be sent on behalf of a bcid
business_connection_id=None,
)
return await self._get_message().edit_media(
media=media,
@@ -516,6 +526,8 @@ class CallbackQuery(TelegramObject):
live_period=live_period,
chat_id=None,
message_id=None,
# inline messages can not be sent on behalf of a bcid
business_connection_id=None,
)
return await self._get_message().edit_live_location(
latitude=latitude,
@@ -579,6 +591,8 @@ class CallbackQuery(TelegramObject):
api_kwargs=api_kwargs,
chat_id=None,
message_id=None,
# inline messages can not be sent on behalf of a bcid
business_connection_id=None,
)
return await self._get_message().stop_live_location(
reply_markup=reply_markup,
+136
View File
@@ -48,6 +48,7 @@ if TYPE_CHECKING:
InputMediaDocument,
InputMediaPhoto,
InputMediaVideo,
InputPaidMedia,
InputPollOption,
LabeledPrice,
LinkPreviewOptions,
@@ -904,6 +905,7 @@ class _ChatBase(TelegramObject):
self,
message_id: int,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
business_connection_id: Optional[str] = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -931,11 +933,13 @@ class _ChatBase(TelegramObject):
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
)
async def unpin_message(
self,
message_id: Optional[int] = None,
business_connection_id: Optional[str] = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -962,6 +966,7 @@ class _ChatBase(TelegramObject):
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
message_id=message_id,
business_connection_id=business_connection_id,
)
async def unpin_all_messages(
@@ -2661,6 +2666,81 @@ class _ChatBase(TelegramObject):
api_kwargs=api_kwargs,
)
async def create_subscription_invite_link(
self,
subscription_period: int,
subscription_price: int,
name: Optional[str] = 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,
) -> "ChatInviteLink":
"""Shortcut for::
await bot.create_chat_subscription_invite_link(
chat_id=update.effective_chat.id, *args, **kwargs
)
For the documentation of the arguments, please see
:meth:`telegram.Bot.create_chat_subscription_invite_link`.
.. versionadded:: 21.5
Returns:
:class:`telegram.ChatInviteLink`
"""
return await self.get_bot().create_chat_subscription_invite_link(
chat_id=self.id,
subscription_period=subscription_period,
subscription_price=subscription_price,
name=name,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
)
async def edit_subscription_invite_link(
self,
invite_link: Union[str, "ChatInviteLink"],
name: Optional[str] = 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,
) -> "ChatInviteLink":
"""Shortcut for::
await bot.edit_chat_subscription_invite_link(
chat_id=update.effective_chat.id, *args, **kwargs
)
For the documentation of the arguments, please see
:meth:`telegram.Bot.edit_chat_subscription_invite_link`.
.. versionadded:: 21.5
Returns:
:class:`telegram.ChatInviteLink`
"""
return await self.get_bot().edit_chat_subscription_invite_link(
chat_id=self.id,
invite_link=invite_link,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
name=name,
)
async def approve_join_request(
self,
user_id: int,
@@ -3257,6 +3337,62 @@ class _ChatBase(TelegramObject):
api_kwargs=api_kwargs,
)
async def send_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,
business_connection_id: Optional[str] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> "Message":
"""Shortcut for::
await bot.send_paid_media(chat_id=update.effective_chat.id, *args, **kwargs)
For the documentation of the arguments, please see
:meth:`telegram.Bot.send_paid_media`.
.. versionadded:: 21.4
Returns:
:class:`telegram.Message`: On success, instance representing the message posted.
"""
return await self.get_bot().send_paid_media(
chat_id=self.id,
star_count=star_count,
media=media,
caption=caption,
parse_mode=parse_mode,
caption_entities=caption_entities,
show_caption_above_media=show_caption_above_media,
disable_notification=disable_notification,
protect_content=protect_content,
reply_parameters=reply_parameters,
reply_markup=reply_markup,
allow_sending_without_reply=allow_sending_without_reply,
reply_to_message_id=reply_to_message_id,
read_timeout=read_timeout,
write_timeout=write_timeout,
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
)
class Chat(_ChatBase):
"""This object represents a chat.
+19 -13
View File
@@ -78,7 +78,9 @@ class BackgroundFill(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["BackgroundFill"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["BackgroundFill"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
@@ -267,7 +269,9 @@ class BackgroundType(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["BackgroundType"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["BackgroundType"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
@@ -303,7 +307,7 @@ class BackgroundTypeFill(BackgroundType):
.. versionadded:: 21.2
Args:
fill (:obj:`telegram.BackgroundFill`): The background fill.
fill (:class:`telegram.BackgroundFill`): The background fill.
dark_theme_dimming (:obj:`int`): Dimming of the background in dark themes, as a
percentage;
0-:tg-const:`telegram.constants.BackgroundTypeLimit.MAX_DIMMING`.
@@ -311,7 +315,7 @@ class BackgroundTypeFill(BackgroundType):
Attributes:
type (:obj:`str`): Type of the background. Always
:attr:`~telegram.BackgroundType.FILL`.
fill (:obj:`telegram.BackgroundFill`): The background fill.
fill (:class:`telegram.BackgroundFill`): The background fill.
dark_theme_dimming (:obj:`int`): Dimming of the background in dark themes, as a
percentage;
0-:tg-const:`telegram.constants.BackgroundTypeLimit.MAX_DIMMING`.
@@ -345,7 +349,7 @@ class BackgroundTypeWallpaper(BackgroundType):
.. versionadded:: 21.2
Args:
document (:obj:`telegram.Document`): Document with the wallpaper
document (:class:`telegram.Document`): Document with the wallpaper
dark_theme_dimming (:obj:`int`): Dimming of the background in dark themes, as a
percentage;
0-:tg-const:`telegram.constants.BackgroundTypeLimit.MAX_DIMMING`.
@@ -357,7 +361,7 @@ class BackgroundTypeWallpaper(BackgroundType):
Attributes:
type (:obj:`str`): Type of the background. Always
:attr:`~telegram.BackgroundType.WALLPAPER`.
document (:obj:`telegram.Document`): Document with the wallpaper
document (:class:`telegram.Document`): Document with the wallpaper
dark_theme_dimming (:obj:`int`): Dimming of the background in dark themes, as a
percentage;
0-:tg-const:`telegram.constants.BackgroundTypeLimit.MAX_DIMMING`.
@@ -403,8 +407,8 @@ class BackgroundTypePattern(BackgroundType):
.. versionadded:: 21.2
Args:
document (:obj:`telegram.Document`): Document with the pattern.
fill (:obj:`telegram.BackgroundFill`): The background fill that is combined with
document (:class:`telegram.Document`): Document with the pattern.
fill (:class:`telegram.BackgroundFill`): The background fill that is combined with
the pattern.
intensity (:obj:`int`): Intensity of the pattern when it is shown above the filled
background;
@@ -418,8 +422,8 @@ class BackgroundTypePattern(BackgroundType):
Attributes:
type (:obj:`str`): Type of the background. Always
:attr:`~telegram.BackgroundType.PATTERN`.
document (:obj:`telegram.Document`): Document with the pattern.
fill (:obj:`telegram.BackgroundFill`): The background fill that is combined with
document (:class:`telegram.Document`): Document with the pattern.
fill (:class:`telegram.BackgroundFill`): The background fill that is combined with
the pattern.
intensity (:obj:`int`): Intensity of the pattern when it is shown above the filled
background;
@@ -507,10 +511,10 @@ class ChatBackground(TelegramObject):
.. versionadded:: 21.2
Args:
type (:obj:`telegram.BackgroundType`): Type of the background.
type (:class:`telegram.BackgroundType`): Type of the background.
Attributes:
type (:obj:`telegram.BackgroundType`): Type of the background.
type (:class:`telegram.BackgroundType`): Type of the background.
"""
__slots__ = ("type",)
@@ -528,7 +532,9 @@ class ChatBackground(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["ChatBackground"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["ChatBackground"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
+15 -5
View File
@@ -110,7 +110,9 @@ class ChatBoostSource(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["ChatBoostSource"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["ChatBoostSource"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
@@ -275,7 +277,9 @@ class ChatBoost(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["ChatBoost"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["ChatBoost"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
@@ -325,7 +329,9 @@ class ChatBoostUpdated(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["ChatBoostUpdated"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["ChatBoostUpdated"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
@@ -382,7 +388,9 @@ class ChatBoostRemoved(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["ChatBoostRemoved"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["ChatBoostRemoved"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
@@ -429,7 +437,9 @@ class UserChatBoosts(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["UserChatBoosts"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["UserChatBoosts"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
+28 -13
View File
@@ -78,7 +78,7 @@ class ChatFullInfo(_ChatBase):
#collectible-usernames>`_; for private chats, supergroups and channels.
.. versionadded:: 20.0
birthdate (:obj:`telegram.Birthdate`, optional): For private chats,
birthdate (:class:`telegram.Birthdate`, optional): For private chats,
the date of birth of the user.
.. versionadded:: 21.1
@@ -94,8 +94,8 @@ class ChatFullInfo(_ChatBase):
chats with business accounts, the opening hours of the business.
.. versionadded:: 21.1
personal_chat (:obj:`telegram.Chat`, optional): For private chats, the personal channel of
the user.
personal_chat (:class:`telegram.Chat`, optional): For private chats, the personal channel
of the user.
.. versionadded:: 21.1
available_reactions (Sequence[:class:`telegram.ReactionType`], optional): List of available
@@ -121,7 +121,8 @@ class ChatFullInfo(_ChatBase):
.. versionadded:: 20.0
emoji_status_expiration_date (:class:`datetime.datetime`, optional): Expiration date of
emoji status of the chat or the other party in a private chat, in seconds.
emoji status of the chat or the other party in a private chat, as a datetime object,
if any.
|datetime_localization|
@@ -194,6 +195,10 @@ class ChatFullInfo(_ChatBase):
chats.
location (:class:`telegram.ChatLocation`, optional): For supergroups, the location to which
the supergroup is connected.
can_send_paid_media (:obj:`bool`, optional): :obj:`True`, if paid media messages can be
sent or forwarded to the channel chat. The field is available only for channel chats.
.. versionadded:: 21.4
Attributes:
id (:obj:`int`): Unique identifier for this chat.
@@ -227,7 +232,7 @@ class ChatFullInfo(_ChatBase):
obtained via :meth:`~telegram.Bot.get_chat`.
.. versionadded:: 20.0
birthdate (:obj:`telegram.Birthdate`): Optional. For private chats,
birthdate (:class:`telegram.Birthdate`): Optional. For private chats,
the date of birth of the user.
.. versionadded:: 21.1
@@ -243,8 +248,8 @@ class ChatFullInfo(_ChatBase):
chats with business accounts, the opening hours of the business.
.. versionadded:: 21.1
personal_chat (:obj:`telegram.Chat`): Optional. For private chats, the personal channel of
the user.
personal_chat (:class:`telegram.Chat`): Optional. For private chats, the personal channel
of the user.
.. versionadded:: 21.1
available_reactions (Tuple[:class:`telegram.ReactionType`]): Optional. List of available
@@ -270,7 +275,8 @@ class ChatFullInfo(_ChatBase):
.. versionadded:: 20.0
emoji_status_expiration_date (:class:`datetime.datetime`): Optional. Expiration date of
emoji status of the chat or the other party in a private chat, in seconds.
emoji status of the chat or the other party in a private chat, as a datetime object,
if any.
|datetime_localization|
@@ -343,6 +349,10 @@ class ChatFullInfo(_ChatBase):
chats.
location (:class:`telegram.ChatLocation`): Optional. For supergroups, the location to which
the supergroup is connected.
can_send_paid_media (:obj:`bool`): Optional. :obj:`True`, if paid media messages can be
sent or forwarded to the channel chat. The field is available only for channel chats.
.. versionadded:: 21.4
.. _accent colors: https://core.telegram.org/bots/api#accent-colors
.. _topics: https://telegram.org/blog/topics-in-groups-collectible-usernames#topics-in-groups
@@ -358,6 +368,7 @@ class ChatFullInfo(_ChatBase):
"business_intro",
"business_location",
"business_opening_hours",
"can_send_paid_media",
"can_set_sticker_set",
"custom_emoji_sticker_set_name",
"description",
@@ -432,6 +443,7 @@ class ChatFullInfo(_ChatBase):
custom_emoji_sticker_set_name: Optional[str] = None,
linked_chat_id: Optional[int] = None,
location: Optional[ChatLocation] = None,
can_send_paid_media: Optional[bool] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
@@ -490,13 +502,16 @@ class ChatFullInfo(_ChatBase):
self.unrestrict_boost_count: Optional[int] = unrestrict_boost_count
self.custom_emoji_sticker_set_name: Optional[str] = custom_emoji_sticker_set_name
self.birthdate: Optional[Birthdate] = birthdate
self.personal_chat: Optional["Chat"] = personal_chat
self.business_intro: Optional["BusinessIntro"] = business_intro
self.business_location: Optional["BusinessLocation"] = business_location
self.business_opening_hours: Optional["BusinessOpeningHours"] = business_opening_hours
self.personal_chat: Optional[Chat] = personal_chat
self.business_intro: Optional[BusinessIntro] = business_intro
self.business_location: Optional[BusinessLocation] = business_location
self.business_opening_hours: Optional[BusinessOpeningHours] = business_opening_hours
self.can_send_paid_media: Optional[bool] = can_send_paid_media
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["ChatFullInfo"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["ChatFullInfo"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
+29 -1
View File
@@ -69,6 +69,16 @@ class ChatInviteLink(TelegramObject):
created using this link.
.. versionadded:: 13.8
subscription_period (:obj:`int`, optional): The number of seconds the subscription will be
active for before the next payment.
.. versionadded:: 21.5
subscription_price (:obj:`int`, optional): The amount of Telegram Stars a user must pay
initially and after each subsequent subscription period to be a member of the chat
using the link.
.. versionadded:: 21.5
Attributes:
invite_link (:obj:`str`): The invite link. If the link was created by another chat
administrator, then the second part of the link will be replaced with ``''``.
@@ -96,6 +106,15 @@ class ChatInviteLink(TelegramObject):
created using this link.
.. versionadded:: 13.8
subscription_period (:obj:`int`): Optional. The number of seconds the subscription will be
active for before the next payment.
.. versionadded:: 21.5
subscription_price (:obj:`int`): Optional. The amount of Telegram Stars a user must pay
initially and after each subsequent subscription period to be a member of the chat
using the link.
.. versionadded:: 21.5
"""
@@ -109,6 +128,8 @@ class ChatInviteLink(TelegramObject):
"member_limit",
"name",
"pending_join_request_count",
"subscription_period",
"subscription_price",
)
def __init__(
@@ -122,6 +143,8 @@ class ChatInviteLink(TelegramObject):
member_limit: Optional[int] = None,
name: Optional[str] = None,
pending_join_request_count: Optional[int] = None,
subscription_period: Optional[int] = None,
subscription_price: Optional[int] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
@@ -140,6 +163,9 @@ class ChatInviteLink(TelegramObject):
self.pending_join_request_count: Optional[int] = (
int(pending_join_request_count) if pending_join_request_count is not None else None
)
self.subscription_period: Optional[int] = subscription_period
self.subscription_price: Optional[int] = subscription_price
self._id_attrs = (
self.invite_link,
self.creates_join_request,
@@ -151,7 +177,9 @@ class ChatInviteLink(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["ChatInviteLink"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["ChatInviteLink"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
+3 -1
View File
@@ -129,7 +129,9 @@ class ChatJoinRequest(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["ChatJoinRequest"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["ChatJoinRequest"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
+3 -1
View File
@@ -68,7 +68,9 @@ class ChatLocation(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["ChatLocation"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["ChatLocation"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
+16 -3
View File
@@ -17,6 +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 ChatMember."""
import datetime
from typing import TYPE_CHECKING, Dict, Final, Optional, Type
@@ -104,7 +105,9 @@ class ChatMember(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["ChatMember"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["ChatMember"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
@@ -389,24 +392,34 @@ class ChatMemberMember(ChatMember):
Args:
user (:class:`telegram.User`): Information about the user.
until_date (:class:`datetime.datetime`, optional): Date when the user's subscription will
expire.
.. versionadded:: 21.5
Attributes:
status (:obj:`str`): The member's status in the chat,
always :tg-const:`telegram.ChatMember.MEMBER`.
user (:class:`telegram.User`): Information about the user.
until_date (:class:`datetime.datetime`): Optional. Date when the user's subscription will
expire.
.. versionadded:: 21.5
"""
__slots__ = ()
__slots__ = ("until_date",)
def __init__(
self,
user: User,
until_date: Optional[datetime.datetime] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(status=ChatMember.MEMBER, user=user, api_kwargs=api_kwargs)
self._freeze()
with self._unfrozen():
self.until_date: Optional[datetime.datetime] = until_date
class ChatMemberRestricted(ChatMember):
+3 -1
View File
@@ -141,7 +141,9 @@ class ChatMemberUpdated(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["ChatMemberUpdated"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["ChatMemberUpdated"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
+3 -1
View File
@@ -231,7 +231,9 @@ class ChatPermissions(TelegramObject):
return cls(*(14 * (False,)))
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["ChatPermissions"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["ChatPermissions"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
+3 -1
View File
@@ -92,7 +92,9 @@ class ChosenInlineResult(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["ChosenInlineResult"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["ChosenInlineResult"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
+3 -3
View File
@@ -44,7 +44,7 @@ class _BaseThumbedMedium(_BaseMedium):
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
file_size (:obj:`int`, optional): File size.
thumbnail (:class:`telegram.PhotoSize`, optional): Thumbnail as defined by sender.
thumbnail (:class:`telegram.PhotoSize`, optional): Thumbnail as defined by the sender.
.. versionadded:: 20.2
@@ -54,7 +54,7 @@ class _BaseThumbedMedium(_BaseMedium):
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
file_size (:obj:`int`): Optional. File size.
thumbnail (:class:`telegram.PhotoSize`): Optional. Thumbnail as defined by sender.
thumbnail (:class:`telegram.PhotoSize`): Optional. Thumbnail as defined by the sender.
.. versionadded:: 20.2
@@ -82,7 +82,7 @@ class _BaseThumbedMedium(_BaseMedium):
@classmethod
def de_json(
cls: Type[ThumbedMT_co], data: Optional[JSONDict], bot: "Bot"
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)
+10 -10
View File
@@ -39,11 +39,11 @@ class Animation(_BaseThumbedMedium):
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
width (:obj:`int`): Video width as defined by sender.
height (:obj:`int`): Video height as defined by sender.
duration (:obj:`int`): Duration of the video in seconds as defined by sender.
file_name (:obj:`str`, optional): Original animation filename as defined by sender.
mime_type (:obj:`str`, optional): MIME type of the file as defined by sender.
width (:obj:`int`): Video width as defined by the sender.
height (:obj:`int`): Video height as defined by the sender.
duration (:obj:`int`): Duration of the video in seconds as defined by the sender.
file_name (:obj:`str`, optional): Original animation filename as defined by the sender.
mime_type (:obj:`str`, optional): MIME type of the file as defined by the sender.
file_size (:obj:`int`, optional): File size in bytes.
thumbnail (:class:`telegram.PhotoSize`, optional): Animation thumbnail as defined by
sender.
@@ -56,11 +56,11 @@ class Animation(_BaseThumbedMedium):
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
width (:obj:`int`): Video width as defined by sender.
height (:obj:`int`): Video height as defined by sender.
duration (:obj:`int`): Duration of the video in seconds as defined by sender.
file_name (:obj:`str`): Optional. Original animation filename as defined by sender.
mime_type (:obj:`str`): Optional. MIME type of the file as defined by sender.
width (:obj:`int`): Video width as defined by the sender.
height (:obj:`int`): Video height as defined by the sender.
duration (:obj:`int`): Duration of the video in seconds as defined by the sender.
file_name (:obj:`str`): Optional. Original animation filename as defined by the sender.
mime_type (:obj:`str`): Optional. MIME type of the file as defined by the sender.
file_size (:obj:`int`): Optional. File size in bytes.
thumbnail (:class:`telegram.PhotoSize`): Optional. Animation thumbnail as defined by
sender.
+12 -12
View File
@@ -39,12 +39,12 @@ class Audio(_BaseThumbedMedium):
or reuse the file.
file_unique_id (:obj:`str`): Unique identifier for this file, which is supposed to be
the same over time and for different bots. Can't be used to download or reuse the file.
duration (:obj:`int`): Duration of the audio in seconds as defined by sender.
performer (:obj:`str`, optional): Performer of the audio as defined by sender or by audio
tags.
title (:obj:`str`, optional): Title of the audio as defined by sender or by audio tags.
file_name (:obj:`str`, optional): Original filename as defined by sender.
mime_type (:obj:`str`, optional): MIME type of the file as defined by sender.
duration (:obj:`int`): Duration of the audio in seconds as defined by the sender.
performer (:obj:`str`, optional): Performer of the audio as defined by the sender or by
audio tags.
title (:obj:`str`, optional): Title of the audio as defined by the sender or by audio tags.
file_name (:obj:`str`, optional): Original filename as defined by the sender.
mime_type (:obj:`str`, optional): MIME type of the file as defined by the sender.
file_size (:obj:`int`, optional): File size in bytes.
thumbnail (:class:`telegram.PhotoSize`, optional): Thumbnail of the album cover to
which the music file belongs.
@@ -56,12 +56,12 @@ class Audio(_BaseThumbedMedium):
or reuse the file.
file_unique_id (:obj:`str`): Unique identifier for this file, which is supposed to be
the same over time and for different bots. Can't be used to download or reuse the file.
duration (:obj:`int`): Duration of the audio in seconds as defined by sender.
performer (:obj:`str`): Optional. Performer of the audio as defined by sender or by audio
tags.
title (:obj:`str`): Optional. Title of the audio as defined by sender or by audio tags.
file_name (:obj:`str`): Optional. Original filename as defined by sender.
mime_type (:obj:`str`): Optional. MIME type of the file as defined by sender.
duration (:obj:`int`): Duration of the audio in seconds as defined by the sender.
performer (:obj:`str`): Optional. Performer of the audio as defined by the sender or by
audio tags.
title (:obj:`str`): Optional. Title of the audio as defined by the sender or by audio tags.
file_name (:obj:`str`): Optional. Original filename as defined by the sender.
mime_type (:obj:`str`): Optional. MIME type of the file as defined by the sender.
file_size (:obj:`int`): Optional. File size in bytes.
thumbnail (:class:`telegram.PhotoSize`): Optional. Thumbnail of the album cover to
which the music file belongs.
+8 -6
View File
@@ -39,10 +39,11 @@ class Document(_BaseThumbedMedium):
or reuse the file.
file_unique_id (:obj:`str`): Unique identifier for this file, which is supposed to be
the same over time and for different bots. Can't be used to download or reuse the file.
file_name (:obj:`str`, optional): Original filename as defined by sender.
mime_type (:obj:`str`, optional): MIME type of the file as defined by sender.
file_name (:obj:`str`, optional): Original filename as defined by the sender.
mime_type (:obj:`str`, optional): MIME type of the file as defined by the sender.
file_size (:obj:`int`, optional): File size in bytes.
thumbnail (:class:`telegram.PhotoSize`, optional): Document thumbnail as defined by sender.
thumbnail (:class:`telegram.PhotoSize`, optional): Document thumbnail as defined by the
sender.
.. versionadded:: 20.2
@@ -51,10 +52,11 @@ class Document(_BaseThumbedMedium):
or reuse the file.
file_unique_id (:obj:`str`): Unique identifier for this file, which is supposed to be
the same over time and for different bots. Can't be used to download or reuse the file.
file_name (:obj:`str`): Optional. Original filename as defined by sender.
mime_type (:obj:`str`): Optional. MIME type of the file as defined by sender.
file_name (:obj:`str`): Optional. Original filename as defined by the sender.
mime_type (:obj:`str`): Optional. MIME type of the file as defined by the sender.
file_size (:obj:`int`): Optional. File size in bytes.
thumbnail (:class:`telegram.PhotoSize`): Optional. Document thumbnail as defined by sender.
thumbnail (:class:`telegram.PhotoSize`): Optional. Document thumbnail as defined by the
sender.
.. versionadded:: 20.2
+41 -6
View File
@@ -22,7 +22,8 @@ import mimetypes
from typing import IO, Optional, Union
from uuid import uuid4
from telegram._utils.files import load_file
from telegram._utils.files import guess_file_name, load_file
from telegram._utils.strings import TextEncoding
from telegram._utils.types import FieldTuple
_DEFAULT_MIME_TYPE = "application/octet-stream"
@@ -52,9 +53,36 @@ class InputFile:
attach (:obj:`bool`, optional): Pass :obj:`True` if the parameter this file belongs to in
the request to Telegram should point to the multipart data via an ``attach://`` URI.
Defaults to `False`.
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`.
Tip:
If you upload extremely large files, you may want to set this to :obj:`False` to
avoid reading the complete file into memory. Additionally, this may be supported
better by the networking backend (in particular it is handled better by
the default :class:`~telegram.request.HTTPXRequest`).
Important:
If you set this to :obj:`False`, you have to ensure that the file handle is still
open when the request is made. In particular, the following snippet can *not* work
as expected.
.. code-block:: python
with open('file.txt', 'rb') as file:
input_file = InputFile(file, read_file_handle=False)
# here the file handle is already closed and the upload will fail
await bot.send_document(chat_id, input_file)
.. versionadded:: 21.5
Attributes:
input_file_content (:obj:`bytes`): The binary content of the file to send.
input_file_content (:obj:`bytes` | :class:`IO`): The binary content of the file to send.
attach_name (:obj:`str`): Optional. If present, the parameter this file belongs to in
the request to Telegram should point to the multipart data via a an URI of the form
``attach://<attach_name>`` URI.
@@ -70,14 +98,18 @@ class InputFile:
obj: Union[IO[bytes], bytes, str],
filename: Optional[str] = None,
attach: bool = False,
read_file_handle: bool = True,
):
if isinstance(obj, bytes):
self.input_file_content: bytes = obj
self.input_file_content: Union[bytes, IO[bytes]] = obj
elif isinstance(obj, str):
self.input_file_content = obj.encode("utf-8")
else:
self.input_file_content = obj.encode(TextEncoding.UTF_8)
elif read_file_handle:
reported_filename, self.input_file_content = load_file(obj)
filename = filename or reported_filename
else:
self.input_file_content = obj
filename = filename or guess_file_name(obj)
self.attach_name: Optional[str] = "attached" + uuid4().hex if attach else None
@@ -94,8 +126,11 @@ class InputFile:
def field_tuple(self) -> FieldTuple:
"""Field tuple representing the contents of the file for upload to the Telegram servers.
.. versionchanged:: 21.5
Content may now be a file handle.
Returns:
Tuple[:obj:`str`, :obj:`bytes`, :obj:`str`]:
Tuple[:obj:`str`, :obj:`bytes` | :class:`IO`, :obj:`str`]:
"""
return self.filename, self.input_file_content, self.mimetype
+172 -22
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/].
"""Base class for Telegram InputMedia Objects."""
from typing import Optional, Sequence, Tuple, Union
from typing import Final, Optional, Sequence, Tuple, Union
from telegram import constants
from telegram._files.animation import Animation
@@ -50,8 +50,8 @@ class InputMedia(TelegramObject):
Args:
media_type (:obj:`str`): Type of media that the instance represents.
media (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | \
:class:`telegram.Animation` | :class:`telegram.Audio` | \
media (:obj:`str` | :term:`file object` | :class:`~telegram.InputFile` | :obj:`bytes` | \
:class:`pathlib.Path` | :class:`telegram.Animation` | :class:`telegram.Audio` | \
:class:`telegram.Document` | :class:`telegram.PhotoSize` | \
:class:`telegram.Video`): File to send.
|fileinputnopath|
@@ -115,13 +115,163 @@ class InputMedia(TelegramObject):
)
class InputPaidMedia(TelegramObject):
"""
Base class for Telegram InputPaidMedia Objects. Currently, it can be one of:
* :class:`telegram.InputMediaPhoto`
* :class:`telegram.InputMediaVideo`
.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
.. versionadded:: 21.4
Args:
type (:obj:`str`): Type of media that the instance represents.
media (:obj:`str` | :term:`file object` | :class:`~telegram.InputFile` | :obj:`bytes` | \
:class:`pathlib.Path` | :class:`telegram.PhotoSize` | :class:`telegram.Video`): File
to send. |fileinputnopath|
Lastly you can pass an existing telegram media object of the corresponding type
to send.
Attributes:
type (:obj:`str`): Type of the input media.
media (:obj:`str` | :class:`telegram.InputFile`): Media to send.
"""
PHOTO: Final[str] = constants.InputPaidMediaType.PHOTO
""":const:`telegram.constants.InputPaidMediaType.PHOTO`"""
VIDEO: Final[str] = constants.InputPaidMediaType.VIDEO
""":const:`telegram.constants.InputPaidMediaType.VIDEO`"""
__slots__ = ("media", "type")
def __init__(
self,
type: str, # pylint: disable=redefined-builtin
media: Union[str, InputFile, PhotoSize, Video],
*,
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(api_kwargs=api_kwargs)
self.type: str = enum.get_member(constants.InputPaidMediaType, type, type)
self.media: Union[str, InputFile, PhotoSize, Video] = media
self._freeze()
class InputPaidMediaPhoto(InputPaidMedia):
"""The paid media to send is a photo.
.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
.. versionadded:: 21.4
Args:
media (:obj:`str` | :term:`file object` | :class:`~telegram.InputFile` | :obj:`bytes` | \
:class:`pathlib.Path` | :class:`telegram.PhotoSize`): File to send. |fileinputnopath|
Lastly you can pass an existing :class:`telegram.PhotoSize` object to send.
Attributes:
type (:obj:`str`): Type of the media, always
:tg-const:`telegram.constants.InputPaidMediaType.PHOTO`.
media (:obj:`str` | :class:`telegram.InputFile`): Photo to send.
"""
__slots__ = ()
def __init__(
self,
media: Union[FileInput, PhotoSize],
*,
api_kwargs: Optional[JSONDict] = None,
):
media = parse_file_input(media, PhotoSize, attach=True, local_mode=True)
super().__init__(type=InputPaidMedia.PHOTO, media=media, api_kwargs=api_kwargs)
self._freeze()
class InputPaidMediaVideo(InputPaidMedia):
"""
The paid media to send is a video.
.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
.. versionadded:: 21.4
Note:
* When using a :class:`telegram.Video` for the :attr:`media` attribute, it will take the
width, height and duration from that video, unless otherwise specified with the optional
arguments.
* :paramref:`thumbnail` will be ignored for small video files, for which Telegram can
easily generate thumbnails. However, this behaviour is undocumented and might be
changed by Telegram.
Args:
media (:obj:`str` | :term:`file object` | :class:`~telegram.InputFile` | :obj:`bytes` | \
:class:`pathlib.Path` | :class:`telegram.Video`): File to send. |fileinputnopath|
Lastly you can pass an existing :class:`telegram.Video` object to send.
thumbnail (:term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | :obj:`str`, \
optional): |thumbdocstringnopath|
width (:obj:`int`, optional): Video width.
height (:obj:`int`, optional): Video height.
duration (:obj:`int`, optional): Video duration in seconds.
supports_streaming (:obj:`bool`, optional): Pass :obj:`True`, if the uploaded video is
suitable for streaming.
Attributes:
type (:obj:`str`): Type of the media, always
:tg-const:`telegram.constants.InputPaidMediaType.VIDEO`.
media (:obj:`str` | :class:`telegram.InputFile`): Video to send.
thumbnail (:class:`telegram.InputFile`): Optional. |thumbdocstringbase|
width (:obj:`int`): Optional. Video width.
height (:obj:`int`): Optional. Video height.
duration (:obj:`int`): Optional. Video duration in seconds.
supports_streaming (:obj:`bool`): Optional. :obj:`True`, if the uploaded video is
suitable for streaming.
"""
__slots__ = ("duration", "height", "supports_streaming", "thumbnail", "width")
def __init__(
self,
media: Union[FileInput, Video],
thumbnail: Optional[FileInput] = None,
width: Optional[int] = None,
height: Optional[int] = None,
duration: Optional[int] = None,
supports_streaming: Optional[bool] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
if isinstance(media, Video):
width = width if width is not None else media.width
height = height if height is not None else media.height
duration = duration if duration is not None else media.duration
media = media.file_id
else:
# We use local_mode=True because we don't have access to the actual setting and want
# things to work in local mode.
media = parse_file_input(media, attach=True, local_mode=True)
super().__init__(type=InputPaidMedia.VIDEO, media=media, api_kwargs=api_kwargs)
with self._unfrozen():
self.thumbnail: Optional[Union[str, InputFile]] = InputMedia._parse_thumbnail_input(
thumbnail
)
self.width: Optional[int] = width
self.height: Optional[int] = height
self.duration: Optional[int] = duration
self.supports_streaming: Optional[bool] = supports_streaming
class InputMediaAnimation(InputMedia):
"""Represents an animation file (GIF or H.264/MPEG-4 AVC video without sound) to be sent.
Note:
When using a :class:`telegram.Animation` for the :attr:`media` attribute, it will take the
width, height and duration from that video, unless otherwise specified with the optional
arguments.
width, height and duration from that animation, unless otherwise specified with the
optional arguments.
.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
@@ -129,8 +279,8 @@ class InputMediaAnimation(InputMedia):
|removed_thumb_note|
Args:
media (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | \
:class:`telegram.Animation`): File to send. |fileinputnopath|
media (:obj:`str` | :term:`file object` | :class:`~telegram.InputFile` | :obj:`bytes` | \
:class:`pathlib.Path` | :class:`telegram.Animation`): File to send. |fileinputnopath|
Lastly you can pass an existing :class:`telegram.Animation` object to send.
.. versionchanged:: 13.2
@@ -252,8 +402,8 @@ class InputMediaPhoto(InputMedia):
.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
Args:
media (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | \
:class:`telegram.PhotoSize`): File to send. |fileinputnopath|
media (:obj:`str` | :term:`file object` | :class:`~telegram.InputFile` | :obj:`bytes` | \
:class:`pathlib.Path` | :class:`telegram.PhotoSize`): File to send. |fileinputnopath|
Lastly you can pass an existing :class:`telegram.PhotoSize` object to send.
.. versionchanged:: 13.2
@@ -352,8 +502,8 @@ class InputMediaVideo(InputMedia):
|removed_thumb_note|
Args:
media (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | \
:class:`telegram.Video`): File to send. |fileinputnopath|
media (:obj:`str` | :term:`file object` | :class:`~telegram.InputFile` | :obj:`bytes` | \
:class:`pathlib.Path` | :class:`telegram.Video`): File to send. |fileinputnopath|
Lastly you can pass an existing :class:`telegram.Video` object to send.
.. versionchanged:: 13.2
@@ -490,8 +640,8 @@ class InputMediaAudio(InputMedia):
|removed_thumb_note|
Args:
media (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | \
:class:`telegram.Audio`): File to send. |fileinputnopath|
media (:obj:`str` | :term:`file object` | :class:`~telegram.InputFile` | :obj:`bytes` | \
:class:`pathlib.Path` | :class:`telegram.Audio`): File to send. |fileinputnopath|
Lastly you can pass an existing :class:`telegram.Audio` object to send.
.. versionchanged:: 13.2
@@ -510,10 +660,10 @@ class InputMediaAudio(InputMedia):
.. versionchanged:: 20.0
|sequenceclassargs|
duration (:obj:`int`, optional): Duration of the audio in seconds as defined by sender.
performer (:obj:`str`, optional): Performer of the audio as defined by sender or by audio
tags.
title (:obj:`str`, optional): Title of the audio as defined by sender or by audio tags.
duration (:obj:`int`, optional): Duration of the audio in seconds as defined by the sender.
performer (:obj:`str`, optional): Performer of the audio as defined by the sender or by
audio tags.
title (:obj:`str`, optional): Title of the audio as defined by the sender or by audio tags.
thumbnail (:term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | :obj:`str`, \
optional): |thumbdocstringnopath|
@@ -533,9 +683,9 @@ class InputMediaAudio(InputMedia):
* |tupleclassattrs|
* |alwaystuple|
duration (:obj:`int`): Optional. Duration of the audio in seconds.
performer (:obj:`str`): Optional. Performer of the audio as defined by sender or by audio
tags.
title (:obj:`str`): Optional. Title of the audio as defined by sender or by audio tags.
performer (:obj:`str`): Optional. Performer of the audio as defined by the sender or by
audio tags.
title (:obj:`str`): Optional. Title of the audio as defined by the sender or by audio tags.
thumbnail (:class:`telegram.InputFile`): Optional. |thumbdocstringbase|
.. versionadded:: 20.2
@@ -594,8 +744,8 @@ class InputMediaDocument(InputMedia):
|removed_thumb_note|
Args:
media (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path` | \
:class:`telegram.Document`): File to send. |fileinputnopath|
media (:obj:`str` | :term:`file object` | :class:`~telegram.InputFile` | :obj:`bytes` \
| :class:`pathlib.Path` | :class:`telegram.Document`): File to send. |fileinputnopath|
Lastly you can pass an existing :class:`telegram.Document` object to send.
.. versionchanged:: 13.2
+4 -3
View File
@@ -41,14 +41,15 @@ class InputSticker(TelegramObject):
order of the arguments has changed.
Args:
sticker (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path`): The
sticker (:obj:`str` | :term:`file object` | :class:`~telegram.InputFile` | :obj:`bytes` \
| :class:`pathlib.Path`): The
added sticker. |uploadinputnopath| Animated and video stickers can't be uploaded via
HTTP URL.
emoji_list (Sequence[:obj:`str`]): Sequence of
:tg-const:`telegram.constants.StickerLimit.MIN_STICKER_EMOJI` -
:tg-const:`telegram.constants.StickerLimit.MAX_STICKER_EMOJI` emoji associated with the
sticker.
mask_position (:obj:`telegram.MaskPosition`, optional): Position where the mask should be
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 (Sequence[:obj:`str`], optional): Sequence of
0-:tg-const:`telegram.constants.StickerLimit.MAX_SEARCH_KEYWORDS` search keywords
@@ -70,7 +71,7 @@ class InputSticker(TelegramObject):
:tg-const:`telegram.constants.StickerLimit.MIN_STICKER_EMOJI` -
:tg-const:`telegram.constants.StickerLimit.MAX_STICKER_EMOJI` emoji associated with the
sticker.
mask_position (:obj:`telegram.MaskPosition`): Optional. Position where the mask should be
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
0-:tg-const:`telegram.constants.StickerLimit.MAX_SEARCH_KEYWORDS` search keywords
+4 -4
View File
@@ -32,8 +32,8 @@ class Location(TelegramObject):
considered equal, if their :attr:`longitude` and :attr:`latitude` are equal.
Args:
longitude (:obj:`float`): Longitude as defined by sender.
latitude (:obj:`float`): Latitude as defined by sender.
longitude (:obj:`float`): Longitude as defined by the sender.
latitude (:obj:`float`): Latitude as defined by the sender.
horizontal_accuracy (:obj:`float`, optional): The radius of uncertainty for the location,
measured in meters; 0-:tg-const:`telegram.Location.HORIZONTAL_ACCURACY`.
live_period (:obj:`int`, optional): Time relative to the message sending date, during which
@@ -45,8 +45,8 @@ class Location(TelegramObject):
approaching another chat member, in meters. For sent live locations only.
Attributes:
longitude (:obj:`float`): Longitude as defined by sender.
latitude (:obj:`float`): Latitude as defined by sender.
longitude (:obj:`float`): Longitude as defined by the sender.
latitude (:obj:`float`): Latitude as defined by the sender.
horizontal_accuracy (:obj:`float`): Optional. The radius of uncertainty for the location,
measured in meters; 0-:tg-const:`telegram.Location.HORIZONTAL_ACCURACY`.
live_period (:obj:`int`): Optional. Time relative to the message sending date, during which
+4 -2
View File
@@ -193,7 +193,7 @@ class Sticker(_BaseThumbedMedium):
""":const:`telegram.constants.StickerType.CUSTOM_EMOJI`"""
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["Sticker"]:
def de_json(cls, data: Optional[JSONDict], bot: Optional["Bot"] = None) -> Optional["Sticker"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
@@ -305,7 +305,9 @@ class StickerSet(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["StickerSet"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["StickerSet"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
if not data:
return None
+1 -1
View File
@@ -103,7 +103,7 @@ class Venue(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["Venue"]:
def de_json(cls, data: Optional[JSONDict], bot: Optional["Bot"] = None) -> Optional["Venue"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
+10 -10
View File
@@ -39,11 +39,11 @@ class Video(_BaseThumbedMedium):
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
width (:obj:`int`): Video width as defined by sender.
height (:obj:`int`): Video height as defined by sender.
duration (:obj:`int`): Duration of the video in seconds as defined by sender.
file_name (:obj:`str`, optional): Original filename as defined by sender.
mime_type (:obj:`str`, optional): MIME type of a file as defined by sender.
width (:obj:`int`): Video width as defined by the sender.
height (:obj:`int`): Video height as defined by the sender.
duration (:obj:`int`): Duration of the video in seconds as defined by the sender.
file_name (:obj:`str`, optional): Original filename as defined by the sender.
mime_type (:obj:`str`, optional): MIME type of a file as defined by the sender.
file_size (:obj:`int`, optional): File size in bytes.
thumbnail (:class:`telegram.PhotoSize`, optional): Video thumbnail.
@@ -55,11 +55,11 @@ class Video(_BaseThumbedMedium):
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
width (:obj:`int`): Video width as defined by sender.
height (:obj:`int`): Video height as defined by sender.
duration (:obj:`int`): Duration of the video in seconds as defined by sender.
file_name (:obj:`str`): Optional. Original filename as defined by sender.
mime_type (:obj:`str`): Optional. MIME type of a file as defined by sender.
width (:obj:`int`): Video width as defined by the sender.
height (:obj:`int`): Video height as defined by the sender.
duration (:obj:`int`): Duration of the video in seconds as defined by the sender.
file_name (:obj:`str`): Optional. Original filename as defined by the sender.
mime_type (:obj:`str`): Optional. MIME type of a file as defined by the sender.
file_size (:obj:`int`): Optional. File size in bytes.
thumbnail (:class:`telegram.PhotoSize`): Optional. Video thumbnail.
+2 -2
View File
@@ -42,7 +42,7 @@ class VideoNote(_BaseThumbedMedium):
Can't be used to download or reuse the file.
length (:obj:`int`): Video width and height (diameter of the video message) as defined
by sender.
duration (:obj:`int`): Duration of the video in seconds as defined by sender.
duration (:obj:`int`): Duration of the video in seconds as defined by the sender.
file_size (:obj:`int`, optional): File size in bytes.
thumbnail (:class:`telegram.PhotoSize`, optional): Video thumbnail.
@@ -56,7 +56,7 @@ class VideoNote(_BaseThumbedMedium):
Can't be used to download or reuse the file.
length (:obj:`int`): Video width and height (diameter of the video message) as defined
by sender.
duration (:obj:`int`): Duration of the video in seconds as defined by sender.
duration (:obj:`int`): Duration of the video in seconds as defined by the sender.
file_size (:obj:`int`): Optional. File size in bytes.
thumbnail (:class:`telegram.PhotoSize`): Optional. Video thumbnail.
+4 -4
View File
@@ -35,8 +35,8 @@ class Voice(_BaseMedium):
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
duration (:obj:`int`): Duration of the audio in seconds as defined by sender.
mime_type (:obj:`str`, optional): MIME type of the file as defined by sender.
duration (:obj:`int`): Duration of the audio in seconds as defined by the sender.
mime_type (:obj:`str`, optional): MIME type of the file as defined by the sender.
file_size (:obj:`int`, optional): File size in bytes.
Attributes:
@@ -45,8 +45,8 @@ class Voice(_BaseMedium):
file_unique_id (:obj:`str`): Unique identifier for this file, which
is supposed to be the same over time and for different bots.
Can't be used to download or reuse the file.
duration (:obj:`int`): Duration of the audio in seconds as defined by sender.
mime_type (:obj:`str`): Optional. MIME type of the file as defined by sender.
duration (:obj:`int`): Duration of the audio in seconds as defined by the sender.
mime_type (:obj:`str`): Optional. MIME type of the file as defined by the sender.
file_size (:obj:`int`): Optional. File size in bytes.
"""
+4 -3
View File
@@ -24,6 +24,7 @@ from telegram._files.photosize import PhotoSize
from telegram._messageentity import MessageEntity
from telegram._telegramobject import TelegramObject
from telegram._utils.argumentparsing import parse_sequence_arg
from telegram._utils.strings import TextEncoding
from telegram._utils.types import JSONDict
if TYPE_CHECKING:
@@ -122,7 +123,7 @@ class Game(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["Game"]:
def de_json(cls, data: Optional[JSONDict], bot: Optional["Bot"] = None) -> Optional["Game"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
@@ -157,10 +158,10 @@ class Game(TelegramObject):
if not self.text:
raise RuntimeError("This Game has no 'text'.")
entity_text = self.text.encode("utf-16-le")
entity_text = self.text.encode(TextEncoding.UTF_16_LE)
entity_text = entity_text[entity.offset * 2 : (entity.offset + entity.length) * 2]
return entity_text.decode("utf-16-le")
return entity_text.decode(TextEncoding.UTF_16_LE)
def parse_text_entities(self, types: Optional[List[str]] = None) -> Dict[MessageEntity, str]:
"""
+3 -1
View File
@@ -61,7 +61,9 @@ class GameHighScore(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["GameHighScore"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["GameHighScore"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
+13 -7
View File
@@ -123,8 +123,10 @@ class Giveaway(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["Giveaway"]:
"""See :obj:`telegram.TelegramObject.de_json`."""
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["Giveaway"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if data is None:
@@ -257,8 +259,10 @@ class GiveawayWinners(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["GiveawayWinners"]:
"""See :obj:`telegram.TelegramObject.de_json`."""
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["GiveawayWinners"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if data is None:
@@ -313,7 +317,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.giveaway_message: Optional[Message] = giveaway_message
self._id_attrs = (
self.winner_count,
@@ -323,8 +327,10 @@ class GiveawayCompleted(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["GiveawayCompleted"]:
"""See :obj:`telegram.TelegramObject.de_json`."""
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["GiveawayCompleted"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if data is None:
+34 -32
View File
@@ -46,7 +46,7 @@ class InlineKeyboardButton(TelegramObject):
working as expected. Putting a game short name in it might, but is not guaranteed to
work.
* If your bot allows for arbitrary callback data, in keyboards returned in a response
from telegram, :attr:`callback_data` maybe be an instance of
from telegram, :attr:`callback_data` may be an instance of
:class:`telegram.ext.InvalidCallbackData`. This will be the case, if the data
associated with the button was already deleted.
@@ -89,10 +89,9 @@ class InlineKeyboardButton(TelegramObject):
Caution:
Only ``HTTPS`` links are allowed after Bot API 6.1.
callback_data (:obj:`str` | :obj:`object`, optional): Data to be sent in a callback query
to the bot when button is pressed, UTF-8
to the bot when the button is pressed, UTF-8
:tg-const:`telegram.InlineKeyboardButton.MIN_CALLBACK_DATA`-
:tg-const:`telegram.InlineKeyboardButton.MAX_CALLBACK_DATA` bytes.
Not supported for messages sent on behalf of a Telegram Business account.
If the bot instance allows arbitrary callback data, anything can be passed.
Tip:
@@ -100,7 +99,7 @@ class InlineKeyboardButton(TelegramObject):
.. seealso:: :wiki:`Arbitrary callback_data <Arbitrary-callback_data>`
web_app (:obj:`telegram.WebAppInfo`, optional): Description of the `Web App
web_app (:class:`telegram.WebAppInfo`, optional): Description of the `Web App
<https://core.telegram.org/bots/webapps>`_ that will be launched when the user presses
the button. The Web App will be able to send an arbitrary message on behalf of the user
using the method :meth:`~telegram.Bot.answer_web_app_query`. Available only in
@@ -108,21 +107,22 @@ class InlineKeyboardButton(TelegramObject):
a Telegram Business account.
.. versionadded:: 20.0
switch_inline_query (:obj:`str`, optional): If set, pressing the button will insert the
bot's username and the specified inline query in the current chat's input field. May be
empty, in which case only the bot's username will be inserted.
This offers a quick way for the user to open your bot in inline mode in the same chat -
good for selecting something from multiple options. Not supported in channels and for
messages sent on behalf of a Telegram Business account.
switch_inline_query (:obj:`str`, optional): If set, pressing the button will prompt the
user to select one of their chats, open that chat and insert the bot's username and the
specified inline query in the input field. May be empty, in which case just the bot's
username will be inserted. Not supported for messages sent on behalf of a Telegram
Business account.
Tip:
This is similar to the new parameter :paramref:`switch_inline_query_chosen_chat`,
This is similar to the parameter :paramref:`switch_inline_query_chosen_chat`,
but gives no control over which chats can be selected.
switch_inline_query_current_chat (:obj:`str`, optional): If set, pressing the button will
prompt the user to select one of their chats of the specified type, open that chat and
insert the bot's username and the specified inline query in the input field. Not
supported for messages sent on behalf of a Telegram Business account.
insert the bot's username and the specified inline query in the current chat's input
field. May be empty, in which case only the bot's username will be inserted.
This offers a quick way for the user to open your bot in inline mode in the same chat
- good for selecting something from multiple options. Not supported in channels and for
messages sent on behalf of a Telegram Business account.
callback_game (:class:`telegram.CallbackGame`, optional): Description of the game that will
be launched when the user presses the button
@@ -135,7 +135,7 @@ class InlineKeyboardButton(TelegramObject):
Note:
This type of button **must** always be the first button in the first row and can
only be used in invoice messages.
switch_inline_query_chosen_chat (:obj:`telegram.SwitchInlineQueryChosenChat`, optional):
switch_inline_query_chosen_chat (:class:`telegram.SwitchInlineQueryChosenChat`, optional):
If set, pressing the button will prompt the user to select one of their chats of the
specified type, open that chat and insert the bot's username and the specified inline
query in the input field. Not supported for messages sent on behalf of a Telegram
@@ -165,11 +165,10 @@ class InlineKeyboardButton(TelegramObject):
Caution:
Only ``HTTPS`` links are allowed after Bot API 6.1.
callback_data (:obj:`str` | :obj:`object`): Optional. Data to be sent in a callback query
to the bot when button is pressed, UTF-8
to the bot when the button is pressed, UTF-8
:tg-const:`telegram.InlineKeyboardButton.MIN_CALLBACK_DATA`-
:tg-const:`telegram.InlineKeyboardButton.MAX_CALLBACK_DATA` bytes.
Not supported for messages sent on behalf of a Telegram Business account.
web_app (:obj:`telegram.WebAppInfo`): Optional. Description of the `Web App
web_app (:class:`telegram.WebAppInfo`): Optional. Description of the `Web App
<https://core.telegram.org/bots/webapps>`_ that will be launched when the user presses
the button. The Web App will be able to send an arbitrary message on behalf of the user
using the method :meth:`~telegram.Bot.answer_web_app_query`. Available only in
@@ -177,21 +176,22 @@ class InlineKeyboardButton(TelegramObject):
a Telegram Business account.
.. versionadded:: 20.0
switch_inline_query (:obj:`str`): Optional. If set, pressing the button will insert the
bot's username and the specified inline query in the current chat's input field. May be
empty, in which case only the bot's username will be inserted.
This offers a quick way for the user to open your bot in inline mode in the same chat -
good for selecting something from multiple options. Not supported in channels and for
messages sent on behalf of a Telegram Business account.
switch_inline_query (:obj:`str`): Optional. If set, pressing the button will prompt the
user to select one of their chats, open that chat and insert the bot's username and the
specified inline query in the input field. May be empty, in which case just the bot's
username will be inserted. Not supported for messages sent on behalf of a Telegram
Business account.
Tip:
This is similar to the new parameter :paramref:`switch_inline_query_chosen_chat`,
This is similar to the parameter :paramref:`switch_inline_query_chosen_chat`,
but gives no control over which chats can be selected.
switch_inline_query_current_chat (:obj:`str`): Optional. If set, pressing the button will
prompt the user to select one of their chats of the specified type, open that chat and
insert the bot's username and the specified inline query in the input field. Not
supported for messages sent on behalf of a Telegram Business account.
insert the bot's username and the specified inline query in the current chat's input
field. May be empty, in which case only the bot's username will be inserted.
This offers a quick way for the user to open your bot in inline mode in the same chat
- good for selecting something from multiple options. Not supported in channels and for
messages sent on behalf of a Telegram Business account.
callback_game (:class:`telegram.CallbackGame`): Optional. Description of the game that will
be launched when the user presses the button.
@@ -204,7 +204,7 @@ class InlineKeyboardButton(TelegramObject):
Note:
This type of button **must** always be the first button in the first row and can
only be used in invoice messages.
switch_inline_query_chosen_chat (:obj:`telegram.SwitchInlineQueryChosenChat`): Optional.
switch_inline_query_chosen_chat (:class:`telegram.SwitchInlineQueryChosenChat`): Optional.
If set, pressing the button will prompt the user to select one of their chats of the
specified type, open that chat and insert the bot's username and the specified inline
query in the input field. Not supported for messages sent on behalf of a Telegram
@@ -284,7 +284,9 @@ class InlineKeyboardButton(TelegramObject):
)
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["InlineKeyboardButton"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["InlineKeyboardButton"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
+4 -2
View File
@@ -42,7 +42,7 @@ class InlineKeyboardMarkup(TelegramObject):
An inline keyboard on a message
.. seealso::
An another kind of keyboard would be the :class:`telegram.ReplyKeyboardMarkup`.
Another kind of keyboard would be the :class:`telegram.ReplyKeyboardMarkup`.
Examples:
* :any:`Inline Keyboard 1 <examples.inlinekeyboard>`
@@ -90,7 +90,9 @@ class InlineKeyboardMarkup(TelegramObject):
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["InlineKeyboardMarkup"]:
def de_json(
cls, data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional["InlineKeyboardMarkup"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
if not data:
return None

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