mirror of
https://github.com/python-telegram-bot/python-telegram-bot.git
synced 2026-06-19 15:45:13 +00:00
Compare commits
127 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c0716dd344 | |||
| 668b49b048 | |||
| 22eb434a62 | |||
| ae2858783a | |||
| 2c227d5977 | |||
| 437261f716 | |||
| 1b98e440fa | |||
| d30ba3d1ef | |||
| 20e0f87f6b | |||
| bd9b0bd126 | |||
| 5d11d7fd42 | |||
| 099ab5d9fa | |||
| 26f943771b | |||
| 9c263fbd1a | |||
| 277031cfb2 | |||
| c513d51147 | |||
| bb6c85609a | |||
| 5b6cd3a33b | |||
| 1cf63c26c5 | |||
| 680dc2b6b8 | |||
| 04d86deb58 | |||
| 03d2359061 | |||
| 29866e2139 | |||
| 7e9537ece2 | |||
| baa01596c3 | |||
| c23eb8ec08 | |||
| 6ae7add722 | |||
| f3bda29e51 | |||
| fe0421a822 | |||
| 0325a024d6 | |||
| 2f65fcc292 | |||
| 2d63c57ed6 | |||
| b73dc5728e | |||
| f452c132fa | |||
| ebf7f3be12 | |||
| dc284a1a73 | |||
| 979988add1 | |||
| 1ae759ff5c | |||
| 1ab91370ac | |||
| 29d073871a | |||
| d03b4ec688 | |||
| 07d9dc7a44 | |||
| f3479cd170 | |||
| 7fcfad41a5 | |||
| c33c541cbe | |||
| 57c2f6e01e | |||
| a52c91996e | |||
| 2345bfbb53 | |||
| cc45f49a4f | |||
| fd6a0fe899 | |||
| 67b0706116 | |||
| 592c6cc6d3 | |||
| 1fc46360ff | |||
| 4ad94cc7f7 | |||
| c6a9fbb5c7 | |||
| af8729769b | |||
| f93f827e33 | |||
| a8f1164b0c | |||
| da11561f87 | |||
| 354a8e0854 | |||
| bc68488c14 | |||
| 19d7939355 | |||
| 3495ce3aeb | |||
| dd9af64a5c | |||
| da3bc6974a | |||
| b1fc0596b9 | |||
| 6d2334c88b | |||
| a0c81ec3d4 | |||
| c8d9898eaa | |||
| 616b0b55ef | |||
| c71612ffae | |||
| 4143d99f56 | |||
| cbe808e471 | |||
| 300ec920a1 | |||
| 075f517458 | |||
| c82a0808d1 | |||
| ea7e5a69aa | |||
| f67e8c0804 | |||
| af130ef5e7 | |||
| 9ef8826f33 | |||
| 61b70efb4c | |||
| 63977ea353 | |||
| ae57d3b7c3 | |||
| 8d76087bed | |||
| 0e90deafb5 | |||
| 39d45124df | |||
| 895403a0b5 | |||
| 8cb177cb2c | |||
| eaf802e07d | |||
| 1ef242a17e | |||
| 7adb4fa2db | |||
| 5c5ee598a2 | |||
| a4ae6f2097 | |||
| fc5a56c15b | |||
| 74112bfd06 | |||
| ab90cd7359 | |||
| 5b0f1697f1 | |||
| 9c7298c17a | |||
| 39abf838fa | |||
| 04b44f4595 | |||
| a0decdac28 | |||
| f77f4b0cf7 | |||
| 82c98b64a7 | |||
| f9ccf560f6 | |||
| 40ab8aadca | |||
| 644d76b592 | |||
| bd24da29cd | |||
| caffb9d66e | |||
| 1efd8e80ab | |||
| 8cc55c3381 | |||
| fbe9eeeaf5 | |||
| ebed8ec7d3 | |||
| 009785f028 | |||
| 7c858473ca | |||
| 58a109aae6 | |||
| 71eff4731c | |||
| c2c8c53d9c | |||
| 3b78934a77 | |||
| 5128748092 | |||
| 03f87750d4 | |||
| 4c4bf2185d | |||
| aaadc70fcc | |||
| ed3acd4b81 | |||
| a00ba52114 | |||
| 0ae991c141 | |||
| 7226aaea04 | |||
| 50a16edb41 |
@@ -1,19 +0,0 @@
|
||||
version = 1
|
||||
|
||||
test_patterns = ["tests/**"]
|
||||
|
||||
exclude_patterns = [
|
||||
"tests/**",
|
||||
"docs/**",
|
||||
"setup.py",
|
||||
"setup-raw.py"
|
||||
]
|
||||
|
||||
[[analyzers]]
|
||||
name = "python"
|
||||
enabled = true
|
||||
|
||||
[analyzers.meta]
|
||||
runtime_version = "3.x.x"
|
||||
max_line_length = 99
|
||||
skip_doc_coverage = ["module", "magic", "init", "nonpublic"]
|
||||
@@ -167,6 +167,7 @@ Feel free to copy (parts of) the checklist to the PR description to remind you o
|
||||
**If the PR contains API changes (otherwise, you can ignore this passage)**
|
||||
|
||||
- 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>`_)
|
||||
|
||||
- New classes:
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<!--
|
||||
Hey! You're PRing? Cool!
|
||||
Please be sure to check out our contribution guide (https://github.com/python-telegram-bot/python-telegram-bot/blob/master/.github/CONTRIBUTING.rst).
|
||||
Especially, please have a look at the check list for PRs (https://github.com/python-telegram-bot/python-telegram-bot/blob/master/.github/CONTRIBUTING.rst#checklist-for-prs). 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.
|
||||
Especially, please have a look at the check list for PRs (https://github.com/python-telegram-bot/python-telegram-bot/blob/master/.github/CONTRIBUTING.rst#check-list-for-prs). 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.
|
||||
-->
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ name: Process Dependabot PRs
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
types: [opened, reopened]
|
||||
|
||||
jobs:
|
||||
process-dependabot-prs:
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
id: dependabot-metadata
|
||||
uses: dependabot/fetch-metadata@v1.6.0
|
||||
|
||||
- uses: actions/checkout@v3.5.2
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.ref }}
|
||||
|
||||
@@ -31,8 +31,8 @@ jobs:
|
||||
exclude: CHANGES.rst
|
||||
|
||||
- name: Commit & Push Changes to PR
|
||||
uses: EndBug/add-and-commit@v9.1.3
|
||||
uses: EndBug/add-and-commit@v9.1.4
|
||||
with:
|
||||
message: 'Update version number in other files'
|
||||
committer_name: GitHub Actions
|
||||
committer_email: 41898282+github-actions[bot]@users.noreply.github.com
|
||||
committer_email: 41898282+github-actions[bot]@users.noreply.github.com
|
||||
|
||||
@@ -14,9 +14,9 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
fail-fast: False
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
name: Test Documentation Build
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- doc-fixes
|
||||
paths:
|
||||
- telegram/**
|
||||
- docs/**
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- doc-fixes
|
||||
|
||||
jobs:
|
||||
test-sphinx-build:
|
||||
@@ -19,9 +18,9 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
fail-fast: False
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
cache: 'pip'
|
||||
@@ -35,7 +34,7 @@ jobs:
|
||||
- name: Build docs
|
||||
run: sphinx-build docs/source docs/build/html -W --keep-going -j auto
|
||||
- name: Upload docs
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: HTML Docs
|
||||
retention-days: 7
|
||||
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
pull-requests: write # for srvaroa/labeler to add labels in PR
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: srvaroa/labeler@v1.6.0
|
||||
- uses: srvaroa/labeler@v1.10.0
|
||||
# Config file at .github/labeler.yml
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
|
||||
@@ -8,10 +8,12 @@ jobs:
|
||||
lock:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/lock-threads@v4.0.1
|
||||
- uses: dessant/lock-threads@v5.0.1
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
issue-inactive-days: '7'
|
||||
issue-lock-reason: ''
|
||||
pr-inactive-days: '7'
|
||||
pr-lock-reason: ''
|
||||
# Don't lock Discussions
|
||||
process-only: 'issues, prs'
|
||||
|
||||
@@ -7,7 +7,7 @@ jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v8
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
# PRs never get stale
|
||||
days-before-stale: 3
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
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'
|
||||
|
||||
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@v4
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v5
|
||||
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.txt
|
||||
python -W ignore -m pip install -r requirements-opts.txt
|
||||
python -W ignore -m pip install -r requirements-dev.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@v2.3
|
||||
if: always() # always run, even if tests fail
|
||||
with:
|
||||
paths: .test_report_official.xml
|
||||
@@ -1,8 +1,10 @@
|
||||
name: Check Type Completeness
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- telegram/**
|
||||
- requirements.txt
|
||||
- requirements-opts.txt
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
@@ -12,10 +14,10 @@ jobs:
|
||||
name: test-type-completeness
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- 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@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.9
|
||||
cache: 'pip'
|
||||
@@ -50,6 +52,14 @@ jobs:
|
||||
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)
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
name: Unit Tests
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- telegram/**
|
||||
- tests/**
|
||||
- requirements.txt
|
||||
- requirements-opts.txt
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
@@ -16,13 +19,13 @@ jobs:
|
||||
runs-on: ${{matrix.os}}
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12.0-beta.3']
|
||||
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
fail-fast: False
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
cache: 'pip'
|
||||
@@ -79,7 +82,7 @@ jobs:
|
||||
|
||||
- name: Test Summary
|
||||
id: test_summary
|
||||
uses: test-summary/action@v2.1
|
||||
uses: test-summary/action@v2.3
|
||||
if: always() # always run, even if tests fail
|
||||
with:
|
||||
paths: |
|
||||
@@ -87,43 +90,9 @@ jobs:
|
||||
.test_report_optionals.xml
|
||||
|
||||
- name: Submit coverage
|
||||
uses: codecov/codecov-action@v3
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
env_vars: OS,PYTHON
|
||||
name: ${{ matrix.os }}-${{ matrix.python-version }}
|
||||
fail_ci_if_error: true
|
||||
|
||||
test_official:
|
||||
name: test-official
|
||||
runs-on: ${{matrix.os}}
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.11]
|
||||
os: [ubuntu-latest]
|
||||
fail-fast: False
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
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.txt
|
||||
python -W ignore -m pip install -r requirements-opts.txt
|
||||
python -W ignore -m pip install -r requirements-dev.txt
|
||||
- name: Compare to official api
|
||||
run: |
|
||||
pytest -v tests/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@v2.1
|
||||
if: always() # always run, even if tests fail
|
||||
with:
|
||||
paths: .test_report_official.xml
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
+32
-40
@@ -1,53 +1,58 @@
|
||||
# Make sure that the additional_dependencies here match requirements.txt
|
||||
# Make sure that the additional_dependencies here match requirements(-opts).txt
|
||||
|
||||
ci:
|
||||
autofix_prs: false
|
||||
autoupdate_schedule: monthly
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 23.3.0
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: 'v0.2.1'
|
||||
hooks:
|
||||
- id: ruff
|
||||
name: ruff
|
||||
additional_dependencies:
|
||||
- httpx~=0.27
|
||||
- tornado~=6.4
|
||||
- APScheduler~=3.10.4
|
||||
- cachetools~=5.3.3
|
||||
- aiolimiter~=1.1.0
|
||||
- repo: https://github.com/psf/black-pre-commit-mirror
|
||||
rev: 24.1.1
|
||||
hooks:
|
||||
- id: black
|
||||
args:
|
||||
- --diff
|
||||
- --check
|
||||
- repo: https://github.com/PyCQA/flake8
|
||||
rev: 6.0.0
|
||||
rev: 7.0.0
|
||||
hooks:
|
||||
- id: flake8
|
||||
- repo: https://github.com/PyCQA/pylint
|
||||
rev: v3.0.0a6
|
||||
rev: v3.0.3
|
||||
hooks:
|
||||
- id: pylint
|
||||
files: ^(telegram|examples)/.*\.py$
|
||||
args:
|
||||
- --rcfile=setup.cfg
|
||||
# run pylint across multiple cpu cores to speed it up-
|
||||
# https://pylint.pycqa.org/en/latest/user_guide/run.html?#parallel-execution to know more
|
||||
- --jobs=0
|
||||
|
||||
files: ^(?!(tests|docs)).*\.py$
|
||||
additional_dependencies:
|
||||
- httpx~=0.24.1
|
||||
- tornado~=6.2
|
||||
- APScheduler~=3.10.1
|
||||
- cachetools~=5.3.1
|
||||
- httpx~=0.27
|
||||
- tornado~=6.4
|
||||
- APScheduler~=3.10.4
|
||||
- cachetools~=5.3.3
|
||||
- aiolimiter~=1.1.0
|
||||
- . # this basically does `pip install -e .`
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v1.4.1
|
||||
rev: v1.8.0
|
||||
hooks:
|
||||
- id: mypy
|
||||
name: mypy-ptb
|
||||
files: ^telegram/.*\.py$
|
||||
files: ^(?!(tests|examples|docs)).*\.py$
|
||||
additional_dependencies:
|
||||
- types-pytz
|
||||
- types-cryptography
|
||||
- types-cachetools
|
||||
- httpx~=0.24.1
|
||||
- tornado~=6.2
|
||||
- APScheduler~=3.10.1
|
||||
- cachetools~=5.3.1
|
||||
- httpx~=0.27
|
||||
- tornado~=6.4
|
||||
- APScheduler~=3.10.4
|
||||
- cachetools~=5.3.3
|
||||
- aiolimiter~=1.1.0
|
||||
- . # this basically does `pip install -e .`
|
||||
- id: mypy
|
||||
@@ -57,34 +62,21 @@ repos:
|
||||
- --no-strict-optional
|
||||
- --follow-imports=silent
|
||||
additional_dependencies:
|
||||
- tornado~=6.2
|
||||
- APScheduler~=3.10.1
|
||||
- cachetools~=5.3.1
|
||||
- tornado~=6.4
|
||||
- APScheduler~=3.10.4
|
||||
- cachetools~=5.3.3
|
||||
- . # this basically does `pip install -e .`
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v3.8.0
|
||||
rev: v3.15.0
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
files: ^(telegram|examples|tests|docs)/.*\.py$
|
||||
args:
|
||||
- --py38-plus
|
||||
- repo: https://github.com/pycqa/isort
|
||||
rev: 5.12.0
|
||||
rev: 5.13.2
|
||||
hooks:
|
||||
- id: isort
|
||||
name: isort
|
||||
args:
|
||||
- --diff
|
||||
- --check
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: 'v0.0.277'
|
||||
hooks:
|
||||
- id: ruff
|
||||
name: ruff
|
||||
files: ^(telegram|examples|tests)/.*\.py$
|
||||
additional_dependencies:
|
||||
- httpx~=0.24.1
|
||||
- tornado~=6.2
|
||||
- APScheduler~=3.10.1
|
||||
- cachetools~=5.3.1
|
||||
- aiolimiter~=1.1.0
|
||||
|
||||
+41
-30
@@ -7,45 +7,56 @@ version: 2
|
||||
|
||||
# Build documentation in the docs/ directory with Sphinx
|
||||
sphinx:
|
||||
configuration: docs/source/conf.py
|
||||
configuration: docs/source/conf.py
|
||||
|
||||
# Optionally build your docs in additional formats such as PDF
|
||||
formats:
|
||||
- pdf
|
||||
- pdf
|
||||
|
||||
# Optionally set the version of Python and requirements required to build your docs
|
||||
python:
|
||||
install:
|
||||
- method: pip
|
||||
path: .
|
||||
- requirements: docs/requirements-docs.txt
|
||||
install:
|
||||
- method: pip
|
||||
path: .
|
||||
- requirements: docs/requirements-docs.txt
|
||||
|
||||
build:
|
||||
os: ubuntu-22.04
|
||||
tools:
|
||||
python: "3" # latest stable cpython version
|
||||
os: ubuntu-22.04
|
||||
tools:
|
||||
python: "3" # latest stable cpython version
|
||||
jobs:
|
||||
post_build:
|
||||
# Based on https://github.com/readthedocs/readthedocs.org/issues/3242#issuecomment-1410321534
|
||||
# This provides a HTML zip file for download, with the same structure as the hosted website
|
||||
- mkdir --parents $READTHEDOCS_OUTPUT/htmlzip
|
||||
- cp --recursive $READTHEDOCS_OUTPUT/html $READTHEDOCS_OUTPUT/$READTHEDOCS_PROJECT
|
||||
# Hide the "other versions" dropdown. This is a workaround for those versions being shown,
|
||||
# but not being accessible, as they are not built. Also, they hide the actual sidebar menu
|
||||
# that is relevant only on ReadTheDocs.
|
||||
- echo "#furo-readthedocs-versions{display:none}" >> $READTHEDOCS_OUTPUT/$READTHEDOCS_PROJECT/_static/styles/furo-extensions.css
|
||||
- cd $READTHEDOCS_OUTPUT ; zip --recurse-path --symlinks htmlzip/$READTHEDOCS_PROJECT.zip $READTHEDOCS_PROJECT
|
||||
|
||||
search:
|
||||
ranking: # bump up rank of commonly searched pages: (default: 0, values range from -10 to 10)
|
||||
telegram.bot.html: 7
|
||||
telegram.message.html: 3
|
||||
telegram.update.html: 3
|
||||
telegram.user.html: 2
|
||||
telegram.chat.html: 2
|
||||
telegram.ext.application.html: 3
|
||||
telegram.ext.filters.html: 3
|
||||
telegram.ext.callbackcontext.html: 2
|
||||
telegram.ext.inlinekeyboardbutton.html: 1
|
||||
ranking: # bump up rank of commonly searched pages: (default: 0, values range from -10 to 10)
|
||||
telegram.bot.html: 7
|
||||
telegram.message.html: 3
|
||||
telegram.update.html: 3
|
||||
telegram.user.html: 2
|
||||
telegram.chat.html: 2
|
||||
telegram.ext.application.html: 3
|
||||
telegram.ext.filters.html: 3
|
||||
telegram.ext.callbackcontext.html: 2
|
||||
telegram.ext.inlinekeyboardbutton.html: 1
|
||||
|
||||
telegram.passport*.html: -7
|
||||
telegram.passport*.html: -7
|
||||
|
||||
ignore:
|
||||
- changelog.html
|
||||
- coc.html
|
||||
- bot_methods.html#
|
||||
- bot_methods.html
|
||||
# Defaults
|
||||
- search.html
|
||||
- search/index.html
|
||||
- 404.html
|
||||
- 404/index.html'
|
||||
ignore:
|
||||
- changelog.html
|
||||
- coc.html
|
||||
- bot_methods.html#
|
||||
- bot_methods.html
|
||||
# Defaults
|
||||
- search.html
|
||||
- search/index.html
|
||||
- 404.html
|
||||
- 404/index.html'
|
||||
|
||||
@@ -21,9 +21,11 @@ Contributors
|
||||
|
||||
The following wonderful people contributed directly or indirectly to this project:
|
||||
|
||||
- `Abdelrahman <https://github.com/aelkheir>`_
|
||||
- `Abshar <https://github.com/abxhr>`_
|
||||
- `Alateas <https://github.com/alateas>`_
|
||||
- `Ales Dokshanin <https://github.com/alesdokshanin>`_
|
||||
- `Alexandre <https://github.com/xTudoS>`_
|
||||
- `Alizia <https://github.com/thefunkycat>`_
|
||||
- `Ambro17 <https://github.com/Ambro17>`_
|
||||
- `Andrej Zhilenkov <https://github.com/Andrej730>`_
|
||||
@@ -68,6 +70,7 @@ The following wonderful people contributed directly or indirectly to this projec
|
||||
- `Joscha Götzer <https://github.com/Rostgnom>`_
|
||||
- `jossalgon <https://github.com/jossalgon>`_
|
||||
- `JRoot3D <https://github.com/JRoot3D>`_
|
||||
- `kenjitagawa <https://github.com/kenjitagawa>`_
|
||||
- `kennethcheo <https://github.com/kennethcheo>`_
|
||||
- `Kirill Vasin <https://github.com/vasinkd>`_
|
||||
- `Kjwon15 <https://github.com/kjwon15>`_
|
||||
@@ -75,6 +78,7 @@ The following wonderful people contributed directly or indirectly to this projec
|
||||
- `Loo Zheng Yuan <https://github.com/loozhengyuan>`_
|
||||
- `LRezende <https://github.com/lrezende>`_
|
||||
- `Luca Bellanti <https://github.com/Trifase>`_
|
||||
- `Lucas Molinari <https://github.com/lucasmolinari>`_
|
||||
- `macrojames <https://github.com/macrojames>`_
|
||||
- `Matheus Lemos <https://github.com/mlemosf>`_
|
||||
- `Michael Dix <https://github.com/Eisberge>`_
|
||||
@@ -120,6 +124,7 @@ The following wonderful people contributed directly or indirectly to this projec
|
||||
- `Wagner Macedo <https://github.com/wagnerluis1982>`_
|
||||
- `wjt <https://github.com/wjt>`_
|
||||
- `Yaw Danso <https://github.com/dglitxh>`_
|
||||
- `Yao Kuan <https://github.com/thatguylah>`_
|
||||
- `zeroone2numeral2 <https://github.com/zeroone2numeral2>`_
|
||||
- `zeshuaro <https://github.com/zeshuaro>`_
|
||||
- `zpavloudis <https://github.com/zpavloudis>`_
|
||||
|
||||
+280
@@ -4,6 +4,286 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
Version 21.0.1
|
||||
==============
|
||||
|
||||
*Released 2024-03-06*
|
||||
|
||||
This is the technical changelog for version 21.0.1. More elaborate release notes can be found in the news channel `@pythontelegrambotchannel <https://t.me/pythontelegrambotchannel>`__.
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- Remove ``docs`` from Package (:pr:`4150`)
|
||||
|
||||
|
||||
Version 21.0
|
||||
============
|
||||
|
||||
*Released 2024-03-06*
|
||||
|
||||
This is the technical changelog for version 21.0. More elaborate release notes can be found in the news channel `@pythontelegrambotchannel <https://t.me/pythontelegrambotchannel>`__.
|
||||
|
||||
Major Changes
|
||||
-------------
|
||||
|
||||
- Remove Functionality Deprecated in API 7.0 (:pr:`4114` closes :issue:`4099`)
|
||||
- API 7.1 (:pr:`4118`)
|
||||
|
||||
New Features
|
||||
------------
|
||||
|
||||
- Add Parameter ``media_write_timeout`` to ``HTTPXRequest`` and Method ``ApplicationBuilder.media_write_timeout`` (:pr:`4120` closes :issue:`3864`)
|
||||
- Handle Properties in ``TelegramObject.__setstate__`` (:pr:`4134` closes :issue:`4111`)
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- Add Missing Slot to ``Updater`` (:pr:`4130` closes :issue:`4127`)
|
||||
|
||||
Documentation Improvements
|
||||
--------------------------
|
||||
|
||||
- Improve HTML Download of Documentation (:pr:`4146` closes :issue:`4050`)
|
||||
- Documentation Improvements (:pr:`4109`, :issue:`4116`)
|
||||
- Update Copyright to 2024 (:pr:`4121` by `@aelkheir <https://github.com/aelkheir>`__ closes :issue:`4041`)
|
||||
|
||||
Internal Changes
|
||||
----------------
|
||||
|
||||
- Apply ``pre-commit`` Checks More Widely (:pr:`4135`)
|
||||
- Refactor and Overhaul ``test_official`` (:pr:`4087` closes :issue:`3874`)
|
||||
- Run Unit Tests in PRs on Requirements Changes (:pr:`4144`)
|
||||
- Make ``Updater.stop`` Independent of ``CancelledError`` (:pr:`4126`)
|
||||
|
||||
Dependency Updates
|
||||
------------------
|
||||
|
||||
- Relax Upper Bound for ``httpx`` Dependency (:pr:`4148`)
|
||||
- Bump ``test-summary/action`` from 2.2 to 2.3 (:pr:`4142`)
|
||||
- Update ``cachetools`` requirement from ~=5.3.2 to ~=5.3.3 (:pr:`4141`)
|
||||
- Update ``httpx`` requirement from ~=0.26.0 to ~=0.27.0 (:pr:`4131`)
|
||||
|
||||
|
||||
Version 20.8
|
||||
============
|
||||
|
||||
*Released 2024-02-08*
|
||||
|
||||
This is the technical changelog for version 20.8. More elaborate release notes can be found in the news channel `@pythontelegrambotchannel <https://t.me/pythontelegrambotchannel>`__.
|
||||
|
||||
Major Changes
|
||||
-------------
|
||||
|
||||
- API 7.0 (:pr:`4034` closes :issue:`4033`, :pr:`4038` by `@aelkheir <https://github.com/aelkheir>`__)
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Fix Type Hint for ``filters`` Parameter of ``MessageHandler`` (:pr:`4039` by `@Palaptin <https://github.com/Palaptin>`__)
|
||||
- Deprecate ``filters.CHAT`` (:pr:`4083` closes :issue:`4062`)
|
||||
- Improve Error Handling in Built-In Webhook Handler (:pr:`3987` closes :issue:`3979`)
|
||||
|
||||
New Features
|
||||
------------
|
||||
|
||||
- Add Parameter ``pattern`` to ``PreCheckoutQueryHandler`` and ``filters.SuccessfulPayment`` (:pr:`4005` by `@aelkheir <https://github.com/aelkheir>`__ closes :issue:`3752`)
|
||||
- Add Missing Conversions of ``type`` to Corresponding Enum from ``telegram.constants`` (:pr:`4067`)
|
||||
- Add Support for Unix Sockets to ``Updater.start_webhook`` (:pr:`3986` closes :issue:`3978`)
|
||||
- Add ``Bot.do_api_request`` (:pr:`4084` closes :issue:`4053`)
|
||||
- Add ``AsyncContextManager`` as Parent Class to ``BaseUpdateProcessor`` (:pr:`4001`)
|
||||
|
||||
Documentation Improvements
|
||||
--------------------------
|
||||
|
||||
- Documentation Improvements (:pr:`3919`)
|
||||
- Add Docstring to Dunder Methods (:pr:`3929` closes :issue:`3926`)
|
||||
- Documentation Improvements (:pr:`4002`, :pr:`4079` by `@kenjitagawa <https://github.com/kenjitagawa>`__, :pr:`4104` by `@xTudoS <https://github.com/xTudoS>`__)
|
||||
|
||||
Internal Changes
|
||||
----------------
|
||||
|
||||
- Drop Usage of DeepSource (:pr:`4100`)
|
||||
- Improve Type Completeness & Corresponding Workflow (:pr:`4035`)
|
||||
- Bump ``ruff`` and Remove ``sort-all`` (:pr:`4075`)
|
||||
- Move Handler Files to ``_handlers`` Subdirectory (:pr:`4064` by `@lucasmolinari <https://github.com/lucasmolinari>`__ closes :issue:`4060`)
|
||||
- Introduce ``sort-all`` Hook for ``pre-commit`` (:pr:`4052`)
|
||||
- Use Recommended ``pre-commit`` Mirror for ``black`` (:pr:`4051`)
|
||||
- Remove Unused ``DEFAULT_20`` (:pr:`3997`)
|
||||
- Migrate From ``setup.cfg`` to ``pyproject.toml`` Where Possible (:pr:`4088`)
|
||||
|
||||
Dependency Updates
|
||||
------------------
|
||||
|
||||
- Bump ``black`` and ``ruff`` (:pr:`4089`)
|
||||
- Bump ``srvaroa/labeler`` from 1.8.0 to 1.10.0 (:pr:`4048`)
|
||||
- Update ``tornado`` requirement from ~=6.3.3 to ~=6.4 (:pr:`3992`)
|
||||
- Bump ``actions/stale`` from 8 to 9 (:pr:`4046`)
|
||||
- Bump ``actions/setup-python`` from 4 to 5 (:pr:`4047`)
|
||||
- ``pre-commit`` autoupdate (:pr:`4101`)
|
||||
- Bump ``actions/upload-artifact`` from 3 to 4 (:pr:`4045`)
|
||||
- ``pre-commit`` autoupdate (:pr:`3996`)
|
||||
- Bump ``furo`` from 2023.9.10 to 2024.1.29 (:pr:`4094`)
|
||||
- ``pre-commit`` autoupdate (:pr:`4043`)
|
||||
- Bump ``codecov/codecov-action`` from 3 to 4 (:pr:`4091`)
|
||||
- Bump ``EndBug/add-and-commit`` from 9.1.3 to 9.1.4 (:pr:`4090`)
|
||||
- Update ``httpx`` requirement from ~=0.25.2 to ~=0.26.0 (:pr:`4024`)
|
||||
- Bump ``pytest`` from 7.4.3 to 7.4.4 (:pr:`4056`)
|
||||
- Bump ``srvaroa/labeler`` from 1.7.0 to 1.8.0 (:pr:`3993`)
|
||||
- Bump ``test-summary/action`` from 2.1 to 2.2 (:pr:`4044`)
|
||||
- Bump ``dessant/lock-threads`` from 4.0.1 to 5.0.1 (:pr:`3994`)
|
||||
|
||||
|
||||
Version 20.7
|
||||
============
|
||||
|
||||
*Released 2023-11-27*
|
||||
|
||||
This is the technical changelog for version 20.7. More elaborate release notes can be found in the news channel `@pythontelegrambotchannel <https://t.me/pythontelegrambotchannel>`__.
|
||||
|
||||
New Features
|
||||
------------
|
||||
|
||||
- Add ``JobQueue.scheduler_configuration`` and Corresponding Warnings (:pr:`3913` closes :issue:`3837`)
|
||||
- Add Parameter ``socket_options`` to ``HTTPXRequest`` (:pr:`3935` closes :issue:`2965`)
|
||||
- Add ``ApplicationBuilder.(get_updates_)socket_options`` (:pr:`3943`)
|
||||
- Improve ``write_timeout`` Handling for Media Methods (:pr:`3952`)
|
||||
- Add ``filters.Mention`` (:pr:`3941` closes :issue:`3799`)
|
||||
- Rename ``proxy_url`` to ``proxy`` and Allow ``httpx.{Proxy, URL}`` as Input (:pr:`3939` closes :issue:`3844`)
|
||||
|
||||
Bug Fixes & Changes
|
||||
-------------------
|
||||
|
||||
- Adjust ``read_timeout`` Behavior for ``Bot.get_updates`` (:pr:`3963` closes :issue:`3893`)
|
||||
- Improve ``BaseHandler.__repr__`` for Callbacks without ``__qualname__`` (:pr:`3934`)
|
||||
- Fix Persistency Issue with Ended Non-Blocking Conversations (:pr:`3962`)
|
||||
- Improve Type Hinting for Arguments with Default Values in ``Bot`` (:pr:`3942`)
|
||||
|
||||
Documentation Improvements
|
||||
--------------------------
|
||||
|
||||
- Add Documentation for ``__aenter__`` and ``__aexit__`` Methods (:pr:`3907` closes :issue:`3886`)
|
||||
- Improve Insertion of Kwargs into ``Bot`` Methods (:pr:`3965`)
|
||||
|
||||
Internal Changes
|
||||
----------------
|
||||
|
||||
- Adjust Tests to New Error Messages (:pr:`3970`)
|
||||
|
||||
Dependency Updates
|
||||
------------------
|
||||
|
||||
- Bump ``pytest-xdist`` from 3.3.1 to 3.4.0 (:pr:`3975`)
|
||||
- ``pre-commit`` autoupdate (:pr:`3967`)
|
||||
- Update ``httpx`` requirement from ~=0.25.1 to ~=0.25.2 (:pr:`3983`)
|
||||
- Bump ``pytest-xdist`` from 3.4.0 to 3.5.0 (:pr:`3982`)
|
||||
- Update ``httpx`` requirement from ~=0.25.0 to ~=0.25.1 (:pr:`3961`)
|
||||
- Bump ``srvaroa/labeler`` from 1.6.1 to 1.7.0 (:pr:`3958`)
|
||||
- Update ``cachetools`` requirement from ~=5.3.1 to ~=5.3.2 (:pr:`3954`)
|
||||
- Bump ``pytest`` from 7.4.2 to 7.4.3 (:pr:`3953`)
|
||||
|
||||
|
||||
Version 20.6
|
||||
============
|
||||
|
||||
*Released 2023-10-03*
|
||||
|
||||
This is the technical changelog for version 20.6. More elaborate release notes can be found in the news channel `@pythontelegrambotchannel <https://t.me/pythontelegrambotchannel>`__.
|
||||
|
||||
Major Changes
|
||||
-------------
|
||||
|
||||
- Drop Backward Compatibility Layer Introduced in :pr:`3853` (API 6.8) (:pr:`3873`)
|
||||
- Full Support for Bot API 6.9 (:pr:`3898`)
|
||||
|
||||
New Features
|
||||
------------
|
||||
|
||||
- Add Rich Equality Comparison to ``WriteAccessAllowed`` (:pr:`3911` closes :issue:`3909`)
|
||||
- Add ``__repr__`` Methods Added in :pr:`3826` closes :issue:`3770` to Sphinx Documentation (:pr:`3901` closes :issue:`3889`)
|
||||
- Add String Representation for Selected Classes (:pr:`3826` closes :issue:`3770`)
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add Support Python 3.12 (:pr:`3915`)
|
||||
- Documentation Improvements (:pr:`3910`)
|
||||
|
||||
Internal Changes
|
||||
----------------
|
||||
|
||||
- Verify Type Hints for Bot Method & Telegram Class Parameters (:pr:`3868`)
|
||||
- Move Bot API Tests to Separate Workflow File (:pr:`3912`)
|
||||
- Fix Failing ``file_size`` Tests (:pr:`3906`)
|
||||
- Set Threshold for DeepSource’s PY-R1000 to High (:pr:`3888`)
|
||||
- One-Time Code Formatting Improvement via ``--preview`` Flag of ``black`` (:pr:`3882`)
|
||||
- Move Dunder Methods to the Top of Class Bodies (:pr:`3883`)
|
||||
- Remove Superfluous ``Defaults.__ne__`` (:pr:`3884`)
|
||||
|
||||
Dependency Updates
|
||||
------------------
|
||||
|
||||
- ``pre-commit`` autoupdate (:pr:`3876`)
|
||||
- Update ``pre-commit`` Dependencies (:pr:`3916`)
|
||||
- Bump ``actions/checkout`` from 3 to 4 (:pr:`3914`)
|
||||
- Update ``httpx`` requirement from ~=0.24.1 to ~=0.25.0 (:pr:`3891`)
|
||||
- Bump ``furo`` from 2023.8.19 to 2023.9.10 (:pr:`3890`)
|
||||
- Bump ``sphinx`` from 7.2.5 to 7.2.6 (:pr:`3892`)
|
||||
- Update ``tornado`` requirement from ~=6.2 to ~=6.3.3 (:pr:`3675`)
|
||||
- Bump ``pytest`` from 7.4.0 to 7.4.2 (:pr:`3881`)
|
||||
|
||||
|
||||
Version 20.5
|
||||
============
|
||||
*Released 2023-09-03*
|
||||
|
||||
This is the technical changelog for version 20.5. More elaborate release notes can be found in the news channel `@pythontelegrambotchannel <https://t.me/pythontelegrambotchannel>`__.
|
||||
|
||||
Major Changes
|
||||
-------------
|
||||
|
||||
- API 6.8 (:pr:`3853`)
|
||||
- Remove Functionality Deprecated Since Bot API 6.5, 6.6 or 6.7 (:pr:`3858`)
|
||||
|
||||
New Features
|
||||
------------
|
||||
|
||||
- Extend Allowed Values for HTTP Version (:pr:`3823` closes :issue:`3821`)
|
||||
- Add ``has_args`` Parameter to ``CommandHandler`` (:pr:`3854` by `@thatguylah <https://github.com/thatguylah>`__ closes :issue:`3798`)
|
||||
- Add ``Application.stop_running()`` and Improve Marking Updates as Read on ``Updater.stop()`` (:pr:`3804`)
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Type Hinting Fixes for ``WebhookInfo`` (:pr:`3871`)
|
||||
- Test and Document ``Exception.__cause__`` on ``NetworkError`` (:pr:`3792` closes :issue:`3778`)
|
||||
- Add Support for Python 3.12 RC (:pr:`3847`)
|
||||
|
||||
Documentation Improvements
|
||||
--------------------------
|
||||
|
||||
- Remove Version Check from Examples (:pr:`3846`)
|
||||
- Documentation Improvements (:pr:`3803`, :pr:`3797`, :pr:`3816` by `@trim21 <https://github.com/trim21>`__, :pr:`3829` by `@aelkheir <https://github.com/aelkheir>`__)
|
||||
- Provide Versions of ``customwebhookbot.py`` with Different Frameworks (:pr:`3820` closes :issue:`3717`)
|
||||
|
||||
Dependency Updates
|
||||
------------------
|
||||
|
||||
- ``pre-commit`` autoupdate (:pr:`3824`)
|
||||
- Bump ``srvaroa/labeler`` from 1.6.0 to 1.6.1 (:pr:`3870`)
|
||||
- Bump ``sphinx`` from 7.0.1 to 7.1.1 (:pr:`3818`)
|
||||
- Bump ``sphinx`` from 7.2.3 to 7.2.5 (:pr:`3869`)
|
||||
- Bump ``furo`` from 2023.5.20 to 2023.7.26 (:pr:`3817`)
|
||||
- Update ``apscheduler`` requirement from ~=3.10.3 to ~=3.10.4 (:pr:`3862`)
|
||||
- Bump ``sphinx`` from 7.2.2 to 7.2.3 (:pr:`3861`)
|
||||
- Bump ``pytest-asyncio`` from 0.21.0 to 0.21.1 (:pr:`3801`)
|
||||
- Bump ``sphinx-paramlinks`` from 0.5.4 to 0.6.0 (:pr:`3840`)
|
||||
- Update ``apscheduler`` requirement from ~=3.10.1 to ~=3.10.3 (:pr:`3851`)
|
||||
- Bump ``furo`` from 2023.7.26 to 2023.8.19 (:pr:`3850`)
|
||||
- Bump ``sphinx`` from 7.1.2 to 7.2.2 (:pr:`3852`)
|
||||
- Bump ``sphinx`` from 7.1.1 to 7.1.2 (:pr:`3827`)
|
||||
|
||||
|
||||
Version 20.4
|
||||
============
|
||||
|
||||
|
||||
+7
-11
@@ -14,7 +14,7 @@
|
||||
:target: https://pypi.org/project/python-telegram-bot/
|
||||
:alt: Supported Python versions
|
||||
|
||||
.. image:: https://img.shields.io/badge/Bot%20API-6.7-blue?logo=telegram
|
||||
.. image:: https://img.shields.io/badge/Bot%20API-7.1-blue?logo=telegram
|
||||
:target: https://core.telegram.org/bots/api-changelog
|
||||
:alt: Supported Bot API versions
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
:target: https://www.gnu.org/licenses/lgpl-3.0.html
|
||||
:alt: LGPLv3 License
|
||||
|
||||
.. image:: https://github.com/python-telegram-bot/python-telegram-bot/workflows/GitHub%20Actions/badge.svg
|
||||
.. 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
|
||||
|
||||
@@ -46,10 +46,6 @@
|
||||
:target: https://app.codacy.com/gh/python-telegram-bot/python-telegram-bot/dashboard
|
||||
:alt: Code quality: Codacy
|
||||
|
||||
.. image:: https://app.deepsource.com/gh/python-telegram-bot/python-telegram-bot.svg/?label=active+issues
|
||||
:target: https://app.deepsource.com/gh/python-telegram-bot/python-telegram-bot/?ref=repository-badge
|
||||
:alt: Code quality: DeepSource
|
||||
|
||||
.. 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
|
||||
@@ -93,7 +89,7 @@ Installing both ``python-telegram-bot`` and ``python-telegram-bot-raw`` in conju
|
||||
Telegram API support
|
||||
====================
|
||||
|
||||
All types and methods of the Telegram Bot API **6.7** are supported.
|
||||
All types and methods of the Telegram Bot API **7.1** are supported.
|
||||
|
||||
Installing
|
||||
==========
|
||||
@@ -135,7 +131,7 @@ As these features are *optional*, the corresponding 3rd party dependencies are n
|
||||
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.24.1 <https://www.python-httpx.org>`_ for
|
||||
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.
|
||||
@@ -152,9 +148,9 @@ PTB can be installed with optional dependencies:
|
||||
* ``pip install "python-telegram-bot[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[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.2 <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.1 <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.1 <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``.
|
||||
* ``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[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]"``.
|
||||
|
||||
|
||||
+6
-10
@@ -14,7 +14,7 @@
|
||||
:target: https://pypi.org/project/python-telegram-bot-raw/
|
||||
:alt: Supported Python versions
|
||||
|
||||
.. image:: https://img.shields.io/badge/Bot%20API-6.7-blue?logo=telegram
|
||||
.. image:: https://img.shields.io/badge/Bot%20API-7.1-blue?logo=telegram
|
||||
:target: https://core.telegram.org/bots/api-changelog
|
||||
:alt: Supported Bot API versions
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
:target: https://www.gnu.org/licenses/lgpl-3.0.html
|
||||
:alt: LGPLv3 License
|
||||
|
||||
.. image:: https://github.com/python-telegram-bot/python-telegram-bot/workflows/GitHub%20Actions/badge.svg
|
||||
.. 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
|
||||
|
||||
@@ -46,10 +46,6 @@
|
||||
:target: https://app.codacy.com/gh/python-telegram-bot/python-telegram-bot/dashboard
|
||||
:alt: Code quality: Codacy
|
||||
|
||||
.. image:: https://app.deepsource.com/gh/python-telegram-bot/python-telegram-bot.svg/?label=active+issues
|
||||
:target: https://app.deepsource.com/gh/python-telegram-bot/python-telegram-bot/?ref=repository-badge
|
||||
:alt: Code quality: DeepSource
|
||||
|
||||
.. 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
|
||||
@@ -89,7 +85,7 @@ Installing both ``python-telegram-bot`` and ``python-telegram-bot-raw`` in conju
|
||||
Telegram API support
|
||||
====================
|
||||
|
||||
All types and methods of the Telegram Bot API **6.7** are supported.
|
||||
All types and methods of the Telegram Bot API **7.1** are supported.
|
||||
|
||||
Installing
|
||||
==========
|
||||
@@ -108,12 +104,12 @@ You can also install ``python-telegram-bot-raw`` from source, though this is usu
|
||||
|
||||
$ git clone https://github.com/python-telegram-bot/python-telegram-bot
|
||||
$ cd python-telegram-bot
|
||||
$ python setup-raw.py install
|
||||
$ 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``.
|
||||
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
|
||||
------------------
|
||||
@@ -136,7 +132,7 @@ As these features are *optional*, the corresponding 3rd party dependencies are n
|
||||
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.24.1 <https://www.python-httpx.org>`_ for
|
||||
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.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2023
|
||||
# Copyright (C) 2015-2024
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
@@ -64,7 +64,7 @@ class AdmonitionInserter:
|
||||
ForwardRef('DefaultValue[DVValueType]')
|
||||
"""
|
||||
|
||||
METHOD_NAMES_FOR_BOT_AND_APPBUILDER: dict[type, str] = {
|
||||
METHOD_NAMES_FOR_BOT_AND_APPBUILDER: typing.ClassVar[dict[type, str]] = {
|
||||
cls: tuple(m[0] for m in _iter_own_public_methods(cls)) # m[0] means we take only names
|
||||
for cls in (telegram.Bot, telegram.ext.ApplicationBuilder)
|
||||
}
|
||||
@@ -159,7 +159,7 @@ class AdmonitionInserter:
|
||||
telegram.ext, inspect.isclass
|
||||
)
|
||||
|
||||
for class_name, inspected_class in classes_to_inspect:
|
||||
for _class_name, inspected_class in classes_to_inspect:
|
||||
# We need to make "<class 'telegram._files.sticker.StickerSet'>" into
|
||||
# "telegram.StickerSet" because that's the way the classes are mentioned in
|
||||
# docstrings.
|
||||
@@ -194,11 +194,11 @@ class AdmonitionInserter:
|
||||
)
|
||||
except NotImplementedError as e:
|
||||
raise NotImplementedError(
|
||||
f"Error generating Sphinx 'Available in' admonition "
|
||||
"Error generating Sphinx 'Available in' admonition "
|
||||
f"(admonition_inserter.py). Class {name_of_class_in_attr} present in "
|
||||
f"attribute {target_attr} of class {name_of_inspected_class_in_docstr}"
|
||||
f" could not be resolved. {str(e)}"
|
||||
)
|
||||
f" could not be resolved. {e!s}"
|
||||
) from e
|
||||
|
||||
# Properties need to be parsed separately because they act like attributes but not
|
||||
# listed as attributes.
|
||||
@@ -237,11 +237,11 @@ class AdmonitionInserter:
|
||||
)
|
||||
except NotImplementedError as e:
|
||||
raise NotImplementedError(
|
||||
f"Error generating Sphinx 'Available in' admonition "
|
||||
"Error generating Sphinx 'Available in' admonition "
|
||||
f"(admonition_inserter.py). Class {name_of_class_in_prop} present in "
|
||||
f"property {prop_name} of class {name_of_inspected_class_in_docstr}"
|
||||
f" could not be resolved. {str(e)}"
|
||||
)
|
||||
f" could not be resolved. {e!s}"
|
||||
) from e
|
||||
|
||||
return self._generate_admonitions(attrs_for_class, admonition_type="available_in")
|
||||
|
||||
@@ -269,10 +269,10 @@ class AdmonitionInserter:
|
||||
)
|
||||
except NotImplementedError as e:
|
||||
raise NotImplementedError(
|
||||
f"Error generating Sphinx 'Returned in' admonition "
|
||||
"Error generating Sphinx 'Returned in' admonition "
|
||||
f"(admonition_inserter.py). {cls}, method {method_name}. "
|
||||
f"Couldn't resolve type hint in return annotation {ret_annot}. {str(e)}"
|
||||
)
|
||||
f"Couldn't resolve type hint in return annotation {ret_annot}. {e!s}"
|
||||
) from e
|
||||
|
||||
return self._generate_admonitions(methods_for_class, admonition_type="returned_in")
|
||||
|
||||
@@ -297,7 +297,7 @@ class AdmonitionInserter:
|
||||
|
||||
# inspect methods of all telegram classes for return statements that indicate
|
||||
# that this given method is a shortcut for a Bot method
|
||||
for class_name, cls in inspect.getmembers(telegram, predicate=inspect.isclass):
|
||||
for _class_name, cls in inspect.getmembers(telegram, predicate=inspect.isclass):
|
||||
# no need to inspect Bot's own methods, as Bot can't have shortcuts in Bot
|
||||
if cls is telegram.Bot:
|
||||
continue
|
||||
@@ -342,10 +342,10 @@ class AdmonitionInserter:
|
||||
)
|
||||
except NotImplementedError as e:
|
||||
raise NotImplementedError(
|
||||
f"Error generating Sphinx 'Use in' admonition "
|
||||
"Error generating Sphinx 'Use in' admonition "
|
||||
f"(admonition_inserter.py). {cls}, method {method_name}, parameter "
|
||||
f"{param}: Couldn't resolve type hint {param.annotation}. {str(e)}"
|
||||
)
|
||||
f"{param}: Couldn't resolve type hint {param.annotation}. {e!s}"
|
||||
) from e
|
||||
|
||||
return self._generate_admonitions(methods_for_class, admonition_type="use_in")
|
||||
|
||||
@@ -359,17 +359,19 @@ class AdmonitionInserter:
|
||||
If no key phrases are found, the admonition will be inserted at the very end.
|
||||
"""
|
||||
for idx, value in list(enumerate(lines)):
|
||||
if (
|
||||
value.startswith(".. seealso:")
|
||||
# The docstring contains heading "Examples:", but Sphinx will have it converted
|
||||
# to ".. admonition: Examples":
|
||||
or value.startswith(".. admonition:: Examples")
|
||||
or value.startswith(".. version")
|
||||
# The space after ":param" is important because docstring can contain ":paramref:"
|
||||
# in its plain text in the beginning of a line (e.g. ExtBot):
|
||||
or value.startswith(":param ")
|
||||
# some classes (like "Credentials") have no params, so insert before attrs:
|
||||
or value.startswith(".. attribute::")
|
||||
if value.startswith(
|
||||
(
|
||||
".. seealso:",
|
||||
# The docstring contains heading "Examples:", but Sphinx will have it converted
|
||||
# to ".. admonition: Examples":
|
||||
".. admonition:: Examples",
|
||||
".. version",
|
||||
# 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 ",
|
||||
# some classes (like "Credentials") have no params, so insert before attrs:
|
||||
".. attribute::",
|
||||
)
|
||||
):
|
||||
return idx
|
||||
return len(lines) - 1
|
||||
@@ -411,7 +413,7 @@ class AdmonitionInserter:
|
||||
# so its page needs no admonitions.
|
||||
continue
|
||||
|
||||
attrs = sorted(attrs)
|
||||
sorted_attrs = sorted(attrs)
|
||||
|
||||
# e.g. for admonition type "use_in" the title will be "Use in" and CSS class "use-in".
|
||||
admonition = f"""
|
||||
@@ -419,11 +421,11 @@ class AdmonitionInserter:
|
||||
.. admonition:: {admonition_type.title().replace("_", " ")}
|
||||
:class: {admonition_type.replace("_", "-")}
|
||||
"""
|
||||
if len(attrs) > 1:
|
||||
for target_attr in attrs:
|
||||
if len(sorted_attrs) > 1:
|
||||
for target_attr in sorted_attrs:
|
||||
admonition += "\n * " + target_attr
|
||||
else:
|
||||
admonition += f"\n {attrs[0]}"
|
||||
admonition += f"\n {sorted_attrs[0]}"
|
||||
|
||||
admonition += "\n " # otherwise an unexpected unindent warning will be issued
|
||||
admonition_for_class[cls] = admonition
|
||||
@@ -516,12 +518,12 @@ class AdmonitionInserter:
|
||||
# If it isn't resolved, we'll have the program throw an exception to be sure.
|
||||
try:
|
||||
cls = self._resolve_class(m.group("class_name"))
|
||||
except AttributeError:
|
||||
except AttributeError as exc:
|
||||
# skip known ForwardRef's that need not be resolved to a Telegram class
|
||||
if self.FORWARD_REF_SKIP_PATTERN.match(str(arg)):
|
||||
pass
|
||||
else:
|
||||
raise NotImplementedError(f"Could not process ForwardRef: {arg}")
|
||||
raise NotImplementedError(f"Could not process ForwardRef: {arg}") from exc
|
||||
else:
|
||||
yield cls
|
||||
|
||||
@@ -587,6 +589,7 @@ class AdmonitionInserter:
|
||||
# If neither option works, this is not a PTB class.
|
||||
except (NameError, AttributeError):
|
||||
continue
|
||||
return None
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2023
|
||||
# Copyright (C) 2015-2024
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
@@ -16,51 +16,81 @@
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
import inspect
|
||||
from typing import List
|
||||
|
||||
keyword_args = [
|
||||
":keyword _sphinx_paramlinks_telegram.Bot.{method}.read_timeout: Value to pass to "
|
||||
":paramref:`telegram.request.BaseRequest.post.read_timeout`. Defaults to {read_timeout}.",
|
||||
":kwtype _sphinx_paramlinks_telegram.Bot.{method}.read_timeout: {read_timeout_type}, optional",
|
||||
":keyword _sphinx_paramlinks_telegram.Bot.{method}.write_timeout: Value to pass to "
|
||||
":paramref:`telegram.request.BaseRequest.post.write_timeout`. Defaults to {write_timeout}.",
|
||||
":kwtype _sphinx_paramlinks_telegram.Bot.{method}.write_timeout: :obj:`float` | :obj:`None`, "
|
||||
"optional",
|
||||
":keyword _sphinx_paramlinks_telegram.Bot.{method}.connect_timeout: Value to pass to "
|
||||
":paramref:`telegram.request.BaseRequest.post.connect_timeout`. Defaults to "
|
||||
":attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.",
|
||||
":kwtype _sphinx_paramlinks_telegram.Bot.{method}.connect_timeout: :obj:`float` | "
|
||||
":obj:`None`, optional",
|
||||
":keyword _sphinx_paramlinks_telegram.Bot.{method}.pool_timeout: Value to pass to "
|
||||
":paramref:`telegram.request.BaseRequest.post.pool_timeout`. Defaults to "
|
||||
":attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.",
|
||||
":kwtype _sphinx_paramlinks_telegram.Bot.{method}.pool_timeout: :obj:`float` | :obj:`None`, "
|
||||
"optional",
|
||||
":keyword _sphinx_paramlinks_telegram.Bot.{method}.api_kwargs: Arbitrary keyword arguments "
|
||||
"to be passed to the Telegram API.",
|
||||
":kwtype _sphinx_paramlinks_telegram.Bot.{method}.api_kwargs: :obj:`dict`, optional",
|
||||
"Keyword Arguments:",
|
||||
(
|
||||
" read_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to "
|
||||
" :paramref:`telegram.request.BaseRequest.post.read_timeout`. Defaults to "
|
||||
" :attr:`~telegram.request.BaseRequest.DEFAULT_NONE`. "
|
||||
),
|
||||
(
|
||||
" write_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to "
|
||||
" :paramref:`telegram.request.BaseRequest.post.write_timeout`. Defaults to "
|
||||
" :attr:`~telegram.request.BaseRequest.DEFAULT_NONE`."
|
||||
),
|
||||
(
|
||||
" connect_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to "
|
||||
" :paramref:`telegram.request.BaseRequest.post.connect_timeout`. Defaults to "
|
||||
" :attr:`~telegram.request.BaseRequest.DEFAULT_NONE`."
|
||||
),
|
||||
(
|
||||
" pool_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to "
|
||||
" :paramref:`telegram.request.BaseRequest.post.pool_timeout`. Defaults to "
|
||||
" :attr:`~telegram.request.BaseRequest.DEFAULT_NONE`."
|
||||
),
|
||||
(
|
||||
" api_kwargs (:obj:`dict`, optional): Arbitrary keyword arguments"
|
||||
" to be passed to the Telegram API. See :meth:`~telegram.Bot.do_api_request` for"
|
||||
" limitations."
|
||||
),
|
||||
"",
|
||||
]
|
||||
write_timeout_sub = [":attr:`~telegram.request.BaseRequest.DEFAULT_NONE`", "``20``"]
|
||||
read_timeout_sub = [
|
||||
":attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.",
|
||||
"``2``. :paramref:`timeout` will be added to this value",
|
||||
|
||||
media_write_timeout_deprecation_methods = [
|
||||
"send_photo",
|
||||
"send_audio",
|
||||
"send_document",
|
||||
"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 = [
|
||||
" 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 "
|
||||
" :attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.",
|
||||
"",
|
||||
"",
|
||||
]
|
||||
get_updates_read_timeout_addition = [
|
||||
" :paramref:`timeout` will be added to this value.",
|
||||
"",
|
||||
"",
|
||||
" .. versionchanged:: 20.7",
|
||||
" Defaults to :attr:`~telegram.request.BaseRequest.DEFAULT_NONE` instead of ",
|
||||
" ``2``.",
|
||||
]
|
||||
read_timeout_type = [":obj:`float` | :obj:`None`", ":obj:`float`"]
|
||||
|
||||
|
||||
def find_insert_pos_for_kwargs(lines: list[str]) -> int:
|
||||
def find_insert_pos_for_kwargs(lines: List[str]) -> int:
|
||||
"""Finds the correct position to insert the keyword arguments and returns the index."""
|
||||
for idx, value in reversed(list(enumerate(lines))): # reversed since :returns: is at the end
|
||||
if value.startswith(":returns:"):
|
||||
if value.startswith("Returns"):
|
||||
return idx
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def is_write_timeout_20(obj: object) -> int:
|
||||
"""inspects the default value of write_timeout parameter of the bot method."""
|
||||
sig = inspect.signature(obj)
|
||||
return 1 if (sig.parameters["write_timeout"].default == 20) else 0
|
||||
return False
|
||||
|
||||
|
||||
def check_timeout_and_api_kwargs_presence(obj: object) -> int:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2023
|
||||
# Copyright (C) 2015-2024
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
@@ -20,6 +20,8 @@ to link to the correct files & lines on github. Can be simplified once
|
||||
https://github.com/sphinx-doc/sphinx/issues/1556 is closed
|
||||
"""
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from typing import Dict, Tuple
|
||||
|
||||
from sphinx.util import logging
|
||||
|
||||
@@ -30,13 +32,13 @@ sphinx_logger = logging.getLogger(__name__)
|
||||
|
||||
# must be a module-level variable so that it can be written to by the `autodoc-process-docstring`
|
||||
# event handler in `sphinx_hooks.py`
|
||||
LINE_NUMBERS = {}
|
||||
LINE_NUMBERS: Dict[str, Tuple[Path, int, int]] = {}
|
||||
|
||||
|
||||
def _git_branch() -> str:
|
||||
"""Get's the current git sha if available or fall back to `master`"""
|
||||
try:
|
||||
output = subprocess.check_output( # skipcq: BAN-B607
|
||||
output = subprocess.check_output(
|
||||
["git", "describe", "--tags", "--always"], stderr=subprocess.STDOUT
|
||||
)
|
||||
return output.decode().strip()
|
||||
@@ -52,7 +54,7 @@ git_branch = _git_branch()
|
||||
base_url = "https://github.com/python-telegram-bot/python-telegram-bot/blob/"
|
||||
|
||||
|
||||
def linkcode_resolve(_, info):
|
||||
def linkcode_resolve(_, info) -> str:
|
||||
"""See www.sphinx-doc.org/en/master/usage/extensions/linkcode.html"""
|
||||
combined = ".".join((info["module"], info["fullname"]))
|
||||
# special casing for ExtBot which is due to the special structure of extbot.rst
|
||||
@@ -71,7 +73,7 @@ def linkcode_resolve(_, info):
|
||||
line_info = LINE_NUMBERS.get(info["module"])
|
||||
|
||||
if not line_info:
|
||||
return
|
||||
return None
|
||||
|
||||
file, start_line, end_line = line_info
|
||||
return f"{base_url}{git_branch}/{file}#L{start_line}-L{end_line}"
|
||||
|
||||
+26
-22
@@ -1,6 +1,6 @@
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2023
|
||||
# Copyright (C) 2015-2024
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
@@ -29,11 +29,10 @@ from docs.auxil.admonition_inserter import AdmonitionInserter
|
||||
from docs.auxil.kwargs_insertion import (
|
||||
check_timeout_and_api_kwargs_presence,
|
||||
find_insert_pos_for_kwargs,
|
||||
is_write_timeout_20,
|
||||
get_updates_read_timeout_addition,
|
||||
keyword_args,
|
||||
read_timeout_sub,
|
||||
read_timeout_type,
|
||||
write_timeout_sub,
|
||||
media_write_timeout_deprecation,
|
||||
media_write_timeout_deprecation_methods,
|
||||
)
|
||||
from docs.auxil.link_code import LINE_NUMBERS
|
||||
|
||||
@@ -68,9 +67,9 @@ def autodoc_skip_member(app, what, name, obj, skip, options):
|
||||
return True
|
||||
break
|
||||
|
||||
if name == "filter" and obj.__module__ == "telegram.ext.filters":
|
||||
if not included_in_obj:
|
||||
return True # return True to exclude from docs.
|
||||
if name == "filter" and obj.__module__ == "telegram.ext.filters" and not included_in_obj:
|
||||
return True # return True to exclude from docs.
|
||||
return None
|
||||
|
||||
|
||||
def autodoc_process_docstring(
|
||||
@@ -107,19 +106,24 @@ def autodoc_process_docstring(
|
||||
f"Couldn't find the correct position to insert the keyword args for {obj}."
|
||||
)
|
||||
|
||||
long_write_timeout = is_write_timeout_20(obj)
|
||||
get_updates_sub = 1 if (method_name == "get_updates") else 0
|
||||
get_updates: bool = method_name == "get_updates"
|
||||
# The below can be done in 1 line with itertools.chain, but this must be modified in-place
|
||||
insert_idx = insert_index
|
||||
for i in range(insert_index, insert_index + len(keyword_args)):
|
||||
lines.insert(
|
||||
i,
|
||||
keyword_args[i - insert_index].format(
|
||||
method=method_name,
|
||||
write_timeout=write_timeout_sub[long_write_timeout],
|
||||
read_timeout=read_timeout_sub[get_updates_sub],
|
||||
read_timeout_type=read_timeout_type[get_updates_sub],
|
||||
),
|
||||
)
|
||||
to_insert = keyword_args[i - insert_index]
|
||||
|
||||
if (
|
||||
"post.write_timeout`. Defaults to" in to_insert
|
||||
and method_name in media_write_timeout_deprecation_methods
|
||||
):
|
||||
effective_insert: list[str] = media_write_timeout_deprecation
|
||||
elif get_updates and to_insert.lstrip().startswith("read_timeout"):
|
||||
effective_insert = [to_insert, *get_updates_read_timeout_addition]
|
||||
else:
|
||||
effective_insert = [to_insert]
|
||||
|
||||
lines[insert_idx:insert_idx] = effective_insert
|
||||
insert_idx += len(effective_insert)
|
||||
|
||||
ADMONITION_INSERTER.insert_admonitions(
|
||||
obj=typing.cast(collections.abc.Callable, obj),
|
||||
@@ -162,11 +166,11 @@ def autodoc_process_docstring(
|
||||
autodoc_process_docstring(app, "method", f"{name}.__init__", obj.__init__, options, lines)
|
||||
|
||||
|
||||
def autodoc_process_bases(app, name, obj, option, bases: list):
|
||||
def autodoc_process_bases(app, name, obj, option, bases: list) -> None:
|
||||
"""Here we fine tune how the base class's classes are displayed."""
|
||||
for idx, base in enumerate(bases):
|
||||
for idx, raw_base in enumerate(bases):
|
||||
# let's use a string representation of the object
|
||||
base = str(base)
|
||||
base = str(raw_base)
|
||||
|
||||
# Special case for abstract context managers which are wrongly resoled for some reason
|
||||
if base.startswith("typing.AbstractAsyncContextManager"):
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2023
|
||||
# Copyright (C) 2015-2024
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
@@ -15,6 +15,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 datetime
|
||||
from enum import Enum
|
||||
|
||||
from docutils.nodes import Element
|
||||
@@ -71,14 +72,21 @@ class TGConstXRefRole(PyXRefRole):
|
||||
if isinstance(value, tuple) and target in (
|
||||
"telegram.constants.BOT_API_VERSION_INFO",
|
||||
"telegram.__version_info__",
|
||||
):
|
||||
return str(value), target
|
||||
if (
|
||||
isinstance(value, datetime.datetime)
|
||||
and value == telegram.constants.ZERO_DATE
|
||||
and target in ("telegram.constants.ZERO_DATE",)
|
||||
):
|
||||
return repr(value), target
|
||||
sphinx_logger.warning(
|
||||
f"%s:%d: WARNING: Did not convert reference %s. :{CONSTANTS_ROLE}: is not supposed"
|
||||
"%s:%d: WARNING: Did not convert reference %s. :%s: is not supposed"
|
||||
" to be used with this type of target.",
|
||||
refnode.source,
|
||||
refnode.line,
|
||||
refnode.rawsource,
|
||||
CONSTANTS_ROLE,
|
||||
)
|
||||
return title, target
|
||||
except Exception as exc:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
sphinx==7.0.1
|
||||
sphinx-pypi-upload
|
||||
furo==2023.5.20
|
||||
git+https://github.com/harshil21/furo-sphinx-search@01efc7be422d7dc02390aab9be68d6f5ce1a5618#egg=furo-sphinx-search
|
||||
sphinx-paramlinks==0.5.4
|
||||
sphinx==7.2.6
|
||||
furo==2024.1.29
|
||||
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
|
||||
|
||||
+80
-59
@@ -1,4 +1,3 @@
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
@@ -8,12 +7,12 @@ from pathlib import Path
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
from sphinx.application import Sphinx
|
||||
|
||||
sys.path.insert(0, os.path.abspath("../.."))
|
||||
sys.path.insert(0, str(Path("../..").resolve().absolute()))
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
# General information about the project.
|
||||
project = "python-telegram-bot"
|
||||
copyright = "2015-2023, Leandro Toledo"
|
||||
copyright = "2015-2024, Leandro Toledo"
|
||||
author = "Leandro Toledo"
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
@@ -21,9 +20,9 @@ author = "Leandro Toledo"
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = "20.4" # telegram.__version__[:3]
|
||||
version = "21.0.1" # telegram.__version__[:3]
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = "20.3" # telegram.__version__
|
||||
release = "21.0.1" # telegram.__version__
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
needs_sphinx = "6.1.3"
|
||||
@@ -39,6 +38,7 @@ extensions = [
|
||||
"sphinx.ext.extlinks",
|
||||
"sphinx_paramlinks",
|
||||
"sphinx_copybutton",
|
||||
"sphinx_inline_tabs",
|
||||
"sphinxcontrib.mermaid",
|
||||
"sphinx_search.extension",
|
||||
]
|
||||
@@ -76,6 +76,14 @@ napoleon_use_admonition_for_examples = True
|
||||
# and we document the types anyway
|
||||
autodoc_typehints = "none"
|
||||
|
||||
# Show docstring for special members
|
||||
autodoc_default_options = {
|
||||
"special-members": True,
|
||||
# For some reason, __weakref__ can not be ignored by using "inherited-members" in all cases
|
||||
# so we list it here.
|
||||
"exclude-members": "__init__, __weakref__",
|
||||
}
|
||||
|
||||
# Fail on warnings & unresolved references etc
|
||||
nitpicky = True
|
||||
|
||||
@@ -95,7 +103,9 @@ linkcheck_ignore = [
|
||||
]
|
||||
linkcheck_allowed_redirects = {
|
||||
# Redirects to the default version are okay
|
||||
r"https://docs\.python-telegram-bot\.org/.*": r"https://docs\.python-telegram-bot\.org/en/[\w\d\.]+/.*",
|
||||
r"https://docs\.python-telegram-bot\.org/.*": (
|
||||
r"https://docs\.python-telegram-bot\.org/en/[\w\d\.]+/.*"
|
||||
),
|
||||
# pre-commit.ci always redirects to the latest run
|
||||
re.escape(
|
||||
"https://results.pre-commit.ci/latest/github/python-telegram-bot/python-telegram-bot/master"
|
||||
@@ -130,71 +140,79 @@ html_theme_options = {
|
||||
"admonition-title-font-size": "0.95rem",
|
||||
"admonition-font-size": "0.92rem",
|
||||
},
|
||||
"announcement": "PTB has undergone significant changes in v20. Please read the documentation "
|
||||
"carefully and also check out the transition guide in the "
|
||||
'<a href="https://github.com/python-telegram-bot/python-telegram-bot/wiki/'
|
||||
'Transition-guide-to-Version-20.0">wiki</a>.',
|
||||
"announcement": (
|
||||
"PTB has undergone significant changes in v20. Please read the documentation "
|
||||
"carefully and also check out the transition guide in the "
|
||||
'<a href="https://github.com/python-telegram-bot/python-telegram-bot/wiki/'
|
||||
'Transition-guide-to-Version-20.0">wiki</a>.'
|
||||
),
|
||||
"footer_icons": [
|
||||
{
|
||||
# Telegram channel logo
|
||||
"name": "Telegram Channel",
|
||||
"url": "https://t.me/pythontelegrambotchannel/",
|
||||
# Following svg is from https://react-icons.github.io/react-icons/search?q=telegram
|
||||
"html": '<svg stroke="currentColor" fill="currentColor" stroke-width="0" '
|
||||
'viewBox="0 0 16 16" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg">'
|
||||
'<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8.287 5.906c-.778.324-2.334.994'
|
||||
"-4.666 2.01-.378.15-.577.298-.595.442-.03.243.275.339.69.47l.175.055c.408.133."
|
||||
"958.288 1.243.294.26.006.549-.1.868-.32 2.179-1.471 3.304-2.214 3.374-2.23.0"
|
||||
"5-.012.12-.026.166.016.047.041.042.12.037.141-.03.129-1.227 1.241-1.846 1.81"
|
||||
"7-.193.18-.33.307-.358.336a8.154 8.154 0 0 1-.188.186c-.38.366-.664.64.015 1.08"
|
||||
"8.327.216.589.393.85.571.284.194.568.387.936.629.093.06.183.125.27.187.331.23"
|
||||
"6.63.448.997.414.214-.02.435-.22.547-.82.265-1.417.786-4.486.906-5.751a1.426 "
|
||||
"1.426 0 0 0-.013-.315.337.337 0 0 0-.114-.217.526.526 0 0 0-.31-.093c-.3.005-.7"
|
||||
'63.166-2.984 1.09z"></path></svg>',
|
||||
"html": (
|
||||
'<svg stroke="currentColor" fill="currentColor" stroke-width="0" '
|
||||
'viewBox="0 0 16 16" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg">'
|
||||
'<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8.287 5.906c-.778.324-2.334.994'
|
||||
"-4.666 2.01-.378.15-.577.298-.595.442-.03.243.275.339.69.47l.175.055c.408.133."
|
||||
"958.288 1.243.294.26.006.549-.1.868-.32 2.179-1.471 3.304-2.214 3.374-2.23.0"
|
||||
"5-.012.12-.026.166.016.047.041.042.12.037.141-.03.129-1.227 1.241-1.846 1.81"
|
||||
"7-.193.18-.33.307-.358.336a8.154 8.154 0 0 1-.188.186c-.38.366-.664.64.015 1.08"
|
||||
"8.327.216.589.393.85.571.284.194.568.387.936.629.093.06.183.125.27.187.331.23"
|
||||
"6.63.448.997.414.214-.02.435-.22.547-.82.265-1.417.786-4.486.906-5.751a1.426 "
|
||||
"1.426 0 0 0-.013-.315.337.337 0 0 0-.114-.217.526.526 0 0 0-.31-.093c-.3.005-.7"
|
||||
'63.166-2.984 1.09z"></path></svg>'
|
||||
),
|
||||
"class": "",
|
||||
},
|
||||
{ # Github logo
|
||||
"name": "GitHub",
|
||||
"url": "https://github.com/python-telegram-bot/python-telegram-bot/",
|
||||
"html": '<svg stroke="currentColor" fill="currentColor" stroke-width="0" '
|
||||
'viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 '
|
||||
"2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.4"
|
||||
"9-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23"
|
||||
".82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 "
|
||||
"0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.2"
|
||||
"7 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.5"
|
||||
"1.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 "
|
||||
'1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z">'
|
||||
"</path></svg>",
|
||||
"html": (
|
||||
'<svg stroke="currentColor" fill="currentColor" stroke-width="0" '
|
||||
'viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 '
|
||||
"2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.4"
|
||||
"9-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23"
|
||||
".82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 "
|
||||
"0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.2"
|
||||
"7 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.5"
|
||||
"1.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 "
|
||||
'1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z">'
|
||||
"</path></svg>"
|
||||
),
|
||||
"class": "",
|
||||
},
|
||||
{ # PTB website logo - globe
|
||||
"name": "python-telegram-bot website",
|
||||
"url": "https://python-telegram-bot.org/",
|
||||
"html": '<svg stroke="currentColor" fill="currentColor" stroke-width="0" '
|
||||
'viewBox="0 0 16 16" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg">'
|
||||
'<path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm7.5-6.923c-.67.204-1.335.82-1.887 '
|
||||
"1.855-.143.268-.276.56-.395.872.705.157 1.472.257 2.282.287V1.077zM4.249 3.53"
|
||||
"9c.142-.384.304-.744.481-1.078a6.7 6.7 0 0 1 .597-.933A7.01 7.01 0 0 0 3.051 "
|
||||
"3.05c.362.184.763.349 1.198.49zM3.509 7.5c.036-1.07.188-2.087.436-3.008a9.124 "
|
||||
"9.124 0 0 1-1.565-.667A6.964 6.964 0 0 0 1.018 7.5h2.49zm1.4-2.741a12.344 "
|
||||
"12.344 0 0 0-.4 2.741H7.5V5.091c-.91-.03-1.783-.145-2.591-.332zM8.5 5.09V7.5h"
|
||||
"2.99a12.342 12.342 0 0 0-.399-2.741c-.808.187-1.681.301-2.591.332zM4.51 8.5c.03"
|
||||
"5.987.176 1.914.399 2.741A13.612 13.612 0 0 1 7.5 10.91V8.5H4.51zm3.99 0v2.409"
|
||||
"c.91.03 1.783.145 2.591.332.223-.827.364-1.754.4-2.741H8.5zm-3.282 3.696c.12.31"
|
||||
"2.252.604.395.872.552 1.035 1.218 1.65 1.887 1.855V11.91c-.81.03-1.577.13-2.28"
|
||||
"2.287zm.11 2.276a6.696 6.696 0 0 1-.598-.933 8.853 8.853 0 0 1-.481-1.079 8.38 "
|
||||
"8.38 0 0 0-1.198.49 7.01 7.01 0 0 0 2.276 1.522zm-1.383-2.964A13.36 13.36 0 0 1"
|
||||
" 3.508 8.5h-2.49a6.963 6.963 0 0 0 1.362 3.675c.47-.258.995-.482 1.565-.667zm"
|
||||
"6.728 2.964a7.009 7.009 0 0 0 2.275-1.521 8.376 8.376 0 0 0-1.197-.49 8.853 "
|
||||
"8.853 0 0 1-.481 1.078 6.688 6.688 0 0 1-.597.933zM8.5 11.909v3.014c.67-.204 "
|
||||
"1.335-.82 1.887-1.855.143-.268.276-.56.395-.872A12.63 12.63 0 0 0 8.5 11.91zm"
|
||||
"3.555-.401c.57.185 1.095.409 1.565.667A6.963 6.963 0 0 0 14.982 8.5h-2.49a1"
|
||||
"3.36 13.36 0 0 1-.437 3.008zM14.982 7.5a6.963 6.963 0 0 0-1.362-3.675c-.47.25"
|
||||
"8-.995.482-1.565.667.248.92.4 1.938.437 3.008h2.49zM11.27 2.461c.177.334.339.6"
|
||||
"94.482 1.078a8.368 8.368 0 0 0 1.196-.49 7.01 7.01 0 0 0-2.275-1.52c.218.283.4"
|
||||
"18.597.597.932zm-.488 1.343a7.765 7.765 0 0 0-.395-.872C9.835 1.897 9.17 1.282 "
|
||||
'8.5 1.077V4.09c.81-.03 1.577-.13 2.282-.287z"></path></svg>',
|
||||
"html": (
|
||||
'<svg stroke="currentColor" fill="currentColor" stroke-width="0" '
|
||||
'viewBox="0 0 16 16" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg">'
|
||||
'<path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm7.5-6.923c-.67.204-1.335.82-1.887 '
|
||||
"1.855-.143.268-.276.56-.395.872.705.157 1.472.257 2.282.287V1.077zM4.249 3.53"
|
||||
"9c.142-.384.304-.744.481-1.078a6.7 6.7 0 0 1 .597-.933A7.01 7.01 0 0 0 3.051 "
|
||||
"3.05c.362.184.763.349 1.198.49zM3.509 7.5c.036-1.07.188-2.087.436-3.008a9.124 "
|
||||
"9.124 0 0 1-1.565-.667A6.964 6.964 0 0 0 1.018 7.5h2.49zm1.4-2.741a12.344 "
|
||||
"12.344 0 0 0-.4 2.741H7.5V5.091c-.91-.03-1.783-.145-2.591-.332zM8.5 5.09V7.5h"
|
||||
"2.99a12.342 12.342 0 0 0-.399-2.741c-.808.187-1.681.301-2.591.332zM4.51 8.5c.03"
|
||||
"5.987.176 1.914.399 2.741A13.612 13.612 0 0 1 7.5 10.91V8.5H4.51zm3.99 0v2.409"
|
||||
"c.91.03 1.783.145 2.591.332.223-.827.364-1.754.4-2.741H8.5zm-3.282 3.696c.12.31"
|
||||
"2.252.604.395.872.552 1.035 1.218 1.65 1.887 1.855V11.91c-.81.03-1.577.13-2.28"
|
||||
"2.287zm.11 2.276a6.696 6.696 0 0 1-.598-.933 8.853 8.853 0 0 1-.481-1.079 8.38 "
|
||||
"8.38 0 0 0-1.198.49 7.01 7.01 0 0 0 2.276 1.522zm-1.383-2.964A13.36 13.36 0 0 1"
|
||||
" 3.508 8.5h-2.49a6.963 6.963 0 0 0 1.362 3.675c.47-.258.995-.482 1.565-.667zm"
|
||||
"6.728 2.964a7.009 7.009 0 0 0 2.275-1.521 8.376 8.376 0 0 0-1.197-.49 8.853 "
|
||||
"8.853 0 0 1-.481 1.078 6.688 6.688 0 0 1-.597.933zM8.5 11.909v3.014c.67-.204 "
|
||||
"1.335-.82 1.887-1.855.143-.268.276-.56.395-.872A12.63 12.63 0 0 0 8.5 11.91zm"
|
||||
"3.555-.401c.57.185 1.095.409 1.565.667A6.963 6.963 0 0 0 14.982 8.5h-2.49a1"
|
||||
"3.36 13.36 0 0 1-.437 3.008zM14.982 7.5a6.963 6.963 0 0 0-1.362-3.675c-.47.25"
|
||||
"8-.995.482-1.565.667.248.92.4 1.938.437 3.008h2.49zM11.27 2.461c.177.334.339.6"
|
||||
"94.482 1.078a8.368 8.368 0 0 0 1.196-.49 7.01 7.01 0 0 0-2.275-1.52c.218.283.4"
|
||||
"18.597.597.932zm-.488 1.343a7.765 7.765 0 0 0-.395-.872C9.835 1.897 9.17 1.282 "
|
||||
'8.5 1.077V4.09c.81-.03 1.577-.13 2.282-.287z"></path></svg>'
|
||||
),
|
||||
"class": "",
|
||||
},
|
||||
],
|
||||
@@ -291,17 +309,20 @@ texinfo_documents = [
|
||||
# Due to Sphinx behaviour, these imports only work when imported here, not at top of module.
|
||||
|
||||
# Not used but must be imported for the linkcode extension to find it
|
||||
from docs.auxil.link_code import linkcode_resolve
|
||||
from docs.auxil.sphinx_hooks import (
|
||||
from docs.auxil.link_code import linkcode_resolve # noqa: E402, F401
|
||||
from docs.auxil.sphinx_hooks import ( # noqa: E402
|
||||
autodoc_process_bases,
|
||||
autodoc_process_docstring,
|
||||
autodoc_skip_member,
|
||||
)
|
||||
from docs.auxil.tg_const_role import CONSTANTS_ROLE, TGConstXRefRole
|
||||
from docs.auxil.tg_const_role import CONSTANTS_ROLE, TGConstXRefRole # noqa: E402
|
||||
|
||||
|
||||
def setup(app: Sphinx):
|
||||
app.connect("autodoc-skip-member", autodoc_skip_member)
|
||||
app.connect("autodoc-process-bases", autodoc_process_bases)
|
||||
app.connect("autodoc-process-docstring", autodoc_process_docstring)
|
||||
# The default priority is 500. We want our function to run before napoleon doc-conversion
|
||||
# and sphinx-paramlinks do, b/c otherwise the inserted kwargs in the bot methods won't show
|
||||
# up in the objects.inv file that Sphinx generates (i.e. not in the search).
|
||||
app.connect("autodoc-process-docstring", autodoc_process_docstring, priority=100)
|
||||
app.add_role_to_domain("py", CONSTANTS_ROLE, TGConstXRefRole())
|
||||
|
||||
@@ -1,7 +1,43 @@
|
||||
``customwebhookbot.py``
|
||||
=======================
|
||||
|
||||
.. literalinclude:: ../../examples/customwebhookbot.py
|
||||
:language: python
|
||||
:linenos:
|
||||
This example is available for different web frameworks.
|
||||
You can select your preferred framework by opening one of the tabs above the code example.
|
||||
|
||||
.. hint::
|
||||
|
||||
The following examples show how different Python web frameworks can be used alongside PTB.
|
||||
This can be useful for two use cases:
|
||||
|
||||
1. For extending the functionality of your existing bot to handling updates of external services
|
||||
2. For extending the functionality of your exisiting web application to also include chat bot functionality
|
||||
|
||||
How the PTB and web framework components of the examples below are viewed surely depends on which use case one has in mind.
|
||||
We are fully aware that a combination of PTB with web frameworks will always mean finding a tradeoff between usability and best practices for both PTB and the web framework and these examples are certainly far from optimal solutions.
|
||||
Please understand them as starting points and use your expertise of the web framework of your choosing to build up on them.
|
||||
You are of course also very welcome to help improve these examples!
|
||||
|
||||
.. tab:: ``starlette``
|
||||
|
||||
.. literalinclude:: ../../examples/customwebhookbot/starlettebot.py
|
||||
:language: python
|
||||
:linenos:
|
||||
|
||||
.. tab:: ``flask``
|
||||
|
||||
.. literalinclude:: ../../examples/customwebhookbot/flaskbot.py
|
||||
:language: python
|
||||
:linenos:
|
||||
|
||||
.. tab:: ``quart``
|
||||
|
||||
.. literalinclude:: ../../examples/customwebhookbot/quartbot.py
|
||||
:language: python
|
||||
:linenos:
|
||||
|
||||
.. tab:: ``Django``
|
||||
|
||||
.. literalinclude:: ../../examples/customwebhookbot/djangobot.py
|
||||
:language: python
|
||||
:linenos:
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
.. tip::
|
||||
When combining ``python-telegram-bot`` with other :mod:`asyncio` based frameworks, using this
|
||||
method is likely not the best choice, as it blocks the event loop until it receives a stop
|
||||
signal as described above.
|
||||
Instead, you can manually call the methods listed below to start and shut down the application
|
||||
and the :attr:`~telegram.ext.Application.updater`.
|
||||
Keeping the event loop running and listening for a stop signal is then up to you.
|
||||
* When combining ``python-telegram-bot`` with other :mod:`asyncio` based frameworks, using this
|
||||
method is likely not the best choice, as it blocks the event loop until it receives a stop
|
||||
signal as described above.
|
||||
Instead, you can manually call the methods listed below to start and shut down the application
|
||||
and the :attr:`~telegram.ext.Application.updater`.
|
||||
Keeping the event loop running and listening for a stop signal is then up to you.
|
||||
* To gracefully stop the execution of this method from within a handler, job or error callback,
|
||||
use :meth:`~telegram.ext.Application.stop_running`.
|
||||
@@ -49,8 +49,12 @@
|
||||
- Used for sending voice messages
|
||||
* - :meth:`~telegram.Bot.copy_message`
|
||||
- Used for copying the contents of an arbitrary message
|
||||
* - :meth:`~telegram.Bot.copy_messages`
|
||||
- Used for copying the contents of an multiple arbitrary messages
|
||||
* - :meth:`~telegram.Bot.forward_message`
|
||||
- Used for forwarding messages
|
||||
* - :meth:`~telegram.Bot.forward_messages`
|
||||
- Used for forwarding multiple messages at once
|
||||
|
||||
.. raw:: html
|
||||
|
||||
@@ -76,6 +80,10 @@
|
||||
- Used for answering a shipping query
|
||||
* - :meth:`~telegram.Bot.answer_web_app_query`
|
||||
- Used for answering a web app query
|
||||
* - :meth:`~telegram.Bot.delete_message`
|
||||
- Used for deleting messages.
|
||||
* - :meth:`~telegram.Bot.delete_messages`
|
||||
- Used for deleting multiple messages as once.
|
||||
* - :meth:`~telegram.Bot.edit_message_caption`
|
||||
- Used for editing captions
|
||||
* - :meth:`~telegram.Bot.edit_message_media`
|
||||
@@ -88,8 +96,8 @@
|
||||
- Used for editing text messages
|
||||
* - :meth:`~telegram.Bot.stop_poll`
|
||||
- Used for stopping the running poll
|
||||
* - :meth:`~telegram.Bot.delete_message`
|
||||
- Used for deleting messages.
|
||||
* - :meth:`~telegram.Bot.set_message_reaction`
|
||||
- Used for setting reactions on messages
|
||||
|
||||
.. raw:: html
|
||||
|
||||
@@ -157,6 +165,8 @@
|
||||
- Used for getting the number of members in a chat
|
||||
* - :meth:`~telegram.Bot.get_chat_member`
|
||||
- Used for getting a member of a chat
|
||||
* - :meth:`~telegram.Bot.get_user_chat_boosts`
|
||||
- Used for getting the list of boosts added to a chat
|
||||
* - :meth:`~telegram.Bot.leave_chat`
|
||||
- Used for leaving a chat
|
||||
|
||||
@@ -237,7 +247,7 @@
|
||||
- Used for setting the keywords of a sticker
|
||||
* - :meth:`~telegram.Bot.set_sticker_mask_position`
|
||||
- Used for setting the mask position of a mask sticker
|
||||
* - :meth:`~telegram.Bot.set_sticker_set_thumb`
|
||||
* - :meth:`~telegram.Bot.set_sticker_set_thumbnail`
|
||||
- Used for setting the thumbnail of a sticker set
|
||||
* - :meth:`~telegram.Bot.set_custom_emoji_sticker_set_thumbnail`
|
||||
- Used for setting the thumbnail of a custom emoji sticker set
|
||||
@@ -328,6 +338,8 @@
|
||||
- Used to reopen the general topic
|
||||
* - :meth:`~telegram.Bot.unpin_all_forum_topic_messages`
|
||||
- Used to unpin all messages in a forum topic
|
||||
* - :meth:`~telegram.Bot.unpin_all_general_forum_topic_messages`
|
||||
- Used to unpin all messages in the general forum topic
|
||||
|
||||
.. raw:: html
|
||||
|
||||
|
||||
@@ -21,6 +21,14 @@ Available Types
|
||||
telegram.callbackquery
|
||||
telegram.chat
|
||||
telegram.chatadministratorrights
|
||||
telegram.chatboost
|
||||
telegram.chatboostadded
|
||||
telegram.chatboostremoved
|
||||
telegram.chatboostsource
|
||||
telegram.chatboostsourcegiftcode
|
||||
telegram.chatboostsourcegiveaway
|
||||
telegram.chatboostsourcepremium
|
||||
telegram.chatboostupdated
|
||||
telegram.chatinvitelink
|
||||
telegram.chatjoinrequest
|
||||
telegram.chatlocation
|
||||
@@ -38,6 +46,7 @@ Available Types
|
||||
telegram.contact
|
||||
telegram.dice
|
||||
telegram.document
|
||||
telegram.externalreplyinfo
|
||||
telegram.file
|
||||
telegram.forcereply
|
||||
telegram.forumtopic
|
||||
@@ -47,6 +56,11 @@ Available Types
|
||||
telegram.forumtopicreopened
|
||||
telegram.generalforumtopichidden
|
||||
telegram.generalforumtopicunhidden
|
||||
telegram.giveaway
|
||||
telegram.giveawaycompleted
|
||||
telegram.giveawaycreated
|
||||
telegram.giveawaywinners
|
||||
telegram.inaccessiblemessage
|
||||
telegram.inlinekeyboardbutton
|
||||
telegram.inlinekeyboardmarkup
|
||||
telegram.inputfile
|
||||
@@ -60,9 +74,11 @@ Available Types
|
||||
telegram.keyboardbutton
|
||||
telegram.keyboardbuttonpolltype
|
||||
telegram.keyboardbuttonrequestchat
|
||||
telegram.keyboardbuttonrequestuser
|
||||
telegram.keyboardbuttonrequestusers
|
||||
telegram.linkpreviewoptions
|
||||
telegram.location
|
||||
telegram.loginurl
|
||||
telegram.maybeinaccessiblemessage
|
||||
telegram.menubutton
|
||||
telegram.menubuttoncommands
|
||||
telegram.menubuttondefault
|
||||
@@ -71,20 +87,35 @@ Available Types
|
||||
telegram.messageautodeletetimerchanged
|
||||
telegram.messageentity
|
||||
telegram.messageid
|
||||
telegram.messageorigin
|
||||
telegram.messageoriginchannel
|
||||
telegram.messageoriginchat
|
||||
telegram.messageoriginhiddenuser
|
||||
telegram.messageoriginuser
|
||||
telegram.messagereactioncountupdated
|
||||
telegram.messagereactionupdated
|
||||
telegram.photosize
|
||||
telegram.poll
|
||||
telegram.pollanswer
|
||||
telegram.polloption
|
||||
telegram.proximityalerttriggered
|
||||
telegram.reactioncount
|
||||
telegram.reactiontype
|
||||
telegram.reactiontypecustomemoji
|
||||
telegram.reactiontypeemoji
|
||||
telegram.replykeyboardmarkup
|
||||
telegram.replykeyboardremove
|
||||
telegram.replyparameters
|
||||
telegram.sentwebappmessage
|
||||
telegram.story
|
||||
telegram.switchinlinequerychosenchat
|
||||
telegram.telegramobject
|
||||
telegram.textquote
|
||||
telegram.update
|
||||
telegram.user
|
||||
telegram.userchatboosts
|
||||
telegram.userprofilephotos
|
||||
telegram.usershared
|
||||
telegram.usersshared
|
||||
telegram.venue
|
||||
telegram.video
|
||||
telegram.videochatended
|
||||
|
||||
@@ -4,4 +4,3 @@ Bot
|
||||
.. autoclass:: telegram.Bot
|
||||
:members:
|
||||
:show-inheritance:
|
||||
:special-members: __reduce__, __deepcopy__
|
||||
@@ -0,0 +1,8 @@
|
||||
ChatBoost
|
||||
=========
|
||||
|
||||
.. versionadded:: 20.8
|
||||
|
||||
.. autoclass:: telegram.ChatBoost
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
ChatBoostAdded
|
||||
==============
|
||||
|
||||
.. autoclass:: telegram.ChatBoostAdded
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,8 @@
|
||||
ChatBoostRemoved
|
||||
================
|
||||
|
||||
.. versionadded:: 20.8
|
||||
|
||||
.. autoclass:: telegram.ChatBoostRemoved
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,8 @@
|
||||
ChatBoostSource
|
||||
===============
|
||||
|
||||
.. versionadded:: 20.8
|
||||
|
||||
.. autoclass:: telegram.ChatBoostSource
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,8 @@
|
||||
ChatBoostSourceGiftCode
|
||||
=======================
|
||||
|
||||
.. versionadded:: 20.8
|
||||
|
||||
.. autoclass:: telegram.ChatBoostSourceGiftCode
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,8 @@
|
||||
ChatBoostSourceGiveaway
|
||||
=======================
|
||||
|
||||
.. versionadded:: 20.8
|
||||
|
||||
.. autoclass:: telegram.ChatBoostSourceGiveaway
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,8 @@
|
||||
ChatBoostSourcePremium
|
||||
======================
|
||||
|
||||
.. versionadded:: 20.8
|
||||
|
||||
.. autoclass:: telegram.ChatBoostSourcePremium
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,8 @@
|
||||
ChatBoostUpdated
|
||||
================
|
||||
|
||||
.. versionadded:: 20.8
|
||||
|
||||
.. autoclass:: telegram.ChatBoostUpdated
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -4,3 +4,6 @@ telegram.constants Module
|
||||
.. automodule:: telegram.constants
|
||||
:members:
|
||||
:show-inheritance:
|
||||
:no-undoc-members:
|
||||
:inherited-members: Enum, EnumMeta, str, int
|
||||
:exclude-members: __format__, __new__, __repr__, __str__
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
ChatBoostHandler
|
||||
================
|
||||
|
||||
.. versionadded:: 20.8
|
||||
|
||||
.. autoclass:: telegram.ext.ChatBoostHandler
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -5,7 +5,7 @@ filters Module
|
||||
The classes in `filters.py` are sorted alphabetically such that :bysource: still is readable
|
||||
|
||||
.. automodule:: telegram.ext.filters
|
||||
:inherited-members: BaseFilter, MessageFilter, UpdateFilter
|
||||
:inherited-members: BaseFilter, MessageFilter, UpdateFilter, object
|
||||
:members:
|
||||
:show-inheritance:
|
||||
:member-order: bysource
|
||||
@@ -6,6 +6,7 @@ Handlers
|
||||
|
||||
telegram.ext.basehandler
|
||||
telegram.ext.callbackqueryhandler
|
||||
telegram.ext.chatboosthandler
|
||||
telegram.ext.chatjoinrequesthandler
|
||||
telegram.ext.chatmemberhandler
|
||||
telegram.ext.choseninlineresulthandler
|
||||
@@ -14,6 +15,7 @@ Handlers
|
||||
telegram.ext.filters
|
||||
telegram.ext.inlinequeryhandler
|
||||
telegram.ext.messagehandler
|
||||
telegram.ext.messagereactionhandler
|
||||
telegram.ext.pollanswerhandler
|
||||
telegram.ext.pollhandler
|
||||
telegram.ext.precheckoutqueryhandler
|
||||
|
||||
@@ -4,4 +4,3 @@ Job
|
||||
.. autoclass:: telegram.ext.Job
|
||||
:members:
|
||||
:show-inheritance:
|
||||
:special-members: __call__
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
MessageReactionHandler
|
||||
======================
|
||||
|
||||
.. autoclass:: telegram.ext.MessageReactionHandler
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
ExternalReplyInfo
|
||||
=================
|
||||
|
||||
.. autoclass:: telegram.ExternalReplyInfo
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
Giveaway
|
||||
========
|
||||
|
||||
.. autoclass:: telegram.Giveaway
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
GiveawayCompleted
|
||||
=================
|
||||
|
||||
.. autoclass:: telegram.GiveawayCompleted
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
GiveawayCreated
|
||||
===============
|
||||
|
||||
.. autoclass:: telegram.GiveawayCreated
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
GiveawayWinners
|
||||
===============
|
||||
|
||||
.. autoclass:: telegram.GiveawayWinners
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
InaccessibleMessage
|
||||
===================
|
||||
|
||||
.. autoclass:: telegram.InaccessibleMessage
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -1,6 +0,0 @@
|
||||
KeyboardButtonRequestUser
|
||||
==================================
|
||||
|
||||
.. autoclass:: telegram.KeyboardButtonRequestUser
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
KeyboardButtonRequestUsers
|
||||
==========================
|
||||
|
||||
.. autoclass:: telegram.KeyboardButtonRequestUsers
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
LinkPreviewOptions
|
||||
==================
|
||||
|
||||
.. autoclass:: telegram.LinkPreviewOptions
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
MaybeInaccessibleMessage
|
||||
========================
|
||||
|
||||
.. autoclass:: telegram.MaybeInaccessibleMessage
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
MessageOrigin
|
||||
=============
|
||||
|
||||
.. autoclass:: telegram.MessageOrigin
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
MessageOriginChannel
|
||||
====================
|
||||
|
||||
.. autoclass:: telegram.MessageOriginChannel
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
MessageOriginChat
|
||||
=================
|
||||
|
||||
.. autoclass:: telegram.MessageOriginChat
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
MessageOriginHiddenUser
|
||||
=======================
|
||||
|
||||
.. autoclass:: telegram.MessageOriginHiddenUser
|
||||
:members:
|
||||
:show-inheritance:
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
MessageOriginUser
|
||||
=================
|
||||
|
||||
.. autoclass:: telegram.MessageOriginUser
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
MessageReactionCountUpdated
|
||||
===========================
|
||||
|
||||
.. autoclass:: telegram.MessageReactionCountUpdated
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
MessageReactionUpdated
|
||||
======================
|
||||
|
||||
.. autoclass:: telegram.MessageReactionUpdated
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
ReactionCount
|
||||
=============
|
||||
|
||||
.. autoclass:: telegram.ReactionCount
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
ReactionType
|
||||
============
|
||||
|
||||
.. autoclass:: telegram.ReactionType
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
ReactionTypeCustomEmoji
|
||||
=======================
|
||||
|
||||
.. autoclass:: telegram.ReactionTypeCustomEmoji
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
ReactionTypeEmoji
|
||||
=================
|
||||
|
||||
.. autoclass:: telegram.ReactionTypeEmoji
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
ReplyParameters
|
||||
===============
|
||||
|
||||
.. autoclass:: telegram.ReplyParameters
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
Story
|
||||
=====
|
||||
|
||||
.. autoclass:: telegram.Story
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -4,4 +4,3 @@ TelegramObject
|
||||
.. autoclass:: telegram.TelegramObject
|
||||
:members:
|
||||
:show-inheritance:
|
||||
:special-members: __repr__, __getitem__, __eq__, __hash__, __setstate__, __getstate__, __deepcopy__, __setattr__, __delattr__
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
TextQuote
|
||||
=========
|
||||
|
||||
.. autoclass:: telegram.TextQuote
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,8 @@
|
||||
UserChatBoosts
|
||||
==============
|
||||
|
||||
.. versionadded:: 20.8
|
||||
|
||||
.. autoclass:: telegram.UserChatBoosts
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -1,6 +0,0 @@
|
||||
UserShared
|
||||
===================
|
||||
|
||||
.. autoclass:: telegram.UserShared
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
UsersShared
|
||||
===========
|
||||
|
||||
.. autoclass:: telegram.UsersShared
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -14,10 +14,6 @@
|
||||
|
||||
.. |thumbdocstringnopath| replace:: |thumbdocstringbase| |uploadinputnopath|
|
||||
|
||||
.. |thumbargumentdeprecation| replace:: As of Bot API 6.6 this argument is deprecated in favor of
|
||||
|
||||
.. |thumbattributedeprecation| replace:: As of Bot API 6.6 this attribute is deprecated in favor of
|
||||
|
||||
.. |editreplymarkup| replace:: It is currently only possible to edit messages without :attr:`telegram.Message.reply_markup` or with inline keyboards.
|
||||
|
||||
.. |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.
|
||||
@@ -57,3 +53,29 @@
|
||||
.. |captionentitiesattr| replace:: Tuple of special entities that appear in the caption, which can be specified instead of ``parse_mode``.
|
||||
|
||||
.. |datetime_localization| replace:: The default timezone of the bot is used for localization, which is UTC unless :attr:`telegram.ext.Defaults.tzinfo` is used.
|
||||
|
||||
.. |post_methods_note| replace:: If you implement custom logic that implies that you will **not** be using :class:`~telegram.ext.Application`'s methods :meth:`~telegram.ext.Application.run_polling` or :meth:`~telegram.ext.Application.run_webhook` to run your application (like it's done in `Custom Webhook Bot Example <https://docs.python-telegram-bot.org/en/stable/examples.customwebhookbot.html>`__), the callback you set in this method **will not be called automatically**. So instead of setting a callback with this method, you have to explicitly ``await`` the function that you want to run at this stage of your application's life (in the `example mentioned above <https://docs.python-telegram-bot.org/en/stable/examples.customwebhookbot.html>`__, that would be in ``async with application`` context manager).
|
||||
|
||||
.. |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_wildcard_note| replace:: Removed the deprecated arguments and attributes ``thumb_*``.
|
||||
|
||||
.. |async_context_manager| replace:: Asynchronous context manager which
|
||||
|
||||
.. |reply_parameters| replace:: Description of the message to reply to.
|
||||
|
||||
.. |rtm_aswr_deprecated| replace:: replacing this argument. PTB will automatically convert this argument to that one, but you should update your code to use the new argument.
|
||||
|
||||
.. |keyword_only_arg| replace:: This argument is now a keyword-only argument.
|
||||
|
||||
.. |text_html| replace:: The return value of this property is a best-effort approach. Unfortunately, it can not be guaranteed that sending a message with the returned string will render in the same way as the original message produces the same :attr:`~telegram.Message.entities`/:attr:`~telegram.Message.caption_entities` as the original message. For example, Telegram recommends that entities of type :attr:`~telegram.MessageEntity.BLOCKQUOTE` and :attr:`~telegram.MessageEntity.PRE` *should* start and end on a new line, but does not enforce this and leaves rendering decisions up to the clients.
|
||||
|
||||
.. |text_markdown| replace:: |text_html| Moreover, markdown formatting is inherently less expressive than HTML, so some edge cases may not be coverable at all. For example, markdown formatting can not specify two consecutive block quotes without a blank line in between, but HTML can.
|
||||
|
||||
.. |reply_quote| replace:: If set to :obj:`True`, the reply is sent as an actual reply to this message. If ``reply_to_message_id`` is passed, this parameter will be ignored. Default: :obj:`True` in group chats and :obj:`False` in private chats.
|
||||
|
||||
.. |do_quote| replace:: If set to :obj:`True`, the replied message is quoted. For a dict, it must be the output of :meth:`~telegram.Message.build_reply_arguments` to specify exact ``reply_parameters``. If ``reply_to_message_id`` or ``reply_parameters`` are passed, this parameter will be ignored. Default: :obj:`True` in group chats and :obj:`False` in private chats.
|
||||
|
||||
.. |non_optional_story_argument| replace:: As of this version, this argument is now required. In accordance with our `stability policy <https://docs.python-telegram-bot.org/en/stable/stability_policy.html>`__, the signature will be kept as optional for now, though they are mandatory and an error will be raised if you don't pass it.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""This example showcases how PTBs "arbitrary callback data" feature can be used.
|
||||
@@ -14,19 +14,6 @@ To use arbitrary callback data, you must install PTB via
|
||||
import logging
|
||||
from typing import List, Tuple, cast
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
|
||||
from telegram.ext import (
|
||||
Application,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
@@ -14,19 +14,6 @@ bot.
|
||||
import logging
|
||||
from typing import Optional, Tuple
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import Chat, ChatMember, ChatMemberUpdated, Update
|
||||
from telegram.constants import ParseMode
|
||||
from telegram.ext import (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
@@ -14,19 +14,6 @@ import logging
|
||||
from collections import defaultdict
|
||||
from typing import DefaultDict, Optional, Set
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
|
||||
from telegram.constants import ParseMode
|
||||
from telegram.ext import (
|
||||
@@ -128,8 +115,7 @@ async def count_click(update: Update, context: CustomContext) -> None:
|
||||
async def print_users(update: Update, context: CustomContext) -> None:
|
||||
"""Show which users have been using this bot."""
|
||||
await update.message.reply_text(
|
||||
"The following user IDs have used this bot: "
|
||||
f'{", ".join(map(str, context.bot_user_ids))}'
|
||||
f"The following user IDs have used this bot: {', '.join(map(str, context.bot_user_ids))}"
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
@@ -16,19 +16,6 @@ bot.
|
||||
|
||||
import logging
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 5):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, Update
|
||||
from telegram.ext import (
|
||||
Application,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
@@ -17,19 +17,6 @@ bot.
|
||||
import logging
|
||||
from typing import Dict
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, Update
|
||||
from telegram.ext import (
|
||||
Application,
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
#!/usr/bin/env python
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
# pylint: disable=import-error,unused-argument
|
||||
"""
|
||||
Simple example of a bot that uses a custom webhook setup and handles custom updates.
|
||||
For the custom webhook setup, the libraries `Django` and `uvicorn` are used. Please
|
||||
install them as `pip install Django~=4.2.4 uvicorn~=0.23.2`.
|
||||
Note that any other `asyncio` based web server framework can be used for a custom webhook setup
|
||||
just as well.
|
||||
|
||||
Usage:
|
||||
Set bot Token, URL, admin CHAT_ID and PORT after the imports.
|
||||
You may also need to change the `listen` value in the uvicorn configuration to match your setup.
|
||||
Press Ctrl-C on the command line or send a signal to the process to stop the bot.
|
||||
"""
|
||||
import asyncio
|
||||
import html
|
||||
import json
|
||||
import logging
|
||||
from dataclasses import dataclass
|
||||
from uuid import uuid4
|
||||
|
||||
import uvicorn
|
||||
from django.conf import settings
|
||||
from django.core.asgi import get_asgi_application
|
||||
from django.http import HttpRequest, HttpResponse, HttpResponseBadRequest
|
||||
from django.urls import path
|
||||
|
||||
from telegram import Update
|
||||
from telegram.constants import ParseMode
|
||||
from telegram.ext import (
|
||||
Application,
|
||||
CallbackContext,
|
||||
CommandHandler,
|
||||
ContextTypes,
|
||||
ExtBot,
|
||||
TypeHandler,
|
||||
)
|
||||
|
||||
# Enable logging
|
||||
logging.basicConfig(
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
|
||||
)
|
||||
# set higher logging level for httpx to avoid all GET and POST requests being logged
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Define configuration constants
|
||||
URL = "https://domain.tld"
|
||||
ADMIN_CHAT_ID = 123456
|
||||
PORT = 8000
|
||||
TOKEN = "123:ABC" # nosec B105
|
||||
|
||||
|
||||
@dataclass
|
||||
class WebhookUpdate:
|
||||
"""Simple dataclass to wrap a custom update type"""
|
||||
|
||||
user_id: int
|
||||
payload: str
|
||||
|
||||
|
||||
class CustomContext(CallbackContext[ExtBot, dict, dict, dict]):
|
||||
"""
|
||||
Custom CallbackContext class that makes `user_data` available for updates of type
|
||||
`WebhookUpdate`.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def from_update(
|
||||
cls,
|
||||
update: object,
|
||||
application: "Application",
|
||||
) -> "CustomContext":
|
||||
if isinstance(update, WebhookUpdate):
|
||||
return cls(application=application, user_id=update.user_id)
|
||||
return super().from_update(update, application)
|
||||
|
||||
|
||||
async def start(update: Update, context: CustomContext) -> None:
|
||||
"""Display a message with instructions on how to use this bot."""
|
||||
payload_url = html.escape(f"{URL}/submitpayload?user_id=<your user id>&payload=<payload>")
|
||||
text = (
|
||||
f"To check if the bot is still running, call <code>{URL}/healthcheck</code>.\n\n"
|
||||
f"To post a custom update, call <code>{payload_url}</code>."
|
||||
)
|
||||
await update.message.reply_html(text=text)
|
||||
|
||||
|
||||
async def webhook_update(update: WebhookUpdate, context: CustomContext) -> None:
|
||||
"""Handle custom updates."""
|
||||
chat_member = await context.bot.get_chat_member(chat_id=update.user_id, user_id=update.user_id)
|
||||
payloads = context.user_data.setdefault("payloads", [])
|
||||
payloads.append(update.payload)
|
||||
combined_payloads = "</code>\n• <code>".join(payloads)
|
||||
text = (
|
||||
f"The user {chat_member.user.mention_html()} has sent a new payload. "
|
||||
f"So far they have sent the following payloads: \n\n• <code>{combined_payloads}</code>"
|
||||
)
|
||||
await context.bot.send_message(chat_id=ADMIN_CHAT_ID, text=text, parse_mode=ParseMode.HTML)
|
||||
|
||||
|
||||
async def telegram(request: HttpRequest) -> HttpResponse:
|
||||
"""Handle incoming Telegram updates by putting them into the `update_queue`"""
|
||||
await ptb_application.update_queue.put(
|
||||
Update.de_json(data=json.loads(request.body), bot=ptb_application.bot)
|
||||
)
|
||||
return HttpResponse()
|
||||
|
||||
|
||||
async def custom_updates(request: HttpRequest) -> HttpResponse:
|
||||
"""
|
||||
Handle incoming webhook updates by also putting them into the `update_queue` if
|
||||
the required parameters were passed correctly.
|
||||
"""
|
||||
try:
|
||||
user_id = int(request.GET["user_id"])
|
||||
payload = request.GET["payload"]
|
||||
except KeyError:
|
||||
return HttpResponseBadRequest(
|
||||
"Please pass both `user_id` and `payload` as query parameters.",
|
||||
)
|
||||
except ValueError:
|
||||
return HttpResponseBadRequest("The `user_id` must be a string!")
|
||||
|
||||
await ptb_application.update_queue.put(WebhookUpdate(user_id=user_id, payload=payload))
|
||||
return HttpResponse()
|
||||
|
||||
|
||||
async def health(_: HttpRequest) -> HttpResponse:
|
||||
"""For the health endpoint, reply with a simple plain text message."""
|
||||
return HttpResponse("The bot is still running fine :)")
|
||||
|
||||
|
||||
# Set up PTB application and a web application for handling the incoming requests.
|
||||
|
||||
context_types = ContextTypes(context=CustomContext)
|
||||
# Here we set updater to None because we want our custom webhook server to handle the updates
|
||||
# and hence we don't need an Updater instance
|
||||
ptb_application = (
|
||||
Application.builder().token(TOKEN).updater(None).context_types(context_types).build()
|
||||
)
|
||||
|
||||
# register handlers
|
||||
ptb_application.add_handler(CommandHandler("start", start))
|
||||
ptb_application.add_handler(TypeHandler(type=WebhookUpdate, callback=webhook_update))
|
||||
|
||||
urlpatterns = [
|
||||
path("telegram", telegram, name="Telegram updates"),
|
||||
path("submitpayload", custom_updates, name="custom updates"),
|
||||
path("healthcheck", health, name="health check"),
|
||||
]
|
||||
settings.configure(ROOT_URLCONF=__name__, SECRET_KEY=uuid4().hex)
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
"""Finalize configuration and run the applications."""
|
||||
webserver = uvicorn.Server(
|
||||
config=uvicorn.Config(
|
||||
app=get_asgi_application(),
|
||||
port=PORT,
|
||||
use_colors=False,
|
||||
host="127.0.0.1",
|
||||
)
|
||||
)
|
||||
|
||||
# Pass webhook settings to telegram
|
||||
await ptb_application.bot.set_webhook(url=f"{URL}/telegram", allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
# Run application and webserver together
|
||||
async with ptb_application:
|
||||
await ptb_application.start()
|
||||
await webserver.serve()
|
||||
await ptb_application.stop()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,170 @@
|
||||
#!/usr/bin/env python
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
# pylint: disable=import-error,unused-argument
|
||||
"""
|
||||
Simple example of a bot that uses a custom webhook setup and handles custom updates.
|
||||
For the custom webhook setup, the libraries `flask`, `asgiref` and `uvicorn` are used. Please
|
||||
install them as `pip install flask[async]~=2.3.2 uvicorn~=0.23.2 asgiref~=3.7.2`.
|
||||
Note that any other `asyncio` based web server framework can be used for a custom webhook setup
|
||||
just as well.
|
||||
|
||||
Usage:
|
||||
Set bot Token, URL, admin CHAT_ID and PORT after the imports.
|
||||
You may also need to change the `listen` value in the uvicorn configuration to match your setup.
|
||||
Press Ctrl-C on the command line or send a signal to the process to stop the bot.
|
||||
"""
|
||||
import asyncio
|
||||
import html
|
||||
import logging
|
||||
from dataclasses import dataclass
|
||||
from http import HTTPStatus
|
||||
|
||||
import uvicorn
|
||||
from asgiref.wsgi import WsgiToAsgi
|
||||
from flask import Flask, Response, abort, make_response, request
|
||||
|
||||
from telegram import Update
|
||||
from telegram.constants import ParseMode
|
||||
from telegram.ext import (
|
||||
Application,
|
||||
CallbackContext,
|
||||
CommandHandler,
|
||||
ContextTypes,
|
||||
ExtBot,
|
||||
TypeHandler,
|
||||
)
|
||||
|
||||
# Enable logging
|
||||
logging.basicConfig(
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
|
||||
)
|
||||
# set higher logging level for httpx to avoid all GET and POST requests being logged
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Define configuration constants
|
||||
URL = "https://domain.tld"
|
||||
ADMIN_CHAT_ID = 123456
|
||||
PORT = 8000
|
||||
TOKEN = "123:ABC" # nosec B105
|
||||
|
||||
|
||||
@dataclass
|
||||
class WebhookUpdate:
|
||||
"""Simple dataclass to wrap a custom update type"""
|
||||
|
||||
user_id: int
|
||||
payload: str
|
||||
|
||||
|
||||
class CustomContext(CallbackContext[ExtBot, dict, dict, dict]):
|
||||
"""
|
||||
Custom CallbackContext class that makes `user_data` available for updates of type
|
||||
`WebhookUpdate`.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def from_update(
|
||||
cls,
|
||||
update: object,
|
||||
application: "Application",
|
||||
) -> "CustomContext":
|
||||
if isinstance(update, WebhookUpdate):
|
||||
return cls(application=application, user_id=update.user_id)
|
||||
return super().from_update(update, application)
|
||||
|
||||
|
||||
async def start(update: Update, context: CustomContext) -> None:
|
||||
"""Display a message with instructions on how to use this bot."""
|
||||
payload_url = html.escape(f"{URL}/submitpayload?user_id=<your user id>&payload=<payload>")
|
||||
text = (
|
||||
f"To check if the bot is still running, call <code>{URL}/healthcheck</code>.\n\n"
|
||||
f"To post a custom update, call <code>{payload_url}</code>."
|
||||
)
|
||||
await update.message.reply_html(text=text)
|
||||
|
||||
|
||||
async def webhook_update(update: WebhookUpdate, context: CustomContext) -> None:
|
||||
"""Handle custom updates."""
|
||||
chat_member = await context.bot.get_chat_member(chat_id=update.user_id, user_id=update.user_id)
|
||||
payloads = context.user_data.setdefault("payloads", [])
|
||||
payloads.append(update.payload)
|
||||
combined_payloads = "</code>\n• <code>".join(payloads)
|
||||
text = (
|
||||
f"The user {chat_member.user.mention_html()} has sent a new payload. "
|
||||
f"So far they have sent the following payloads: \n\n• <code>{combined_payloads}</code>"
|
||||
)
|
||||
await context.bot.send_message(chat_id=ADMIN_CHAT_ID, text=text, parse_mode=ParseMode.HTML)
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
"""Set up PTB application and a web application for handling the incoming requests."""
|
||||
context_types = ContextTypes(context=CustomContext)
|
||||
# Here we set updater to None because we want our custom webhook server to handle the updates
|
||||
# and hence we don't need an Updater instance
|
||||
application = (
|
||||
Application.builder().token(TOKEN).updater(None).context_types(context_types).build()
|
||||
)
|
||||
|
||||
# register handlers
|
||||
application.add_handler(CommandHandler("start", start))
|
||||
application.add_handler(TypeHandler(type=WebhookUpdate, callback=webhook_update))
|
||||
|
||||
# Pass webhook settings to telegram
|
||||
await application.bot.set_webhook(url=f"{URL}/telegram", allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
# Set up webserver
|
||||
flask_app = Flask(__name__)
|
||||
|
||||
@flask_app.post("/telegram") # type: ignore[misc]
|
||||
async def telegram() -> Response:
|
||||
"""Handle incoming Telegram updates by putting them into the `update_queue`"""
|
||||
await application.update_queue.put(Update.de_json(data=request.json, bot=application.bot))
|
||||
return Response(status=HTTPStatus.OK)
|
||||
|
||||
@flask_app.route("/submitpayload", methods=["GET", "POST"]) # type: ignore[misc]
|
||||
async def custom_updates() -> Response:
|
||||
"""
|
||||
Handle incoming webhook updates by also putting them into the `update_queue` if
|
||||
the required parameters were passed correctly.
|
||||
"""
|
||||
try:
|
||||
user_id = int(request.args["user_id"])
|
||||
payload = request.args["payload"]
|
||||
except KeyError:
|
||||
abort(
|
||||
HTTPStatus.BAD_REQUEST,
|
||||
"Please pass both `user_id` and `payload` as query parameters.",
|
||||
)
|
||||
except ValueError:
|
||||
abort(HTTPStatus.BAD_REQUEST, "The `user_id` must be a string!")
|
||||
|
||||
await application.update_queue.put(WebhookUpdate(user_id=user_id, payload=payload))
|
||||
return Response(status=HTTPStatus.OK)
|
||||
|
||||
@flask_app.get("/healthcheck") # type: ignore[misc]
|
||||
async def health() -> Response:
|
||||
"""For the health endpoint, reply with a simple plain text message."""
|
||||
response = make_response("The bot is still running fine :)", HTTPStatus.OK)
|
||||
response.mimetype = "text/plain"
|
||||
return response
|
||||
|
||||
webserver = uvicorn.Server(
|
||||
config=uvicorn.Config(
|
||||
app=WsgiToAsgi(flask_app),
|
||||
port=PORT,
|
||||
use_colors=False,
|
||||
host="127.0.0.1",
|
||||
)
|
||||
)
|
||||
|
||||
# Run application and webserver together
|
||||
async with application:
|
||||
await application.start()
|
||||
await webserver.serve()
|
||||
await application.stop()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,171 @@
|
||||
#!/usr/bin/env python
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
# pylint: disable=import-error,unused-argument
|
||||
"""
|
||||
Simple example of a bot that uses a custom webhook setup and handles custom updates.
|
||||
For the custom webhook setup, the libraries `quart` and `uvicorn` are used. Please
|
||||
install them as `pip install quart~=0.18.4 uvicorn~=0.23.2`.
|
||||
Note that any other `asyncio` based web server framework can be used for a custom webhook setup
|
||||
just as well.
|
||||
|
||||
Usage:
|
||||
Set bot Token, URL, admin CHAT_ID and PORT after the imports.
|
||||
You may also need to change the `listen` value in the uvicorn configuration to match your setup.
|
||||
Press Ctrl-C on the command line or send a signal to the process to stop the bot.
|
||||
"""
|
||||
import asyncio
|
||||
import html
|
||||
import logging
|
||||
from dataclasses import dataclass
|
||||
from http import HTTPStatus
|
||||
|
||||
import uvicorn
|
||||
from quart import Quart, Response, abort, make_response, request
|
||||
|
||||
from telegram import Update
|
||||
from telegram.constants import ParseMode
|
||||
from telegram.ext import (
|
||||
Application,
|
||||
CallbackContext,
|
||||
CommandHandler,
|
||||
ContextTypes,
|
||||
ExtBot,
|
||||
TypeHandler,
|
||||
)
|
||||
|
||||
# Enable logging
|
||||
logging.basicConfig(
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
|
||||
)
|
||||
# set higher logging level for httpx to avoid all GET and POST requests being logged
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Define configuration constants
|
||||
URL = "https://domain.tld"
|
||||
ADMIN_CHAT_ID = 123456
|
||||
PORT = 8000
|
||||
TOKEN = "123:ABC" # nosec B105
|
||||
|
||||
|
||||
@dataclass
|
||||
class WebhookUpdate:
|
||||
"""Simple dataclass to wrap a custom update type"""
|
||||
|
||||
user_id: int
|
||||
payload: str
|
||||
|
||||
|
||||
class CustomContext(CallbackContext[ExtBot, dict, dict, dict]):
|
||||
"""
|
||||
Custom CallbackContext class that makes `user_data` available for updates of type
|
||||
`WebhookUpdate`.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def from_update(
|
||||
cls,
|
||||
update: object,
|
||||
application: "Application",
|
||||
) -> "CustomContext":
|
||||
if isinstance(update, WebhookUpdate):
|
||||
return cls(application=application, user_id=update.user_id)
|
||||
return super().from_update(update, application)
|
||||
|
||||
|
||||
async def start(update: Update, context: CustomContext) -> None:
|
||||
"""Display a message with instructions on how to use this bot."""
|
||||
payload_url = html.escape(f"{URL}/submitpayload?user_id=<your user id>&payload=<payload>")
|
||||
text = (
|
||||
f"To check if the bot is still running, call <code>{URL}/healthcheck</code>.\n\n"
|
||||
f"To post a custom update, call <code>{payload_url}</code>."
|
||||
)
|
||||
await update.message.reply_html(text=text)
|
||||
|
||||
|
||||
async def webhook_update(update: WebhookUpdate, context: CustomContext) -> None:
|
||||
"""Handle custom updates."""
|
||||
chat_member = await context.bot.get_chat_member(chat_id=update.user_id, user_id=update.user_id)
|
||||
payloads = context.user_data.setdefault("payloads", [])
|
||||
payloads.append(update.payload)
|
||||
combined_payloads = "</code>\n• <code>".join(payloads)
|
||||
text = (
|
||||
f"The user {chat_member.user.mention_html()} has sent a new payload. "
|
||||
f"So far they have sent the following payloads: \n\n• <code>{combined_payloads}</code>"
|
||||
)
|
||||
await context.bot.send_message(chat_id=ADMIN_CHAT_ID, text=text, parse_mode=ParseMode.HTML)
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
"""Set up PTB application and a web application for handling the incoming requests."""
|
||||
context_types = ContextTypes(context=CustomContext)
|
||||
# Here we set updater to None because we want our custom webhook server to handle the updates
|
||||
# and hence we don't need an Updater instance
|
||||
application = (
|
||||
Application.builder().token(TOKEN).updater(None).context_types(context_types).build()
|
||||
)
|
||||
|
||||
# register handlers
|
||||
application.add_handler(CommandHandler("start", start))
|
||||
application.add_handler(TypeHandler(type=WebhookUpdate, callback=webhook_update))
|
||||
|
||||
# Pass webhook settings to telegram
|
||||
await application.bot.set_webhook(url=f"{URL}/telegram", allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
# Set up webserver
|
||||
quart_app = Quart(__name__)
|
||||
|
||||
@quart_app.post("/telegram") # type: ignore[misc]
|
||||
async def telegram() -> Response:
|
||||
"""Handle incoming Telegram updates by putting them into the `update_queue`"""
|
||||
await application.update_queue.put(
|
||||
Update.de_json(data=await request.get_json(), bot=application.bot)
|
||||
)
|
||||
return Response(status=HTTPStatus.OK)
|
||||
|
||||
@quart_app.route("/submitpayload", methods=["GET", "POST"]) # type: ignore[misc]
|
||||
async def custom_updates() -> Response:
|
||||
"""
|
||||
Handle incoming webhook updates by also putting them into the `update_queue` if
|
||||
the required parameters were passed correctly.
|
||||
"""
|
||||
try:
|
||||
user_id = int(request.args["user_id"])
|
||||
payload = request.args["payload"]
|
||||
except KeyError:
|
||||
abort(
|
||||
HTTPStatus.BAD_REQUEST,
|
||||
"Please pass both `user_id` and `payload` as query parameters.",
|
||||
)
|
||||
except ValueError:
|
||||
abort(HTTPStatus.BAD_REQUEST, "The `user_id` must be a string!")
|
||||
|
||||
await application.update_queue.put(WebhookUpdate(user_id=user_id, payload=payload))
|
||||
return Response(status=HTTPStatus.OK)
|
||||
|
||||
@quart_app.get("/healthcheck") # type: ignore[misc]
|
||||
async def health() -> Response:
|
||||
"""For the health endpoint, reply with a simple plain text message."""
|
||||
response = await make_response("The bot is still running fine :)", HTTPStatus.OK)
|
||||
response.mimetype = "text/plain"
|
||||
return response
|
||||
|
||||
webserver = uvicorn.Server(
|
||||
config=uvicorn.Config(
|
||||
app=quart_app,
|
||||
port=PORT,
|
||||
use_colors=False,
|
||||
host="127.0.0.1",
|
||||
)
|
||||
)
|
||||
|
||||
# Run application and webserver together
|
||||
async with application:
|
||||
await application.start()
|
||||
await webserver.serve()
|
||||
await application.stop()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -1,15 +1,15 @@
|
||||
#!/usr/bin/env python
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
# pylint: disable=import-error,wrong-import-position
|
||||
# pylint: disable=import-error,unused-argument
|
||||
"""
|
||||
Simple example of a bot that uses a custom webhook setup and handles custom updates.
|
||||
For the custom webhook setup, the libraries `starlette` and `uvicorn` are used. Please install
|
||||
them as `pip install starlette~=0.20.0 uvicorn~=0.17.0`.
|
||||
them as `pip install starlette~=0.20.0 uvicorn~=0.23.2`.
|
||||
Note that any other `asyncio` based web server framework can be used for a custom webhook setup
|
||||
just as well.
|
||||
|
||||
Usage:
|
||||
Set bot token, url, admin chat_id and port at the start of the `main` function.
|
||||
Set bot Token, URL, admin CHAT_ID and PORT after the imports.
|
||||
You may also need to change the `listen` value in the uvicorn configuration to match your setup.
|
||||
Press Ctrl-C on the command line or send a signal to the process to stop the bot.
|
||||
"""
|
||||
@@ -25,20 +25,6 @@ from starlette.requests import Request
|
||||
from starlette.responses import PlainTextResponse, Response
|
||||
from starlette.routing import Route
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
|
||||
from telegram import Update
|
||||
from telegram.constants import ParseMode
|
||||
from telegram.ext import (
|
||||
@@ -59,6 +45,12 @@ logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Define configuration constants
|
||||
URL = "https://domain.tld"
|
||||
ADMIN_CHAT_ID = 123456
|
||||
PORT = 8000
|
||||
TOKEN = "123:ABC" # nosec B105
|
||||
|
||||
|
||||
@dataclass
|
||||
class WebhookUpdate:
|
||||
@@ -87,17 +79,16 @@ class CustomContext(CallbackContext[ExtBot, dict, dict, dict]):
|
||||
|
||||
async def start(update: Update, context: CustomContext) -> None:
|
||||
"""Display a message with instructions on how to use this bot."""
|
||||
url = context.bot_data["url"]
|
||||
payload_url = html.escape(f"{url}/submitpayload?user_id=<your user id>&payload=<payload>")
|
||||
payload_url = html.escape(f"{URL}/submitpayload?user_id=<your user id>&payload=<payload>")
|
||||
text = (
|
||||
f"To check if the bot is still running, call <code>{url}/healthcheck</code>.\n\n"
|
||||
f"To check if the bot is still running, call <code>{URL}/healthcheck</code>.\n\n"
|
||||
f"To post a custom update, call <code>{payload_url}</code>."
|
||||
)
|
||||
await update.message.reply_html(text=text)
|
||||
|
||||
|
||||
async def webhook_update(update: WebhookUpdate, context: CustomContext) -> None:
|
||||
"""Callback that handles the custom updates."""
|
||||
"""Handle custom updates."""
|
||||
chat_member = await context.bot.get_chat_member(chat_id=update.user_id, user_id=update.user_id)
|
||||
payloads = context.user_data.setdefault("payloads", [])
|
||||
payloads.append(update.payload)
|
||||
@@ -106,33 +97,24 @@ async def webhook_update(update: WebhookUpdate, context: CustomContext) -> None:
|
||||
f"The user {chat_member.user.mention_html()} has sent a new payload. "
|
||||
f"So far they have sent the following payloads: \n\n• <code>{combined_payloads}</code>"
|
||||
)
|
||||
await context.bot.send_message(
|
||||
chat_id=context.bot_data["admin_chat_id"], text=text, parse_mode=ParseMode.HTML
|
||||
)
|
||||
await context.bot.send_message(chat_id=ADMIN_CHAT_ID, text=text, parse_mode=ParseMode.HTML)
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
"""Set up the application and a custom webserver."""
|
||||
url = "https://domain.tld"
|
||||
admin_chat_id = 123456
|
||||
port = 8000
|
||||
|
||||
"""Set up PTB application and a web application for handling the incoming requests."""
|
||||
context_types = ContextTypes(context=CustomContext)
|
||||
# Here we set updater to None because we want our custom webhook server to handle the updates
|
||||
# and hence we don't need an Updater instance
|
||||
application = (
|
||||
Application.builder().token("TOKEN").updater(None).context_types(context_types).build()
|
||||
Application.builder().token(TOKEN).updater(None).context_types(context_types).build()
|
||||
)
|
||||
# save the values in `bot_data` such that we may easily access them in the callbacks
|
||||
application.bot_data["url"] = url
|
||||
application.bot_data["admin_chat_id"] = admin_chat_id
|
||||
|
||||
# register handlers
|
||||
application.add_handler(CommandHandler("start", start))
|
||||
application.add_handler(TypeHandler(type=WebhookUpdate, callback=webhook_update))
|
||||
|
||||
# Pass webhook settings to telegram
|
||||
await application.bot.set_webhook(url=f"{url}/telegram", allowed_updates=Update.ALL_TYPES)
|
||||
await application.bot.set_webhook(url=f"{URL}/telegram", allowed_updates=Update.ALL_TYPES)
|
||||
|
||||
# Set up webserver
|
||||
async def telegram(request: Request) -> Response:
|
||||
@@ -178,7 +160,7 @@ async def main() -> None:
|
||||
webserver = uvicorn.Server(
|
||||
config=uvicorn.Config(
|
||||
app=starlette_app,
|
||||
port=port,
|
||||
port=PORT,
|
||||
use_colors=False,
|
||||
host="127.0.0.1",
|
||||
)
|
||||
+12
-18
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""Bot that explains Telegram's "Deep Linking Parameters" functionality.
|
||||
@@ -20,20 +20,13 @@ bot.
|
||||
|
||||
import logging
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update, helpers
|
||||
from telegram import (
|
||||
InlineKeyboardButton,
|
||||
InlineKeyboardMarkup,
|
||||
LinkPreviewOptions,
|
||||
Update,
|
||||
helpers,
|
||||
)
|
||||
from telegram.constants import ParseMode
|
||||
from telegram.ext import Application, CallbackQueryHandler, CommandHandler, ContextTypes, filters
|
||||
|
||||
@@ -70,8 +63,7 @@ async def deep_linked_level_1(update: Update, context: ContextTypes.DEFAULT_TYPE
|
||||
bot = context.bot
|
||||
url = helpers.create_deep_linked_url(bot.username, SO_COOL)
|
||||
text = (
|
||||
"Awesome, you just accessed hidden functionality! "
|
||||
"Now let's get back to the private chat."
|
||||
"Awesome, you just accessed hidden functionality! Now let's get back to the private chat."
|
||||
)
|
||||
keyboard = InlineKeyboardMarkup.from_button(
|
||||
InlineKeyboardButton(text="Continue here!", url=url)
|
||||
@@ -84,7 +76,9 @@ async def deep_linked_level_2(update: Update, context: ContextTypes.DEFAULT_TYPE
|
||||
bot = context.bot
|
||||
url = helpers.create_deep_linked_url(bot.username, USING_ENTITIES)
|
||||
text = f'You can also mask the deep-linked URLs as links: <a href="{url}">▶️ CLICK HERE</a>.'
|
||||
await update.message.reply_text(text, parse_mode=ParseMode.HTML, disable_web_page_preview=True)
|
||||
await update.message.reply_text(
|
||||
text, parse_mode=ParseMode.HTML, link_preview_options=LinkPreviewOptions(is_disabled=True)
|
||||
)
|
||||
|
||||
|
||||
async def deep_linked_level_3(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
|
||||
+1
-14
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
@@ -17,19 +17,6 @@ bot.
|
||||
|
||||
import logging
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import ForceReply, Update
|
||||
from telegram.ext import Application, CommandHandler, ContextTypes, MessageHandler, filters
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""This is a very simple example on how one could implement a custom error handler."""
|
||||
@@ -8,19 +8,6 @@ import json
|
||||
import logging
|
||||
import traceback
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import Update
|
||||
from telegram.constants import ParseMode
|
||||
from telegram.ext import Application, CommandHandler, ContextTypes
|
||||
@@ -53,7 +40,7 @@ async def error_handler(update: object, context: ContextTypes.DEFAULT_TYPE) -> N
|
||||
# You might need to add some logic to deal with messages longer than the 4096 character limit.
|
||||
update_str = update.to_dict() if isinstance(update, Update) else str(update)
|
||||
message = (
|
||||
f"An exception was raised while handling an update\n"
|
||||
"An exception was raised while handling an update\n"
|
||||
f"<pre>update = {html.escape(json.dumps(update_str, indent=2, ensure_ascii=False))}"
|
||||
"</pre>\n\n"
|
||||
f"<pre>context.chat_data = {html.escape(str(context.chat_data))}</pre>\n\n"
|
||||
|
||||
+1
-14
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
@@ -18,19 +18,6 @@ import logging
|
||||
from html import escape
|
||||
from uuid import uuid4
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import InlineQueryResultArticle, InputTextMessageContent, Update
|
||||
from telegram.constants import ParseMode
|
||||
from telegram.ext import Application, CommandHandler, ContextTypes, InlineQueryHandler
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
@@ -8,19 +8,6 @@ Basic example for a bot that uses inline keyboards. For an in-depth explanation,
|
||||
"""
|
||||
import logging
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
|
||||
from telegram.ext import Application, CallbackQueryHandler, CommandHandler, ContextTypes
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""Simple inline keyboard bot with multiple CallbackQueryHandlers.
|
||||
@@ -16,19 +16,6 @@ Press Ctrl-C on the command line to stop the bot.
|
||||
"""
|
||||
import logging
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
|
||||
from telegram.ext import (
|
||||
Application,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
@@ -17,19 +17,6 @@ bot.
|
||||
import logging
|
||||
from typing import Any, Dict, Tuple
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
|
||||
from telegram.ext import (
|
||||
Application,
|
||||
|
||||
+1
-14
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
@@ -17,19 +17,6 @@ To use Telegram Passport, you must install PTB via
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 5):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import Update
|
||||
from telegram.ext import Application, ContextTypes, MessageHandler, filters
|
||||
|
||||
|
||||
+1
-14
@@ -1,24 +1,11 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""Basic example for a bot that can receive payment from user."""
|
||||
|
||||
import logging
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import LabeledPrice, ShippingOption, Update
|
||||
from telegram.ext import (
|
||||
Application,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
@@ -17,19 +17,6 @@ bot.
|
||||
import logging
|
||||
from typing import Dict
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, Update
|
||||
from telegram.ext import (
|
||||
Application,
|
||||
@@ -72,7 +59,7 @@ async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
||||
if context.user_data:
|
||||
reply_text += (
|
||||
f" You already told me your {', '.join(context.user_data.keys())}. Why don't you "
|
||||
f"tell me something more about yourself? Or change anything I already know."
|
||||
"tell me something more about yourself? Or change anything I already know."
|
||||
)
|
||||
else:
|
||||
reply_text += (
|
||||
|
||||
+1
-14
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
@@ -9,19 +9,6 @@ one the user sends the bot
|
||||
"""
|
||||
import logging
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import (
|
||||
KeyboardButton,
|
||||
KeyboardButtonPollType,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=wrong-import-position
|
||||
"""Simple Bot to reply to Telegram messages.
|
||||
|
||||
This is built on the API wrapper, see echobot.py to see the same example built
|
||||
@@ -11,19 +10,6 @@ import contextlib
|
||||
import logging
|
||||
from typing import NoReturn
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment] # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import Bot, Update
|
||||
from telegram.error import Forbidden, NetworkError
|
||||
|
||||
|
||||
+1
-14
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument, wrong-import-position
|
||||
# pylint: disable=unused-argument
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
@@ -24,19 +24,6 @@ To use the JobQueue, you must install PTB via
|
||||
|
||||
import logging
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import Update
|
||||
from telegram.ext import Application, CommandHandler, ContextTypes
|
||||
|
||||
|
||||
+5
-16
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=unused-argument,wrong-import-position
|
||||
# pylint: disable=unused-argument
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
"""
|
||||
@@ -11,19 +11,6 @@ require a bot token.
|
||||
import json
|
||||
import logging
|
||||
|
||||
from telegram import __version__ as TG_VER
|
||||
|
||||
try:
|
||||
from telegram import __version_info__
|
||||
except ImportError:
|
||||
__version_info__ = (0, 0, 0, 0, 0) # type: ignore[assignment]
|
||||
|
||||
if __version_info__ < (20, 0, 0, "alpha", 1):
|
||||
raise RuntimeError(
|
||||
f"This example is not compatible with your current PTB version {TG_VER}. To view the "
|
||||
f"{TG_VER} version of this example, "
|
||||
f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
|
||||
)
|
||||
from telegram import KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove, Update, WebAppInfo
|
||||
from telegram.ext import Application, CommandHandler, ContextTypes, MessageHandler, filters
|
||||
|
||||
@@ -58,8 +45,10 @@ async def web_app_data(update: Update, context: ContextTypes.DEFAULT_TYPE) -> No
|
||||
# (see webappbot.html)
|
||||
data = json.loads(update.effective_message.web_app_data.data)
|
||||
await update.message.reply_html(
|
||||
text=f"You selected the color with the HEX value <code>{data['hex']}</code>. The "
|
||||
f"corresponding RGB value is <code>{tuple(data['rgb'].values())}</code>.",
|
||||
text=(
|
||||
f"You selected the color with the HEX value <code>{data['hex']}</code>. The "
|
||||
f"corresponding RGB value is <code>{tuple(data['rgb'].values())}</code>."
|
||||
),
|
||||
reply_markup=ReplyKeyboardRemove(),
|
||||
)
|
||||
|
||||
|
||||
+112
-5
@@ -1,21 +1,128 @@
|
||||
# BLACK:
|
||||
[tool.black]
|
||||
line-length = 99
|
||||
target-version = ['py38', 'py39', 'py310', 'py311']
|
||||
|
||||
# ISORT:
|
||||
[tool.isort] # black config
|
||||
profile = "black"
|
||||
line_length = 99
|
||||
|
||||
# RUFF:
|
||||
[tool.ruff]
|
||||
line-length = 99
|
||||
target-version = "py38"
|
||||
show-fixes = true
|
||||
|
||||
[tool.ruff.lint]
|
||||
preview = true
|
||||
explicit-preview-rules = true
|
||||
ignore = ["PLR2004", "PLR0911", "PLR0912", "PLR0913", "PLR0915", "PERF203"]
|
||||
select = ["E", "F", "I", "PL", "UP", "RUF", "PTH", "C4", "B", "PIE", "SIM", "RET", "RSE",
|
||||
"G", "ISC", "PT", "ASYNC", "TCH", "CPY", "SLOT", "PERF",]
|
||||
"G", "ISC", "PT", "ASYNC", "TCH", "SLOT", "PERF", "PYI", "FLY", "AIR", "RUF022",
|
||||
"RUF023", "Q", "INP",]
|
||||
# Add "FURB" after it's out of preview
|
||||
|
||||
[tool.ruff.per-file-ignores]
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
"tests/*.py" = ["B018"]
|
||||
"**/__init__.py" = ["CPY001"]
|
||||
"examples/**.py" = ["CPY001"]
|
||||
"tests/**.py" = ["RUF012"]
|
||||
"tests/**.py" = ["RUF012", "ASYNC101"]
|
||||
"docs/**.py" = ["INP001"]
|
||||
|
||||
# PYLINT:
|
||||
[tool.pylint."messages control"]
|
||||
enable = ["useless-suppression"]
|
||||
disable = ["duplicate-code", "too-many-arguments", "too-many-public-methods",
|
||||
"too-few-public-methods", "broad-exception-caught", "too-many-instance-attributes",
|
||||
"fixme", "missing-function-docstring", "missing-class-docstring", "too-many-locals",
|
||||
"too-many-lines", "too-many-branches", "too-many-statements", "cyclic-import"
|
||||
]
|
||||
|
||||
[tool.pylint.main]
|
||||
# run pylint across multiple cpu cores to speed it up-
|
||||
# https://pylint.pycqa.org/en/latest/user_guide/run.html?#parallel-execution to know more
|
||||
jobs = 0
|
||||
|
||||
[tool.pylint.classes]
|
||||
exclude-protected = ["_unfrozen"]
|
||||
|
||||
# PYTEST:
|
||||
[tool.pytest.ini_options]
|
||||
testpaths = ["tests"]
|
||||
addopts = "--no-success-flaky-report -rsxX"
|
||||
filterwarnings = [
|
||||
"error",
|
||||
"ignore::DeprecationWarning",
|
||||
'ignore:Tasks created via `Application\.create_task` while the application is not running',
|
||||
"ignore::ResourceWarning",
|
||||
# TODO: Write so good code that we don't need to ignore ResourceWarnings anymore
|
||||
# Unfortunately due to https://github.com/pytest-dev/pytest/issues/8343 we can't have this here
|
||||
# and instead do a trick directly in tests/conftest.py
|
||||
# ignore::telegram.utils.deprecate.TelegramDeprecationWarning
|
||||
]
|
||||
markers = [
|
||||
"dev", # If you want to test a specific test, use this
|
||||
"no_req",
|
||||
"req",
|
||||
]
|
||||
asyncio_mode = "auto"
|
||||
log_format = "%(funcName)s - Line %(lineno)d - %(message)s"
|
||||
# log_level = "DEBUG" # uncomment to see DEBUG logs
|
||||
|
||||
# MYPY:
|
||||
[tool.mypy]
|
||||
warn_unused_ignores = true
|
||||
warn_unused_configs = true
|
||||
disallow_untyped_defs = true
|
||||
disallow_incomplete_defs = true
|
||||
disallow_untyped_decorators = true
|
||||
show_error_codes = true
|
||||
python_version = "3.8"
|
||||
|
||||
# For some files, it's easier to just disable strict-optional all together instead of
|
||||
# cluttering the code with `# type: ignore`s or stuff like
|
||||
# `if self.text is None: raise RuntimeError()`
|
||||
[[tool.mypy.overrides]]
|
||||
module = [
|
||||
"telegram._callbackquery",
|
||||
"telegram._file",
|
||||
"telegram._message",
|
||||
"telegram._files.file"
|
||||
]
|
||||
strict_optional = false
|
||||
|
||||
# type hinting for asyncio in webhookhandler is a bit tricky because it depends on the OS
|
||||
[[tool.mypy.overrides]]
|
||||
module = "telegram.ext._utils.webhookhandler"
|
||||
warn_unused_ignores = false
|
||||
|
||||
# The libs listed below are only used for the `customwebhookbot_*.py` examples
|
||||
# let's just ignore type checking for them for now
|
||||
[[tool.mypy.overrides]]
|
||||
module = [
|
||||
"flask.*",
|
||||
"quart.*",
|
||||
"starlette.*",
|
||||
"uvicorn.*",
|
||||
"asgiref.*",
|
||||
"django.*",
|
||||
"apscheduler.*", # not part of `customwebhookbot_*.py` examples
|
||||
]
|
||||
ignore_missing_imports = true
|
||||
|
||||
# COVERAGE:
|
||||
[tool.coverage.run]
|
||||
branch = true
|
||||
source = ["telegram"]
|
||||
parallel = true
|
||||
concurrency = ["thread", "multiprocessing"]
|
||||
omit = [
|
||||
"tests/",
|
||||
"telegram/__main__.py"
|
||||
]
|
||||
|
||||
[tool.coverage.report]
|
||||
exclude_also = [
|
||||
"@overload",
|
||||
"@abstractmethod",
|
||||
"if TYPE_CHECKING:"
|
||||
]
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
pre-commit # needed for pre-commit hooks in the git commit command
|
||||
|
||||
# For the test suite
|
||||
pytest==7.4.0
|
||||
pytest-asyncio==0.21.0 # needed because pytest doesn't come with native support for coroutines as tests
|
||||
pytest-xdist==3.3.1 # xdist runs tests in parallel
|
||||
pytest==7.4.4
|
||||
pytest-asyncio==0.21.1 # needed because pytest doesn't come with native support for coroutines as tests
|
||||
pytest-xdist==3.5.0 # xdist runs tests in parallel
|
||||
flaky # Used for flaky tests (flaky decorator)
|
||||
beautifulsoup4 # used in test_official for parsing tg docs
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user