Compare commits

..

43 Commits

Author SHA1 Message Date
Bibo-Joshi fc3863ac9a Bump Version to v22.1 (#4791) 2025-05-15 22:18:11 +02:00
Bibo-Joshi c57e9fa5d6 Documentation Improvements (#4730)
Co-authored-by: Poolitzer <github@poolitzer.eu>
Co-authored-by: Abdelrahman Elkheir <90580077+aelkheir@users.noreply.github.com>
2025-05-15 21:57:07 +02:00
Bibo-Joshi 7078059e80 Full Support for Bot API 9.0 (#4756)
Co-authored-by: Abdelrahman Elkheir <90580077+aelkheir@users.noreply.github.com>
2025-05-15 21:56:10 +02:00
pre-commit-ci[bot] c34e19edfd Bump pre-commit Hooks to Latest Versions (#4748)
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>
2025-05-12 21:23:25 +02:00
dependabot[bot] 2fc04e1e10 Bump actions/upload-artifact from 4.5.0 to 4.6.2 (#4776)
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>
2025-05-03 21:03:39 +02:00
dependabot[bot] 08006013c3 Bump actions/download-artifact from 4.2.1 to 4.3.0 (#4779)
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>
2025-05-03 20:40:35 +02:00
dependabot[bot] 4c61403322 Bump codecov/codecov-action from 5.1.2 to 5.4.2 (#4775)
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>
2025-05-03 20:40:02 +02:00
dependabot[bot] b0faae9d47 Bump stefanzweifel/git-auto-commit-action from 5.1.0 to 5.2.0 (#4777)
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>
2025-05-03 20:39:19 +02:00
dependabot[bot] 4868565b71 Bump github/codeql-action from 3.28.13 to 3.28.16 (#4778)
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>
2025-05-03 20:38:58 +02:00
Bibo-Joshi 486ceaa6cf Clarify Documentation and Type Hints of Input(Paid)Media (#4762)
Co-authored-by: aelkheir <90580077+aelkheir@users.noreply.github.com>
2025-04-20 10:48:51 +02:00
Bibo-Joshi 54ce1d8d82 Fine Tune chango and Release Workflows (#4758) 2025-04-19 18:40:47 +02:00
ngrogolev 17ae6a7028 Fix Handling of Defaults for InputPaidMedia (#4761)
Co-authored-by: Nikita Grogolev <ngrogolev@leantech.ai>
2025-04-19 17:02:43 +02:00
Bibo-Joshi c6e12b1958 Drop Backward Compatibility for user_id in send_gift (#4692) 2025-04-11 19:16:31 +02:00
Poolitzer ed9496b91a Ensure Proper Execution of Bot.shutdown (#4733) 2025-04-08 19:45:10 +02:00
dependabot[bot] 7823822a41 Bump actions/setup-python from 5.4.0 to 5.5.0 (#4742)
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>
2025-04-07 20:26:31 +02:00
Bibo-Joshi a9e53af3d1 Update AUTHORS.rst, Adding @aelkheir to Active Development Team (#4747) 2025-04-07 19:55:31 +02:00
dependabot[bot] e69069d2c8 Bump github/codeql-action from 3.28.10 to 3.28.13 (#4743)
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>
2025-04-06 20:32:46 +02:00
dependabot[bot] 511222c191 Bump codecov/test-results-action from 1.0.2 to 1.1.0 (#4741)
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>
2025-04-06 20:25:39 +02:00
dependabot[bot] 036910ec0c Bump astral-sh/setup-uv from 5.3.1 to 5.4.1 (#4744)
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>
2025-04-06 20:25:13 +02:00
dependabot[bot] 3cd8a409ee Bump actions/download-artifact from 4.1.8 to 4.2.1 (#4745)
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>
2025-04-06 20:10:00 +02:00
Abdelrahman Elkheir 83676dec16 Reenable test_official Blocked by Debug Remnant (#4746)
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
2025-04-06 20:04:00 +02:00
Bibo-Joshi 9ebd48903b Bump Version to v22.0 (#4719) 2025-03-15 09:53:21 +01:00
Bibo-Joshi 1cf000c806 Remove Functionality Deprecated in v20.x (#4671) 2025-03-15 09:21:37 +01:00
Bibo-Joshi 150328799a Bump Bibo-Joshi/chango from 0.3.2 to 0.4.0 (#4712) 2025-03-09 16:02:24 +01:00
dependabot[bot] 6d7134608f Bump sphinx from 8.1.3 to 8.2.3 (#4710)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <dependabot[bot]@users.noreply.github.com>
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
2025-03-08 19:55:21 +01:00
dependabot[bot] 8266870ed7 Bump pytest from 8.3.4 to 8.3.5 (#4709)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <dependabot[bot]@users.noreply.github.com>
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
2025-03-08 19:55:08 +01:00
dependabot[bot] 519dee7e0c Bump pypa/gh-action-pypi-publish from 1.12.3 to 1.12.4 (#4701)
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
2025-03-02 10:57:12 +01:00
dependabot[bot] 753f3727aa Bump Bibo-Joshi/chango from 0.3.1 to 0.3.2 (#4700)
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
2025-03-02 10:56:42 +01:00
dependabot[bot] 892a66d0e8 Bump astral-sh/setup-uv from 5.2.2 to 5.3.1 (#4699)
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
2025-03-02 10:56:11 +01:00
dependabot[bot] d5e5874f96 Bump srvaroa/labeler from 1.12.0 to 1.13.0 (#4698)
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
2025-03-02 10:54:56 +01:00
dependabot[bot] a5dacab8a9 Bump github/codeql-action from 3.28.8 to 3.28.10 (#4697)
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
2025-03-02 10:54:18 +01:00
Bibo-Joshi 76d8eaf0f2 Add chango As Changelog Management Tool (#4672) 2025-03-01 18:35:16 +01:00
Bibo-Joshi 1e4f31f1bb Bump Version to v21.11.1 (#4696) 2025-03-01 12:45:22 +01:00
Bibo-Joshi 3464f24129 Fix ReadTheDocs Build (#4695) 2025-03-01 12:28:05 +01:00
Bibo-Joshi 9323caf2b8 Bump Version to v21.11 (#4694) 2025-03-01 12:03:34 +01:00
Bibo-Joshi 77c25931a9 Stabilize Linkcheck Test (#4693) 2025-03-01 11:31:41 +01:00
Poolitzer b75948ede4 Full Support for Bot API 8.3 (#4676)
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
Co-authored-by: Abdelrahman Elkheir <90580077+aelkheir@users.noreply.github.com>
2025-03-01 11:13:46 +01:00
Bibo-Joshi b0d22acedb Add Bootstrapping Logic to Application.run_* (#4673) 2025-03-01 11:12:59 +01:00
Bibo-Joshi 35a48f82f4 Documentation Improvements (#4641)
Co-authored-by: Poolitzer <github@poolitzer.eu>
2025-02-27 20:18:15 +01:00
Bibo-Joshi 5d73132838 Make provider_token Argument Optional (#4689) 2025-02-26 20:57:57 +01:00
Bibo-Joshi 7c23087d08 Remove Deprecated InlineQueryResultArticle.hide_url (#4640) 2025-02-17 17:49:31 +01:00
vavasik800 2d5f4a68bb Fix a Bug in edit_user_star_subscription (#4681) 2025-02-15 16:21:33 +01:00
Bibo-Joshi f9f1533c40 Refactor Tests for TelegramObject Classes with Subclasses (#4654) 2025-02-06 12:46:33 +01:00
212 changed files with 12512 additions and 3724 deletions
+31 -29
View File
@@ -157,45 +157,47 @@ Check-list for PRs
This checklist is a non-exhaustive reminder of things that should be done before a PR is merged, both for you as contributor and for the maintainers.
Feel free to copy (parts of) the checklist to the PR description to remind you or the maintainers of open points or if you have questions on anything.
- Added ``.. versionadded:: NEXT.VERSION``, ``.. versionchanged:: NEXT.VERSION``, ``.. deprecated:: NEXT.VERSION`` or ``.. versionremoved:: NEXT.VERSION`` to the docstrings for user facing changes (for methods/class descriptions, arguments and attributes)
- Created new or adapted existing unit tests
- Documented code changes according to the `CSI standard <https://standards.mousepawmedia.com/en/stable/csi.html>`__
- Added myself alphabetically to ``AUTHORS.rst`` (optional)
- Added new classes & modules to the docs and all suitable ``__all__`` s
- Checked the `Stability Policy <https://docs.python-telegram-bot.org/stability_policy.html>`_ in case of deprecations or changes to documented behavior
.. code-block:: markdown
**If the PR contains API changes (otherwise, you can ignore this passage)**
## Check-list for PRs
- Checked the Bot API specific sections of the `Stability Policy <https://docs.python-telegram-bot.org/stability_policy.html>`_
- Created a PR to remove functionality deprecated in the previous Bot API release (`see here <https://docs.python-telegram-bot.org/en/stable/stability_policy.html#case-2>`_)
- [ ] Added `.. versionadded:: NEXT.VERSION`, ``.. versionchanged:: NEXT.VERSION``, ``.. deprecated:: NEXT.VERSION`` or ``.. versionremoved:: NEXT.VERSION` to the docstrings for user facing changes (for methods/class descriptions, arguments and attributes)
- [ ] Created new or adapted existing unit tests
- [ ] Documented code changes according to the [CSI standard](https://standards.mousepawmedia.com/en/stable/csi.html)
- [ ] Added myself alphabetically to `AUTHORS.rst` (optional)
- [ ] Added new classes & modules to the docs and all suitable ``__all__`` s
- [ ] Checked the [Stability Policy](https://docs.python-telegram-bot.org/stability_policy.html) in case of deprecations or changes to documented behavior
- New classes:
**If the PR contains API changes (otherwise, you can ignore this passage)**
- Added ``self._id_attrs`` and corresponding documentation
- ``__init__`` accepts ``api_kwargs`` as kw-only
- [ ] Checked the Bot API specific sections of the [Stability Policy](https://docs.python-telegram-bot.org/stability_policy.html)
- [ ] Created a PR to remove functionality deprecated in the previous Bot API release ([see here](https://docs.python-telegram-bot.org/en/stable/stability_policy.html#case-2))
- Added new shortcuts:
- New Classes
- In :class:`~telegram.Chat` & :class:`~telegram.User` for all methods that accept ``chat/user_id``
- In :class:`~telegram.Message` for all methods that accept ``chat_id`` and ``message_id``
- For new :class:`~telegram.Message` shortcuts: Added ``quote`` argument if methods accepts ``reply_to_message_id``
- In :class:`~telegram.CallbackQuery` for all methods that accept either ``chat_id`` and ``message_id`` or ``inline_message_id``
- [ ] Added `self._id_attrs` and corresponding documentation
- [ ] `__init__` accepts `api_kwargs` as keyword-only
- If relevant:
- Added New Shortcuts
- Added new constants at :mod:`telegram.constants` and shortcuts to them as class variables
- Link new and existing constants in docstrings instead of hard-coded numbers and strings
- Add new message types to :attr:`telegram.Message.effective_attachment`
- Added new handlers for new update types
- [ ] In [`telegram.Chat`](https://python-telegram-bot.readthedocs.io/en/stable/telegram.chat.html) \& [`telegram.User`](https://python-telegram-bot.readthedocs.io/en/stable/telegram.user.html) for all methods that accept `chat/user_id`
- [ ] In [`telegram.Message`](https://python-telegram-bot.readthedocs.io/en/stable/telegram.message.html) for all methods that accept `chat_id` and `message_id`
- [ ] For new `telegram.Message` shortcuts: Added `quote` argument if methods accept `reply_to_message_id`
- [ ] In [`telegram.CallbackQuery`](https://python-telegram-bot.readthedocs.io/en/stable/telegram.callbackquery.html) for all methods that accept either `chat_id` and `message_id` or `inline_message_id`
- Add the handlers to the warning loop in the :class:`~telegram.ext.ConversationHandler`
- If Relevant
- Added new filters for new message (sub)types
- Added or updated documentation for the changed class(es) and/or method(s)
- Added the new method(s) to ``_extbot.py``
- Added or updated ``bot_methods.rst``
- Updated the Bot API version number in all places: ``README.rst`` (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`
- [ ] Added new constants at `telegram.constants` and shortcuts to them as class variables
- [ ] Linked new and existing constants in docstrings instead of hard-coded numbers and strings
- [ ] Added new message types to `telegram.Message.effective_attachment`
- [ ] Added new handlers for new update types
- [ ] Added the handlers to the warning loop in the [`telegram.ext.ConversationHandler`](https://python-telegram-bot.readthedocs.io/en/stable/telegram.ext.conversationhandler.html)
- [ ] Added new filters for new message (sub)types
- [ ] Added or updated documentation for the changed class(es) and/or method(s)
- [ ] Added the new method(s) to `_extbot.py`
- [ ] Added or updated `bot_methods.rst`
- [ ] Updated the Bot API version number in all places: `README.rst` (including the badge) and `telegram.constants.BOT_API_VERSION_INFO`
- [ ] Added logic for arbitrary callback data in `telegram.ext.ExtBot` for new methods that either accept a `reply_markup` in some form or have a return type that is/contains [`telegram.Message`](https://python-telegram-bot.readthedocs.io/en/stable/telegram.message.html)
Documenting
===========
@@ -0,0 +1,5 @@
<b>We've just released {tag}</b>.
Thank you to everyone who contributed to this release.
As usual, upgrade using <code>pip install -U python-telegram-bot</code>.
The release notes can be found <a href="https://docs.python-telegram-bot.org/en/{tag}/changelog.html">here</a>.
+66
View File
@@ -0,0 +1,66 @@
name: Chango
on:
pull_request:
types:
- opened
- reopened
- synchronize
permissions: {}
jobs:
create-chango-fragment:
permissions:
# Give the default GITHUB_TOKEN write permission to commit and push the
# added or changed files to the repository.
contents: write
name: Create chango Fragment
runs-on: ubuntu-latest
outputs:
IS_RELEASE_PR: ${{ steps.check_title.outputs.IS_RELEASE_PR }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
# needed for commit and push step at the end
persist-credentials: true
- name: Check PR Title
id: check_title
run: | # zizmor: ignore[template-injection]
if [[ "$(echo "${{ github.event.pull_request.title }}" | tr '[:upper:]' '[:lower:]')" =~ ^bump\ version\ to\ .* ]]; then
echo "COMMIT_AND_PUSH=false" >> $GITHUB_OUTPUT
echo "IS_RELEASE_PR=true" >> $GITHUB_OUTPUT
else
echo "COMMIT_AND_PUSH=true" >> $GITHUB_OUTPUT
echo "IS_RELEASE_PR=false" >> $GITHUB_OUTPUT
fi
# Create the new fragment
- uses: Bibo-Joshi/chango@9d6bd9d7612eca5fab2c5161687011be59baaf19 # v0.4.0
with:
github-token: ${{ secrets.CHANGO_PAT }}
query-issue-types: true
commit-and-push: ${{ steps.check_title.outputs.COMMIT_AND_PUSH }}
# Run `chango release` if applicable - needs some additional setup.
- name: Set up Python
if: steps.check_title.outputs.IS_RELEASE_PR == 'true'
uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5.5.0
with:
python-version: "3.x"
- name: Do Release
if: steps.check_title.outputs.IS_RELEASE_PR == 'true'
run: |
cd ./target-repo
git add changes/unreleased/*
pip install . -r docs/requirements-docs.txt
VERSION_TAG=$(python -c "from telegram import __version__; print(f'{__version__}')")
chango release --uid $VERSION_TAG
- name: Commit & Push
if: steps.check_title.outputs.IS_RELEASE_PR == 'true'
uses: stefanzweifel/git-auto-commit-action@b863ae1933cb653a53c021fe36dbb774e1fb9403 # v5.2.0
with:
commit_message: "Do chango Release"
repository: ./target-repo
+41
View File
@@ -0,0 +1,41 @@
name: Test Admonitions Generation
on:
pull_request:
paths:
- telegram/**
- docs/**
- .github/workflows/docs-admonitions.yml
push:
branches:
- master
permissions: {}
jobs:
test-admonitions:
name: Test Admonitions Generation
runs-on: ${{matrix.os}}
permissions:
# for uploading artifacts
actions: write
strategy:
matrix:
python-version: ['3.12']
os: [ubuntu-latest]
fail-fast: False
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5.5.0
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
cache-dependency-path: '**/requirements*.txt'
- name: Install dependencies
run: |
python -W ignore -m pip install --upgrade pip
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
+41
View File
@@ -0,0 +1,41 @@
name: Check Links in Documentation
on:
schedule:
# First day of month at 05:46 in every 2nd month
- cron: '46 5 1 */2 *'
pull_request:
paths:
- .github/workflows/docs-linkcheck.yml
permissions: {}
jobs:
test-sphinx-build:
name: test-sphinx-linkcheck
runs-on: ${{matrix.os}}
strategy:
matrix:
python-version: ['3.12']
os: [ubuntu-latest]
fail-fast: False
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5.5.0
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -W ignore -m pip install --upgrade pip
python -W ignore -m pip install -r requirements-dev-all.txt
- name: Check Links
run: sphinx-build docs/source docs/build/html --keep-going -j auto -b linkcheck
- name: Upload linkcheck output
# Run also if the previous steps failed
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: linkcheck-output
path: docs/build/html/output.*
+2 -2
View File
@@ -21,13 +21,13 @@ jobs:
with:
persist-credentials: false
- name: Install the latest version of uv
uses: astral-sh/setup-uv@4db96194c378173c656ce18a155ffc14a9fc4355 # v5.2.2
uses: astral-sh/setup-uv@0c5e2b8115b80b4c7c5ddf6ffdd634974642d182 # v5.4.1
- name: Run zizmor
run: uvx zizmor --persona=pedantic --format sarif . > results.sarif
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8
uses: github/codeql-action/upload-sarif@28deaeda66b76a05916b6923827895f2b14ab387 # v3.28.16
with:
sarif_file: results.sarif
category: zizmor
+1 -1
View File
@@ -13,7 +13,7 @@ jobs:
pull-requests: write # for srvaroa/labeler to add labels in PR
runs-on: ubuntu-latest
steps:
- uses: srvaroa/labeler@fe4b1c73bb8abf2f14a44a6912a8b4fee835d631 # v1.12.0
- uses: srvaroa/labeler@0a20eccb8c94a1ee0bed5f16859aece1c45c3e55 # v1.13.0
# Config file at .github/labeler.yml
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+41 -10
View File
@@ -21,7 +21,7 @@ jobs:
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0
uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5.5.0
with:
python-version: "3.x"
- name: Install pypa/build
@@ -30,7 +30,7 @@ jobs:
- name: Build a binary wheel and a source tarball
run: python3 -m build
- name: Store the distribution packages
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: python-package-distributions
path: dist/
@@ -55,12 +55,12 @@ jobs:
steps:
- name: Download all the dists
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: python-package-distributions
path: dist/
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@67339c736fd9354cd4f8cb0b744f2b82a74b5c70 # v1.12.3
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4
compute-signatures:
name: Compute SHA1 Sums and Sign with Sigstore
@@ -74,7 +74,7 @@ jobs:
steps:
- name: Download all the dists
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: python-package-distributions
path: dist/
@@ -92,7 +92,7 @@ jobs:
./dist/*.tar.gz
./dist/*.whl
- name: Store the distribution packages and signatures
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: python-package-distributions-and-signatures
path: dist/
@@ -110,8 +110,11 @@ jobs:
actions: read # for downloading artifacts
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: Download all the dists
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: python-package-distributions-and-signatures
path: dist/
@@ -119,13 +122,14 @@ jobs:
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.
# Create a tag and a GitHub Release. The description is filled by the static template, we
# just insert the correct tag in the template.
run: >-
sed "s/{tag}/$TAG/g" .github/workflows/assets/release_template.html |
gh release create
"$TAG"
--repo '${{ github.repository }}'
--generate-notes
--notes-file -
- name: Upload artifact signatures to GitHub Release
env:
GITHUB_TOKEN: ${{ github.token }}
@@ -137,3 +141,30 @@ jobs:
gh release upload
"$TAG" dist/**
--repo '${{ github.repository }}'
telegram-channel:
name: Publish to Telegram Channel
needs:
- github-release
runs-on: ubuntu-latest
environment:
name: release_pypi
permissions: {}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: Publish to Telegram Channel
env:
TAG: ${{ needs.build.outputs.TAG }}
# This secret is configured only for the `pypi-release` branch
BOT_TOKEN: ${{ secrets.CHANNEL_BOT_TOKEN }}
run: >-
sed "s/{tag}/$TAG/g" .github/workflows/assets/release_template.html |
curl
-X POST "https://api.telegram.org/bot$BOT_TOKEN/sendMessage"
-d "chat_id=@pythontelegrambotchannel"
-d "parse_mode=HTML"
--data-urlencode "text@-"
+14 -10
View File
@@ -21,7 +21,7 @@ jobs:
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0
uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5.5.0
with:
python-version: "3.x"
- name: Install pypa/build
@@ -30,7 +30,7 @@ jobs:
- name: Build a binary wheel and a source tarball
run: python3 -m build
- name: Store the distribution packages
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: python-package-distributions
path: dist/
@@ -55,12 +55,12 @@ jobs:
steps:
- name: Download all the dists
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: python-package-distributions
path: dist/
- name: Publish to Test PyPI
uses: pypa/gh-action-pypi-publish@67339c736fd9354cd4f8cb0b744f2b82a74b5c70 # v1.12.3
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4
with:
repository-url: https://test.pypi.org/legacy/
@@ -76,7 +76,7 @@ jobs:
steps:
- name: Download all the dists
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: python-package-distributions
path: dist/
@@ -94,7 +94,7 @@ jobs:
./dist/*.tar.gz
./dist/*.whl
- name: Store the distribution packages and signatures
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: python-package-distributions-and-signatures
path: dist/
@@ -112,8 +112,11 @@ jobs:
actions: read # for downloading artifacts
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: Download all the dists
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: python-package-distributions-and-signatures
path: dist/
@@ -121,14 +124,15 @@ jobs:
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.
# Create a tag and a GitHub Release *draft*. The description is filled by the static
# template, we just insert the correct tag in the template.
run: >-
sed "s/{tag}/$TAG/g" .github/workflows/assets/release_template.html |
gh release create
"$TAG"
--repo '${{ github.repository }}'
--generate-notes
--draft
--notes-file -
- name: Upload artifact signatures to GitHub Release
env:
GITHUB_TOKEN: ${{ github.token }}
+51
View File
@@ -0,0 +1,51 @@
name: Bot API Tests
on:
pull_request:
paths:
- telegram/**
- tests/**
push:
branches:
- master
schedule:
# Run monday and friday morning at 03:07 - odd time to spread load on GitHub Actions
- cron: '7 3 * * 1,5'
permissions: {}
jobs:
check-conformity:
name: check-conformity
runs-on: ${{matrix.os}}
strategy:
matrix:
python-version: [3.11]
os: [ubuntu-latest]
fail-fast: False
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5.5.0
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -W ignore -m pip install --upgrade pip
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
exit $?
env:
TEST_OFFICIAL: "true"
shell: bash --noprofile --norc {0}
- name: Test Summary
id: test_summary
uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 # v2.4
if: always() # always run, even if tests fail
with:
paths: .test_report_official.xml
+23
View File
@@ -0,0 +1,23 @@
name: Check Type Completeness
on:
pull_request:
paths:
- telegram/**
- pyproject.toml
- .github/workflows/type_completeness.yml
push:
branches:
- master
permissions: {}
jobs:
test-type-completeness:
name: test-type-completeness
runs-on: ubuntu-latest
steps:
- uses: Bibo-Joshi/pyright-type-completeness@c85a67ff3c66f51dcbb2d06bfcf4fe83a57d69cc # v1.0.1
with:
package-name: telegram
python-version: 3.12
pyright-version: ~=1.1.367
File diff suppressed because one or more lines are too long
+6 -6
View File
@@ -7,7 +7,7 @@ ci:
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: 'v0.8.6'
rev: 'v0.11.9'
hooks:
- id: ruff
name: ruff
@@ -18,18 +18,18 @@ repos:
- cachetools>=5.3.3,<5.5.0
- aiolimiter~=1.1,<1.3
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 24.10.0
rev: 25.1.0
hooks:
- id: black
args:
- --diff
- --check
- repo: https://github.com/PyCQA/flake8
rev: 7.1.1
rev: 7.2.0
hooks:
- id: flake8
- repo: https://github.com/PyCQA/pylint
rev: v3.3.3
rev: v3.3.6
hooks:
- id: pylint
files: ^(?!(tests|docs)).*\.py$
@@ -41,7 +41,7 @@ repos:
- aiolimiter~=1.1,<1.3
- . # this basically does `pip install -e .`
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.14.1
rev: v1.15.0
hooks:
- id: mypy
name: mypy-ptb
@@ -74,7 +74,7 @@ repos:
args:
- --py39-plus
- repo: https://github.com/pycqa/isort
rev: 5.13.2
rev: 6.0.1
hooks:
- id: isort
name: isort
+1 -1
View File
@@ -18,7 +18,7 @@ python:
install:
- method: pip
path: .
- requirements: docs/requirements-docs.txt
- requirements: requirements-dev-all.txt
build:
os: ubuntu-22.04
+4 -4
View File
@@ -7,10 +7,8 @@ The current development team includes
- `Hinrich Mahler <https://github.com/Bibo-Joshi>`_ (maintainer)
- `Poolitzer <https://github.com/Poolitzer>`_ (community liaison)
- `Shivam <https://github.com/Starry69>`_
- `Harshil <https://github.com/harshil21>`_
- `Dmitry Kolomatskiy <https://github.com/lemontree210>`_
- `Aditya <https://github.com/clot27>`_
- `Abdelrahman <https://github.com/aelkheir>`_
Emeritus maintainers include
`Jannes Höke <https://github.com/jh0ker>`_ (`@jh0ker <https://t.me/jh0ker>`_ on Telegram),
@@ -21,7 +19,7 @@ Contributors
The following wonderful people contributed directly or indirectly to this project:
- `Abdelrahman <https://github.com/aelkheir>`_
- `Aditya <https://github.com/clot27>`_
- `Abshar <https://github.com/abxhr>`_
- `Abubakar Alaya <https://github.com/Ecode2>`_
- `Alateas <https://github.com/alateas>`_
@@ -42,6 +40,7 @@ The following wonderful people contributed directly or indirectly to this projec
- `daimajia <https://github.com/daimajia>`_
- `Daniel Reed <https://github.com/nmlorg>`_
- `D David Livingston <https://github.com/daviddl9>`_
- `Dmitry Kolomatskiy <https://github.com/lemontree210>`_
- `DonalDuck004 <https://github.com/DonalDuck004>`_
- `Eana Hufwe <https://github.com/blueset>`_
- `Ehsan Online <https://github.com/ehsanonline>`_
@@ -122,6 +121,7 @@ The following wonderful people contributed directly or indirectly to this projec
- `Sam Mosleh <https://github.com/sam-mosleh>`_
- `Sascha <https://github.com/saschalalala>`_
- `Shelomentsev D <https://github.com/shelomentsevd>`_
- `Shivam <https://github.com/Starry69>`_
- `Shivam Saini <https://github.com/shivamsn97>`_
- `Siloé Garcez <https://github.com/roast-lord>`_
- `Simon Schürrle <https://github.com/SitiSchu>`_
+3 -3
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-8.2-blue?logo=telegram
.. image:: https://img.shields.io/badge/Bot%20API-9.0-blue?logo=telegram
:target: https://core.telegram.org/bots/api-changelog
:alt: Supported Bot API version
@@ -19,7 +19,7 @@
:target: https://pypistats.org/packages/python-telegram-bot
:alt: PyPi Package Monthly Download
.. image:: https://readthedocs.org/projects/python-telegram-bot/badge/?version=stable
.. image:: https://app.readthedocs.org/projects/python-telegram-bot/badge/?version=stable
:target: https://docs.python-telegram-bot.org/en/stable/
:alt: Documentation Status
@@ -81,7 +81,7 @@ After installing_ the library, be sure to check out the section on `working with
Telegram API support
~~~~~~~~~~~~~~~~~~~~
All types and methods of the Telegram Bot API **8.2** are natively supported by this library.
All types and methods of the Telegram Bot API **9.0** are natively supported by this library.
In addition, Bot API functionality not yet natively included can still be used as described `in our wiki <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Bot-API-Forward-Compatibility>`_.
Notable Features
@@ -0,0 +1,19 @@
breaking = """This release removes all functionality that was deprecated in v20.x. This is in line with our :ref:`stability policy <stability-policy>`.
This includes the following changes:
- Removed ``filters.CHAT`` (all messages have an associated chat) and ``filters.StatusUpdate.USER_SHARED`` (use ``filters.StatusUpdate.USERS_SHARED`` instead).
- Removed ``Defaults.disable_web_page_preview`` and ``Defaults.quote``. Use ``Defaults.link_preview_options`` and ``Defaults.do_quote`` instead.
- Removed ``ApplicationBuilder.(get_updates_)proxy_url`` and ``HTTPXRequest.proxy_url``. Use ``ApplicationBuilder.(get_updates_)proxy`` and ``HTTPXRequest.proxy`` instead.
- Removed the ``*_timeout`` arguments of ``Application.run_polling`` and ``Updater.start_webhook``. Instead, specify the values via ``ApplicationBuilder.get_updates_*_timeout``.
- Removed ``constants.InlineQueryLimit.MIN_SWITCH_PM_TEXT_LENGTH``. Use ``constants.InlineQueryResultsButtonLimit.MAX_START_PARAMETER_LENGTH`` instead.
- Removed the argument ``quote`` of ``Message.reply_*``. Use ``do_quote`` instead.
- Removed the superfluous ``EncryptedPassportElement.credentials`` without replacement.
- Changed attribute value of ``PassportFile.file_date`` from :obj:`int` to :class:`datetime.datetime`. Make sure to adjust your code accordingly.
- Changed the attribute value of ``PassportElementErrors.file_hashes`` from :obj:`list` to :obj:`tuple`. Make sure to adjust your code accordingly.
- Make ``BaseRequest.read_timeout`` an abstract property. If you subclass ``BaseRequest``, you need to implement this property.
- The default value for ``write_timeout`` now defaults to ``DEFAULT_NONE`` also for bot methods that send media. Previously, it was ``20``. If you subclass ``BaseRequest``, make sure to use your desired write timeout if ``RequestData.multipart_data`` is set.
"""
[[pull_requests]]
uid = "4671"
author_uid = "Bibo-Joshi"
closes_threads = ["4659"]
@@ -0,0 +1,5 @@
documentation = "Add `chango <https://chango.readthedocs.io/stable/>`_ As Changelog Management Tool"
[[pull_requests]]
uid = "4672"
author_uid = "Bibo-Joshi"
closes_threads = ["4321"]
@@ -0,0 +1,5 @@
internal = "Bump github/codeql-action from 3.28.8 to 3.28.10"
[[pull_requests]]
uid = "4697"
author_uid = "dependabot"
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Bump srvaroa/labeler from 1.12.0 to 1.13.0"
[[pull_requests]]
uid = "4698"
author_uid = "dependabot"
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Bump astral-sh/setup-uv from 5.2.2 to 5.3.1"
[[pull_requests]]
uid = "4699"
author_uid = "dependabot"
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Bump Bibo-Joshi/chango from 0.3.1 to 0.3.2"
[[pull_requests]]
uid = "4700"
author_uid = "dependabot"
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Bump pypa/gh-action-pypi-publish from 1.12.3 to 1.12.4"
[[pull_requests]]
uid = "4701"
author_uid = "dependabot"
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Bump pytest from 8.3.4 to 8.3.5"
[[pull_requests]]
uid = "4709"
author_uid = "dependabot"
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Bump sphinx from 8.1.3 to 8.2.3"
[[pull_requests]]
uid = "4710"
author_uid = "dependabot"
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Bump Bibo-Joshi/chango from 0.3.2 to 0.4.0"
[[pull_requests]]
uid = "4712"
author_uid = "Bibo-Joshi"
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Bump Version to v22.0"
[[pull_requests]]
uid = "4719"
author_uid = "Bibo-Joshi"
closes_threads = []
@@ -0,0 +1,5 @@
breaking = "Drop backward compatibility for ``user_id`` in ``send_gift`` by updating the order of parameters. Please adapt your code accordingly or use keyword arguments."
[[pull_requests]]
uid = "4692"
author_uid = "Bibo-Joshi"
closes_threads = []
@@ -0,0 +1,9 @@
documentation = "Documentation Improvements. Among others, add missing ``Returns`` field in ``User.get_profile_photos``"
[[pull_requests]]
uid = "4730"
author_uid = "Bibo-Joshi"
closes_threads = []
[[pull_requests]]
uid = "4740"
author_uid = "aelkheir"
closes_threads = []
@@ -0,0 +1,5 @@
bugfixes = "Ensure execution of ``Bot.shutdown()`` even if ``Bot.get_me()`` fails in ``Bot.initialize()``"
[[pull_requests]]
uid = "4733"
author_uid = "Poolitzer"
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Bump codecov/test-results-action from 1.0.2 to 1.1.0"
[[pull_requests]]
uid = "4741"
author_uid = "dependabot"
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Bump actions/setup-python from 5.4.0 to 5.5.0"
[[pull_requests]]
uid = "4742"
author_uid = "dependabot"
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Bump github/codeql-action from 3.28.10 to 3.28.13"
[[pull_requests]]
uid = "4743"
author_uid = "dependabot"
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Bump astral-sh/setup-uv from 5.3.1 to 5.4.1"
[[pull_requests]]
uid = "4744"
author_uid = "dependabot"
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Bump actions/download-artifact from 4.1.8 to 4.2.1"
[[pull_requests]]
uid = "4745"
author_uid = "dependabot"
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Reenable ``test_official`` Blocked by Debug Remnant"
[[pull_requests]]
uid = "4746"
author_uid = "aelkheir"
closes_threads = []
@@ -0,0 +1,5 @@
documentation = "Update ``AUTHORS.rst``, Adding `@aelkheir <https://github.com/aelkheir>`_ to Active Development Team"
[[pull_requests]]
uid = "4747"
author_uid = "Bibo-Joshi"
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Bump `pre-commit` Hooks to Latest Versions"
[[pull_requests]]
uid = "4748"
author_uid = "pre-commit-ci"
closes_threads = []
@@ -0,0 +1,51 @@
features = "Full Support for Bot API 9.0"
deprecations = """This release comes with several deprecations, in line with our :ref:`stability policy <stability-policy>`.
This includes the following:
- Deprecated ``telegram.constants.StarTransactionsLimit.NANOSTAR_MIN_AMOUNT`` and ``telegram.constants.StarTransactionsLimit.NANOSTAR_MAX_AMOUNT``. These members will be replaced by ``telegram.constants.NanostarLimit.MIN_AMOUNT`` and ``telegram.constants.NanostarLimit.MAX_AMOUNT``.
- Deprecated the class ``telegram.constants.StarTransactions``. Its only member ``telegram.constants.StarTransactions.NANOSTAR_VALUE`` will be replaced by ``telegram.constants.Nanostar.VALUE``.
- Bot API 9.0 deprecated ``BusinessConnection.can_reply`` in favor of ``BusinessConnection.rights``
- Bot API 9.0 deprecated ``ChatFullInfo.can_send_gift`` in favor of ``ChatFullInfo.accepted_gift_types``.
- Bot API 9.0 introduced these new required fields to existing classes:
- ``TransactionPartnerUser.transaction_type``
- ``ChatFullInfo.accepted_gift_types``
Passing these values as positional arguments is deprecated. We encourage you to use keyword arguments instead, as the the signature will be updated in a future release.
These deprecations are backward compatible, but we strongly recommend to update your code to use the new members.
"""
[[pull_requests]]
uid = "4756"
author_uid = "Bibo-Joshi"
closes_threads = ["4754"]
[[pull_requests]]
uid = "4757"
author_uid = "Bibo-Joshi"
closes_threads = []
[[pull_requests]]
uid = "4759"
author_uid = "Bibo-Joshi"
closes_threads = []
[[pull_requests]]
uid = "4763"
author_uid = "aelkheir"
closes_threads = []
[[pull_requests]]
uid = "4766"
author_uid = "Bibo-Joshi"
[[pull_requests]]
uid = "4769"
author_uid = "aelkheir"
closes_threads = []
[[pull_requests]]
uid = "4773"
author_uid = "aelkheir"
closes_threads = []
[[pull_requests]]
uid = "4781"
author_uid = "aelkheir"
closes_threads = []
[[pull_requests]]
uid = "4782"
author_uid = "Bibo-Joshi"
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Fine-tune ``chango`` and release workflows"
[[pull_requests]]
uid = "4758"
author_uid = "Bibo-Joshi"
closes_threads = ["4720"]
@@ -0,0 +1,6 @@
bugfixes = "Fix Handling of ``Defaults`` for ``InputPaidMedia``"
[[pull_requests]]
uid = "4761"
author_uid = "ngrogolev"
closes_threads = ["4753"]
@@ -0,0 +1,5 @@
documentation = "Clarify Documentation and Type Hints of ``InputMedia`` and ``InputPaidMedia``. Note that the ``media`` parameter accepts only objects of type ``str`` and ``InputFile``. The respective subclasses of ``Input(Paid)Media`` each accept a broader range of input type for the ``media`` parameter."
[[pull_requests]]
uid = "4762"
author_uid = "Bibo-Joshi"
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Bump codecov/codecov-action from 5.1.2 to 5.4.2"
[[pull_requests]]
uid = "4775"
author_uid = "dependabot"
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Bump actions/upload-artifact from 4.5.0 to 4.6.2"
[[pull_requests]]
uid = "4776"
author_uid = "dependabot"
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Bump stefanzweifel/git-auto-commit-action from 5.1.0 to 5.2.0"
[[pull_requests]]
uid = "4777"
author_uid = "dependabot"
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Bump github/codeql-action from 3.28.13 to 3.28.16"
[[pull_requests]]
uid = "4778"
author_uid = "dependabot"
closes_threads = []
@@ -0,0 +1,5 @@
internal = "Bump actions/download-artifact from 4.2.1 to 4.3.0"
[[pull_requests]]
uid = "4779"
author_uid = "dependabot"
closes_threads = []
@@ -0,0 +1,5 @@
other = "Bump Version to v22.1"
[[pull_requests]]
uid = "4791"
author_uid = "Bibo-Joshi"
closes_threads = []
+58 -4
View File
@@ -1,8 +1,62 @@
.. _ptb-changelog:
Version 21.11.1
===============
=========
Changelog
=========
*Released 2025-03-01*
This is the technical changelog for version 21.11. More elaborate release notes can be found in the news channel `@pythontelegrambotchannel <https://t.me/pythontelegrambotchannel>`_.
Documentation Improvements
--------------------------
- Fix ReadTheDocs Build (:pr:`4695`)
Version 21.11
=============
*Released 2025-03-01*
This is the technical changelog for version 21.11. More elaborate release notes can be found in the news channel `@pythontelegrambotchannel <https://t.me/pythontelegrambotchannel>`_.
Major Changes and New Features
------------------------------
- Full Support for Bot API 8.3 (:pr:`4676` closes :issue:`4677`, :pr:`4682` by `aelkheir <https://github.com/aelkheir>`_, :pr:`4690` by `aelkheir <https://github.com/aelkheir>`_, :pr:`4691` by `aelkheir <https://github.com/aelkheir>`_)
- Make ``provider_token`` Argument Optional (:pr:`4689`)
- Remove Deprecated ``InlineQueryResultArticle.hide_url`` (:pr:`4640` closes :issue:`4638`)
- Accept ``datetime.timedelta`` Input in ``Bot`` Method Parameters (:pr:`4651`)
- Extend Customization Support for ``Bot.base_(file_)url`` (:pr:`4632` closes :issue:`3355`)
- Support ``allow_paid_broadcast`` in ``AIORateLimiter`` (:pr:`4627` closes :issue:`4578`)
- Add ``BaseUpdateProcessor.current_concurrent_updates`` (:pr:`4626` closes :issue:`3984`)
Minor Changes and Bug Fixes
---------------------------
- Add Bootstrapping Logic to ``Application.run_*`` (:pr:`4673` closes :issue:`4657`)
- Fix a Bug in ``edit_user_star_subscription`` (:pr:`4681` by `vavasik800 <https://github.com/vavasik800>`_)
- Simplify Handling of Empty Data in ``TelegramObject.de_json`` and Friends (:pr:`4617` closes :issue:`4614`)
Documentation Improvements
--------------------------
- Documentation Improvements (:pr:`4641`)
- Overhaul Admonition Insertion in Documentation (:pr:`4462` closes :issue:`4414`)
Internal Changes
----------------
- Stabilize Linkcheck Test (:pr:`4693`)
- Bump ``pre-commit`` Hooks to Latest Versions (:pr:`4643`)
- Refactor Tests for ``TelegramObject`` Classes with Subclasses (:pr:`4654` closes :issue:`4652`)
- Use Fine Grained Permissions for GitHub Actions Workflows (:pr:`4668`)
Dependency Updates
------------------
- Bump ``actions/setup-python`` from 5.3.0 to 5.4.0 (:pr:`4665`)
- Bump ``dependabot/fetch-metadata`` from 2.2.0 to 2.3.0 (:pr:`4666`)
- Bump ``actions/stale`` from 9.0.0 to 9.1.0 (:pr:`4667`)
- Bump ``astral-sh/setup-uv`` from 5.1.0 to 5.2.2 (:pr:`4664`)
- Bump ``codecov/test-results-action`` from 1.0.1 to 1.0.2 (:pr:`4663`)
Version 21.10
=============
+105
View File
@@ -0,0 +1,105 @@
# noqa: INP001
# pylint: disable=import-error
"""Configuration for the chango changelog tool"""
import re
from collections.abc import Collection
from pathlib import Path
from typing import Optional
from chango import Version
from chango.concrete import DirectoryChanGo, DirectoryVersionScanner, HeaderVersionHistory
from chango.concrete.sections import GitHubSectionChangeNote, Section, SectionVersionNote
version_scanner = DirectoryVersionScanner(base_directory=".", unreleased_directory="unreleased")
class ChangoSectionChangeNote(
GitHubSectionChangeNote.with_sections( # type: ignore[misc]
[
Section(uid="highlights", title="Highlights", sort_order=0),
Section(uid="breaking", title="Breaking Changes", sort_order=1),
Section(uid="security", title="Security Changes", sort_order=2),
Section(uid="deprecations", title="Deprecations", sort_order=3),
Section(uid="features", title="New Features", sort_order=4),
Section(uid="bugfixes", title="Bug Fixes", sort_order=5),
Section(uid="dependencies", title="Dependencies", sort_order=6),
Section(uid="other", title="Other Changes", sort_order=7),
Section(uid="documentation", title="Documentation", sort_order=8),
Section(uid="internal", title="Internal Changes", sort_order=9),
]
)
):
"""Custom change note type for PTB. Mainly overrides get_sections to map labels to sections"""
OWNER = "python-telegram-bot"
REPOSITORY = "python-telegram-bot"
@classmethod
def get_sections(
cls,
labels: Collection[str],
issue_types: Optional[Collection[str]],
) -> set[str]:
"""Override get_sections to have customized auto-detection of relevant sections based on
the pull request and linked issues. Certainly not perfect in all cases, but should be a
good start for most PRs.
"""
combined_labels = set(labels) | (set(issue_types or []))
mapping = {
"🐛 bug": "bugfixes",
"💡 feature": "features",
"🧹 chore": "internal",
"⚙️ bot-api": "features",
"⚙️ documentation": "documentation",
"⚙️ tests": "internal",
"⚙️ ci-cd": "internal",
"⚙️ security": "security",
"⚙️ examples": "documentation",
"⚙️ type-hinting": "other",
"🛠 refactor": "internal",
"🛠 breaking": "breaking",
"⚙️ dependencies": "dependencies",
"🔗 github-actions": "internal",
"🛠 code-quality": "internal",
}
# we want to return *all* from the mapping that are in the combined_labels
# removing superfluous sections from the fragment is a tad easier than adding them
found = {section for label, section in mapping.items() if label in combined_labels}
# if we have not found any sections, we default to "other"
return found or {"other"}
class CustomChango(DirectoryChanGo):
"""Custom ChanGo class for overriding release"""
def release(self, version: Version) -> bool:
"""replace "14.5" with version.uid except in the contrib guide
then call super
"""
root = Path(__file__).parent.parent / "telegram"
python_files = root.rglob("*.py")
pattern = re.compile(r"NEXT\.VERSION")
excluded_paths = {root / "docs/source/contribute.rst"}
for file_path in python_files:
if str(file_path) in excluded_paths:
continue
content = file_path.read_text(encoding="utf-8")
modified = pattern.sub(version.uid, content)
if content != modified:
file_path.write_text(modified, encoding="utf-8")
return super().release(version)
chango_instance = CustomChango(
change_note_type=ChangoSectionChangeNote,
version_note_type=SectionVersionNote,
version_history_type=HeaderVersionHistory,
scanner=version_scanner,
)
View File
+9 -9
View File
@@ -47,29 +47,29 @@ keyword_args = [
"",
]
media_write_timeout_deprecation_methods = [
"send_photo",
media_write_timeout_change_methods = [
"add_sticker_to_set",
"create_new_sticker_set",
"send_animation",
"send_audio",
"send_document",
"send_media_group",
"send_photo",
"send_sticker",
"send_video",
"send_video_note",
"send_animation",
"send_voice",
"send_media_group",
"set_chat_photo",
"upload_sticker_file",
"add_sticker_to_set",
"create_new_sticker_set",
]
media_write_timeout_deprecation = [
media_write_timeout_change = [
" write_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to "
" :paramref:`telegram.request.BaseRequest.post.write_timeout`. By default, ``20`` "
" seconds are used as write timeout."
"",
"",
" .. deprecated:: 20.7",
" In future versions, the default value will be changed to "
" .. versionchanged:: 22.0",
" The default value changed to "
" :attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.",
"",
"",
+11 -7
View File
@@ -15,12 +15,12 @@
#
# 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
from pathlib import Path
from typing import TYPE_CHECKING
from sphinx.application import Sphinx
@@ -32,11 +32,15 @@ from docs.auxil.kwargs_insertion import (
find_insert_pos_for_kwargs,
get_updates_read_timeout_addition,
keyword_args,
media_write_timeout_deprecation,
media_write_timeout_deprecation_methods,
media_write_timeout_change,
media_write_timeout_change_methods,
)
from docs.auxil.link_code import LINE_NUMBERS
if TYPE_CHECKING:
import collections.abc
ADMONITION_INSERTER = AdmonitionInserter()
# Some base classes are implementation detail
@@ -116,9 +120,9 @@ def autodoc_process_docstring(
if (
"post.write_timeout`. Defaults to" in to_insert
and method_name in media_write_timeout_deprecation_methods
and method_name in media_write_timeout_change_methods
):
effective_insert: list[str] = media_write_timeout_deprecation
effective_insert: list[str] = media_write_timeout_change
elif get_updates and to_insert.lstrip().startswith("read_timeout"):
effective_insert = [to_insert, *get_updates_read_timeout_addition]
else:
@@ -128,7 +132,7 @@ def autodoc_process_docstring(
insert_idx += len(effective_insert)
ADMONITION_INSERTER.insert_admonitions(
obj=typing.cast(collections.abc.Callable, obj),
obj=typing.cast("collections.abc.Callable", obj),
docstring_lines=lines,
)
@@ -136,7 +140,7 @@ def autodoc_process_docstring(
# (where applicable)
if what == "class":
ADMONITION_INSERTER.insert_admonitions(
obj=typing.cast(type, obj), # since "what" == class, we know it's not just object
obj=typing.cast("type", obj), # since "what" == class, we know it's not just object
docstring_lines=lines,
)
+2 -1
View File
@@ -1,4 +1,5 @@
sphinx==8.1.3
chango~=0.4.0
sphinx==8.2.3
furo==2024.8.6
furo-sphinx-search @ git+https://github.com/harshil21/furo-sphinx-search@v0.2.0.1
sphinx-paramlinks==0.6.0
+9 -1
View File
@@ -1 +1,9 @@
.. include:: ../../CHANGES.rst
.. _ptb-changelog:
=========
Changelog
=========
.. chango::
.. include:: ../../changes/LEGACY.rst
+16
View File
@@ -8,6 +8,11 @@ from pathlib import Path
# documentation root, use os.path.abspath to make it absolute, like shown here.
from sphinx.application import Sphinx
if sys.version_info < (3, 12):
# Due to dependency on chango
raise RuntimeError("This documentation needs at least Python 3.12")
sys.path.insert(0, str(Path("../..").resolve().absolute()))
# -- General configuration ------------------------------------------------
@@ -36,6 +41,7 @@ needs_sphinx = "8.1.3"
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
"chango.sphinx_ext",
"sphinx.ext.autodoc",
"sphinx.ext.napoleon",
"sphinx.ext.intersphinx",
@@ -52,6 +58,9 @@ extensions = [
if os.environ.get("READTHEDOCS", "") == "True":
extensions.append("sphinx_build_compatibility.extension")
# Configuration for the chango sphinx directive
chango_pyproject_toml_path = Path(__file__).parent.parent.parent
# For shorter links to Wiki in docstrings
extlinks = {
"wiki": ("https://github.com/python-telegram-bot/python-telegram-bot/wiki/%s", "%s"),
@@ -111,6 +120,13 @@ linkcheck_ignore = [
# Anchors are apparently inserted by GitHub dynamically, so let's skip checking them
"https://github.com/python-telegram-bot/python-telegram-bot/tree/master/examples#",
r"https://github\.com/python-telegram-bot/python-telegram-bot/wiki/[\w\-_,]+\#",
# The LGPL license link regularly causes network errors for some reason
re.escape("https://www.gnu.org/licenses/lgpl-3.0.html"),
# The doc-fixes branch may not always exist - doesn't matter, we only link to it from the
# contributing guide
re.escape("https://docs.python-telegram-bot.org/en/doc-fixes"),
# Apparently has some human-verification check and gives 403 in the sphinx build
re.escape("https://stackoverflow.com/questions/tagged/python-telegram-bot"),
]
linkcheck_allowed_redirects = {
# Redirects to the default version are okay
+1 -1
View File
@@ -61,7 +61,7 @@ for this one, too!
:any:`examples.nestedconversationbot`
-------------------------------------
A even more complex example of a bot that uses the nested
An even more complex example of a bot that uses the nested
``ConversationHandler``\ s. While its certainly not that complex that
you couldnt built it without nested ``ConversationHanldler``\ s, it
gives a good impression on how to work with them. Of course, there is a
+54 -2
View File
@@ -161,8 +161,6 @@
- Used for unpinning a message
* - :meth:`~telegram.Bot.unpin_all_chat_messages`
- Used for unpinning all pinned chat messages
* - :meth:`~telegram.Bot.get_business_connection`
- Used for getting information about the business account.
* - :meth:`~telegram.Bot.get_user_profile_photos`
- Used for obtaining user's profile pictures
* - :meth:`~telegram.Bot.get_chat`
@@ -396,6 +394,60 @@
- Used for obtaining the bot's Telegram Stars transactions
* - :meth:`~telegram.Bot.refund_star_payment`
- Used for refunding a payment in Telegram Stars
* - :meth:`~telegram.Bot.gift_premium_subscription`
- Used for gifting Telegram Premium to another user.
.. raw:: html
</details>
<br>
.. raw:: html
<details>
<summary>Business Related Methods</summary>
.. list-table::
:align: left
:widths: 1 4
* - :meth:`~telegram.Bot.get_business_connection`
- Used for getting information about the business account.
* - :meth:`~telegram.Bot.get_business_account_gifts`
- Used for getting gifts owned by the business account.
* - :meth:`~telegram.Bot.get_business_account_star_balance`
- Used for getting the amount of Stars owned by the business account.
* - :meth:`~telegram.Bot.read_business_message`
- Used for marking a message as read.
* - :meth:`~telegram.Bot.delete_story`
- Used for deleting business stories posted by the bot.
* - :meth:`~telegram.Bot.delete_business_messages`
- Used for deleting business messages.
* - :meth:`~telegram.Bot.remove_business_account_profile_photo`
- Used for removing the business accounts profile photo
* - :meth:`~telegram.Bot.set_business_account_name`
- Used for setting the business account name.
* - :meth:`~telegram.Bot.set_business_account_username`
- Used for setting the business account username.
* - :meth:`~telegram.Bot.set_business_account_bio`
- Used for setting the business account bio.
* - :meth:`~telegram.Bot.set_business_account_gift_settings`
- Used for setting the business account gift settings.
* - :meth:`~telegram.Bot.set_business_account_profile_photo`
- Used for setting the business accounts profile photo
* - :meth:`~telegram.Bot.post_story`
- Used for posting a story on behalf of business account.
* - :meth:`~telegram.Bot.edit_story`
- Used for editing business stories posted by the bot.
* - :meth:`~telegram.Bot.convert_gift_to_stars`
- Used for converting owned reqular gifts to stars.
* - :meth:`~telegram.Bot.upgrade_gift`
- Used for upgrading owned regular gifts to unique ones.
* - :meth:`~telegram.Bot.transfer_gift`
- Used for transferring owned unique gifts to another user.
* - :meth:`~telegram.Bot.transfer_business_account_stars`
- Used for transfering Stars from the business account balance to the bot's balance.
.. raw:: html
+2
View File
@@ -1,3 +1,5 @@
.. _stability-policy:
Stability Policy
================
@@ -0,0 +1,6 @@
AcceptedGiftTypes
=================
.. autoclass:: telegram.AcceptedGiftTypes
:members:
:show-inheritance:
+29
View File
@@ -4,6 +4,7 @@ Available Types
.. toctree::
:titlesonly:
telegram.acceptedgifttypes
telegram.animation
telegram.audio
telegram.birthdate
@@ -19,6 +20,7 @@ Available Types
telegram.botdescription
telegram.botname
telegram.botshortdescription
telegram.businessbotrights
telegram.businessconnection
telegram.businessintro
telegram.businesslocation
@@ -75,6 +77,7 @@ Available Types
telegram.forumtopicreopened
telegram.generalforumtopichidden
telegram.generalforumtopicunhidden
telegram.giftinfo
telegram.giveaway
telegram.giveawaycompleted
telegram.giveawaycreated
@@ -92,13 +95,20 @@ Available Types
telegram.inputpaidmedia
telegram.inputpaidmediaphoto
telegram.inputpaidmediavideo
telegram.inputprofilephoto
telegram.inputprofilephotoanimated
telegram.inputprofilephotostatic
telegram.inputpolloption
telegram.inputstorycontent
telegram.inputstorycontentphoto
telegram.inputstorycontentvideo
telegram.keyboardbutton
telegram.keyboardbuttonpolltype
telegram.keyboardbuttonrequestchat
telegram.keyboardbuttonrequestusers
telegram.linkpreviewoptions
telegram.location
telegram.locationaddress
telegram.loginurl
telegram.maybeinaccessiblemessage
telegram.menubutton
@@ -116,12 +126,17 @@ Available Types
telegram.messageoriginuser
telegram.messagereactioncountupdated
telegram.messagereactionupdated
telegram.ownedgift
telegram.ownedgiftregular
telegram.ownedgifts
telegram.ownedgiftunique
telegram.paidmedia
telegram.paidmediainfo
telegram.paidmediaphoto
telegram.paidmediapreview
telegram.paidmediapurchased
telegram.paidmediavideo
telegram.paidmessagepricechanged
telegram.photosize
telegram.poll
telegram.pollanswer
@@ -138,9 +153,23 @@ Available Types
telegram.sentwebappmessage
telegram.shareduser
telegram.story
telegram.storyarea
telegram.storyareaposition
telegram.storyareatype
telegram.storyareatypelink
telegram.storyareatypelocation
telegram.storyareatypesuggestedreaction
telegram.storyareatypeuniquegift
telegram.storyareatypeweather
telegram.switchinlinequerychosenchat
telegram.telegramobject
telegram.textquote
telegram.uniquegift
telegram.uniquegiftbackdrop
telegram.uniquegiftbackdropcolors
telegram.uniquegiftinfo
telegram.uniquegiftmodel
telegram.uniquegiftsymbol
telegram.update
telegram.user
telegram.userchatboosts
@@ -0,0 +1,6 @@
BusinessBotRights
=================
.. autoclass:: telegram.BusinessBotRights
:members:
:show-inheritance:
+7
View File
@@ -0,0 +1,7 @@
GiftInfo
========
.. autoclass:: telegram.GiftInfo
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
InputProfilePhoto
=================
.. autoclass:: telegram.InputProfilePhoto
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
InputProfilePhotoAnimated
=========================
.. autoclass:: telegram.InputProfilePhotoAnimated
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
InputProfilePhotoStatic
=======================
.. autoclass:: telegram.InputProfilePhotoStatic
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
InputStoryContent
=================
.. autoclass:: telegram.InputStoryContent
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
InputStoryContentPhoto
======================
.. autoclass:: telegram.InputStoryContentPhoto
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
InputStoryContentVideo
======================
.. autoclass:: telegram.InputStoryContentVideo
:members:
:show-inheritance:
+6
View File
@@ -0,0 +1,6 @@
LocationAddress
===============
.. autoclass:: telegram.LocationAddress
:members:
:show-inheritance:
+6
View File
@@ -0,0 +1,6 @@
OwnedGift
=========
.. autoclass:: telegram.OwnedGift
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
OwnedGiftRegular
================
.. autoclass:: telegram.OwnedGiftRegular
:members:
:show-inheritance:
+6
View File
@@ -0,0 +1,6 @@
OwnedGifts
==========
.. autoclass:: telegram.OwnedGifts
:members:
:show-inheritance:
+6
View File
@@ -0,0 +1,6 @@
OwnedGiftUnique
===============
.. autoclass:: telegram.OwnedGiftUnique
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
PaidMessagePriceChanged
=======================
.. autoclass:: telegram.PaidMessagePriceChanged
:members:
:show-inheritance:
+2
View File
@@ -22,11 +22,13 @@ Your bot can accept payments from Telegram users. Please see the `introduction t
telegram.shippingaddress
telegram.shippingoption
telegram.shippingquery
telegram.staramount
telegram.startransaction
telegram.startransactions
telegram.successfulpayment
telegram.transactionpartner
telegram.transactionpartneraffiliateprogram
telegram.transactionpartnerchat
telegram.transactionpartnerfragment
telegram.transactionpartnerother
telegram.transactionpartnertelegramads
+6
View File
@@ -0,0 +1,6 @@
StarAmount
==========
.. autoclass:: telegram.StarAmount
:members:
:show-inheritance:
+6
View File
@@ -0,0 +1,6 @@
StoryArea
=========
.. autoclass:: telegram.StoryArea
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
StoryAreaPosition
=================
.. autoclass:: telegram.StoryAreaPosition
:members:
:show-inheritance:
+6
View File
@@ -0,0 +1,6 @@
StoryAreaType
=============
.. autoclass:: telegram.StoryAreaType
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
StoryAreaTypeLink
=================
.. autoclass:: telegram.StoryAreaTypeLink
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
StoryAreaTypeLocation
=====================
.. autoclass:: telegram.StoryAreaTypeLocation
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
StoryAreaTypeSuggestedReaction
==============================
.. autoclass:: telegram.StoryAreaTypeSuggestedReaction
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
StoryAreaTypeUniqueGift
=======================
.. autoclass:: telegram.StoryAreaTypeUniqueGift
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
StoryAreaTypeWeather
====================
.. autoclass:: telegram.StoryAreaTypeWeather
:members:
:show-inheritance:
@@ -0,0 +1,7 @@
TransactionPartnerChat
======================
.. autoclass:: telegram.TransactionPartnerChat
:members:
:show-inheritance:
:inherited-members: TransactionPartner
+7
View File
@@ -0,0 +1,7 @@
UniqueGift
==========
.. autoclass:: telegram.UniqueGift
:members:
:show-inheritance:
@@ -0,0 +1,7 @@
UniqueGiftBackdrop
==================
.. autoclass:: telegram.UniqueGiftBackdrop
:members:
:show-inheritance:
@@ -0,0 +1,7 @@
UniqueGiftBackdropColors
========================
.. autoclass:: telegram.UniqueGiftBackdropColors
:members:
:show-inheritance:
+7
View File
@@ -0,0 +1,7 @@
UniqueGiftInfo
==============
.. autoclass:: telegram.UniqueGiftInfo
:members:
:show-inheritance:
+7
View File
@@ -0,0 +1,7 @@
UniqueGiftModel
===============
.. autoclass:: telegram.UniqueGiftModel
:members:
:show-inheritance:
@@ -0,0 +1,7 @@
UniqueGiftSymbol
================
.. autoclass:: telegram.UniqueGiftSymbol
:members:
:show-inheritance:
+3 -1
View File
@@ -98,4 +98,6 @@
.. |tz-naive-dtms| replace:: For timezone naive :obj:`datetime.datetime` objects, the default timezone of the bot will be used, which is UTC unless :attr:`telegram.ext.Defaults.tzinfo` is used.
.. |time-period-input| replace:: :class:`datetime.timedelta` objects are accepted in addition to plain :obj:`int` values.
.. |org-verify| replace:: `on behalf of the organization <https://telegram.org/verify#third-party-verification>`__
.. |time-period-input| replace:: :class:`datetime.timedelta` objects are accepted in addition to plain :obj:`int` values.
+1 -1
View File
@@ -69,7 +69,7 @@ async def list_button(update: Update, context: ContextTypes.DEFAULT_TYPE) -> Non
# Get the data from the callback_data.
# If you're using a type checker like MyPy, you'll have to use typing.cast
# to make the checker get the expected type of the callback_data
number, number_list = cast(tuple[int, list[int]], query.data)
number, number_list = cast("tuple[int, list[int]]", query.data)
# append the number to the list
number_list.append(number)
-203
View File
@@ -1,203 +0,0 @@
#!/usr/bin/env python
# pylint: disable=unused-argument
# This program is dedicated to the public domain under the CC0 license.
"""Simple state machine to handle user support.
One admin is supported. The admin can have one active conversation at a time. Other users
are put on hold until the admin finishes the current conversation.
In each conversation, the admin and the user take turns to send messages.
"""
import logging
from typing import Optional
from telegram import Update
from telegram.ext import (
Application,
CommandHandler,
ContextTypes,
FiniteStateMachine,
MessageHandler,
State,
StateInfo,
filters,
)
# Enable logging
logging.basicConfig(
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.DEBUG
)
logging.getLogger("httpx").setLevel(logging.WARNING)
logging.getLogger("httpcore").setLevel(logging.WARNING)
logging.getLogger("telegram").setLevel(logging.WARNING)
logging.getLogger("telegram.ext.Application").setLevel(logging.DEBUG)
logger = logging.getLogger(__name__)
class UserSupportMachine(FiniteStateMachine[Optional[int]]):
HOLD = State("HOLD")
WELCOMING = State("WELCOMING")
WAITING_FOR_REPLY = State("WAITING_FOR_REPLY")
WRITING = State("WRITING")
def __init__(self, admin_id: int):
self.admin_id = admin_id
super().__init__()
def _get_admin_state(self) -> tuple[State, int]:
return self._states[self.admin_id]
def get_state_info(self, update: object) -> StateInfo[Optional[int]]:
if not isinstance(update, Update) or not (user := update.effective_user):
key = None
state, version = self.states[key]
return StateInfo(key=key, state=state, version=version)
# Admin is easy - just return the state
admin_state, admin_version = self._get_admin_state()
if user.id == self.admin_id:
logging.debug("Returning admin state: %s", admin_state)
return StateInfo(self.admin_id, admin_state, admin_version)
# If the user state is active in the conversation, we can just return that state
user_state, user_version = self._states[user.id]
if user_state.matches(self.WELCOMING | self.WRITING | self.WAITING_FOR_REPLY):
logging.debug("Returning user state: %s", user_state)
return StateInfo(user.id, user_state, user_version)
# On first interaction, we need to determine what to do with the user
# if the admin is not idle, we put the user on hold. Otherwise, they may send the first
# message, and we put the admin in waiting for reply to avoid another user occupying the
# admin first
effective_user_state = self.HOLD if admin_state != State.IDLE else self.WELCOMING
self._do_set_state(user.id, effective_user_state, user_version)
if effective_user_state == self.WELCOMING:
self._do_set_state(self.admin_id, self.WAITING_FOR_REPLY)
logging.debug("Returning user state: %s", effective_user_state)
return StateInfo(user.id, effective_user_state, user_version)
async def welcome_user(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
await update.effective_message.forward(context.bot_data["admin_id"])
suffix = ""
if UserSupportMachine.HOLD in context.fsm.get_state_history(context.fsm_state_info.key)[:-1]:
suffix = " Thank you for patiently waiting. We hope you enjoyed the music."
await update.effective_message.reply_text(
"Welcome! Your message has been forwarded to the admin. "
f"They will get back to you soon.{suffix}"
)
await context.set_state(UserSupportMachine.WAITING_FOR_REPLY)
await context.fsm.set_state(context.bot_data["admin_id"], UserSupportMachine.WRITING)
context.bot_data["active_user"] = update.effective_user.id
async def conversation_timeout(context: ContextTypes.DEFAULT_TYPE) -> None:
active_user = context.bot_data.get("active_user")
admin_id = context.bot_data["admin_id"]
async def handle(user_id: int) -> None:
await context.bot.send_message(
user_id, "The conversation has been stopped due to inactivity."
)
await context.fsm.set_state(user_id, State.IDLE)
if active_user:
await handle(active_user)
await handle(admin_id)
async def handle_reply(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
if not (active_user := context.bot_data.get("active_user")):
logger.warning("No active user found, ignoring message")
target = (
active_user
if update.effective_user.id == (admin_id := context.bot_data["admin_id"])
else admin_id
)
await context.bot.send_message(target, update.effective_message.text)
logging.debug("Forwarded message to %s", target)
await context.set_state(UserSupportMachine.WAITING_FOR_REPLY)
logging.debug("Done setting state to WAITING_FOR_REPLY for %s", target)
await context.fsm.set_state(target, UserSupportMachine.WRITING)
logging.debug("Done setting state to WRITING for %s, context.fsm_key")
context.fsm.schedule_timeout(
when=30,
callback=conversation_timeout,
cancel_keys=[active_user, admin_id],
)
async def stop_conversation(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
text = "The conversation has been stopped."
admin_id = context.bot_data["admin_id"]
active_user = context.bot_data.get("active_user")
await context.bot.send_message(admin_id, text)
await context.fsm.set_state(admin_id, State.IDLE)
if active_user:
await context.bot.send_message(active_user, text)
await context.fsm.set_state(active_user, State.IDLE)
async def hold_melody(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
await update.effective_message.reply_text(
"You have been put on hold. The admin will get back to you soon. Please hear some music "
"while you wait: https://www.youtube.com/watch?v=dQw4w9WgXcQ"
)
async def not_your_turn(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
await update.effective_message.reply_text(
"It's not your turn yet. Please wait for the other party to reply to your message."
)
async def unsupported_message(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
await update.effective_message.reply_text("This message is not supported.")
def main() -> None:
application = Application.builder().token("TOKEN").build()
application.fsm = UserSupportMachine(admin_id=123456)
application.fsm.set_job_queue(application.job_queue)
application.bot_data["admin_id"] = application.fsm.admin_id
# Users are welcomed only if they are in the corresponding state
application.add_handler(
MessageHandler(~filters.User(application.fsm.admin_id) & filters.TEXT, welcome_user),
state=UserSupportMachine.WELCOMING,
)
# Conversation logic:
# * forward messages between user and admin
# * stop the conversation at any time (admin or user)
# * point out that the other party is currently writing
# Important: Order matters!
application.add_handler(
CommandHandler("stop", stop_conversation),
state=UserSupportMachine.WAITING_FOR_REPLY | UserSupportMachine.WRITING,
)
application.add_handler(
MessageHandler(filters.TEXT, handle_reply), state=UserSupportMachine.WRITING
)
application.add_handler(
MessageHandler(filters.TEXT, not_your_turn), state=UserSupportMachine.WAITING_FOR_REPLY
)
# If the admin is busy, put the user on hold
application.add_handler(
MessageHandler(filters.TEXT, hold_melody), state=UserSupportMachine.HOLD
)
# Fallback
application.add_handler(MessageHandler(filters.ALL, unsupported_message), state=State.ANY)
application.run_polling(allowed_updates=Update.ALL_TYPES)
if __name__ == "__main__":
main()
-172
View File
@@ -1,172 +0,0 @@
#!/usr/bin/env python
# pylint: disable=unused-argument
# This program is dedicated to the public domain under the CC0 license.
"""State machine bot showcasing how concurrency can be handled with FSM.
How to use:
* Use Case 1: Concurrent balance updates
- /unsafe_update <balance_update>: Unsafe update of the wallet balance. Send the command
multiple times in quick succession (less than 1 second) to see the effect
- /safe_update <balance_update>: Safe update of the wallet balance. Send the command
multiple times in quick succession (less than 1 second) to see the effect
* Use Case 2: Declare a winner - who is the fastest?
- /unsafe_declare_winner: Unsafe declaration of the user as winner. Send the command
multiple times in quick succession (less than 1 second) to see the effect. Needs restart
after the winner is declared.
- /safe_declare_winner: Safe declaration of the user as winner. Send the command
multiple times in quick succession (less than 1 second) to see the effect. Needs restart
after the winner is declared.
"""
import asyncio
import logging
from telegram import Update
from telegram.constants import ChatAction
from telegram.ext import (
Application,
CommandHandler,
ContextTypes,
FiniteStateMachine,
MessageHandler,
State,
StateInfo,
filters,
)
# Enable logging
logging.basicConfig(
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.DEBUG
)
logging.getLogger("httpx").setLevel(logging.WARNING)
logging.getLogger("httpcore").setLevel(logging.WARNING)
logging.getLogger("telegram").setLevel(logging.WARNING)
logging.getLogger("telegram.ext.Application").setLevel(logging.DEBUG)
logger = logging.getLogger(__name__)
class ConcurrentMachine(FiniteStateMachine[None]):
"""This FSM only knows a global state for the whole bot"""
UPDATING_BALANCE = State("UPDATING_BALANCE")
WINNER_DECLARED = State("WINNER_DECLARED")
def get_state_info(self, update: object) -> StateInfo[None]:
state, version = self.states[None]
return StateInfo(key=None, state=state, version=version)
########################################
# Use case 1: Concurrent balance updates
########################################
async def update_balance(context: ContextTypes.DEFAULT_TYPE, update: Update) -> None:
initial_balance = context.bot_data.get("balance", 0)
balance_update = int(context.args[0])
# Simulate heavy computation
await update.effective_message.reply_text(
f"Initiating balance update: {initial_balance}. Updating ..."
)
await update.effective_chat.send_action(ChatAction.TYPING)
await asyncio.sleep(4.5)
new_balance = context.bot_data["balance"] = initial_balance + balance_update
await update.effective_message.reply_text(f"Balance updated. New balance: {new_balance}")
async def unsafe_update(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"""Unsafe update of the wallet balance"""
# Simulate heavy computation *before* the update is processed
await asyncio.sleep(1)
await context.fsm.set_state(context.fsm_state_info.key, ConcurrentMachine.UPDATING_BALANCE)
# At this point, the lock is released such that multiple updates can update
# the balance concurrently. This can lead to race conditions.
await update_balance(context, update)
await context.fsm.set_state(context.fsm_state_info.key, State.IDLE)
async def safe_update(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"""Safe update of the wallet balance"""
# Simulate heavy computation *before* the update is processed
await asyncio.sleep(1)
async with context.as_fsm_state(ConcurrentMachine.UPDATING_BALANCE):
# At this point, the lock is acquired such that only one update can update
# the balance at a time. This prevents race conditions.
await update_balance(context, update)
async def busy(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"""Busy state"""
await update.effective_message.reply_text("I'm busy, try again later.")
####################################################
# Use case 2: Declare a winner - who is the fastest?
####################################################
async def declare_winner_unsafe(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"""Declare the user as winner"""
# Simulate heavy computation *before* the update is processed
await asyncio.sleep(1)
# Unsafe state update: No version check, so the state might have already changed
await context.fsm.set_state(context.fsm_state_info.key, ConcurrentMachine.WINNER_DECLARED)
await update.effective_message.reply_text("You are the winner!")
async def declare_winner_safe(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"""Declare the user as winner"""
# Simulate heavy computation *before* the update is processed
await asyncio.sleep(1)
try:
await context.set_state(ConcurrentMachine.WINNER_DECLARED)
await update.effective_message.reply_text("You are the winner!")
except ValueError:
await update.effective_message.reply_text(
"Sorry, you are too late. Someone else was faster."
)
def main() -> None:
application = Application.builder().token("TOKEN").concurrent_updates(True).build()
application.fsm = ConcurrentMachine()
# Note: OR-combination of states is used here to allow both use cases to be handled
# in parallel. Not really necessary for the showcasing, just a nice touch :)
# Use case 2: Declare a winner - who is the fastest?
application.add_handler(
CommandHandler("unsafe_declare_winner", declare_winner_unsafe),
state=State.IDLE | ConcurrentMachine.UPDATING_BALANCE,
)
application.add_handler(
CommandHandler("safe_declare_winner", declare_winner_safe),
state=State.IDLE | ConcurrentMachine.UPDATING_BALANCE,
)
# Use case 1: Concurrent balance updates
application.add_handler(
CommandHandler("unsafe_update", unsafe_update, has_args=1),
state=State.IDLE | ConcurrentMachine.WINNER_DECLARED,
)
application.add_handler(
CommandHandler("safe_update", safe_update, has_args=1),
state=State.IDLE | ConcurrentMachine.WINNER_DECLARED,
)
# Order matters, so this needs to be added last
application.add_handler(
MessageHandler(filters.ALL, busy), state=ConcurrentMachine.UPDATING_BALANCE
)
application.run_polling(allowed_updates=Update.ALL_TYPES)
if __name__ == "__main__":
main()
+8 -2
View File
@@ -61,9 +61,9 @@ async def start_with_shipping_callback(update: Update, context: ContextTypes.DEF
title,
description,
payload,
PAYMENT_PROVIDER_TOKEN,
currency,
prices,
provider_token=PAYMENT_PROVIDER_TOKEN,
need_name=True,
need_phone_number=True,
need_email=True,
@@ -90,7 +90,13 @@ async def start_without_shipping_callback(
# optionally pass need_name=True, need_phone_number=True,
# need_email=True, need_shipping_address=True, is_flexible=True
await context.bot.send_invoice(
chat_id, title, description, payload, PAYMENT_PROVIDER_TOKEN, currency, prices
chat_id,
title,
description,
payload,
currency,
prices,
provider_token=PAYMENT_PROVIDER_TOKEN,
)
+6 -2
View File
@@ -105,6 +105,11 @@ search-paths = ["telegram"]
[tool.hatch.build]
packages = ["telegram"]
# CHANGO
[tool.chango]
sys_path = "changes"
chango_instance = { name= "chango_instance", module = "config" }
# BLACK:
[tool.black]
line-length = 99
@@ -120,8 +125,7 @@ line-length = 99
show-fixes = true
[tool.ruff.lint]
preview = true
explicit-preview-rules = true # TODO: Drop this when RUF022 and RUF023 are out of preview
typing-extensions = false
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",
+1 -1
View File
@@ -4,7 +4,7 @@
build
# For the test suite
pytest==8.3.4
pytest==8.3.5
# needed because pytest doesn't come with native support for coroutines as tests
pytest-asyncio==0.21.2
+66 -1
View File
@@ -20,6 +20,7 @@
__author__ = "devs@python-telegram-bot.org"
__all__ = (
"AcceptedGiftTypes",
"AffiliateInfo",
"Animation",
"Audio",
@@ -46,6 +47,7 @@ __all__ = (
"BotDescription",
"BotName",
"BotShortDescription",
"BusinessBotRights",
"BusinessConnection",
"BusinessIntro",
"BusinessLocation",
@@ -103,6 +105,7 @@ __all__ = (
"GeneralForumTopicHidden",
"GeneralForumTopicUnhidden",
"Gift",
"GiftInfo",
"Gifts",
"Giveaway",
"GiveawayCompleted",
@@ -150,7 +153,13 @@ __all__ = (
"InputPaidMediaPhoto",
"InputPaidMediaVideo",
"InputPollOption",
"InputProfilePhoto",
"InputProfilePhotoAnimated",
"InputProfilePhotoStatic",
"InputSticker",
"InputStoryContent",
"InputStoryContentPhoto",
"InputStoryContentVideo",
"InputTextMessageContent",
"InputVenueMessageContent",
"Invoice",
@@ -161,6 +170,7 @@ __all__ = (
"LabeledPrice",
"LinkPreviewOptions",
"Location",
"LocationAddress",
"LoginUrl",
"MaskPosition",
"MaybeInaccessibleMessage",
@@ -180,12 +190,17 @@ __all__ = (
"MessageReactionCountUpdated",
"MessageReactionUpdated",
"OrderInfo",
"OwnedGift",
"OwnedGiftRegular",
"OwnedGiftUnique",
"OwnedGifts",
"PaidMedia",
"PaidMediaInfo",
"PaidMediaPhoto",
"PaidMediaPreview",
"PaidMediaPurchased",
"PaidMediaVideo",
"PaidMessagePriceChanged",
"PassportData",
"PassportElementError",
"PassportElementErrorDataField",
@@ -227,22 +242,38 @@ __all__ = (
"ShippingAddress",
"ShippingOption",
"ShippingQuery",
"StarAmount",
"StarTransaction",
"StarTransactions",
"Sticker",
"StickerSet",
"Story",
"StoryArea",
"StoryAreaPosition",
"StoryAreaType",
"StoryAreaTypeLink",
"StoryAreaTypeLocation",
"StoryAreaTypeSuggestedReaction",
"StoryAreaTypeUniqueGift",
"StoryAreaTypeWeather",
"SuccessfulPayment",
"SwitchInlineQueryChosenChat",
"TelegramObject",
"TextQuote",
"TransactionPartner",
"TransactionPartnerAffiliateProgram",
"TransactionPartnerChat",
"TransactionPartnerFragment",
"TransactionPartnerOther",
"TransactionPartnerTelegramAds",
"TransactionPartnerTelegramApi",
"TransactionPartnerUser",
"UniqueGift",
"UniqueGiftBackdrop",
"UniqueGiftBackdropColors",
"UniqueGiftInfo",
"UniqueGiftModel",
"UniqueGiftSymbol",
"Update",
"User",
"UserChatBoosts",
@@ -271,10 +302,12 @@ __all__ = (
"warnings",
)
from telegram._payment.stars.staramount import StarAmount
from telegram._payment.stars.startransactions import StarTransaction, StarTransactions
from telegram._payment.stars.transactionpartner import (
TransactionPartner,
TransactionPartnerAffiliateProgram,
TransactionPartnerChat,
TransactionPartnerFragment,
TransactionPartnerOther,
TransactionPartnerTelegramAds,
@@ -299,6 +332,7 @@ from ._botcommandscope import (
from ._botdescription import BotDescription, BotShortDescription
from ._botname import BotName
from ._business import (
BusinessBotRights,
BusinessConnection,
BusinessIntro,
BusinessLocation,
@@ -350,6 +384,11 @@ from ._chatpermissions import ChatPermissions
from ._choseninlineresult import ChosenInlineResult
from ._copytextbutton import CopyTextButton
from ._dice import Dice
from ._files._inputstorycontent import (
InputStoryContent,
InputStoryContentPhoto,
InputStoryContentVideo,
)
from ._files.animation import Animation
from ._files.audio import Audio
from ._files.chatphoto import ChatPhoto
@@ -368,6 +407,11 @@ from ._files.inputmedia import (
InputPaidMediaPhoto,
InputPaidMediaVideo,
)
from ._files.inputprofilephoto import (
InputProfilePhoto,
InputProfilePhotoAnimated,
InputProfilePhotoStatic,
)
from ._files.inputsticker import InputSticker
from ._files.location import Location
from ._files.photosize import PhotoSize
@@ -389,7 +433,7 @@ from ._forumtopic import (
from ._games.callbackgame import CallbackGame
from ._games.game import Game
from ._games.gamehighscore import GameHighScore
from ._gifts import Gift, Gifts
from ._gifts import AcceptedGiftTypes, Gift, GiftInfo, Gifts
from ._giveaway import Giveaway, GiveawayCompleted, GiveawayCreated, GiveawayWinners
from ._inline.inlinekeyboardbutton import InlineKeyboardButton
from ._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
@@ -441,6 +485,7 @@ from ._messageorigin import (
MessageOriginUser,
)
from ._messagereactionupdated import MessageReactionCountUpdated, MessageReactionUpdated
from ._ownedgift import OwnedGift, OwnedGiftRegular, OwnedGifts, OwnedGiftUnique
from ._paidmedia import (
PaidMedia,
PaidMediaInfo,
@@ -449,6 +494,7 @@ from ._paidmedia import (
PaidMediaPurchased,
PaidMediaVideo,
)
from ._paidmessagepricechanged import PaidMessagePriceChanged
from ._passport.credentials import (
Credentials,
DataCredentials,
@@ -504,8 +550,27 @@ from ._replykeyboardremove import ReplyKeyboardRemove
from ._sentwebappmessage import SentWebAppMessage
from ._shared import ChatShared, SharedUser, UsersShared
from ._story import Story
from ._storyarea import (
LocationAddress,
StoryArea,
StoryAreaPosition,
StoryAreaType,
StoryAreaTypeLink,
StoryAreaTypeLocation,
StoryAreaTypeSuggestedReaction,
StoryAreaTypeUniqueGift,
StoryAreaTypeWeather,
)
from ._switchinlinequerychosenchat import SwitchInlineQueryChosenChat
from ._telegramobject import TelegramObject
from ._uniquegift import (
UniqueGift,
UniqueGiftBackdrop,
UniqueGiftBackdropColors,
UniqueGiftInfo,
UniqueGiftModel,
UniqueGiftSymbol,
)
from ._update import Update
from ._user import User
from ._userprofilephotos import UserProfilePhotos

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