Compare commits

...

30 Commits

Author SHA1 Message Date
Hinrich Mahler f6d009d3ac Bump version to v21.1 2024-04-12 12:39:38 +02:00
Bibo-Joshi 153894728c Documentation Improvements (#4171, #4158)
Signed-off-by: teslaedison <qingchengqiushuang@gmail.com>
Co-authored-by: teslaedison <156734008+teslaedison@users.noreply.github.com>
2024-04-12 12:03:01 +02:00
Harshil 5fa457974d API 7.2 (#4180, #4181)
Co-authored-by: Mahdyar Hasanpour <mahdyar@duck.com>
Co-authored-by: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com>
Co-authored-by: Abdelrahman Elkheir <90580077+aelkheir@users.noreply.github.com>
Co-authored-by: Aditya <adityayadav11082@gmail.com>
2024-04-12 11:58:25 +02:00
Harshil 3ec7bb819c Make ChatAdministratorRights.can_*_stories Required (API 7.1) (#4192)
Co-authored-by: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com>
2024-04-06 17:13:43 +02:00
pre-commit-ci[bot] 040cd2c2fc pre-commit autoupdate (#4184)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
2024-04-05 17:26:08 +02:00
Abdelrahman Elkheir 474f9c9693 Make Message.reply_* Reply in the Same Topic by Default (#4170)
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
2024-04-03 11:32:39 +02:00
dependabot[bot] e18ca0d5e1 Bump dependabot/fetch-metadata from 1.6.0 to 2.0.0 (#4185)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
2024-04-02 22:19:33 +02:00
Bibo-Joshi 7331fff3fc Temporarily Mark Tests with get_sticker_set as XFAIL due to API 7.2 Update (#4190) 2024-04-02 22:13:54 +02:00
Abdelrahman Elkheir 23536ee759 Add Update.effective_sender (#4168) 2024-03-30 18:21:13 +01:00
Poolitzer 2d8d43f2a5 Accept Socket Objects for Webhooks (#4161) 2024-03-24 21:04:10 +01:00
Bibo-Joshi 8a542e22a0 Refactor Debug logging in Bot to Improve Type Hinting (#4151) 2024-03-24 12:34:08 +01:00
Hinrich Mahler c0716dd344 Bump version to v21.0.1 2024-03-06 22:15:30 +01:00
Bibo-Joshi 668b49b048 Remove docs from Package (#4150) 2024-03-06 22:04:19 +01:00
Hinrich Mahler 22eb434a62 Bump version to v21.0 2024-03-06 21:09:47 +01:00
Bibo-Joshi ae2858783a Documentation Improvements (#4109, #4116)
Co-authored-by: Aditya <adityayadav11082@gmail.com>
Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com>
Co-authored-by: Maurice Banerjee Palmer <31225563+mbanerjeepalmer@users.noreply.github.com>
2024-03-06 14:45:50 +01:00
Bibo-Joshi 2c227d5977 Relax Upper Bound for httpx Dependency (#4148) 2024-03-06 13:20:38 +01:00
Bibo-Joshi 437261f716 Improve HTML Download of Documentation (#4146) 2024-03-05 17:16:14 +01:00
dependabot[bot] 1b98e440fa Bump test-summary/action from 2.2 to 2.3 (#4142)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <dependabot[bot]@users.noreply.github.com>
Co-authored-by: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com>
2024-03-03 19:28:06 +01:00
Bibo-Joshi d30ba3d1ef Run Unit Tests in PRs on Requirements Changes (#4144) 2024-03-03 19:27:21 +01:00
Bibo-Joshi 20e0f87f6b Make Updater.stop Independent of CancelledError (#4126) 2024-03-03 19:22:42 +01:00
Harshil bd9b0bd126 Handle Properties in TelegramObject.__setstate__ (#4134)
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
2024-03-03 19:22:26 +01:00
dependabot[bot] 5d11d7fd42 Update cachetools requirement from ~=5.3.2 to ~=5.3.3 (#4141)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <dependabot[bot]@users.noreply.github.com>
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
2024-03-02 11:34:03 +01:00
Poolitzer 099ab5d9fa API 7.1 (#4118)
Co-authored-by: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com>
Co-authored-by: Harshil <37377066+harshil21@users.noreply.github.com>
2024-03-02 10:56:15 +01:00
Bibo-Joshi 26f943771b Apply pre-commit Checks More Widely (#4135) 2024-02-29 19:11:03 +01:00
Bibo-Joshi 9c263fbd1a Add Parameter media_write_timeout to HTTPXRequest and Method ApplicationBuilder.media_write_timeout (#4120) 2024-02-26 17:47:04 +01:00
Bibo-Joshi 277031cfb2 Remove Functionality Deprecated in API 7.0 (#4114) 2024-02-25 10:34:47 +01:00
dependabot[bot] c513d51147 Update httpx requirement from ~=0.26.0 to ~=0.27.0 (#4131)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <dependabot[bot]@users.noreply.github.com>
Co-authored-by: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com>
2024-02-24 15:14:26 +01:00
Harshil bb6c85609a Add Missing Slot to Updater (#4130) 2024-02-24 12:31:50 +01:00
Abdelrahman Elkheir 5b6cd3a33b Update Copyright to 2024 (#4121) 2024-02-19 20:06:25 +01:00
Harshil 1cf63c26c5 Refactor and Overhaul test_official (#4087) 2024-02-09 18:12:13 +01:00
429 changed files with 6965 additions and 3140 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
- name: Fetch Dependabot metadata
id: dependabot-metadata
uses: dependabot/fetch-metadata@v1.6.0
uses: dependabot/fetch-metadata@v2.0.0
- uses: actions/checkout@v4
with:
+3 -4
View File
@@ -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:
+5 -4
View File
@@ -1,8 +1,9 @@
name: Bot API Tests
on:
pull_request:
branches:
- master
paths:
- telegram/**
- tests/**
push:
branches:
- master
@@ -33,7 +34,7 @@ jobs:
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
pytest -v tests/test_official/test_official.py --junit-xml=.test_report_official.xml
exit $?
env:
TEST_OFFICIAL: "true"
@@ -41,7 +42,7 @@ jobs:
- name: Test Summary
id: test_summary
uses: test-summary/action@v2.2
uses: test-summary/action@v2.3
if: always() # always run, even if tests fail
with:
paths: .test_report_official.xml
+4 -2
View File
@@ -1,8 +1,10 @@
name: Check Type Completeness
on:
pull_request:
branches:
- master
paths:
- telegram/**
- requirements.txt
- requirements-opts.txt
push:
branches:
- master
+6 -5
View File
@@ -1,13 +1,14 @@
name: Unit Tests
on:
pull_request:
branches:
- master
paths:
- telegram/**
- tests/**
- requirements.txt
- requirements-opts.txt
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'
@@ -81,7 +82,7 @@ jobs:
- name: Test Summary
id: test_summary
uses: test-summary/action@v2.2
uses: test-summary/action@v2.3
if: always() # always run, even if tests fail
with:
paths: |
+14 -16
View File
@@ -6,19 +6,18 @@ ci:
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: 'v0.2.1'
rev: 'v0.3.5'
hooks:
- id: ruff
name: ruff
files: ^(telegram|examples|tests)/.*\.py$
additional_dependencies:
- httpx~=0.26.0
- httpx~=0.27
- tornado~=6.4
- APScheduler~=3.10.4
- cachetools~=5.3.2
- cachetools~=5.3.3
- aiolimiter~=1.1.0
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 24.1.1
rev: 24.3.0
hooks:
- id: black
args:
@@ -29,31 +28,31 @@ repos:
hooks:
- id: flake8
- repo: https://github.com/PyCQA/pylint
rev: v3.0.3
rev: v3.1.0
hooks:
- id: pylint
files: ^(telegram|examples)/.*\.py$
files: ^(?!(tests|docs)).*\.py$
additional_dependencies:
- httpx~=0.26.0
- httpx~=0.27
- tornado~=6.4
- APScheduler~=3.10.4
- cachetools~=5.3.2
- cachetools~=5.3.3
- aiolimiter~=1.1.0
- . # this basically does `pip install -e .`
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.8.0
rev: v1.9.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.26.0
- httpx~=0.27
- tornado~=6.4
- APScheduler~=3.10.4
- cachetools~=5.3.2
- cachetools~=5.3.3
- aiolimiter~=1.1.0
- . # this basically does `pip install -e .`
- id: mypy
@@ -65,13 +64,12 @@ repos:
additional_dependencies:
- tornado~=6.4
- APScheduler~=3.10.4
- cachetools~=5.3.2
- cachetools~=5.3.3
- . # this basically does `pip install -e .`
- repo: https://github.com/asottile/pyupgrade
rev: v3.15.0
rev: v3.15.2
hooks:
- id: pyupgrade
files: ^(telegram|examples|tests|docs)/.*\.py$
args:
- --py38-plus
- repo: https://github.com/pycqa/isort
+41 -31
View File
@@ -7,46 +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
- htmlzip
- 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'
+103
View File
@@ -4,6 +4,109 @@
Changelog
=========
Version 21.1
==============
*Released 2024-04-12*
This is the technical changelog for version 21.1. More elaborate release notes can be found in the news channel `@pythontelegrambotchannel <https://t.me/pythontelegrambotchannel>`__.
Major Changes
-------------
- API 7.2 (:pr:`4180` closes :issue:`4179` and :issue:`4181`, :issue:`4181`)
- Make ``ChatAdministratorRights/ChatMemberAdministrator.can_*_stories`` Required (API 7.1) (:pr:`4192`)
Minor Changes
-------------
- Refactor Debug logging in ``Bot`` to Improve Type Hinting (:pr:`4151` closes :issue:`4010`)
New Features
------------
- Make ``Message.reply_*`` Reply in the Same Topic by Default (:pr:`4170` by `@aelkheir <https://github.com/aelkheir>`__ closes :issue:`4139`)
- Accept Socket Objects for Webhooks (:pr:`4161` closes :issue:`4078`)
- Add ``Update.effective_sender`` (:pr:`4168` by `@aelkheir <https://github.com/aelkheir>`__ closes :issue:`4085`)
Documentation Improvements
--------------------------
- Documentation Improvements (:pr:`4171`, :pr:`4158` by `@teslaedison <https://github.com/teslaedison>`__)
Internal Changes
----------------
- Temporarily Mark Tests with ``get_sticker_set`` as XFAIL due to API 7.2 Update (:pr:`4190`)
Dependency Updates
------------------
- ``pre-commit`` autoupdate (:pr:`4184`)
- Bump ``dependabot/fetch-metadata`` from 1.6.0 to 2.0.0 (:pr:`4185`)
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
============
+4 -8
View File
@@ -14,7 +14,7 @@
:target: https://pypi.org/project/python-telegram-bot/
:alt: Supported Python versions
.. image:: https://img.shields.io/badge/Bot%20API-7.0-blue?logo=telegram
.. image:: https://img.shields.io/badge/Bot%20API-7.2-blue?logo=telegram
:target: https://core.telegram.org/bots/api-changelog
:alt: Supported Bot API versions
@@ -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 **7.0** are supported.
All types and methods of the Telegram Bot API **7.2** 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.26.0 <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.
@@ -153,7 +149,7 @@ PTB can be installed with optional dependencies:
* ``pip install "python-telegram-bot[http2]"`` installs `httpx[http2] <https://www.python-httpx.org/#dependencies>`_. Use this, if you want to use HTTP/2.
* ``pip install "python-telegram-bot[rate-limiter]"`` installs `aiolimiter~=1.1.0 <https://aiolimiter.readthedocs.io/en/stable/>`_. Use this, if you want to use ``telegram.ext.AIORateLimiter``.
* ``pip install "python-telegram-bot[webhooks]"`` installs the `tornado~=6.4 <https://www.tornadoweb.org/en/stable/>`_ library. Use this, if you want to use ``telegram.ext.Updater.start_webhook``/``telegram.ext.Application.run_webhook``.
* ``pip install "python-telegram-bot[callback-data]"`` installs the `cachetools~=5.3.2 <https://cachetools.readthedocs.io/en/latest/>`_ library. Use this, if you want to use `arbitrary callback_data <https://github.com/python-telegram-bot/python-telegram-bot/wiki/Arbitrary-callback_data>`_.
* ``pip install "python-telegram-bot[callback-data]"`` installs the `cachetools~=5.3.3 <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]"``.
+5 -9
View File
@@ -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-7.0-blue?logo=telegram
.. image:: https://img.shields.io/badge/Bot%20API-7.2-blue?logo=telegram
:target: https://core.telegram.org/bots/api-changelog
:alt: Supported Bot API versions
@@ -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 **7.0** are supported.
All types and methods of the Telegram Bot API **7.2** 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.26.0 <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.
View File
View File
+32 -29
View File
@@ -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.
@@ -197,8 +197,8 @@ class AdmonitionInserter:
"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.
@@ -240,8 +240,8 @@ class AdmonitionInserter:
"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")
@@ -271,8 +271,8 @@ class AdmonitionInserter:
raise NotImplementedError(
"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
@@ -344,8 +344,8 @@ class AdmonitionInserter:
raise NotImplementedError(
"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__":
+4 -4
View File
@@ -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,6 +16,7 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
import inspect
from typing import List
keyword_args = [
"Keyword Arguments:",
@@ -84,13 +85,12 @@ get_updates_read_timeout_addition = [
]
def find_insert_pos_for_kwargs(lines: list[str]) -> int:
def find_insert_pos_for_kwargs(lines: List[str]) -> int:
"""Finds the correct position to insert the keyword arguments and returns the index."""
for idx, value in reversed(list(enumerate(lines))): # reversed since :returns: is at the end
if value.startswith("Returns"):
return idx
else:
return False
return False
def check_timeout_and_api_kwargs_presence(obj: object) -> int:
+6 -4
View File
@@ -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,7 +32,7 @@ sphinx_logger = logging.getLogger(__name__)
# must be a module-level variable so that it can be written to by the `autodoc-process-docstring`
# event handler in `sphinx_hooks.py`
LINE_NUMBERS = {}
LINE_NUMBERS: Dict[str, Tuple[Path, int, int]] = {}
def _git_branch() -> str:
@@ -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}"
+8 -8
View File
@@ -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
@@ -67,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(
@@ -118,7 +118,7 @@ def autodoc_process_docstring(
):
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
effective_insert = [to_insert, *get_updates_read_timeout_addition]
else:
effective_insert = [to_insert]
@@ -166,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"):
+3 -2
View File
@@ -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
@@ -81,11 +81,12 @@ class TGConstXRefRole(PyXRefRole):
):
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 -1
View File
@@ -1,6 +1,6 @@
sphinx==7.2.6
furo==2024.1.29
git+https://github.com/harshil21/furo-sphinx-search@v0.2.0.1
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
+7 -14
View File
@@ -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.8" # telegram.__version__[:3]
version = "21.1" # telegram.__version__[:3]
# The full version, including alpha/beta/rc tags.
release = "20.8" # telegram.__version__
release = "21.1" # telegram.__version__
# If your documentation needs a minimal Sphinx version, state it here.
needs_sphinx = "6.1.3"
@@ -141,12 +140,6 @@ 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>.'
),
"footer_icons": [
{
# Telegram channel logo
@@ -310,13 +303,13 @@ 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):
+8 -4
View File
@@ -113,6 +113,10 @@
:align: left
:widths: 1 4
* - :meth:`~telegram.Bot.approve_chat_join_request`
- Used for approving a chat join request
* - :meth:`~telegram.Bot.decline_chat_join_request`
- Used for declining a chat join request
* - :meth:`~telegram.Bot.ban_chat_member`
- Used for banning a member from the chat
* - :meth:`~telegram.Bot.unban_chat_member`
@@ -137,10 +141,6 @@
- Used for editing a non-primary invite link
* - :meth:`~telegram.Bot.revoke_chat_invite_link`
- Used for revoking an invite link created by the bot
* - :meth:`~telegram.Bot.approve_chat_join_request`
- Used for approving a chat join request
* - :meth:`~telegram.Bot.decline_chat_join_request`
- Used for declining a chat join request
* - :meth:`~telegram.Bot.set_chat_photo`
- Used for setting a photo to a chat
* - :meth:`~telegram.Bot.delete_chat_photo`
@@ -155,6 +155,8 @@
- Used for unpinning a message
* - :meth:`~telegram.Bot.unpin_all_chat_messages`
- Used for unpinning all pinned chat messages
* - :meth:`~telegram.Bot.get_business_connection`
- Used for getting information about the business account.
* - :meth:`~telegram.Bot.get_user_profile_photos`
- Used for obtaining user's profile pictures
* - :meth:`~telegram.Bot.get_chat`
@@ -237,6 +239,8 @@
- Used for setting a sticker set of a chat
* - :meth:`~telegram.Bot.delete_chat_sticker_set`
- Used for deleting the set sticker set of a chat
* - :meth:`~telegram.Bot.replace_sticker_in_set`
- Used for replacing a sticker in a set
* - :meth:`~telegram.Bot.set_sticker_position_in_set`
- Used for moving a sticker's position in the set
* - :meth:`~telegram.Bot.set_sticker_set_title`
+9 -2
View File
@@ -6,6 +6,7 @@ Available Types
telegram.animation
telegram.audio
telegram.birthdate
telegram.botcommand
telegram.botcommandscope
telegram.botcommandscopeallchatadministrators
@@ -18,10 +19,17 @@ Available Types
telegram.botdescription
telegram.botname
telegram.botshortdescription
telegram.businessconnection
telegram.businessintro
telegram.businesslocation
telegram.businessopeninghours
telegram.businessopeninghoursinterval
telegram.businessmessagesdeleted
telegram.callbackquery
telegram.chat
telegram.chatadministratorrights
telegram.chatboost
telegram.chatboostadded
telegram.chatboostremoved
telegram.chatboostsource
telegram.chatboostsourcegiftcode
@@ -73,7 +81,6 @@ Available Types
telegram.keyboardbutton
telegram.keyboardbuttonpolltype
telegram.keyboardbuttonrequestchat
telegram.keyboardbuttonrequestuser
telegram.keyboardbuttonrequestusers
telegram.linkpreviewoptions
telegram.location
@@ -107,6 +114,7 @@ Available Types
telegram.replykeyboardremove
telegram.replyparameters
telegram.sentwebappmessage
telegram.shareduser
telegram.story
telegram.switchinlinequerychosenchat
telegram.telegramobject
@@ -115,7 +123,6 @@ Available Types
telegram.user
telegram.userchatboosts
telegram.userprofilephotos
telegram.usershared
telegram.usersshared
telegram.venue
telegram.video
+7
View File
@@ -0,0 +1,7 @@
Birthdate
=========
.. autoclass:: telegram.Birthdate
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
BusinessConnection
==================
.. autoclass:: telegram.BusinessConnection
:members:
:show-inheritance:
+6
View File
@@ -0,0 +1,6 @@
BusinessIntro
==================
.. autoclass:: telegram.BusinessIntro
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
BusinessLocation
==================
.. autoclass:: telegram.BusinessLocation
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
BusinessMessagesDeleted
=======================
.. autoclass:: telegram.BusinessMessagesDeleted
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
BusinessOpeningHours
====================
.. autoclass:: telegram.BusinessOpeningHours
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
BusinessOpeningHoursInterval
============================
.. autoclass:: telegram.BusinessOpeningHoursInterval
:members:
:show-inheritance:
+6
View File
@@ -0,0 +1,6 @@
ChatBoostAdded
==============
.. autoclass:: telegram.ChatBoostAdded
:members:
:show-inheritance:
+3 -1
View File
@@ -4,4 +4,6 @@ telegram.constants Module
.. automodule:: telegram.constants
:members:
:show-inheritance:
:inherited-members: Enum, EnumMeta
:no-undoc-members:
:inherited-members: Enum, EnumMeta, str, int
:exclude-members: __format__, __new__, __repr__, __str__
@@ -0,0 +1,6 @@
BusinessConnectionHandler
=========================
.. autoclass:: telegram.ext.BusinessConnectionHandler
:members:
:show-inheritance:
@@ -0,0 +1,6 @@
BusinessMessagesDeletedHandler
==============================
.. autoclass:: telegram.ext.BusinessMessagesDeletedHandler
:members:
:show-inheritance:
@@ -5,6 +5,8 @@ Handlers
:titlesonly:
telegram.ext.basehandler
telegram.ext.businessconnectionhandler
telegram.ext.businessmessagesdeletedhandler
telegram.ext.callbackqueryhandler
telegram.ext.chatboosthandler
telegram.ext.chatjoinrequesthandler
@@ -1,6 +0,0 @@
KeyboardButtonRequestUser
=========================
.. autoclass:: telegram.KeyboardButtonRequestUser
:members:
:show-inheritance:
@@ -1,6 +1,7 @@
UserShared
SharedUser
==========
.. autoclass:: telegram.UserShared
.. autoclass:: telegram.SharedUser
:members:
:show-inheritance:
+5 -1
View File
@@ -68,7 +68,7 @@
.. |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:: In future versions, this argument will become a keyword-only 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.
@@ -77,3 +77,7 @@
.. |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.
.. |business_id_str| replace:: Unique identifier of the business connection on behalf of which the message will be sent.
+10 -2
View File
@@ -20,7 +20,13 @@ bot.
import logging
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,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:
+4 -1
View File
@@ -20,12 +20,13 @@ explicit-preview-rules = true
ignore = ["PLR2004", "PLR0911", "PLR0912", "PLR0913", "PLR0915", "PERF203"]
select = ["E", "F", "I", "PL", "UP", "RUF", "PTH", "C4", "B", "PIE", "SIM", "RET", "RSE",
"G", "ISC", "PT", "ASYNC", "TCH", "SLOT", "PERF", "PYI", "FLY", "AIR", "RUF022",
"RUF023", "Q", "INP",]
"RUF023", "Q", "INP", "W"]
# Add "FURB" after it's out of preview
[tool.ruff.lint.per-file-ignores]
"tests/*.py" = ["B018"]
"tests/**.py" = ["RUF012", "ASYNC101"]
"docs/**.py" = ["INP001"]
# PYLINT:
[tool.pylint."messages control"]
@@ -64,6 +65,8 @@ markers = [
"req",
]
asyncio_mode = "auto"
log_format = "%(funcName)s - Line %(lineno)d - %(message)s"
# log_level = "DEBUG" # uncomment to see DEBUG logs
# MYPY:
[tool.mypy]
+1 -1
View File
@@ -20,7 +20,7 @@ tornado~=6.4 # webhooks!ext
# Cachetools and APS don't have a strict stability policy.
# Let's be cautious for now.
cachetools~=5.3.2 # callback-data!ext
cachetools~=5.3.3 # callback-data!ext
APScheduler~=3.10.4 # job-queue!ext
# pytz is required by APS and just needs the lower bound due to #2120
+3 -2
View File
@@ -5,5 +5,6 @@
# When dependencies release new versions and tests succeed, we should try to expand the allowed
# versions and only increase the lower bound if necessary
# httpx has no stable release yet, so let's be cautious for now
httpx ~= 0.26.0
# httpx has no stable release yet, but we've had no stability problems since v20.0a0 either
# Since there have been requests to relax the bound a bit, we allow versions < 1.0.0
httpx ~= 0.27
+1 -1
View File
@@ -5,4 +5,4 @@ license_files = LICENSE, LICENSE.dual, LICENSE.lesser
max-line-length = 99
ignore = W503, W605
extend-ignore = E203, E704
exclude = setup.py, setup-raw.py docs/source/conf.py
exclude = setup.py, setup_raw.py docs/source/conf.py
+44 -44
View File
@@ -4,15 +4,16 @@ import subprocess
import sys
from collections import defaultdict
from pathlib import Path
from typing import Any, Dict, List, Tuple
from setuptools import find_packages, setup
def get_requirements():
def get_requirements() -> List[str]:
"""Build the requirements list for this project"""
requirements_list = []
with Path("requirements.txt").open() as reqs:
with Path("requirements.txt").open(encoding="utf-8") as reqs:
for install in reqs:
if install.startswith("#"):
continue
@@ -21,11 +22,11 @@ def get_requirements():
return requirements_list
def get_packages_requirements(raw=False):
def get_packages_requirements(raw: bool = False) -> Tuple[List[str], List[str]]:
"""Build the package & requirements list for this project"""
reqs = get_requirements()
exclude = ["tests*"]
exclude = ["tests*", "docs*"]
if raw:
exclude.append("telegram.ext*")
@@ -34,68 +35,69 @@ def get_packages_requirements(raw=False):
return packs, reqs
def get_optional_requirements(raw=False):
def get_optional_requirements(raw: bool = False) -> Dict[str, List[str]]:
"""Build the optional dependencies"""
requirements = defaultdict(list)
with Path("requirements-opts.txt").open() as reqs:
with Path("requirements-opts.txt").open(encoding="utf-8") as reqs:
for line in reqs:
line = line.strip()
if not line or line.startswith("#"):
effective_line = line.strip()
if not effective_line or effective_line.startswith("#"):
continue
dependency, names = line.split("#")
dependency, names = effective_line.split("#")
dependency = dependency.strip()
for name in names.split(","):
name = name.strip()
if name.endswith("!ext"):
effective_name = name.strip()
if effective_name.endswith("!ext"):
if raw:
continue
else:
name = name[:-4]
requirements["ext"].append(dependency)
requirements[name].append(dependency)
effective_name = effective_name[:-4]
requirements["ext"].append(dependency)
requirements[effective_name].append(dependency)
requirements["all"].append(dependency)
return requirements
def get_setup_kwargs(raw=False):
def get_setup_kwargs(raw: bool = False) -> Dict[str, Any]:
"""Builds a dictionary of kwargs for the setup function"""
packages, requirements = get_packages_requirements(raw=raw)
raw_ext = "-raw" if raw else ""
readme = Path(f'README{"_RAW" if raw else ""}.rst')
version_file = Path("telegram/_version.py").read_text()
version_file = Path("telegram/_version.py").read_text(encoding="utf-8")
first_part = version_file.split("# SETUP.PY MARKER")[0]
exec(first_part)
exec(first_part) # pylint: disable=exec-used
kwargs = dict(
script_name=f"setup{raw_ext}.py",
name=f"python-telegram-bot{raw_ext}",
version=locals()["__version__"],
author="Leandro Toledo",
author_email="devs@python-telegram-bot.org",
license="LGPLv3",
url="https://python-telegram-bot.org/",
# Keywords supported by PyPI can be found at https://github.com/pypa/warehouse/blob/aafc5185e57e67d43487ce4faa95913dd4573e14/warehouse/templates/packaging/detail.html#L20-L58
project_urls={
return {
"script_name": f"setup{raw_ext}.py",
"name": f"python-telegram-bot{raw_ext}",
"version": locals()["__version__"],
"author": "Leandro Toledo",
"author_email": "devs@python-telegram-bot.org",
"license": "LGPLv3",
"url": "https://python-telegram-bot.org/",
# Keywords supported by PyPI can be found at
# https://github.com/pypa/warehouse/blob/aafc5185e57e67d43487ce4faa95913dd4573e14/
# warehouse/templates/packaging/detail.html#L20-L58
"project_urls": {
"Documentation": "https://docs.python-telegram-bot.org",
"Bug Tracker": "https://github.com/python-telegram-bot/python-telegram-bot/issues",
"Source Code": "https://github.com/python-telegram-bot/python-telegram-bot",
"News": "https://t.me/pythontelegrambotchannel",
"Changelog": "https://docs.python-telegram-bot.org/en/stable/changelog.html",
},
download_url=f"https://pypi.org/project/python-telegram-bot{raw_ext}/",
keywords="python telegram bot api wrapper",
description="We have made you a wrapper you can't refuse",
long_description=readme.read_text(),
long_description_content_type="text/x-rst",
packages=packages,
install_requires=requirements,
extras_require=get_optional_requirements(raw=raw),
include_package_data=True,
classifiers=[
"download_url": f"https://pypi.org/project/python-telegram-bot{raw_ext}/",
"keywords": "python telegram bot api wrapper",
"description": "We have made you a wrapper you can't refuse",
"long_description": readme.read_text(encoding="utf-8"),
"long_description_content_type": "text/x-rst",
"packages": packages,
"install_requires": requirements,
"extras_require": get_optional_requirements(raw=raw),
"include_package_data": True,
"classifiers": [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
@@ -111,16 +113,14 @@ def get_setup_kwargs(raw=False):
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
],
python_requires=">=3.8",
)
return kwargs
"python_requires": ">=3.8",
}
def main():
def main() -> None:
# If we're building, build ptb-raw as well
if set(sys.argv[1:]) in [{"bdist_wheel"}, {"sdist"}, {"sdist", "bdist_wheel"}]:
args = ["python", "setup-raw.py"]
args = ["python", "setup_raw.py"]
args.extend(sys.argv[1:])
subprocess.run(args, check=True, capture_output=True)
View File
+22 -9
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
@@ -22,6 +22,7 @@ __author__ = "devs@python-telegram-bot.org"
__all__ = (
"Animation",
"Audio",
"Birthdate",
"Bot",
"BotCommand",
"BotCommandScope",
@@ -35,11 +36,18 @@ __all__ = (
"BotDescription",
"BotName",
"BotShortDescription",
"BusinessConnection",
"BusinessIntro",
"BusinessLocation",
"BusinessMessagesDeleted",
"BusinessOpeningHours",
"BusinessOpeningHoursInterval",
"CallbackGame",
"CallbackQuery",
"Chat",
"ChatAdministratorRights",
"ChatBoost",
"ChatBoostAdded",
"ChatBoostRemoved",
"ChatBoostSource",
"ChatBoostSourceGiftCode",
@@ -130,7 +138,6 @@ __all__ = (
"KeyboardButton",
"KeyboardButtonPollType",
"KeyboardButtonRequestChat",
"KeyboardButtonRequestUser",
"KeyboardButtonRequestUsers",
"LabeledPrice",
"LinkPreviewOptions",
@@ -184,6 +191,7 @@ __all__ = (
"SecureData",
"SecureValue",
"SentWebAppMessage",
"SharedUser",
"ShippingAddress",
"ShippingOption",
"ShippingQuery",
@@ -198,7 +206,6 @@ __all__ = (
"User",
"UserChatBoosts",
"UserProfilePhotos",
"UserShared",
"UsersShared",
"Venue",
"Video",
@@ -225,6 +232,7 @@ __all__ = (
from . import _version, constants, error, helpers, request, warnings
from ._birthdate import Birthdate
from ._bot import Bot
from ._botcommand import BotCommand
from ._botcommandscope import (
@@ -239,11 +247,20 @@ from ._botcommandscope import (
)
from ._botdescription import BotDescription, BotShortDescription
from ._botname import BotName
from ._business import (
BusinessConnection,
BusinessIntro,
BusinessLocation,
BusinessMessagesDeleted,
BusinessOpeningHours,
BusinessOpeningHoursInterval,
)
from ._callbackquery import CallbackQuery
from ._chat import Chat
from ._chatadministratorrights import ChatAdministratorRights
from ._chatboost import (
ChatBoost,
ChatBoostAdded,
ChatBoostRemoved,
ChatBoostSource,
ChatBoostSourceGiftCode,
@@ -338,11 +355,7 @@ from ._inline.inputtextmessagecontent import InputTextMessageContent
from ._inline.inputvenuemessagecontent import InputVenueMessageContent
from ._keyboardbutton import KeyboardButton
from ._keyboardbuttonpolltype import KeyboardButtonPollType
from ._keyboardbuttonrequest import (
KeyboardButtonRequestChat,
KeyboardButtonRequestUser,
KeyboardButtonRequestUsers,
)
from ._keyboardbuttonrequest import KeyboardButtonRequestChat, KeyboardButtonRequestUsers
from ._linkpreviewoptions import LinkPreviewOptions
from ._loginurl import LoginUrl
from ._menubutton import MenuButton, MenuButtonCommands, MenuButtonDefault, MenuButtonWebApp
@@ -397,7 +410,7 @@ from ._reply import ExternalReplyInfo, ReplyParameters, TextQuote
from ._replykeyboardmarkup import ReplyKeyboardMarkup
from ._replykeyboardremove import ReplyKeyboardRemove
from ._sentwebappmessage import SentWebAppMessage
from ._shared import ChatShared, UserShared, UsersShared
from ._shared import ChatShared, SharedUser, UsersShared
from ._story import Story
from ._switchinlinequerychosenchat import SwitchInlineQueryChosenChat
from ._telegramobject import TelegramObject
+1 -1
View File
@@ -1,7 +1,7 @@
# !/usr/bin/env python
#
# 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
+88
View File
@@ -0,0 +1,88 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2024
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser Public License for more details.
#
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram Birthday."""
from datetime import datetime
from typing import Optional
from telegram._telegramobject import TelegramObject
from telegram._utils.types import JSONDict
class Birthdate(TelegramObject):
"""
This object represents a user's birthday.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`day`, and :attr:`month` are equal.
.. versionadded:: 21.1
Args:
day (:obj:`int`): Day of the user's birth; 1-31.
month (:obj:`int`): Month of the user's birth; 1-12.
year (:obj:`int`, optional): Year of the user's birth.
Attributes:
day (:obj:`int`): Day of the user's birth; 1-31.
month (:obj:`int`): Month of the user's birth; 1-12.
year (:obj:`int`): Optional. Year of the user's birth.
"""
__slots__ = ("day", "month", "year")
def __init__(
self,
day: int,
month: int,
year: Optional[int] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(api_kwargs=api_kwargs)
# Required
self.day: int = day
self.month: int = month
# Optional
self.year: Optional[int] = year
self._id_attrs = (
self.day,
self.month,
)
self._freeze()
def to_date(self, year: Optional[int] = None) -> datetime:
"""Return the birthdate as a datetime object.
Args:
year (:obj:`int`, optional): The year to use. Required, if the :attr:`year` was not
present.
Returns:
:obj:`datetime.datetime`: The birthdate as a datetime object.
"""
if self.year is None and year is None:
raise ValueError(
"The `year` argument is required if the `year` attribute was not present."
)
return datetime(year or self.year, self.month, self.day) # type: ignore[arg-type]
+666 -561
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+445
View File
@@ -0,0 +1,445 @@
#!/usr/bin/env python
# pylint: disable=redefined-builtin
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2024
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser Public License for more details.
#
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/]
"""This module contains the Telegram Business related classes."""
from datetime import datetime
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from telegram._chat import Chat
from telegram._files.location import Location
from telegram._files.sticker import Sticker
from telegram._telegramobject import TelegramObject
from telegram._user import User
from telegram._utils.argumentparsing import parse_sequence_arg
from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp
from telegram._utils.types import JSONDict
if TYPE_CHECKING:
from telegram import Bot
class BusinessConnection(TelegramObject):
"""
Describes the connection of the bot with a business account.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal if their :attr:`id`, :attr:`user`, :attr:`user_chat_id`, :attr:`date`,
:attr:`can_reply`, and :attr:`is_enabled` are equal.
.. versionadded:: 21.1
Args:
id (:obj:`str`): Unique identifier of the business connection.
user (:class:`telegram.User`): Business account user that created the business connection.
user_chat_id (:obj:`int`): Identifier of a private chat with the user who created the
business connection.
date (:obj:`datetime.datetime`): Date the connection was established in Unix time.
can_reply (:obj:`bool`): True, if the bot can act on behalf of the business account in
chats that were active in the last 24 hours.
is_enabled (:obj:`bool`): True, if the connection is active.
Attributes:
id (:obj:`str`): Unique identifier of the business connection.
user (:class:`telegram.User`): Business account user that created the business connection.
user_chat_id (:obj:`int`): Identifier of a private chat with the user who created the
business connection.
date (:obj:`datetime.datetime`): Date the connection was established in Unix time.
can_reply (:obj:`bool`): True, if the bot can act on behalf of the business account in
chats that were active in the last 24 hours.
is_enabled (:obj:`bool`): True, if the connection is active.
"""
__slots__ = (
"can_reply",
"date",
"id",
"is_enabled",
"user",
"user_chat_id",
)
def __init__(
self,
id: str,
user: "User",
user_chat_id: int,
date: datetime,
can_reply: bool,
is_enabled: bool,
*,
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(api_kwargs=api_kwargs)
self.id: str = id
self.user: User = user
self.user_chat_id: int = user_chat_id
self.date: datetime = date
self.can_reply: bool = can_reply
self.is_enabled: bool = is_enabled
self._id_attrs = (
self.id,
self.user,
self.user_chat_id,
self.date,
self.can_reply,
self.is_enabled,
)
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["BusinessConnection"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if not data:
return None
# Get the local timezone from the bot if it has defaults
loc_tzinfo = extract_tzinfo_from_defaults(bot)
data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo)
data["user"] = User.de_json(data.get("user"), bot)
return super().de_json(data=data, bot=bot)
class BusinessMessagesDeleted(TelegramObject):
"""
This object is received when messages are deleted from a connected business account.
Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal if their :attr:`business_connection_id`, :attr:`message_ids`, and
:attr:`chat` are equal.
.. versionadded:: 21.1
Args:
business_connection_id (:obj:`str`): Unique identifier of the business connection.
chat (:class:`telegram.Chat`): Information about a chat in the business account. The bot
may not have access to the chat or the corresponding user.
message_ids (Sequence[:obj:`int`]): A list of identifiers of the deleted messages in the
chat of the business account.
Attributes:
business_connection_id (:obj:`str`): Unique identifier of the business connection.
chat (:class:`telegram.Chat`): Information about a chat in the business account. The bot
may not have access to the chat or the corresponding user.
message_ids (Tuple[:obj:`int`]): A list of identifiers of the deleted messages in the
chat of the business account.
"""
__slots__ = (
"business_connection_id",
"chat",
"message_ids",
)
def __init__(
self,
business_connection_id: str,
chat: Chat,
message_ids: Sequence[int],
*,
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(api_kwargs=api_kwargs)
self.business_connection_id: str = business_connection_id
self.chat: Chat = chat
self.message_ids: Tuple[int, ...] = parse_sequence_arg(message_ids)
self._id_attrs = (
self.business_connection_id,
self.chat,
self.message_ids,
)
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["BusinessMessagesDeleted"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if not data:
return None
data["chat"] = Chat.de_json(data.get("chat"), bot)
return super().de_json(data=data, bot=bot)
class BusinessIntro(TelegramObject):
"""
This object represents the intro of a business account.
Objects of this class are comparable in terms of equality.
Two objects of this class are considered equal, if their
:attr:`title`, :attr:`message` and :attr:`sticker` are equal.
.. versionadded:: 21.1
Args:
title (:obj:`str`, optional): Title text of the business intro.
message (:obj:`str`, optional): Message text of the business intro.
sticker (:class:`telegram.Sticker`, optional): Sticker of the business intro.
Attributes:
title (:obj:`str`): Optional. Title text of the business intro.
message (:obj:`str`): Optional. Message text of the business intro.
sticker (:class:`telegram.Sticker`): Optional. Sticker of the business intro.
"""
__slots__ = (
"message",
"sticker",
"title",
)
def __init__(
self,
title: Optional[str] = None,
message: Optional[str] = None,
sticker: Optional[Sticker] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(api_kwargs=api_kwargs)
self.title: Optional[str] = title
self.message: Optional[str] = message
self.sticker: Optional[Sticker] = sticker
self._id_attrs = (self.title, self.message, self.sticker)
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["BusinessIntro"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if not data:
return None
data["sticker"] = Sticker.de_json(data.get("sticker"), bot)
return super().de_json(data=data, bot=bot)
class BusinessLocation(TelegramObject):
"""
This object represents the location of a business account.
Objects of this class are comparable in terms of equality.
Two objects of this class are considered equal, if their
:attr:`address` is equal.
.. versionadded:: 21.1
Args:
address (:obj:`str`): Address of the business.
location (:class:`telegram.Location`, optional): Location of the business.
Attributes:
address (:obj:`str`): Address of the business.
location (:class:`telegram.Location`): Optional. Location of the business.
"""
__slots__ = (
"address",
"location",
)
def __init__(
self,
address: str,
location: Optional[Location] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(api_kwargs=api_kwargs)
self.address: str = address
self.location: Optional[Location] = location
self._id_attrs = (self.address,)
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["BusinessLocation"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if not data:
return None
data["location"] = Location.de_json(data.get("location"), bot)
return super().de_json(data=data, bot=bot)
class BusinessOpeningHoursInterval(TelegramObject):
"""
This object represents the time intervals describing business opening hours.
Objects of this class are comparable in terms of equality.
Two objects of this class are considered equal, if their
:attr:`opening_minute` and :attr:`closing_minute` are equal.
.. versionadded:: 21.1
Examples:
A day has (24 * 60 =) 1440 minutes, a week has (7 * 1440 =) 10080 minutes.
Starting the the minute's sequence from Monday, example values of
:attr:`opening_minute`, :attr:`closing_minute` will map to the following day times:
* Monday - 8am to 8:30pm:
- ``opening_minute = 480`` :guilabel:`8 * 60`
- ``closing_minute = 1230`` :guilabel:`20 * 60 + 30`
* Tuesday - 24 hours:
- ``opening_minute = 1440`` :guilabel:`24 * 60`
- ``closing_minute = 2879`` :guilabel:`2 * 24 * 60 - 1`
* Sunday - 12am - 11:58pm:
- ``opening_minute = 8640`` :guilabel:`6 * 24 * 60`
- ``closing_minute = 10078`` :guilabel:`7 * 24 * 60 - 2`
Args:
opening_minute (:obj:`int`): The minute's sequence number in a week, starting on Monday,
marking the start of the time interval during which the business is open;
0 - 7 * 24 * 60.
closing_minute (:obj:`int`): The minute's
sequence number in a week, starting on Monday, marking the end of the time interval
during which the business is open; 0 - 8 * 24 * 60
Attributes:
opening_minute (:obj:`int`): The minute's sequence number in a week, starting on Monday,
marking the start of the time interval during which the business is open;
0 - 7 * 24 * 60.
closing_minute (:obj:`int`): The minute's
sequence number in a week, starting on Monday, marking the end of the time interval
during which the business is open; 0 - 8 * 24 * 60
"""
__slots__ = ("_closing_time", "_opening_time", "closing_minute", "opening_minute")
def __init__(
self,
opening_minute: int,
closing_minute: int,
*,
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(api_kwargs=api_kwargs)
self.opening_minute: int = opening_minute
self.closing_minute: int = closing_minute
self._opening_time: Optional[Tuple[int, int, int]] = None
self._closing_time: Optional[Tuple[int, int, int]] = None
self._id_attrs = (self.opening_minute, self.closing_minute)
self._freeze()
def _parse_minute(self, minute: int) -> Tuple[int, int, int]:
return (minute // 1440, minute % 1440 // 60, minute % 1440 % 60)
@property
def opening_time(self) -> Tuple[int, int, int]:
"""Convenience attribute. A :obj:`tuple` parsed from :attr:`opening_minute`. It contains
the `weekday`, `hour` and `minute` in the same ranges as :attr:`datetime.datetime.weekday`,
:attr:`datetime.datetime.hour` and :attr:`datetime.datetime.minute`
Returns:
Tuple[:obj:`int`, :obj:`int`, :obj:`int`]:
"""
if self._opening_time is None:
self._opening_time = self._parse_minute(self.opening_minute)
return self._opening_time
@property
def closing_time(self) -> Tuple[int, int, int]:
"""Convenience attribute. A :obj:`tuple` parsed from :attr:`closing_minute`. It contains
the `weekday`, `hour` and `minute` in the same ranges as :attr:`datetime.datetime.weekday`,
:attr:`datetime.datetime.hour` and :attr:`datetime.datetime.minute`
Returns:
Tuple[:obj:`int`, :obj:`int`, :obj:`int`]:
"""
if self._closing_time is None:
self._closing_time = self._parse_minute(self.closing_minute)
return self._closing_time
class BusinessOpeningHours(TelegramObject):
"""
This object represents the opening hours of a business account.
Objects of this class are comparable in terms of equality.
Two objects of this class are considered equal, if their
:attr:`time_zone_name` and :attr:`opening_hours` are equal.
.. versionadded:: 21.1
Args:
time_zone_name (:obj:`str`): Unique name of the time zone for which the opening
hours are defined.
opening_hours (Sequence[:class:`telegram.BusinessOpeningHoursInterval`]): List of
time intervals describing business opening hours.
Attributes:
time_zone_name (:obj:`str`): Unique name of the time zone for which the opening
hours are defined.
opening_hours (Sequence[:class:`telegram.BusinessOpeningHoursInterval`]): List of
time intervals describing business opening hours.
"""
__slots__ = ("opening_hours", "time_zone_name")
def __init__(
self,
time_zone_name: str,
opening_hours: Sequence[BusinessOpeningHoursInterval],
*,
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(api_kwargs=api_kwargs)
self.time_zone_name: str = time_zone_name
self.opening_hours: Sequence[BusinessOpeningHoursInterval] = parse_sequence_arg(
opening_hours
)
self._id_attrs = (self.time_zone_name, self.opening_hours)
self._freeze()
@classmethod
def de_json(cls, data: Optional[JSONDict], bot: "Bot") -> Optional["BusinessOpeningHours"]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
if not data:
return None
data["opening_hours"] = BusinessOpeningHoursInterval.de_list(
data.get("opening_hours"), bot
)
return super().de_json(data=data, bot=bot)
+4 -4
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
@@ -209,11 +209,11 @@ class CallbackQuery(TelegramObject):
self,
text: str,
parse_mode: ODVInput[str] = DEFAULT_NONE,
disable_web_page_preview: ODVInput[bool] = DEFAULT_NONE,
reply_markup: Optional["InlineKeyboardMarkup"] = None,
entities: Optional[Sequence["MessageEntity"]] = None,
link_preview_options: ODVInput["LinkPreviewOptions"] = DEFAULT_NONE,
*,
disable_web_page_preview: Optional[bool] = None,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -808,13 +808,13 @@ class CallbackQuery(TelegramObject):
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_markup: Optional[ReplyMarkup] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
*,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
+180 -43
View File
@@ -2,7 +2,7 @@
# pylint: disable=redefined-builtin
#
# 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
@@ -23,6 +23,7 @@ from html import escape
from typing import TYPE_CHECKING, Final, Optional, Sequence, Tuple, Union
from telegram import constants
from telegram._birthdate import Birthdate
from telegram._chatlocation import ChatLocation
from telegram._chatpermissions import ChatPermissions
from telegram._files.chatphoto import ChatPhoto
@@ -44,6 +45,9 @@ if TYPE_CHECKING:
Animation,
Audio,
Bot,
BusinessIntro,
BusinessLocation,
BusinessOpeningHours,
ChatInviteLink,
ChatMember,
Contact,
@@ -169,6 +173,21 @@ class Chat(TelegramObject):
only in :meth:`telegram.Bot.get_chat`.
.. versionadded:: 20.0
business_intro (:class:`telegram.BusinessIntro`, optional): For private chats with
business accounts, the intro of the business. Returned only in
:meth:`telegram.Bot.get_chat`.
.. versionadded:: 21.1
business_location (:class:`telegram.BusinessLocation`, optional): For private chats with
business accounts, the location of the business. Returned only in
:meth:`telegram.Bot.get_chat`.
.. versionadded:: 21.1
business_opening_hours (:class:`telegram.BusinessOpeningHours`, optional): For private
chats with business accounts, the opening hours of the business. Returned only in
:meth:`telegram.Bot.get_chat`.
.. versionadded:: 21.1
available_reactions (Sequence[:class:`telegram.ReactionType`], optional): List of available
reactions allowed in the chat. If omitted, then all of
:const:`telegram.constants.ReactionEmoji` are allowed. Returned only in
@@ -219,6 +238,24 @@ class Chat(TelegramObject):
:meth:`telegram.Bot.get_chat`.
.. versionadded:: 20.0
unrestrict_boost_count (:obj:`int`, optional): For supergroups, the minimum number of
boosts that a non-administrator user needs to add in order to ignore slow mode and chat
permissions. Returned only in :meth:`telegram.Bot.get_chat`.
.. versionadded:: 21.0
custom_emoji_sticker_set_name (:obj:`str`, optional): For supergroups, the name of the
group's custom emoji sticker set. Custom emoji from this set can be used by all users
and bots in the group. Returned only in :meth:`telegram.Bot.get_chat`.
.. versionadded:: 21.0
birthdate (:obj:`telegram.Birthdate`, optional): For private chats,
the date of birth of the user. Returned only in :meth:`telegram.Bot.get_chat`.
.. versionadded:: 21.1
personal_chat (:obj:`telegram.Chat`, optional): For private chats, the personal channel of
the user. Returned only in :meth:`telegram.Bot.get_chat`.
.. versionadded:: 21.1
Attributes:
id (:obj:`int`): Unique identifier for this chat. This number may be greater than 32 bits
@@ -302,6 +339,21 @@ class Chat(TelegramObject):
obtained via :meth:`~telegram.Bot.get_chat`.
.. versionadded:: 20.0
business_intro (:class:`telegram.BusinessIntro`): Optional. For private chats with
business accounts, the intro of the business. Returned only in
:meth:`telegram.Bot.get_chat`.
.. versionadded:: 21.1
business_location (:class:`telegram.BusinessLocation`): Optional. For private chats with
business accounts, the location of the business. Returned only in
:meth:`telegram.Bot.get_chat`.
.. versionadded:: 21.1
business_opening_hours (:class:`telegram.BusinessOpeningHours`): Optional. For private
chats with business accounts, the opening hours of the business. Returned only in
:meth:`telegram.Bot.get_chat`.
.. versionadded:: 21.1
available_reactions (Tuple[:class:`telegram.ReactionType`]): Optional. List of available
reactions allowed in the chat. If omitted, then all of
:const:`telegram.constants.ReactionEmoji` are allowed. Returned only in
@@ -352,6 +404,24 @@ class Chat(TelegramObject):
:meth:`telegram.Bot.get_chat`.
.. versionadded:: 20.0
unrestrict_boost_count (:obj:`int`): Optional. For supergroups, the minimum number of
boosts that a non-administrator user needs to add in order to ignore slow mode and chat
permissions. Returned only in :meth:`telegram.Bot.get_chat`.
.. versionadded:: 21.0
custom_emoji_sticker_set_name (:obj:`str`): Optional. For supergroups, the name of the
group's custom emoji sticker set. Custom emoji from this set can be used by all users
and bots in the group. Returned only in :meth:`telegram.Bot.get_chat`.
.. versionadded:: 21.0
birthdate (:obj:`telegram.Birthdate`): Optional. For private chats,
the date of birth of the user. Returned only in :meth:`telegram.Bot.get_chat`.
.. versionadded:: 21.1
personal_chat (:obj:`telegram.Chat`): Optional. For private chats, the personal channel of
the user. Returned only in :meth:`telegram.Bot.get_chat`.
.. versionadded:: 21.1
.. _topics: https://telegram.org/blog/topics-in-groups-collectible-usernames#topics-in-groups
.. _accent colors: https://core.telegram.org/bots/api#accent-colors
@@ -363,7 +433,12 @@ class Chat(TelegramObject):
"available_reactions",
"background_custom_emoji_id",
"bio",
"birthdate",
"business_intro",
"business_location",
"business_opening_hours",
"can_set_sticker_set",
"custom_emoji_sticker_set_name",
"description",
"emoji_status_custom_emoji_id",
"emoji_status_expiration_date",
@@ -384,6 +459,7 @@ class Chat(TelegramObject):
"location",
"message_auto_delete_time",
"permissions",
"personal_chat",
"photo",
"pinned_message",
"profile_accent_color_id",
@@ -392,6 +468,7 @@ class Chat(TelegramObject):
"sticker_set_name",
"title",
"type",
"unrestrict_boost_count",
"username",
)
@@ -446,6 +523,13 @@ class Chat(TelegramObject):
profile_accent_color_id: Optional[int] = None,
profile_background_custom_emoji_id: Optional[str] = None,
has_visible_history: Optional[bool] = None,
unrestrict_boost_count: Optional[int] = None,
custom_emoji_sticker_set_name: Optional[str] = None,
birthdate: Optional[Birthdate] = None,
personal_chat: Optional["Chat"] = None,
business_intro: Optional["BusinessIntro"] = None,
business_location: Optional["BusinessLocation"] = None,
business_opening_hours: Optional["BusinessOpeningHours"] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
@@ -493,6 +577,13 @@ class Chat(TelegramObject):
self.background_custom_emoji_id: Optional[str] = background_custom_emoji_id
self.profile_accent_color_id: Optional[int] = profile_accent_color_id
self.profile_background_custom_emoji_id: Optional[str] = profile_background_custom_emoji_id
self.unrestrict_boost_count: Optional[int] = unrestrict_boost_count
self.custom_emoji_sticker_set_name: Optional[str] = custom_emoji_sticker_set_name
self.birthdate: Optional[Birthdate] = birthdate
self.personal_chat: Optional["Chat"] = personal_chat
self.business_intro: Optional["BusinessIntro"] = business_intro
self.business_location: Optional["BusinessLocation"] = business_location
self.business_opening_hours: Optional["BusinessOpeningHours"] = business_opening_hours
self._id_attrs = (self.id,)
@@ -555,12 +646,24 @@ class Chat(TelegramObject):
)
data["photo"] = ChatPhoto.de_json(data.get("photo"), bot)
from telegram import Message # pylint: disable=import-outside-toplevel
from telegram import ( # pylint: disable=import-outside-toplevel
BusinessIntro,
BusinessLocation,
BusinessOpeningHours,
Message,
)
data["pinned_message"] = Message.de_json(data.get("pinned_message"), bot)
data["permissions"] = ChatPermissions.de_json(data.get("permissions"), bot)
data["location"] = ChatLocation.de_json(data.get("location"), bot)
data["available_reactions"] = ReactionType.de_list(data.get("available_reactions"), bot)
data["birthdate"] = Birthdate.de_json(data.get("birthdate"), bot)
data["personal_chat"] = cls.de_json(data.get("personal_chat"), bot)
data["business_intro"] = BusinessIntro.de_json(data.get("business_intro"), bot)
data["business_location"] = BusinessLocation.de_json(data.get("business_location"), bot)
data["business_opening_hours"] = BusinessOpeningHours.de_json(
data.get("business_opening_hours"), bot
)
api_kwargs = {}
# This is a deprecated field that TG still returns for backwards compatibility
@@ -1143,7 +1246,7 @@ class Chat(TelegramObject):
async def set_administrator_custom_title(
self,
user_id: Union[int, str],
user_id: int,
custom_title: str,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -1411,17 +1514,18 @@ class Chat(TelegramObject):
self,
text: str,
parse_mode: ODVInput[str] = DEFAULT_NONE,
disable_web_page_preview: ODVInput[bool] = DEFAULT_NONE,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
reply_markup: Optional[ReplyMarkup] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
entities: Optional[Sequence["MessageEntity"]] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
link_preview_options: ODVInput["LinkPreviewOptions"] = DEFAULT_NONE,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
disable_web_page_preview: Optional[bool] = None,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -1457,6 +1561,7 @@ class Chat(TelegramObject):
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
)
async def delete_message(
@@ -1529,12 +1634,13 @@ class Chat(TelegramObject):
Union["InputMediaAudio", "InputMediaDocument", "InputMediaPhoto", "InputMediaVideo"]
],
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -1572,12 +1678,14 @@ class Chat(TelegramObject):
parse_mode=parse_mode,
caption_entities=caption_entities,
reply_parameters=reply_parameters,
business_connection_id=business_connection_id,
)
async def send_chat_action(
self,
action: str,
message_thread_id: Optional[int] = None,
business_connection_id: Optional[str] = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -1604,6 +1712,7 @@ class Chat(TelegramObject):
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
business_connection_id=business_connection_id,
)
send_action = send_chat_action
@@ -1614,16 +1723,17 @@ class Chat(TelegramObject):
photo: Union[FileInput, "PhotoSize"],
caption: Optional[str] = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
reply_markup: Optional[ReplyMarkup] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
has_spoiler: Optional[bool] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
filename: Optional[str] = None,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -1661,6 +1771,7 @@ class Chat(TelegramObject):
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
has_spoiler=has_spoiler,
business_connection_id=business_connection_id,
)
async def send_contact(
@@ -1669,14 +1780,15 @@ class Chat(TelegramObject):
first_name: Optional[str] = None,
last_name: Optional[str] = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
reply_markup: Optional[ReplyMarkup] = None,
vcard: Optional[str] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
contact: Optional["Contact"] = None,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -1713,6 +1825,7 @@ class Chat(TelegramObject):
allow_sending_without_reply=allow_sending_without_reply,
protect_content=protect_content,
message_thread_id=message_thread_id,
business_connection_id=business_connection_id,
)
async def send_audio(
@@ -1723,16 +1836,17 @@ class Chat(TelegramObject):
title: Optional[str] = None,
caption: Optional[str] = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
reply_markup: Optional[ReplyMarkup] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
filename: Optional[str] = None,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -1773,6 +1887,7 @@ class Chat(TelegramObject):
pool_timeout=pool_timeout,
api_kwargs=api_kwargs,
thumbnail=thumbnail,
business_connection_id=business_connection_id,
)
async def send_document(
@@ -1780,17 +1895,18 @@ class Chat(TelegramObject):
document: Union[FileInput, "Document"],
caption: Optional[str] = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
reply_markup: Optional[ReplyMarkup] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
disable_content_type_detection: Optional[bool] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
filename: Optional[str] = None,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -1829,19 +1945,21 @@ class Chat(TelegramObject):
caption_entities=caption_entities,
protect_content=protect_content,
message_thread_id=message_thread_id,
business_connection_id=business_connection_id,
)
async def send_dice(
self,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
reply_markup: Optional[ReplyMarkup] = None,
emoji: Optional[str] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -1873,19 +1991,21 @@ class Chat(TelegramObject):
allow_sending_without_reply=allow_sending_without_reply,
protect_content=protect_content,
message_thread_id=message_thread_id,
business_connection_id=business_connection_id,
)
async def send_game(
self,
game_short_name: str,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
reply_markup: Optional["InlineKeyboardMarkup"] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -1917,6 +2037,7 @@ class Chat(TelegramObject):
allow_sending_without_reply=allow_sending_without_reply,
protect_content=protect_content,
message_thread_id=message_thread_id,
business_connection_id=business_connection_id,
)
async def send_invoice(
@@ -1938,18 +2059,18 @@ class Chat(TelegramObject):
need_shipping_address: Optional[bool] = None,
is_flexible: Optional[bool] = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
reply_markup: Optional["InlineKeyboardMarkup"] = None,
provider_data: Optional[Union[str, object]] = None,
send_phone_number_to_provider: Optional[bool] = None,
send_email_to_provider: Optional[bool] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
max_tip_amount: Optional[int] = None,
suggested_tip_amounts: Optional[Sequence[int]] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -2018,17 +2139,18 @@ class Chat(TelegramObject):
latitude: Optional[float] = None,
longitude: Optional[float] = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
reply_markup: Optional[ReplyMarkup] = None,
live_period: Optional[int] = None,
horizontal_accuracy: Optional[float] = None,
heading: Optional[int] = None,
proximity_alert_radius: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
location: Optional["Location"] = None,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -2067,6 +2189,7 @@ class Chat(TelegramObject):
allow_sending_without_reply=allow_sending_without_reply,
protect_content=protect_content,
message_thread_id=message_thread_id,
business_connection_id=business_connection_id,
)
async def send_animation(
@@ -2078,16 +2201,17 @@ class Chat(TelegramObject):
caption: Optional[str] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
reply_markup: Optional[ReplyMarkup] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
has_spoiler: Optional[bool] = None,
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
filename: Optional[str] = None,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -2129,20 +2253,22 @@ class Chat(TelegramObject):
message_thread_id=message_thread_id,
has_spoiler=has_spoiler,
thumbnail=thumbnail,
business_connection_id=business_connection_id,
)
async def send_sticker(
self,
sticker: Union[FileInput, "Sticker"],
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
reply_markup: Optional[ReplyMarkup] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
emoji: Optional[str] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -2175,6 +2301,7 @@ class Chat(TelegramObject):
protect_content=protect_content,
message_thread_id=message_thread_id,
emoji=emoji,
business_connection_id=business_connection_id,
)
async def send_venue(
@@ -2185,16 +2312,17 @@ class Chat(TelegramObject):
address: Optional[str] = None,
foursquare_id: Optional[str] = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
reply_markup: Optional[ReplyMarkup] = None,
foursquare_type: Optional[str] = None,
google_place_id: Optional[str] = None,
google_place_type: Optional[str] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
venue: Optional["Venue"] = None,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -2235,6 +2363,7 @@ class Chat(TelegramObject):
allow_sending_without_reply=allow_sending_without_reply,
protect_content=protect_content,
message_thread_id=message_thread_id,
business_connection_id=business_connection_id,
)
async def send_video(
@@ -2243,20 +2372,21 @@ class Chat(TelegramObject):
duration: Optional[int] = None,
caption: Optional[str] = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
reply_markup: Optional[ReplyMarkup] = None,
width: Optional[int] = None,
height: Optional[int] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
supports_streaming: Optional[bool] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
has_spoiler: Optional[bool] = None,
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
filename: Optional[str] = None,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -2299,6 +2429,7 @@ class Chat(TelegramObject):
protect_content=protect_content,
message_thread_id=message_thread_id,
has_spoiler=has_spoiler,
business_connection_id=business_connection_id,
)
async def send_video_note(
@@ -2307,14 +2438,15 @@ class Chat(TelegramObject):
duration: Optional[int] = None,
length: Optional[int] = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
reply_markup: Optional[ReplyMarkup] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
thumbnail: Optional[FileInput] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
filename: Optional[str] = None,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -2351,6 +2483,7 @@ class Chat(TelegramObject):
filename=filename,
protect_content=protect_content,
message_thread_id=message_thread_id,
business_connection_id=business_connection_id,
)
async def send_voice(
@@ -2359,15 +2492,16 @@ class Chat(TelegramObject):
duration: Optional[int] = None,
caption: Optional[str] = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
reply_markup: Optional[ReplyMarkup] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
filename: Optional[str] = None,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -2405,6 +2539,7 @@ class Chat(TelegramObject):
filename=filename,
protect_content=protect_content,
message_thread_id=message_thread_id,
business_connection_id=business_connection_id,
)
async def send_poll(
@@ -2417,18 +2552,19 @@ class Chat(TelegramObject):
correct_option_id: Optional[CorrectOptionID] = None,
is_closed: Optional[bool] = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
reply_markup: Optional[ReplyMarkup] = None,
explanation: Optional[str] = None,
explanation_parse_mode: ODVInput[str] = DEFAULT_NONE,
open_period: Optional[int] = None,
close_date: Optional[Union[int, datetime]] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
explanation_entities: Optional[Sequence["MessageEntity"]] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
business_connection_id: Optional[str] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -2471,6 +2607,7 @@ class Chat(TelegramObject):
explanation_entities=explanation_entities,
protect_content=protect_content,
message_thread_id=message_thread_id,
business_connection_id=business_connection_id,
)
async def send_copy(
@@ -2481,13 +2618,13 @@ class Chat(TelegramObject):
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_markup: Optional[ReplyMarkup] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -2535,13 +2672,13 @@ class Chat(TelegramObject):
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
disable_notification: ODVInput[bool] = DEFAULT_NONE,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
reply_markup: Optional[ReplyMarkup] = None,
protect_content: ODVInput[bool] = DEFAULT_NONE,
message_thread_id: Optional[int] = None,
reply_parameters: Optional["ReplyParameters"] = None,
*,
reply_to_message_id: Optional[int] = None,
allow_sending_without_reply: ODVInput[bool] = DEFAULT_NONE,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
@@ -2557,7 +2694,7 @@ class Chat(TelegramObject):
.. seealso:: :meth:`send_copy`, :meth:`send_copies`, :meth:`copy_messages`.
Returns:
:class:`telegram.Message`: On success, instance representing the message posted.
:class:`telegram.MessageId`: On success, returns the MessageId of the sent message.
"""
return await self.get_bot().copy_message(
+49 -34
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
@@ -44,12 +44,16 @@ class ChatAdministratorRights(TelegramObject):
:attr:`can_post_stories`, :attr:`can_edit_stories`, and :attr:`can_delete_stories` are
considered as well when comparing objects of this type in terms of equality.
.. versionchanged:: 21.1
As of this version, :attr:`can_post_stories`, :attr:`can_edit_stories`,
and :attr:`can_delete_stories` is now required. Thus, the order of arguments had to be
changed.
Args:
is_anonymous (:obj:`bool`): :obj:`True`, if the user's presence in the chat is hidden.
can_manage_chat (:obj:`bool`): :obj:`True`, if the administrator can access the chat event
log, chat statistics, boost list in channels, see channel members, report spam
messages, see anonymous administrators in supergroups and ignore slow mode.
Implied by any other administrator privilege.
log, get boost list, see hidden supergroup and channel members, report spam messages
and ignore slow mode. Implied by any other administrator privilege.
can_delete_messages (:obj:`bool`): :obj:`True`, if the administrator can delete messages of
other users.
can_manage_video_chats (:obj:`bool`): :obj:`True`, if the administrator can manage video
@@ -61,38 +65,43 @@ class ChatAdministratorRights(TelegramObject):
that they have promoted, directly or indirectly (promoted by administrators that
were appointed by the user).
can_change_info (:obj:`bool`): :obj:`True`, if the user is allowed to change the chat title
,photo and other settings.
, photo and other settings.
can_invite_users (:obj:`bool`): :obj:`True`, if the user is allowed to invite new users to
the chat.
can_post_messages (:obj:`bool`, optional): :obj:`True`, if the administrator can post
messages in the channel, or access channel statistics; channels only.
messages in the channel, or access channel statistics; for channels only.
can_edit_messages (:obj:`bool`, optional): :obj:`True`, if the administrator can edit
messages of other users.
messages of other users and can pin messages; for channels only.
can_pin_messages (:obj:`bool`, optional): :obj:`True`, if the user is allowed to pin
messages; groups and supergroups only.
can_post_stories (:obj:`bool`, optional): :obj:`True`, if the administrator can post
stories in the channel; channels only.
messages; for groups and supergroups only.
can_post_stories (:obj:`bool`): :obj:`True`, if the administrator can post
stories to the chat.
.. versionadded:: 20.6
can_edit_stories (:obj:`bool`, optional): :obj:`True`, if the administrator can edit
stories posted by other users; channels only.
.. versionchanged:: 21.0
|non_optional_story_argument|
can_edit_stories (:obj:`bool`): :obj:`True`, if the administrator can edit
stories posted by other users.
.. versionadded:: 20.6
can_delete_stories (:obj:`bool`, optional): :obj:`True`, if the administrator can delete
stories posted by other users; channels only.
.. versionchanged:: 21.0
|non_optional_story_argument|
can_delete_stories (:obj:`bool`): :obj:`True`, if the administrator can delete
stories posted by other users.
.. versionadded:: 20.6
.. versionchanged:: 21.0
|non_optional_story_argument|
can_manage_topics (:obj:`bool`, optional): :obj:`True`, if the user is allowed
to create, rename, close, and reopen forum topics; supergroups only.
to create, rename, close, and reopen forum topics; for supergroups only.
.. versionadded:: 20.0
Attributes:
is_anonymous (:obj:`bool`): :obj:`True`, if the user's presence in the chat is hidden.
can_manage_chat (:obj:`bool`): :obj:`True`, if the administrator can access the chat event
log, chat statistics, boost list in channels, see channel members, report spam
messages, see anonymous administrators in supergroups and ignore slow mode.
Implied by any other administrator privilege.
log, get boost list, see hidden supergroup and channel members, report spam messages
and ignore slow mode. Implied by any other administrator privilege.
can_delete_messages (:obj:`bool`): :obj:`True`, if the administrator can delete messages of
other users.
can_manage_video_chats (:obj:`bool`): :obj:`True`, if the administrator can manage video
@@ -108,25 +117,31 @@ class ChatAdministratorRights(TelegramObject):
can_invite_users (:obj:`bool`): :obj:`True`, if the user is allowed to invite new users to
the chat.
can_post_messages (:obj:`bool`): Optional. :obj:`True`, if the administrator can post
messages in the channel, or access channel statistics; channels only.
messages in the channel, or access channel statistics; for channels only.
can_edit_messages (:obj:`bool`): Optional. :obj:`True`, if the administrator can edit
messages of other users.
messages of other users and can pin messages; for channels only.
can_pin_messages (:obj:`bool`): Optional. :obj:`True`, if the user is allowed to pin
messages; groups and supergroups only.
can_post_stories (:obj:`bool`): Optional. :obj:`True`, if the administrator can post
stories in the channel; channels only.
messages; for groups and supergroups only.
can_post_stories (:obj:`bool`): :obj:`True`, if the administrator can post
stories to the chat.
.. versionadded:: 20.6
can_edit_stories (:obj:`bool`): Optional. :obj:`True`, if the administrator can edit
stories posted by other users; channels only.
.. versionchanged:: 21.0
|non_optional_story_argument|
can_edit_stories (:obj:`bool`): :obj:`True`, if the administrator can edit
stories posted by other users.
.. versionadded:: 20.6
can_delete_stories (:obj:`bool`): Optional. :obj:`True`, if the administrator can delete
stories posted by other users; channels only.
.. versionchanged:: 21.0
|non_optional_story_argument|
can_delete_stories (:obj:`bool`): :obj:`True`, if the administrator can delete
stories posted by other users.
.. versionadded:: 20.6
.. versionchanged:: 21.0
|non_optional_story_argument|
can_manage_topics (:obj:`bool`): Optional. :obj:`True`, if the user is allowed
to create, rename, close, and reopen forum topics; supergroups only.
to create, rename, close, and reopen forum topics; for supergroups only.
.. versionadded:: 20.0
"""
@@ -159,13 +174,13 @@ class ChatAdministratorRights(TelegramObject):
can_promote_members: bool,
can_change_info: bool,
can_invite_users: bool,
can_post_stories: bool,
can_edit_stories: bool,
can_delete_stories: bool,
can_post_messages: Optional[bool] = None,
can_edit_messages: Optional[bool] = None,
can_pin_messages: Optional[bool] = None,
can_manage_topics: Optional[bool] = None,
can_post_stories: Optional[bool] = None,
can_edit_stories: Optional[bool] = None,
can_delete_stories: Optional[bool] = None,
*,
api_kwargs: Optional[JSONDict] = None,
) -> None:
@@ -179,13 +194,13 @@ class ChatAdministratorRights(TelegramObject):
self.can_promote_members: bool = can_promote_members
self.can_change_info: bool = can_change_info
self.can_invite_users: bool = can_invite_users
self.can_post_stories: bool = can_post_stories
self.can_edit_stories: bool = can_edit_stories
self.can_delete_stories: bool = can_delete_stories
# Optionals
self.can_post_messages: Optional[bool] = can_post_messages
self.can_edit_messages: Optional[bool] = can_edit_messages
self.can_pin_messages: Optional[bool] = can_pin_messages
self.can_post_stories: Optional[bool] = can_post_stories
self.can_edit_stories: Optional[bool] = can_edit_stories
self.can_delete_stories: Optional[bool] = can_delete_stories
self.can_manage_topics: Optional[bool] = can_manage_topics
self._id_attrs = (
+33
View File
@@ -34,6 +34,39 @@ if TYPE_CHECKING:
from telegram import Bot
class ChatBoostAdded(TelegramObject):
"""
This object represents a service message about a user boosting a chat.
Objects of this class are comparable in terms of equality.
Two objects of this class are considered equal, if their
:attr:`boost_count` are equal.
.. versionadded:: 21.0
Args:
boost_count (:obj:`int`): Number of boosts added by the user.
Attributes:
boost_count (:obj:`int`): Number of boosts added by the user.
"""
__slots__ = ("boost_count",)
def __init__(
self,
boost_count: int,
*,
api_kwargs: Optional[JSONDict] = None,
) -> None:
super().__init__(api_kwargs=api_kwargs)
self.boost_count: int = boost_count
self._id_attrs = (self.boost_count,)
self._freeze()
class ChatBoostSource(TelegramObject):
"""
Base class for Telegram ChatBoostSource objects. It can be one of:
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+50 -34
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
@@ -191,15 +191,19 @@ class ChatMemberAdministrator(ChatMember):
* The argument :paramref:`can_manage_topics` was added, which changes the position of the
optional argument :paramref:`custom_title`.
.. versionchanged:: 21.1
As of this version, :attr:`can_post_stories`, :attr:`can_edit_stories`,
and :attr:`can_delete_stories` is now required. Thus, the order of arguments had to be
changed.
Args:
user (:class:`telegram.User`): Information about the user.
can_be_edited (:obj:`bool`): :obj:`True`, if the bot
is allowed to edit administrator privileges of that user.
is_anonymous (:obj:`bool`): :obj:`True`, if the user's
presence in the chat is hidden.
can_manage_chat (:obj:`bool`): :obj:`True`, if the administrator
can access the chat event log, chat statistics, message statistics in
channels, see channel members, see anonymous administrators in supergroups
can_manage_chat (:obj:`bool`): :obj:`True`, if the administrator can access the chat event
log, get boost list, see hidden supergroup and channel members, report spam messages
and ignore slow mode. Implied by any other administrator privilege.
can_delete_messages (:obj:`bool`): :obj:`True`, if the
administrator can delete messages of other users.
@@ -218,27 +222,33 @@ class ChatMemberAdministrator(ChatMember):
can_invite_users (:obj:`bool`): :obj:`True`, if the user can invite
new users to the chat.
can_post_messages (:obj:`bool`, optional): :obj:`True`, if the
administrator can post messages in the channel, or access channel statistics; channels
only.
administrator can post messages in the channel, or access channel statistics;
for channels only.
can_edit_messages (:obj:`bool`, optional): :obj:`True`, if the
administrator can edit messages of other users and can pin
messages; channels only.
messages; for channels only.
can_pin_messages (:obj:`bool`, optional): :obj:`True`, if the user is allowed
to pin messages; groups and supergroups only.
can_post_stories (:obj:`bool`, optional): :obj:`True`, if the administrator can post
stories in the channel; channels only.
to pin messages; for groups and supergroups only.
can_post_stories (:obj:`bool`): :obj:`True`, if the administrator can post
stories to the chat.
.. versionadded:: 20.6
can_edit_stories (:obj:`bool`, optional): :obj:`True`, if the administrator can edit
stories posted by other users; channels only.
.. versionchanged:: 21.0
|non_optional_story_argument|
can_edit_stories (:obj:`bool`): :obj:`True`, if the administrator can edit
stories posted by other users.
.. versionadded:: 20.6
can_delete_stories (:obj:`bool`, optional): :obj:`True`, if the administrator can delete
stories posted by other users; channels only.
.. versionchanged:: 21.0
|non_optional_story_argument|
can_delete_stories (:obj:`bool`): :obj:`True`, if the administrator can delete
stories posted by other users.
.. versionadded:: 20.6
.. versionchanged:: 21.0
|non_optional_story_argument|
can_manage_topics (:obj:`bool`, optional): :obj:`True`, if the user is allowed
to create, rename, close, and reopen forum topics; supergroups only.
to create, rename, close, and reopen forum topics; for supergroups only.
.. versionadded:: 20.0
custom_title (:obj:`str`, optional): Custom title for this user.
@@ -252,9 +262,8 @@ class ChatMemberAdministrator(ChatMember):
is_anonymous (:obj:`bool`): :obj:`True`, if the user's
presence in the chat is hidden.
can_manage_chat (:obj:`bool`): :obj:`True`, if the administrator can access the chat event
log, chat statistics, boost list in channels, see channel members, report spam
messages, see anonymous administrators in supergroups and ignore slow mode.
Implied by any other administrator privilege.
log, get boost list, see hidden supergroup and channel members, report spam messages
and ignore slow mode. Implied by any other administrator privilege.
can_delete_messages (:obj:`bool`): :obj:`True`, if the
administrator can delete messages of other users.
can_manage_video_chats (:obj:`bool`): :obj:`True`, if the
@@ -273,26 +282,32 @@ class ChatMemberAdministrator(ChatMember):
new users to the chat.
can_post_messages (:obj:`bool`): Optional. :obj:`True`, if the
administrator can post messages in the channel or access channel statistics;
channels only.
for channels only.
can_edit_messages (:obj:`bool`): Optional. :obj:`True`, if the
administrator can edit messages of other users and can pin
messages; channels only.
messages; for channels only.
can_pin_messages (:obj:`bool`): Optional. :obj:`True`, if the user is allowed
to pin messages; groups and supergroups only.
can_post_stories (:obj:`bool`): Optional. :obj:`True`, if the administrator can post
stories in the channel; channels only.
to pin messages; for groups and supergroups only.
can_post_stories (:obj:`bool`): :obj:`True`, if the administrator can post
stories to the chat.
.. versionadded:: 20.6
can_edit_stories (:obj:`bool`): Optional. :obj:`True`, if the administrator can edit
stories posted by other users; channels only.
.. versionchanged:: 21.0
|non_optional_story_argument|
can_edit_stories (:obj:`bool`): :obj:`True`, if the administrator can edit
stories posted by other users.
.. versionadded:: 20.6
can_delete_stories (:obj:`bool`): Optional. :obj:`True`, if the administrator can delete
stories posted by other users; channels only.
.. versionchanged:: 21.0
|non_optional_story_argument|
can_delete_stories (:obj:`bool`): :obj:`True`, if the administrator can delete
stories posted by other users.
.. versionadded:: 20.6
.. versionchanged:: 21.0
|non_optional_story_argument|
can_manage_topics (:obj:`bool`): Optional. :obj:`True`, if the user is allowed
to create, rename, close, and reopen forum topics; supergroups only
to create, rename, close, and reopen forum topics; for supergroups only
.. versionadded:: 20.0
custom_title (:obj:`str`): Optional. Custom title for this user.
@@ -330,14 +345,14 @@ class ChatMemberAdministrator(ChatMember):
can_promote_members: bool,
can_change_info: bool,
can_invite_users: bool,
can_post_stories: bool,
can_edit_stories: bool,
can_delete_stories: bool,
can_post_messages: Optional[bool] = None,
can_edit_messages: Optional[bool] = None,
can_pin_messages: Optional[bool] = None,
can_manage_topics: Optional[bool] = None,
custom_title: Optional[str] = None,
can_post_stories: Optional[bool] = None,
can_edit_stories: Optional[bool] = None,
can_delete_stories: Optional[bool] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
@@ -352,14 +367,15 @@ class ChatMemberAdministrator(ChatMember):
self.can_promote_members: bool = can_promote_members
self.can_change_info: bool = can_change_info
self.can_invite_users: bool = can_invite_users
self.can_post_stories: bool = can_post_stories
self.can_edit_stories: bool = can_edit_stories
self.can_delete_stories: bool = can_delete_stories
# Optionals
self.can_post_messages: Optional[bool] = can_post_messages
self.can_edit_messages: Optional[bool] = can_edit_messages
self.can_pin_messages: Optional[bool] = can_pin_messages
self.can_manage_topics: Optional[bool] = can_manage_topics
self.custom_title: Optional[str] = custom_title
self.can_post_stories: Optional[bool] = can_post_stories
self.can_edit_stories: Optional[bool] = can_edit_stories
self.can_delete_stories: Optional[bool] = can_delete_stories
class ChatMemberMember(ChatMember):
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -2,7 +2,7 @@
# pylint: disable=too-many-arguments
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+22 -2
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
@@ -36,6 +36,10 @@ class InputSticker(TelegramObject):
.. versionadded:: 20.2
.. versionchanged:: 21.1
As of Bot API 7.2, the new argument :paramref:`format` is a required argument, and thus the
order of the arguments has changed.
Args:
sticker (:obj:`str` | :term:`file object` | :obj:`bytes` | :class:`pathlib.Path`): The
added sticker. |uploadinputnopath| Animated and video stickers can't be uploaded via
@@ -52,6 +56,13 @@ class InputSticker(TelegramObject):
:tg-const:`telegram.constants.StickerLimit.MAX_KEYWORD_LENGTH` characters. For
":tg-const:`telegram.constants.StickerType.REGULAR`" and
":tg-const:`telegram.constants.StickerType.CUSTOM_EMOJI`" stickers only.
format (:obj:`str`): Format of the added sticker, must be one of
:tg-const:`telegram.constants.StickerFormat.STATIC` for a
``.WEBP`` or ``.PNG`` image, :tg-const:`telegram.constants.StickerFormat.ANIMATED`
for a ``.TGS`` animation, :tg-const:`telegram.constants.StickerFormat.VIDEO` for a WEBM
video.
.. versionadded:: 21.1
Attributes:
sticker (:obj:`str` | :class:`telegram.InputFile`): The added sticker.
@@ -67,15 +78,23 @@ class InputSticker(TelegramObject):
:tg-const:`telegram.constants.StickerLimit.MAX_KEYWORD_LENGTH` characters. For
":tg-const:`telegram.constants.StickerType.REGULAR`" and
":tg-const:`telegram.constants.StickerType.CUSTOM_EMOJI`" stickers only.
":tg-const:`telegram.constants.StickerType.CUSTOM_EMOJI`" stickers only.
format (:obj:`str`): Format of the added sticker, must be one of
:tg-const:`telegram.constants.StickerFormat.STATIC` for a
``.WEBP`` or ``.PNG`` image, :tg-const:`telegram.constants.StickerFormat.ANIMATED`
for a ``.TGS`` animation, :tg-const:`telegram.constants.StickerFormat.VIDEO` for a WEBM
video.
.. versionadded:: 21.1
"""
__slots__ = ("emoji_list", "keywords", "mask_position", "sticker")
__slots__ = ("emoji_list", "format", "keywords", "mask_position", "sticker")
def __init__(
self,
sticker: FileInput,
emoji_list: Sequence[str],
format: str, # pylint: disable=redefined-builtin
mask_position: Optional[MaskPosition] = None,
keywords: Optional[Sequence[str]] = None,
*,
@@ -91,6 +110,7 @@ class InputSticker(TelegramObject):
attach=True,
)
self.emoji_list: Tuple[str, ...] = parse_sequence_arg(emoji_list)
self.format: str = format
self.mask_position: Optional[MaskPosition] = mask_position
self.keywords: Tuple[str, ...] = parse_sequence_arg(keywords)
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+35 -8
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
@@ -27,6 +27,8 @@ from telegram._telegramobject import TelegramObject
from telegram._utils import enum
from telegram._utils.argumentparsing import parse_sequence_arg
from telegram._utils.types import JSONDict
from telegram._utils.warnings import warn
from telegram.warnings import PTBDeprecationWarning
if TYPE_CHECKING:
from telegram import Bot
@@ -227,6 +229,11 @@ class StickerSet(TelegramObject):
.. versionchanged:: 20.0
The parameter ``contains_masks`` has been removed. Use :paramref:`sticker_type` instead.
.. versionchanged:: 21.1
The parameters ``is_video`` and ``is_animated`` are deprecated and now made optional. Thus,
the order of the arguments had to be changed.
.. versionchanged:: 20.5
|removed_thumb_note|
@@ -234,9 +241,16 @@ class StickerSet(TelegramObject):
name (:obj:`str`): Sticker set name.
title (:obj:`str`): Sticker set title.
is_animated (:obj:`bool`): :obj:`True`, if the sticker set contains animated stickers.
is_video (:obj:`bool`): :obj:`True`, if the sticker set contains video stickers.
.. deprecated:: 21.1
Bot API 7.2 deprecated this field. This parameter will be removed in a future
version of the library.
is_video (:obj:`bool`): :obj:`True`, if the sticker set contains video stickers.
.. versionadded:: 13.11
.. deprecated:: 21.1
Bot API 7.2 deprecated this field. This parameter will be removed in a future
version of the library.
stickers (Sequence[:class:`telegram.Sticker`]): List of all set stickers.
.. versionchanged:: 20.0
@@ -256,9 +270,16 @@ class StickerSet(TelegramObject):
name (:obj:`str`): Sticker set name.
title (:obj:`str`): Sticker set title.
is_animated (:obj:`bool`): :obj:`True`, if the sticker set contains animated stickers.
is_video (:obj:`bool`): :obj:`True`, if the sticker set contains video stickers.
.. deprecated:: 21.1
Bot API 7.2 deprecated this field. This parameter will be removed in a future
version of the library.
is_video (:obj:`bool`): :obj:`True`, if the sticker set contains video stickers.
.. versionadded:: 13.11
.. deprecated:: 21.1
Bot API 7.2 deprecated this field. This parameter will be removed in a future
version of the library.
stickers (Tuple[:class:`telegram.Sticker`]): List of all set stickers.
.. versionchanged:: 20.0
@@ -289,10 +310,10 @@ class StickerSet(TelegramObject):
self,
name: str,
title: str,
is_animated: bool,
stickers: Sequence[Sticker],
is_video: bool,
sticker_type: str,
is_animated: Optional[bool] = None,
is_video: Optional[bool] = None,
thumbnail: Optional[PhotoSize] = None,
*,
api_kwargs: Optional[JSONDict] = None,
@@ -300,13 +321,19 @@ class StickerSet(TelegramObject):
super().__init__(api_kwargs=api_kwargs)
self.name: str = name
self.title: str = title
self.is_animated: bool = is_animated
self.is_video: bool = is_video
self.stickers: Tuple[Sticker, ...] = parse_sequence_arg(stickers)
self.sticker_type: str = sticker_type
# Optional
self.thumbnail: Optional[PhotoSize] = thumbnail
if is_animated is not None or is_video is not None:
warn(
"The parameters `is_animated` and `is_video` are deprecated and will be removed "
"in a future version.",
PTBDeprecationWarning,
stacklevel=2,
)
self.is_animated: Optional[bool] = is_animated
self.is_video: Optional[bool] = is_video
self._id_attrs = (self.name,)
self._freeze()
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -2,7 +2,7 @@
# pylint: disable=too-many-arguments
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# 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

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