mirror of
https://github.com/python-telegram-bot/python-telegram-bot.git
synced 2026-06-23 09:45:30 +00:00
Compare commits
66 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3d4e0500bf | |||
| 042d4bb2a4 | |||
| 1e22d570a3 | |||
| 2719c54899 | |||
| a5c8e98ee7 | |||
| 40113bb3ad | |||
| e8fac19de3 | |||
| 820ae3b7d6 | |||
| 4b3315db6f | |||
| 3ed05991ad | |||
| 38637ecf62 | |||
| bb5357a815 | |||
| f55018abd9 | |||
| 8df35fd53b | |||
| 23774383dc | |||
| 28680ac1d5 | |||
| ec9b16ac7b | |||
| bfad2fa1f3 | |||
| 8a8b1215c8 | |||
| 2aa456d637 | |||
| 445bcde686 | |||
| 6facde9534 | |||
| 046ec28361 | |||
| 3d00ae25df | |||
| aeedcfb874 | |||
| 6d7a61ae72 | |||
| d75e0f6014 | |||
| dbb3b16edc | |||
| 7c3bba42cc | |||
| 8754980448 | |||
| 5614af1847 | |||
| e362a5b59d | |||
| dd20237f55 | |||
| c5ab8930b9 | |||
| f5b746f1ba | |||
| 4fe4eea893 | |||
| e39b6abe61 | |||
| 6012fa65c1 | |||
| ef9dbacf7e | |||
| e13cd58773 | |||
| 1f5311b473 | |||
| eae139d3e9 | |||
| 160ffed5ad | |||
| 8cda3f7a71 | |||
| d7929a8de4 | |||
| e018445513 | |||
| 4601eedf0f | |||
| 6cd0c14c02 | |||
| b6a0853896 | |||
| 16a49ec659 | |||
| ee34d57521 | |||
| 5d7c6ad541 | |||
| 915cd64140 | |||
| 56f7d18853 | |||
| b04869f36a | |||
| 70057a67c5 | |||
| 8d4b484f7b | |||
| 073bed3a01 | |||
| 5ceb6f8f36 | |||
| b6ef30a454 | |||
| 1b515a16d6 | |||
| b3069348ca | |||
| 454ab050c0 | |||
| d19ae5084a | |||
| 6aacde189e | |||
| 5d3f5575ab |
+18
-3
@@ -1,5 +1,20 @@
|
||||
languages:
|
||||
Python: true
|
||||
exclude_paths:
|
||||
- "telegram/emoji.py"
|
||||
- "tests/*"
|
||||
- "examples/*"
|
||||
engines:
|
||||
duplication:
|
||||
enabled: true
|
||||
config:
|
||||
languages:
|
||||
- python:
|
||||
checks:
|
||||
Similar code:
|
||||
enabled: false
|
||||
|
||||
radon:
|
||||
enabled: true
|
||||
config:
|
||||
threshold: "C"
|
||||
ratings:
|
||||
paths:
|
||||
- "**.py"
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
[run]
|
||||
source = telegram
|
||||
omit = telegram/vendor/*
|
||||
|
||||
[report]
|
||||
omit =
|
||||
tests/
|
||||
telegram/vendor/*
|
||||
+33
-18
@@ -1,10 +1,10 @@
|
||||
How To Contribute
|
||||
===================
|
||||
=================
|
||||
|
||||
Every open source project lives from the generous help by contributors that sacrifice their time and ``python-telegram-bot`` is no different. To make participation as pleasant as possible, this project adheres to the `Code of Conduct`_ by the Python Software Foundation.
|
||||
|
||||
Setting things up
|
||||
-------------------
|
||||
-----------------
|
||||
|
||||
1. Fork the ``python-telegram-bot`` repository to your GitHub account.
|
||||
|
||||
@@ -35,7 +35,7 @@ Setting things up
|
||||
$ pre-commit install
|
||||
|
||||
Finding something to do
|
||||
###################
|
||||
#######################
|
||||
|
||||
If you already know what you'd like to work on, you can skip this section.
|
||||
|
||||
@@ -44,7 +44,7 @@ If you have an idea for something to do, first check if it's already been filed
|
||||
Another great way to start contributing is by writing tests. Tests are really important because they help prevent developers from accidentally breaking existing code, allowing them to build cool things faster. If you're interested in helping out, let the development team know by posting to the `developers' mailing list`_, and we'll help you get started.
|
||||
|
||||
Instructions for making a code change
|
||||
####################
|
||||
#####################################
|
||||
|
||||
The central development branch is ``master``, which should be clean and ready for release at any time. In general, all changes should be done as feature branches based off of ``master``.
|
||||
|
||||
@@ -89,7 +89,7 @@ Here's how to make a one-off code change.
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ nosetests -v
|
||||
$ pytest -v
|
||||
|
||||
- To actually make the commit (this will trigger tests for yapf, lint and pep8 automatically):
|
||||
|
||||
@@ -129,13 +129,19 @@ Here's how to make a one-off code change.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ git checkout your-branch-name
|
||||
$ git fetch upstream
|
||||
$ git merge upstream/master
|
||||
$ ...[fix the conflicts]...
|
||||
$ ...[make sure the tests pass before committing]...
|
||||
$ git commit -a
|
||||
$ git push origin your-branch-name
|
||||
$ git checkout your-branch-name
|
||||
$ git fetch upstream
|
||||
$ git merge upstream/master
|
||||
$ ...[fix the conflicts]...
|
||||
$ ...[make sure the tests pass before committing]...
|
||||
$ git commit -a
|
||||
$ git push origin your-branch-name
|
||||
|
||||
- If after merging you see local modified files in ``telegram/vendor/`` directory, that you didn't actually touch, that means you need to update submodules with this command:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ git submodule update --init --recursive
|
||||
|
||||
- At the end, the reviewer will merge the pull request.
|
||||
|
||||
@@ -149,20 +155,29 @@ Here's how to make a one-off code change.
|
||||
7. **Celebrate.** Congratulations, you have contributed to ``python-telegram-bot``!
|
||||
|
||||
Style commandments
|
||||
---------------------
|
||||
------------------
|
||||
|
||||
Specific commandments
|
||||
#####################
|
||||
|
||||
- Avoid using "double quotes" where you can reasonably use 'single quotes'.
|
||||
|
||||
AssertEqual argument order
|
||||
######################
|
||||
Assert comparison order
|
||||
#######################
|
||||
|
||||
- assertEqual method's arguments should be in ('actual', 'expected') order.
|
||||
- assert statements should compare in **actual** == **expected** order.
|
||||
For example (assuming ``test_call`` is the thing being tested):
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# GOOD
|
||||
assert test_call() == 5
|
||||
|
||||
# BAD
|
||||
assert 5 == test_call()
|
||||
|
||||
Properly calling callables
|
||||
#######################
|
||||
##########################
|
||||
|
||||
Methods, functions and classes can specify optional parameters (with default
|
||||
values) using Python's keyword arg syntax. When providing a value to such a
|
||||
@@ -180,7 +195,7 @@ This gives us the flexibility to re-order arguments and more importantly
|
||||
to add new required arguments. It's also more explicit and easier to read.
|
||||
|
||||
Properly defining optional arguments
|
||||
########################
|
||||
####################################
|
||||
|
||||
It's always good to not initialize optional arguments at class creation,
|
||||
instead use ``**kwargs`` to get them. It's well known Telegram API can
|
||||
|
||||
@@ -17,4 +17,4 @@
|
||||
files: ^telegram/.*\.py$
|
||||
args:
|
||||
- --errors-only
|
||||
- --disable=no-name-in-module,import-error
|
||||
- --disable=import-error
|
||||
|
||||
+9
-6
@@ -1,7 +1,6 @@
|
||||
language: python
|
||||
python:
|
||||
- "2.7"
|
||||
- "3.3"
|
||||
- "3.4"
|
||||
- "3.5"
|
||||
- "3.6"
|
||||
@@ -18,18 +17,22 @@ branches:
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.cache/pip
|
||||
- $HOME/.pre-commit
|
||||
before_cache:
|
||||
- rm -f $HOME/.cache/pip/log/debug.log
|
||||
- rm -f $HOME/.pre-commit/pre-commit.log
|
||||
|
||||
install:
|
||||
- pip install coveralls
|
||||
- pip install -U codecov pytest-cov
|
||||
- pip install -U wheel
|
||||
- pip install -r requirements.txt
|
||||
- pip install -r requirements-dev.txt
|
||||
- pip install -U -r requirements.txt
|
||||
- pip install -U -r requirements-dev.txt
|
||||
- if [[ $TRAVIS_PYTHON_VERSION != 'pypy'* ]]; then pip install ujson; fi
|
||||
|
||||
script:
|
||||
- python travis.py
|
||||
- pytest -v -m nocoverage
|
||||
- pytest -v -m "not nocoverage" --cov
|
||||
|
||||
after_success:
|
||||
coveralls
|
||||
- coverage combine
|
||||
- codecov -F Travis
|
||||
+5
-3
@@ -16,8 +16,8 @@ Contributors
|
||||
The following wonderful people contributed directly or indirectly to this project:
|
||||
|
||||
- `Alateas <https://github.com/alateas>`_
|
||||
- `Avanatiker <https://github.com/Avanatiker>`_
|
||||
- `Anton Tagunov <https://github.com/anton-tagunov>`_
|
||||
- `Avanatiker <https://github.com/Avanatiker>`_
|
||||
- `Balduro <https://github.com/Balduro>`_
|
||||
- `bimmlerd <https://github.com/bimmlerd>`_
|
||||
- `d-qoi <https://github.com/d-qoi>`_
|
||||
@@ -29,15 +29,17 @@ The following wonderful people contributed directly or indirectly to this projec
|
||||
- `evgfilim1 <https://github.com/evgfilim1>`_
|
||||
- `franciscod <https://github.com/franciscod>`_
|
||||
- `Hugo Damer <https://github.com/HakimusGIT>`_
|
||||
- `ihoru <https://github.com/ihoru>`_
|
||||
- `Jacob Bom <https://github.com/bomjacob>`_
|
||||
- `JASON0916 <https://github.com/JASON0916>`_
|
||||
- `jeffffc <https://github.com/jeffffc>`_
|
||||
- `Jelle Besseling <https://github.com/pingiun>`_
|
||||
- `jh0ker <https://github.com/jh0ker>`_
|
||||
- `jlmadurga <https://github.com/jlmadurga>`_
|
||||
- `John Yong <https://github.com/whipermr5>`_
|
||||
- `Joscha Götzer <https://github.com/Rostgnom>`_
|
||||
- `jossalgon <https://github.com/jossalgon>`_
|
||||
- `JRoot3D <https://github.com/JRoot3D>`_
|
||||
- `jlmadurga <https://github.com/jlmadurga>`_
|
||||
- `Kjwon15 <https://github.com/kjwon15>`_
|
||||
- `Li-aung Yip <https://github.com/LiaungYip>`_
|
||||
- `macrojames <https://github.com/macrojames>`_
|
||||
@@ -51,9 +53,9 @@ The following wonderful people contributed directly or indirectly to this projec
|
||||
- `Patrick Hofmann <https://github.com/PH89>`_
|
||||
- `Pieter Schutz <https://github.com/eldinnie>`_
|
||||
- `Rahiel Kasim <https://github.com/rahiel>`_
|
||||
- `Joscha Götzer <https://github.com/Rostgnom>`_
|
||||
- `Sascha <https://github.com/saschalalala>`_
|
||||
- `Shelomentsev D <https://github.com/shelomentsevd>`_
|
||||
- `Simon Schürrle <https://github.com/SitiSchu>`_
|
||||
- `sooyhwang <https://github.com/sooyhwang>`_
|
||||
- `thodnev <https://github.com/thodnev>`_
|
||||
- `Valentijn <https://github.com/Faalentijn>`_
|
||||
|
||||
+92
@@ -1,6 +1,98 @@
|
||||
=======
|
||||
Changes
|
||||
=======
|
||||
**2017-12-08**
|
||||
*Released 9.0.0*
|
||||
|
||||
Breaking changes (possibly)
|
||||
|
||||
- Drop support for python 3.3 (PR `#930`_)
|
||||
|
||||
|
||||
New Features
|
||||
|
||||
- Support Bot API 3.5 (PR `#920`_)
|
||||
|
||||
|
||||
Changes
|
||||
|
||||
- Fix race condition in dispatcher start/stop (`#887`_)
|
||||
- Log error trace if there is no error handler registered (`#694`_)
|
||||
- Update examples with consistent string formatting (`#870`_)
|
||||
- Various changes and improvements to the docs.
|
||||
|
||||
.. _`#920`: https://github.com/python-telegram-bot/python-telegram-bot/pull/920
|
||||
.. _`#930`: https://github.com/python-telegram-bot/python-telegram-bot/pull/930
|
||||
.. _`#887`: https://github.com/python-telegram-bot/python-telegram-bot/pull/887
|
||||
.. _`#694`: https://github.com/python-telegram-bot/python-telegram-bot/pull/694
|
||||
.. _`#870`: https://github.com/python-telegram-bot/python-telegram-bot/pull/870
|
||||
|
||||
**2017-10-15**
|
||||
*Released 8.1.1*
|
||||
|
||||
- Fix Commandhandler crashing on single character messages (PR `#873`_).
|
||||
|
||||
.. _`#873`: https://github.com/python-telegram-bot/python-telegram-bot/pull/871
|
||||
|
||||
**2017-10-14**
|
||||
*Released 8.1.0*
|
||||
|
||||
New features
|
||||
- Support Bot API 3.4 (PR `#865`_).
|
||||
|
||||
Changes
|
||||
- MessageHandler & RegexHandler now consider channel_updates.
|
||||
- Fix command not recognized if it is directly followed by a newline (PR `#869`_).
|
||||
- Removed Bot._message_wrapper (PR `#822`_).
|
||||
- Unitests are now also running on AppVeyor (Windows VM).
|
||||
- Various unitest improvements.
|
||||
- Documentation fixes.
|
||||
|
||||
.. _`#822`: https://github.com/python-telegram-bot/python-telegram-bot/pull/822
|
||||
.. _`#865`: https://github.com/python-telegram-bot/python-telegram-bot/pull/865
|
||||
.. _`#869`: https://github.com/python-telegram-bot/python-telegram-bot/pull/869
|
||||
|
||||
**2017-09-01**
|
||||
*Released 8.0.0*
|
||||
|
||||
New features
|
||||
|
||||
- Fully support Bot Api 3.3 (PR `#806`_).
|
||||
- DispatcherHandlerStop (`see docs`_).
|
||||
- Regression fix for text_html & text_markdown (PR `#777`_).
|
||||
- Added effective_attachment to message (PR `#766`_).
|
||||
|
||||
Non backward compatible changes
|
||||
|
||||
- Removed Botan support from the library (PR `#776`_).
|
||||
- Fully support Bot Api 3.3 (PR `#806`_).
|
||||
- Remove de_json() (PR `#789`_).
|
||||
|
||||
Changes
|
||||
|
||||
- Sane defaults for tcp socket options on linux (PR `#754`_).
|
||||
- Add RESTRICTED as constant to ChatMember (PR `#761`_).
|
||||
- Add rich comparison to CallbackQuery (PR `#764`_).
|
||||
- Fix get_game_high_scores (PR `#771`_).
|
||||
- Warn on small con_pool_size during custom initalization of Updater (PR `#793`_).
|
||||
- Catch exceptions in error handlerfor errors that happen during polling (PR `#810`_).
|
||||
- For testing we switched to pytest (PR `#788`_).
|
||||
- Lots of small improvements to our tests and documentation.
|
||||
|
||||
|
||||
.. _`see docs`: http://python-telegram-bot.readthedocs.io/en/stable/telegram.ext.dispatcher.html#telegram.ext.Dispatcher.add_handler
|
||||
.. _`#777`: https://github.com/python-telegram-bot/python-telegram-bot/pull/777
|
||||
.. _`#806`: https://github.com/python-telegram-bot/python-telegram-bot/pull/806
|
||||
.. _`#766`: https://github.com/python-telegram-bot/python-telegram-bot/pull/766
|
||||
.. _`#776`: https://github.com/python-telegram-bot/python-telegram-bot/pull/776
|
||||
.. _`#789`: https://github.com/python-telegram-bot/python-telegram-bot/pull/789
|
||||
.. _`#754`: https://github.com/python-telegram-bot/python-telegram-bot/pull/754
|
||||
.. _`#761`: https://github.com/python-telegram-bot/python-telegram-bot/pull/761
|
||||
.. _`#764`: https://github.com/python-telegram-bot/python-telegram-bot/pull/764
|
||||
.. _`#771`: https://github.com/python-telegram-bot/python-telegram-bot/pull/771
|
||||
.. _`#788`: https://github.com/python-telegram-bot/python-telegram-bot/pull/788
|
||||
.. _`#793`: https://github.com/python-telegram-bot/python-telegram-bot/pull/793
|
||||
.. _`#810`: https://github.com/python-telegram-bot/python-telegram-bot/pull/810
|
||||
|
||||
**2017-07-28**
|
||||
*Released 7.0.1*
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at devs@python-telegram-bot.org. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
@@ -2,7 +2,7 @@
|
||||
.PHONY: clean pep257 pep8 yapf lint test install
|
||||
|
||||
PYLINT := pylint
|
||||
NOSETESTS := nosetests
|
||||
PYTEST := pytest
|
||||
PEP257 := pep257
|
||||
PEP8 := flake8
|
||||
YAPF := yapf
|
||||
@@ -29,7 +29,7 @@ lint:
|
||||
$(PYLINT) -E telegram --disable=no-name-in-module,import-error
|
||||
|
||||
test:
|
||||
$(NOSETESTS) -v
|
||||
$(PYTEST) -v
|
||||
|
||||
install:
|
||||
$(PIP) install -r requirements.txt -r requirements-dev.txt
|
||||
@@ -41,11 +41,11 @@ help:
|
||||
@echo "- pep8 Check style with flake8"
|
||||
@echo "- lint Check style with pylint"
|
||||
@echo "- yapf Check style with yapf"
|
||||
@echo "- test Run tests"
|
||||
@echo "- test Run tests using pytest"
|
||||
@echo
|
||||
@echo "Available variables:"
|
||||
@echo "- PYLINT default: $(PYLINT)"
|
||||
@echo "- NOSETESTS default: $(NOSETESTS)"
|
||||
@echo "- PYTEST default: $(PYTEST)"
|
||||
@echo "- PEP257 default: $(PEP257)"
|
||||
@echo "- PEP8 default: $(PEP8)"
|
||||
@echo "- YAPF default: $(YAPF)"
|
||||
|
||||
+12
-4
@@ -31,13 +31,17 @@ We have made you a wrapper you can't refuse
|
||||
:target: https://travis-ci.org/python-telegram-bot/python-telegram-bot
|
||||
:alt: Travis CI Status
|
||||
|
||||
.. image:: https://img.shields.io/appveyor/ci/Eldinnie/python-telegram-bot/master.svg?logo=appveyor
|
||||
:target: https://ci.appveyor.com/project/Eldinnie/python-telegram-bot
|
||||
:alt: AppVeyor CI Status
|
||||
|
||||
.. image:: https://codeclimate.com/github/python-telegram-bot/python-telegram-bot/badges/gpa.svg
|
||||
:target: https://codeclimate.com/github/python-telegram-bot/python-telegram-bot
|
||||
:alt: Code Climate
|
||||
|
||||
.. image:: https://coveralls.io/repos/python-telegram-bot/python-telegram-bot/badge.svg?branch=master&service=github
|
||||
:target: https://coveralls.io/github/python-telegram-bot/python-telegram-bot?branch=master
|
||||
:alt: Coveralls
|
||||
.. image:: https://codecov.io/gh/python-telegram-bot/python-telegram-bot/branch/master/graph/badge.svg
|
||||
:target: https://codecov.io/gh/python-telegram-bot/python-telegram-bot
|
||||
:alt: Code coverage
|
||||
|
||||
.. image:: http://isitmaintained.com/badge/resolution/python-telegram-bot/python-telegram-bot.svg
|
||||
:target: http://isitmaintained.com/project/python-telegram-bot/python-telegram-bot
|
||||
@@ -47,6 +51,10 @@ We have made you a wrapper you can't refuse
|
||||
:target: https://telegram.me/pythontelegrambotgroup
|
||||
:alt: Telegram Group
|
||||
|
||||
.. image:: https://img.shields.io/badge/IRC-Channel-blue.svg
|
||||
:target: https://webchat.freenode.net/?channels=##python-telegram-bot
|
||||
:alt: IRC Bridge
|
||||
|
||||
=================
|
||||
Table of contents
|
||||
=================
|
||||
@@ -88,7 +96,7 @@ make the development of bots easy and straightforward. These classes are contain
|
||||
Telegram API support
|
||||
====================
|
||||
|
||||
As of **23. July 2017**, all types and methods of the Telegram Bot API 3.2 are supported.
|
||||
All types and methods of the Telegram Bot API 3.4 are supported.
|
||||
|
||||
==========
|
||||
Installing
|
||||
|
||||
+18
-10
@@ -7,25 +7,33 @@ environment:
|
||||
# isn't covered by this document) at the time of writing.
|
||||
|
||||
- PYTHON: "C:\\Python27"
|
||||
- PYTHON: "C:\\Python33"
|
||||
- PYTHON: "C:\\Python34"
|
||||
- PYTHON: "C:\\Python35"
|
||||
- PYTHON: "C:\\Python36"
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
skip_branch_with_pr: true
|
||||
|
||||
max_jobs: 1
|
||||
|
||||
install:
|
||||
# We need wheel installed to build wheels
|
||||
- "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
|
||||
- "git submodule update --init --recursive"
|
||||
- "%PYTHON%\\python.exe -m pip install -U wheel"
|
||||
- "%PYTHON%\\python.exe -m pip install -r requirements.txt"
|
||||
- "%PYTHON%\\python.exe -m pip install -r requirements-dev.txt"
|
||||
# Check that we have the expected version and architecture for Python
|
||||
- "python --version"
|
||||
# We need wheel installed to build wheels
|
||||
- "pip install -U codecov pytest-cov"
|
||||
- "pip install -U wheel"
|
||||
- "pip install -r requirements.txt"
|
||||
- "pip install -r requirements-dev.txt"
|
||||
|
||||
build: off
|
||||
|
||||
cache: C:\Users\appveyor\pip\wheels
|
||||
|
||||
test_script:
|
||||
- "%python%\\Scripts\\nosetests -v --with-flaky --no-flaky-report tests"
|
||||
- "pytest -m \"not nocoverage\" --cov --cov-report xml:coverage.xml"
|
||||
|
||||
after_test:
|
||||
# This step builds your wheels.
|
||||
- "%PYTHON%\\python.exe setup.py bdist_wheel"
|
||||
- "codecov -f coverage.xml -F Appveyor"
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
comment:
|
||||
layout: "diff, files"
|
||||
behavior: default
|
||||
require_changes: false
|
||||
+2
-2
@@ -58,9 +58,9 @@ author = u'Leandro Toledo'
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '7.0' # telegram.__version__[:3]
|
||||
version = '9.0' # telegram.__version__[:3]
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '7.0.1' # telegram.__version__
|
||||
release = '9.0.0' # telegram.__version__
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
||||
@@ -12,6 +12,10 @@ objects in the package reflect the types as defined by the `telegram bot api <ht
|
||||
.. toctree::
|
||||
telegram
|
||||
|
||||
Changelog
|
||||
---------
|
||||
|
||||
.. include:: ..\\..\\CHANGES.rst
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
telegram.contrib.Botan
|
||||
======================
|
||||
|
||||
.. autoclass:: telegram.contrib.Botan
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -1,18 +0,0 @@
|
||||
telegram.contrib package
|
||||
========================
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
.. toctree::
|
||||
|
||||
telegram.contrib.botan
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. automodule:: telegram.contrib
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
:noindex:
|
||||
@@ -0,0 +1,6 @@
|
||||
telegram.ext.Job
|
||||
=====================
|
||||
|
||||
.. autoclass:: telegram.ext.Job
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -6,6 +6,7 @@ telegram.ext package
|
||||
telegram.ext.updater
|
||||
telegram.ext.dispatcher
|
||||
telegram.ext.filters
|
||||
telegram.ext.job
|
||||
telegram.ext.jobqueue
|
||||
telegram.ext.messagequeue
|
||||
telegram.ext.delayqueue
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
telegram.InputMedia
|
||||
===================
|
||||
|
||||
.. autoclass:: telegram.InputMedia
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
telegram.InputMediaPhoto
|
||||
========================
|
||||
|
||||
.. autoclass:: telegram.InputMediaPhoto
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,6 @@
|
||||
telegram.InputMediaVideo
|
||||
========================
|
||||
|
||||
.. autoclass:: telegram.InputMediaVideo
|
||||
:members:
|
||||
:show-inheritance:
|
||||
@@ -3,7 +3,7 @@ telegram package
|
||||
|
||||
.. toctree::
|
||||
|
||||
telegram.contrib
|
||||
telegram.utils.helpers
|
||||
telegram.ext
|
||||
telegram.audio
|
||||
telegram.bot
|
||||
@@ -21,6 +21,9 @@ telegram package
|
||||
telegram.inlinekeyboardbutton
|
||||
telegram.inlinekeyboardmarkup
|
||||
telegram.inputfile
|
||||
telegram.inputmedia
|
||||
telegram.inputmediaphoto
|
||||
telegram.inputmediavideo
|
||||
telegram.keyboardbutton
|
||||
telegram.location
|
||||
telegram.message
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
telegram.utils.helpers Module
|
||||
=============================
|
||||
|
||||
.. automodule:: telegram.utils.helpers
|
||||
:members:
|
||||
:show-inheritance:
|
||||
+4
-1
@@ -1,6 +1,6 @@
|
||||
# Examples
|
||||
|
||||
The examples in this folder are small bots meant to show you how a bot that is written with `python-telegram-bot` looks like. Some bots focus on one specific aspect of the Telegram Bot API while others focus on one of the mechanics of this library. Except for the `echobot.py` example, they all use the high-level framework this library provides with the `telegram.ext` submodule.
|
||||
The examples in this folder are small bots meant to show you how a bot that is written with `python-telegram-bot` looks like. Some bots focus on one specific aspect of the Telegram Bot API while others focus on one of the mechanics of this library. Except for the [`echobot.py`](#pure-api) example, they all use the high-level framework this library provides with the [`telegram.ext`](https://python-telegram-bot.readthedocs.io/en/latest/telegram.ext.html) submodule.
|
||||
|
||||
All examples are licensed under the [CC0 License](https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/LICENSE.txt) and are therefore fully dedicated to the public domain. You can use them as the base for your own bots without worrying about copyrights.
|
||||
|
||||
@@ -22,5 +22,8 @@ This example sheds some light on inline keyboards, callback queries and message
|
||||
### [`inlinebot.py`](https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/inlinebot.py)
|
||||
A basic example of an [inline bot](https://core.telegram.org/bots/inline). Don't forget to enable inline mode with [@BotFather](https://telegram.me/BotFather).
|
||||
|
||||
### [`paymentbot.py`](https://github.com/python-telegram-bot/python-telegram-bot/blob/examples/inlinebot.py)
|
||||
A basic example of a bot that can accept payments. Don't forget to enable and configure payments with [@BotFather](https://telegram.me/BotFather).
|
||||
|
||||
## Pure API
|
||||
The [`echobot.py`](https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/echobot.py) example uses only the pure, "bare-metal" API wrapper.
|
||||
|
||||
@@ -46,7 +46,7 @@ def start(bot, update):
|
||||
|
||||
def gender(bot, update):
|
||||
user = update.message.from_user
|
||||
logger.info("Gender of %s: %s" % (user.first_name, update.message.text))
|
||||
logger.info("Gender of %s: %s", user.first_name, update.message.text)
|
||||
update.message.reply_text('I see! Please send me a photo of yourself, '
|
||||
'so I know what you look like, or send /skip if you don\'t want to.',
|
||||
reply_markup=ReplyKeyboardRemove())
|
||||
@@ -58,7 +58,7 @@ def photo(bot, update):
|
||||
user = update.message.from_user
|
||||
photo_file = bot.get_file(update.message.photo[-1].file_id)
|
||||
photo_file.download('user_photo.jpg')
|
||||
logger.info("Photo of %s: %s" % (user.first_name, 'user_photo.jpg'))
|
||||
logger.info("Photo of %s: %s", user.first_name, 'user_photo.jpg')
|
||||
update.message.reply_text('Gorgeous! Now, send me your location please, '
|
||||
'or send /skip if you don\'t want to.')
|
||||
|
||||
@@ -67,7 +67,7 @@ def photo(bot, update):
|
||||
|
||||
def skip_photo(bot, update):
|
||||
user = update.message.from_user
|
||||
logger.info("User %s did not send a photo." % user.first_name)
|
||||
logger.info("User %s did not send a photo.", user.first_name)
|
||||
update.message.reply_text('I bet you look great! Now, send me your location please, '
|
||||
'or send /skip.')
|
||||
|
||||
@@ -77,8 +77,8 @@ def skip_photo(bot, update):
|
||||
def location(bot, update):
|
||||
user = update.message.from_user
|
||||
user_location = update.message.location
|
||||
logger.info("Location of %s: %f / %f"
|
||||
% (user.first_name, user_location.latitude, user_location.longitude))
|
||||
logger.info("Location of %s: %f / %f", user.first_name, user_location.latitude,
|
||||
user_location.longitude)
|
||||
update.message.reply_text('Maybe I can visit you sometime! '
|
||||
'At last, tell me something about yourself.')
|
||||
|
||||
@@ -87,7 +87,7 @@ def location(bot, update):
|
||||
|
||||
def skip_location(bot, update):
|
||||
user = update.message.from_user
|
||||
logger.info("User %s did not send a location." % user.first_name)
|
||||
logger.info("User %s did not send a location.", user.first_name)
|
||||
update.message.reply_text('You seem a bit paranoid! '
|
||||
'At last, tell me something about yourself.')
|
||||
|
||||
@@ -96,7 +96,7 @@ def skip_location(bot, update):
|
||||
|
||||
def bio(bot, update):
|
||||
user = update.message.from_user
|
||||
logger.info("Bio of %s: %s" % (user.first_name, update.message.text))
|
||||
logger.info("Bio of %s: %s", user.first_name, update.message.text)
|
||||
update.message.reply_text('Thank you! I hope we can talk again some day.')
|
||||
|
||||
return ConversationHandler.END
|
||||
@@ -104,7 +104,7 @@ def bio(bot, update):
|
||||
|
||||
def cancel(bot, update):
|
||||
user = update.message.from_user
|
||||
logger.info("User %s canceled the conversation." % user.first_name)
|
||||
logger.info("User %s canceled the conversation.", user.first_name)
|
||||
update.message.reply_text('Bye! I hope we can talk again some day.',
|
||||
reply_markup=ReplyKeyboardRemove())
|
||||
|
||||
@@ -112,7 +112,8 @@ def cancel(bot, update):
|
||||
|
||||
|
||||
def error(bot, update, error):
|
||||
logger.warn('Update "%s" caused error "%s"' % (update, error))
|
||||
"""Log Errors caused by Updates."""
|
||||
logger.warning('Update "%s" caused error "%s"', update, error)
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
@@ -41,7 +41,7 @@ def facts_to_str(user_data):
|
||||
facts = list()
|
||||
|
||||
for key, value in user_data.items():
|
||||
facts.append('%s - %s' % (key, value))
|
||||
facts.append('{} - {}'.format(key, value))
|
||||
|
||||
return "\n".join(facts).join(['\n', '\n'])
|
||||
|
||||
@@ -58,7 +58,8 @@ def start(bot, update):
|
||||
def regular_choice(bot, update, user_data):
|
||||
text = update.message.text
|
||||
user_data['choice'] = text
|
||||
update.message.reply_text('Your %s? Yes, I would love to hear about that!' % text.lower())
|
||||
update.message.reply_text(
|
||||
'Your {}? Yes, I would love to hear about that!'.format(text.lower()))
|
||||
|
||||
return TYPING_REPLY
|
||||
|
||||
@@ -77,10 +78,9 @@ def received_information(bot, update, user_data):
|
||||
del user_data['choice']
|
||||
|
||||
update.message.reply_text("Neat! Just so you know, this is what you already told me:"
|
||||
"%s"
|
||||
"You can tell me more, or change your opinion on something."
|
||||
% facts_to_str(user_data),
|
||||
reply_markup=markup)
|
||||
"{}"
|
||||
"You can tell me more, or change your opinion on something.".format(
|
||||
facts_to_str(user_data)), reply_markup=markup)
|
||||
|
||||
return CHOOSING
|
||||
|
||||
@@ -90,15 +90,16 @@ def done(bot, update, user_data):
|
||||
del user_data['choice']
|
||||
|
||||
update.message.reply_text("I learned these facts about you:"
|
||||
"%s"
|
||||
"Until next time!" % facts_to_str(user_data))
|
||||
"{}"
|
||||
"Until next time!".format(facts_to_str(user_data)))
|
||||
|
||||
user_data.clear()
|
||||
return ConversationHandler.END
|
||||
|
||||
|
||||
def error(bot, update, error):
|
||||
logger.warn('Update "%s" caused error "%s"' % (update, error))
|
||||
"""Log Errors caused by Updates."""
|
||||
logger.warning('Update "%s" caused error "%s"', update, error)
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
+9
-4
@@ -1,9 +1,11 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Simple Bot to reply to Telegram messages. This is built on the API wrapper, see
|
||||
# echobot2.py to see the same example built on the telegram.ext bot framework.
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
"""Simple Bot to reply to Telegram messages.
|
||||
|
||||
This is built on the API wrapper, see echobot2.py to see the same example built
|
||||
on the telegram.ext bot framework.
|
||||
This program is dedicated to the public domain under the CC0 license.
|
||||
"""
|
||||
import logging
|
||||
import telegram
|
||||
from telegram.error import NetworkError, Unauthorized
|
||||
@@ -12,7 +14,9 @@ from time import sleep
|
||||
|
||||
update_id = None
|
||||
|
||||
|
||||
def main():
|
||||
"""Run the bot."""
|
||||
global update_id
|
||||
# Telegram Bot Authorization Token
|
||||
bot = telegram.Bot('TOKEN')
|
||||
@@ -37,6 +41,7 @@ def main():
|
||||
|
||||
|
||||
def echo(bot):
|
||||
"""Echo the message the user sent."""
|
||||
global update_id
|
||||
# Request updates after the last update_id
|
||||
for update in bot.get_updates(offset=update_id, timeout=10):
|
||||
|
||||
+11
-5
@@ -1,9 +1,10 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Simple Bot to reply to Telegram messages
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
"""
|
||||
|
||||
"""Simple Bot to reply to Telegram messages.
|
||||
|
||||
This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
This Bot uses the Updater class to handle the bot.
|
||||
|
||||
First, a few handler functions are defined. Then, those functions are passed to
|
||||
@@ -29,22 +30,27 @@ logger = logging.getLogger(__name__)
|
||||
# Define a few command handlers. These usually take the two arguments bot and
|
||||
# update. Error handlers also receive the raised TelegramError object in error.
|
||||
def start(bot, update):
|
||||
"""Send a message when the command /start is issued."""
|
||||
update.message.reply_text('Hi!')
|
||||
|
||||
|
||||
def help(bot, update):
|
||||
"""Send a message when the command /help is issued."""
|
||||
update.message.reply_text('Help!')
|
||||
|
||||
|
||||
def echo(bot, update):
|
||||
"""Echo the user message."""
|
||||
update.message.reply_text(update.message.text)
|
||||
|
||||
|
||||
def error(bot, update, error):
|
||||
logger.warn('Update "%s" caused error "%s"' % (update, error))
|
||||
"""Log Errors caused by Updates."""
|
||||
logger.warning('Update "%s" caused error "%s"', update, error)
|
||||
|
||||
|
||||
def main():
|
||||
"""Start the bot."""
|
||||
# Create the EventHandler and pass it your bot's token.
|
||||
updater = Updater("TOKEN")
|
||||
|
||||
|
||||
+30
-29
@@ -1,9 +1,10 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Simple Bot to reply to Telegram messages
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
"""
|
||||
|
||||
"""Simple Bot to reply to Telegram messages.
|
||||
|
||||
This program is dedicated to the public domain under the CC0 license.
|
||||
|
||||
This Bot uses the Updater class to handle the bot.
|
||||
|
||||
First, a few handler functions are defined. Then, those functions are passed to
|
||||
@@ -19,6 +20,8 @@ from uuid import uuid4
|
||||
|
||||
import re
|
||||
|
||||
from telegram.utils.helpers import escape_markdown
|
||||
|
||||
from telegram import InlineQueryResultArticle, ParseMode, \
|
||||
InputTextMessageContent
|
||||
from telegram.ext import Updater, InlineQueryHandler, CommandHandler
|
||||
@@ -34,45 +37,43 @@ logger = logging.getLogger(__name__)
|
||||
# Define a few command handlers. These usually take the two arguments bot and
|
||||
# update. Error handlers also receive the raised TelegramError object in error.
|
||||
def start(bot, update):
|
||||
"""Send a message when the command /start is issued."""
|
||||
update.message.reply_text('Hi!')
|
||||
|
||||
|
||||
def help(bot, update):
|
||||
"""Send a message when the command /help is issued."""
|
||||
update.message.reply_text('Help!')
|
||||
|
||||
|
||||
def escape_markdown(text):
|
||||
"""Helper function to escape telegram markup symbols"""
|
||||
escape_chars = '\*_`\['
|
||||
return re.sub(r'([%s])' % escape_chars, r'\\\1', text)
|
||||
|
||||
|
||||
def inlinequery(bot, update):
|
||||
"""Handle the inline query."""
|
||||
query = update.inline_query.query
|
||||
results = list()
|
||||
|
||||
results.append(InlineQueryResultArticle(id=uuid4(),
|
||||
title="Caps",
|
||||
input_message_content=InputTextMessageContent(
|
||||
query.upper())))
|
||||
|
||||
results.append(InlineQueryResultArticle(id=uuid4(),
|
||||
title="Bold",
|
||||
input_message_content=InputTextMessageContent(
|
||||
"*%s*" % escape_markdown(query),
|
||||
parse_mode=ParseMode.MARKDOWN)))
|
||||
|
||||
results.append(InlineQueryResultArticle(id=uuid4(),
|
||||
title="Italic",
|
||||
input_message_content=InputTextMessageContent(
|
||||
"_%s_" % escape_markdown(query),
|
||||
parse_mode=ParseMode.MARKDOWN)))
|
||||
results = [
|
||||
InlineQueryResultArticle(
|
||||
id=uuid4(),
|
||||
title="Caps",
|
||||
input_message_content=InputTextMessageContent(
|
||||
query.upper())),
|
||||
InlineQueryResultArticle(
|
||||
id=uuid4(),
|
||||
title="Bold",
|
||||
input_message_content=InputTextMessageContent(
|
||||
"*{}*".format(escape_markdown(query)),
|
||||
parse_mode=ParseMode.MARKDOWN)),
|
||||
InlineQueryResultArticle(
|
||||
id=uuid4(),
|
||||
title="Italic",
|
||||
input_message_content=InputTextMessageContent(
|
||||
"_{}_".format(escape_markdown(query)),
|
||||
parse_mode=ParseMode.MARKDOWN))]
|
||||
|
||||
update.inline_query.answer(results)
|
||||
|
||||
|
||||
def error(bot, update, error):
|
||||
logger.warning('Update "%s" caused error "%s"' % (update, error))
|
||||
"""Log Errors caused by Updates."""
|
||||
logger.warning('Update "%s" caused error "%s"', update, error)
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
+23
-16
@@ -1,15 +1,16 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Basic example for a bot that uses inline keyboards.
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
"""Basic example for a bot that uses inline keyboards.
|
||||
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
"""
|
||||
import logging
|
||||
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
|
||||
from telegram.ext import Updater, CommandHandler, CallbackQueryHandler
|
||||
|
||||
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||
level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def start(bot, update):
|
||||
@@ -26,7 +27,7 @@ def start(bot, update):
|
||||
def button(bot, update):
|
||||
query = update.callback_query
|
||||
|
||||
bot.edit_message_text(text="Selected option: %s" % query.data,
|
||||
bot.edit_message_text(text="Selected option: {}".format(query.data),
|
||||
chat_id=query.message.chat_id,
|
||||
message_id=query.message.message_id)
|
||||
|
||||
@@ -36,20 +37,26 @@ def help(bot, update):
|
||||
|
||||
|
||||
def error(bot, update, error):
|
||||
logging.warning('Update "%s" caused error "%s"' % (update, error))
|
||||
"""Log Errors caused by Updates."""
|
||||
logger.warning('Update "%s" caused error "%s"', update, error)
|
||||
|
||||
|
||||
# Create the Updater and pass it your bot's token.
|
||||
updater = Updater("TOKEN")
|
||||
def main():
|
||||
# Create the Updater and pass it your bot's token.
|
||||
updater = Updater("TOKEN")
|
||||
|
||||
updater.dispatcher.add_handler(CommandHandler('start', start))
|
||||
updater.dispatcher.add_handler(CallbackQueryHandler(button))
|
||||
updater.dispatcher.add_handler(CommandHandler('help', help))
|
||||
updater.dispatcher.add_error_handler(error)
|
||||
updater.dispatcher.add_handler(CommandHandler('start', start))
|
||||
updater.dispatcher.add_handler(CallbackQueryHandler(button))
|
||||
updater.dispatcher.add_handler(CommandHandler('help', help))
|
||||
updater.dispatcher.add_error_handler(error)
|
||||
|
||||
# Start the Bot
|
||||
updater.start_polling()
|
||||
# Start the Bot
|
||||
updater.start_polling()
|
||||
|
||||
# Run the bot until the user presses Ctrl-C or the process receives SIGINT,
|
||||
# SIGTERM or SIGABRT
|
||||
updater.idle()
|
||||
# Run the bot until the user presses Ctrl-C or the process receives SIGINT,
|
||||
# SIGTERM or SIGABRT
|
||||
updater.idle()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
+10
-6
@@ -1,8 +1,10 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Basic example for a bot that can receive payment from user.
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
"""Basic example for a bot that can receive payment from user.
|
||||
|
||||
This program is dedicated to the public domain under the CC0 license.
|
||||
"""
|
||||
|
||||
from telegram import (LabeledPrice, ShippingOption)
|
||||
from telegram.ext import (Updater, CommandHandler, MessageHandler,
|
||||
@@ -10,13 +12,15 @@ from telegram.ext import (Updater, CommandHandler, MessageHandler,
|
||||
import logging
|
||||
|
||||
# Enable logging
|
||||
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
|
||||
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||
level=logging.INFO)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def error(bot, update, error):
|
||||
logger.warn('Update "%s" caused error "%s"' % (update, error))
|
||||
"""Log Errors caused by Updates."""
|
||||
logger.warning('Update "%s" caused error "%s"', update, error)
|
||||
|
||||
|
||||
def start_callback(bot, update):
|
||||
@@ -31,7 +35,7 @@ def start_with_shipping_callback(bot, update):
|
||||
description = "Payment Example using python-telegram-bot"
|
||||
# select a payload just for you to recognize its the donation from your bot
|
||||
payload = "Custom-Payload"
|
||||
# get your provider_token at @botfather, see https://core.telegram.org/bots/payments#getting-a-token
|
||||
# In order to get a provider_token see https://core.telegram.org/bots/payments#getting-a-token
|
||||
provider_token = "PROVIDER_TOKEN"
|
||||
start_parameter = "test-payment"
|
||||
currency = "USD"
|
||||
@@ -55,7 +59,7 @@ def start_without_shipping_callback(bot, update):
|
||||
description = "Payment Example using python-telegram-bot"
|
||||
# select a payload just for you to recognize its the donation from your bot
|
||||
payload = "Custom-Payload"
|
||||
# get your provider_token at @botfather, see https://core.telegram.org/bots/payments#getting-a-token
|
||||
# In order to get a provider_token see https://core.telegram.org/bots/payments#getting-a-token
|
||||
provider_token = "PROVIDER_TOKEN"
|
||||
start_parameter = "test-payment"
|
||||
currency = "USD"
|
||||
|
||||
+14
-11
@@ -1,9 +1,11 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Simple Bot to send timed Telegram messages
|
||||
|
||||
|
||||
"""Simple Bot to send timed Telegram messages.
|
||||
|
||||
# This program is dedicated to the public domain under the CC0 license.
|
||||
"""
|
||||
|
||||
This Bot uses the Updater class to handle the bot and the JobQueue to send
|
||||
timed messages.
|
||||
|
||||
@@ -17,7 +19,7 @@ Press Ctrl-C on the command line or send a signal to the process to stop the
|
||||
bot.
|
||||
"""
|
||||
|
||||
from telegram.ext import Updater, CommandHandler, Job
|
||||
from telegram.ext import Updater, CommandHandler
|
||||
import logging
|
||||
|
||||
# Enable logging
|
||||
@@ -34,12 +36,12 @@ def start(bot, update):
|
||||
|
||||
|
||||
def alarm(bot, job):
|
||||
"""Function to send the alarm message"""
|
||||
"""Send the alarm message."""
|
||||
bot.send_message(job.context, text='Beep!')
|
||||
|
||||
|
||||
def set(bot, update, args, job_queue, chat_data):
|
||||
"""Adds a job to the queue"""
|
||||
def set_timer(bot, update, args, job_queue, chat_data):
|
||||
"""Add a job to the queue."""
|
||||
chat_id = update.message.chat_id
|
||||
try:
|
||||
# args[0] should contain the time for the timer in seconds
|
||||
@@ -59,8 +61,7 @@ def set(bot, update, args, job_queue, chat_data):
|
||||
|
||||
|
||||
def unset(bot, update, chat_data):
|
||||
"""Removes the job if the user changed their mind"""
|
||||
|
||||
"""Remove the job if the user changed their mind."""
|
||||
if 'job' not in chat_data:
|
||||
update.message.reply_text('You have no active timer')
|
||||
return
|
||||
@@ -73,10 +74,12 @@ def unset(bot, update, chat_data):
|
||||
|
||||
|
||||
def error(bot, update, error):
|
||||
logger.warning('Update "%s" caused error "%s"' % (update, error))
|
||||
"""Log Errors caused by Updates."""
|
||||
logger.warning('Update "%s" caused error "%s"', update, error)
|
||||
|
||||
|
||||
def main():
|
||||
"""Run bot."""
|
||||
updater = Updater("TOKEN")
|
||||
|
||||
# Get the dispatcher to register handlers
|
||||
@@ -85,7 +88,7 @@ def main():
|
||||
# on different commands - answer in Telegram
|
||||
dp.add_handler(CommandHandler("start", start))
|
||||
dp.add_handler(CommandHandler("help", start))
|
||||
dp.add_handler(CommandHandler("set", set,
|
||||
dp.add_handler(CommandHandler("set", set_timer,
|
||||
pass_args=True,
|
||||
pass_job_queue=True,
|
||||
pass_chat_data=True))
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
flake8
|
||||
nose
|
||||
pep257
|
||||
pylint
|
||||
flaky
|
||||
yapf
|
||||
pre-commit
|
||||
pre-commit-hooks
|
||||
beautifulsoup4
|
||||
rednose
|
||||
pytest
|
||||
pytest-timeout
|
||||
|
||||
@@ -17,3 +17,21 @@ ignore = W503
|
||||
based_on_style = google
|
||||
split_before_logical_operator = True
|
||||
column_limit = 99
|
||||
|
||||
[tool:pytest]
|
||||
testpaths = tests
|
||||
addopts = --no-success-flaky-report -rsxX
|
||||
filterwarnings =
|
||||
error
|
||||
ignore::DeprecationWarning
|
||||
|
||||
[coverage:run]
|
||||
branch = True
|
||||
source = telegram
|
||||
parallel = True
|
||||
concurrency = thread, multiprocessing
|
||||
omit =
|
||||
tests/
|
||||
telegram/__main__.py
|
||||
telegram/vendor/*
|
||||
|
||||
|
||||
@@ -53,7 +53,6 @@ with codecs.open('README.rst', 'r', 'utf-8') as fd:
|
||||
'Programming Language :: Python :: 2',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.3',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
'Programming Language :: Python :: 3.6'
|
||||
|
||||
@@ -96,6 +96,9 @@ from .constants import (MAX_MESSAGE_LENGTH, MAX_CAPTION_LENGTH, SUPPORTED_WEBHOO
|
||||
MAX_FILESIZE_DOWNLOAD, MAX_FILESIZE_UPLOAD,
|
||||
MAX_MESSAGES_PER_SECOND_PER_CHAT, MAX_MESSAGES_PER_SECOND,
|
||||
MAX_MESSAGES_PER_MINUTE_PER_GROUP)
|
||||
from .files.inputmedia import InputMedia
|
||||
from .files.inputmediavideo import InputMediaVideo
|
||||
from .files.inputmediaphoto import InputMediaPhoto
|
||||
from .version import __version__ # flake8: noqa
|
||||
|
||||
__author__ = 'devs@python-telegram-bot.org'
|
||||
@@ -121,5 +124,6 @@ __all__ = [
|
||||
'MAX_MESSAGES_PER_SECOND', 'MAX_MESSAGES_PER_MINUTE_PER_GROUP', 'WebhookInfo', 'Animation',
|
||||
'Game', 'GameHighScore', 'VideoNote', 'LabeledPrice', 'SuccessfulPayment', 'ShippingOption',
|
||||
'ShippingAddress', 'PreCheckoutQuery', 'OrderInfo', 'Invoice', 'ShippingQuery', 'ChatPhoto',
|
||||
'StickerSet', 'MaskPosition', 'CallbackGame'
|
||||
'StickerSet', 'MaskPosition', 'CallbackGame', 'InputMedia', 'InputMediaPhoto',
|
||||
'InputMediaVideo'
|
||||
]
|
||||
|
||||
+2
-3
@@ -27,9 +27,7 @@ from abc import ABCMeta
|
||||
|
||||
|
||||
class TelegramObject(object):
|
||||
"""
|
||||
Base class for most telegram objects.
|
||||
"""
|
||||
"""Base class for most telegram objects."""
|
||||
|
||||
__metaclass__ = ABCMeta
|
||||
_id_attrs = ()
|
||||
@@ -53,6 +51,7 @@ class TelegramObject(object):
|
||||
"""
|
||||
Returns:
|
||||
:obj:`str`
|
||||
|
||||
"""
|
||||
|
||||
return json.dumps(self.to_dict())
|
||||
|
||||
+363
-167
File diff suppressed because it is too large
Load Diff
+12
-13
@@ -31,7 +31,7 @@ class CallbackQuery(TelegramObject):
|
||||
|
||||
Note:
|
||||
* In Python `from` is a reserved word, use `from_user` instead.
|
||||
Exactly one of the fields :attr:`data` or :attr:`game_short_name` will be present.
|
||||
* Exactly one of the fields :attr:`data` or :attr:`game_short_name` will be present.
|
||||
|
||||
Attributes:
|
||||
id (:obj:`str`): Unique identifier for this query.
|
||||
@@ -66,6 +66,7 @@ class CallbackQuery(TelegramObject):
|
||||
until you call :attr:`answer`. It is, therefore, necessary to react
|
||||
by calling :attr:`telegram.Bot.answer_callback_query` even if no notification to the user
|
||||
is needed (e.g., without specifying any of the optional parameters).
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -90,6 +91,8 @@ class CallbackQuery(TelegramObject):
|
||||
|
||||
self.bot = bot
|
||||
|
||||
self._id_attrs = (self.id,)
|
||||
|
||||
@classmethod
|
||||
def de_json(cls, data, bot):
|
||||
if not data:
|
||||
@@ -110,20 +113,18 @@ class CallbackQuery(TelegramObject):
|
||||
return data
|
||||
|
||||
def answer(self, *args, **kwargs):
|
||||
"""
|
||||
Shortcut for::
|
||||
"""Shortcut for::
|
||||
|
||||
bot.answer_callback_query(update.callback_query.id, *args, **kwargs)
|
||||
|
||||
Returns:
|
||||
:obj:`bool`: On success, ``True`` is returned.
|
||||
"""
|
||||
|
||||
"""
|
||||
return self.bot.answerCallbackQuery(self.id, *args, **kwargs)
|
||||
|
||||
def edit_message_text(self, *args, **kwargs):
|
||||
"""
|
||||
Shortcut for either::
|
||||
"""Shortcut for either::
|
||||
|
||||
bot.edit_message_text(chat_id=update.callback_query.message.chat_id,
|
||||
message_id=update.callback_query.message.message_id,
|
||||
@@ -137,8 +138,8 @@ class CallbackQuery(TelegramObject):
|
||||
Returns:
|
||||
:class:`telegram.Message`: On success, if edited message is sent by the bot, the
|
||||
edited Message is returned, otherwise ``True`` is returned.
|
||||
"""
|
||||
|
||||
"""
|
||||
if self.inline_message_id:
|
||||
return self.bot.edit_message_text(
|
||||
inline_message_id=self.inline_message_id, *args, **kwargs)
|
||||
@@ -147,8 +148,7 @@ class CallbackQuery(TelegramObject):
|
||||
chat_id=self.message.chat_id, message_id=self.message.message_id, *args, **kwargs)
|
||||
|
||||
def edit_message_caption(self, *args, **kwargs):
|
||||
"""
|
||||
Shortcut for either::
|
||||
"""Shortcut for either::
|
||||
|
||||
bot.edit_message_caption(chat_id=update.callback_query.message.chat_id,
|
||||
message_id=update.callback_query.message.message_id,
|
||||
@@ -162,8 +162,8 @@ class CallbackQuery(TelegramObject):
|
||||
Returns:
|
||||
:class:`telegram.Message`: On success, if edited message is sent by the bot, the
|
||||
edited Message is returned, otherwise ``True`` is returned.
|
||||
"""
|
||||
|
||||
"""
|
||||
if self.inline_message_id:
|
||||
return self.bot.edit_message_caption(
|
||||
inline_message_id=self.inline_message_id, *args, **kwargs)
|
||||
@@ -172,8 +172,7 @@ class CallbackQuery(TelegramObject):
|
||||
chat_id=self.message.chat_id, message_id=self.message.message_id, *args, **kwargs)
|
||||
|
||||
def edit_message_reply_markup(self, *args, **kwargs):
|
||||
"""
|
||||
Shortcut for either::
|
||||
"""Shortcut for either::
|
||||
|
||||
bot.edit_message_replyMarkup(chat_id=update.callback_query.message.chat_id,
|
||||
message_id=update.callback_query.message.message_id,
|
||||
@@ -187,8 +186,8 @@ class CallbackQuery(TelegramObject):
|
||||
Returns:
|
||||
:class:`telegram.Message`: On success, if edited message is sent by the bot, the
|
||||
edited Message is returned, otherwise ``True`` is returned.
|
||||
"""
|
||||
|
||||
"""
|
||||
if self.inline_message_id:
|
||||
return self.bot.edit_message_reply_markup(
|
||||
inline_message_id=self.inline_message_id, *args, **kwargs)
|
||||
|
||||
+36
-23
@@ -23,8 +23,7 @@ from telegram import TelegramObject, ChatPhoto
|
||||
|
||||
|
||||
class Chat(TelegramObject):
|
||||
"""
|
||||
This object represents a chat.
|
||||
"""This object represents a chat.
|
||||
|
||||
Attributes:
|
||||
id (:obj:`int`): Unique identifier for this chat.
|
||||
@@ -37,6 +36,11 @@ class Chat(TelegramObject):
|
||||
photo (:class:`telegram.ChatPhoto`): Optional. Chat photo.
|
||||
description (:obj:`str`): Optional. Description, for supergroups and channel chats.
|
||||
invite_link (:obj:`str`): Optional. Chat invite link, for supergroups and channel chats.
|
||||
pinned_message (:class:`telegram.Message`): Optional. Pinned message, for supergroups.
|
||||
Returned only in get_chat.
|
||||
sticker_set_name (:obj:`str`): Optional. For supergroups, name of Group sticker set.
|
||||
can_set_sticker_set (:obj:`bool`): Optional. ``True``, if the bot can change group the
|
||||
sticker set.
|
||||
|
||||
Args:
|
||||
id (:obj:`int`): Unique identifier for this chat. This number may be greater than 32 bits
|
||||
@@ -57,7 +61,13 @@ class Chat(TelegramObject):
|
||||
Returned only in get_chat.
|
||||
invite_link (:obj:`str`, optional): Chat invite link, for supergroups and channel chats.
|
||||
Returned only in get_chat.
|
||||
pinned_message (:class:`telegram.Message`, optional): Pinned message, for supergroups.
|
||||
Returned only in get_chat.
|
||||
bot (:class:`telegram.Bot`, optional): The Bot to use for instance methods.
|
||||
sticker_set_name (:obj:`str`, optional): For supergroups, name of Group sticker set.
|
||||
Returned only in get_chat.
|
||||
can_set_sticker_set (:obj:`bool`, optional): ``True``, if the bot can change group the
|
||||
sticker set. Returned only in get_chat.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
@@ -83,6 +93,9 @@ class Chat(TelegramObject):
|
||||
photo=None,
|
||||
description=None,
|
||||
invite_link=None,
|
||||
pinned_message=None,
|
||||
sticker_set_name=None,
|
||||
can_set_sticker_set=None,
|
||||
**kwargs):
|
||||
# Required
|
||||
self.id = int(id)
|
||||
@@ -96,6 +109,9 @@ class Chat(TelegramObject):
|
||||
self.photo = photo
|
||||
self.description = description
|
||||
self.invite_link = invite_link
|
||||
self.pinned_message = pinned_message
|
||||
self.sticker_set_name = sticker_set_name
|
||||
self.can_set_sticker_set = can_set_sticker_set
|
||||
|
||||
self.bot = bot
|
||||
self._id_attrs = (self.id,)
|
||||
@@ -106,36 +122,36 @@ class Chat(TelegramObject):
|
||||
return None
|
||||
|
||||
data['photo'] = ChatPhoto.de_json(data.get('photo'), bot)
|
||||
from telegram import Message
|
||||
data['pinned_message'] = Message.de_json(data.get('pinned_message'), bot)
|
||||
|
||||
return cls(bot=bot, **data)
|
||||
|
||||
def send_action(self, *args, **kwargs):
|
||||
"""
|
||||
Shortcut for::
|
||||
"""Shortcut for::
|
||||
|
||||
bot.send_chat_action(update.message.chat.id, *args, **kwargs)
|
||||
|
||||
Returns:
|
||||
:obj:`bool`: If the action was sent successfully.
|
||||
|
||||
"""
|
||||
|
||||
return self.bot.send_chat_action(self.id, *args, **kwargs)
|
||||
|
||||
def leave(self, *args, **kwargs):
|
||||
"""
|
||||
Shortcut for::
|
||||
"""Shortcut for::
|
||||
|
||||
bot.leave_chat(update.message.chat.id, *args, **kwargs)
|
||||
|
||||
Returns:
|
||||
:obj:`bool` If the action was sent successfully.
|
||||
"""
|
||||
|
||||
"""
|
||||
return self.bot.leave_chat(self.id, *args, **kwargs)
|
||||
|
||||
def get_administrators(self, *args, **kwargs):
|
||||
"""
|
||||
Shortcut for::
|
||||
"""Shortcut for::
|
||||
|
||||
bot.get_chat_administrators(update.message.chat.id, *args, **kwargs)
|
||||
|
||||
@@ -144,39 +160,36 @@ class Chat(TelegramObject):
|
||||
:class:`telegram.ChatMember` objects that contains information about all
|
||||
chat administrators except other bots. If the chat is a group or a supergroup
|
||||
and no administrators were appointed, only the creator will be returned
|
||||
"""
|
||||
|
||||
"""
|
||||
return self.bot.get_chat_administrators(self.id, *args, **kwargs)
|
||||
|
||||
def get_members_count(self, *args, **kwargs):
|
||||
"""
|
||||
Shortcut for::
|
||||
"""Shortcut for::
|
||||
|
||||
bot.get_chat_members_count(update.message.chat.id, *args, **kwargs)
|
||||
|
||||
Returns:
|
||||
:obj:`int`
|
||||
"""
|
||||
|
||||
"""
|
||||
return self.bot.get_chat_members_count(self.id, *args, **kwargs)
|
||||
|
||||
def get_member(self, *args, **kwargs):
|
||||
"""
|
||||
Shortcut for::
|
||||
"""Shortcut for::
|
||||
|
||||
bot.get_chat_member(update.message.chat.id, *args, **kwargs)
|
||||
|
||||
Returns:
|
||||
:class:`telegram.ChatMember`
|
||||
"""
|
||||
|
||||
"""
|
||||
return self.bot.get_chat_member(self.id, *args, **kwargs)
|
||||
|
||||
def kick_member(self, *args, **kwargs):
|
||||
"""
|
||||
Shortcut for::
|
||||
"""Shortcut for::
|
||||
|
||||
bot.kick_chat_member(update.message.chat.id, *args, **kwargs)
|
||||
bot.kick_chat_member(update.message.chat.id, *args, **kwargs)
|
||||
|
||||
Returns:
|
||||
:obj:`bool`: If the action was sent succesfully.
|
||||
@@ -185,17 +198,17 @@ class Chat(TelegramObject):
|
||||
This method will only work if the `All Members Are Admins` setting is off in the
|
||||
target group. Otherwise members may only be removed by the group's creator or by the
|
||||
member that added them.
|
||||
"""
|
||||
|
||||
"""
|
||||
return self.bot.kick_chat_member(self.id, *args, **kwargs)
|
||||
|
||||
def unban_member(self, *args, **kwargs):
|
||||
"""
|
||||
Shortcut for::
|
||||
"""Shortcut for::
|
||||
|
||||
bot.unban_chat_member(update.message.chat.id, *args, **kwargs)
|
||||
bot.unban_chat_member(update.message.chat.id, *args, **kwargs)
|
||||
|
||||
Returns:
|
||||
:obj:`bool`: If the action was sent successfully.
|
||||
|
||||
"""
|
||||
return self.bot.unban_chat_member(self.id, *args, **kwargs)
|
||||
|
||||
@@ -21,9 +21,7 @@
|
||||
|
||||
|
||||
class ChatAction(object):
|
||||
"""
|
||||
Helper class to provide constants for different chatactions
|
||||
"""
|
||||
"""Helper class to provide constants for different chatactions."""
|
||||
|
||||
FIND_LOCATION = 'find_location'
|
||||
""":obj:`str`: 'find_location'"""
|
||||
|
||||
@@ -23,8 +23,7 @@ from telegram.utils.helpers import to_timestamp, from_timestamp
|
||||
|
||||
|
||||
class ChatMember(TelegramObject):
|
||||
"""
|
||||
This object contains information about one member of the chat.
|
||||
"""This object contains information about one member of the chat.
|
||||
|
||||
Attributes:
|
||||
user (:class:`telegram.User`): Information about the user.
|
||||
@@ -59,7 +58,7 @@ class ChatMember(TelegramObject):
|
||||
Args:
|
||||
user (:class:`telegram.User`): Information about the user.
|
||||
status (:obj:`str`): The member's status in the chat. Can be 'creator', 'administrator',
|
||||
'member', 'left' or 'kicked'.
|
||||
'member', 'restricted', 'left' or 'kicked'.
|
||||
until_date (:class:`datetime.datetime`, optional): Restricted and kicked only. Date when
|
||||
restrictions will be lifted for this user.
|
||||
can_be_edited (:obj:`bool`, optional): Administrators only. True, if the bot is allowed to
|
||||
@@ -91,8 +90,8 @@ class ChatMember(TelegramObject):
|
||||
send animations, games, stickers and use inline bots, implies can_send_media_messages.
|
||||
can_add_web_page_previews (:obj:`bool`, optional): Restricted only. True, if user may add
|
||||
web page previews to his messages, implies can_send_media_messages.
|
||||
"""
|
||||
|
||||
"""
|
||||
ADMINISTRATOR = 'administrator'
|
||||
""":obj:`str`: 'administrator'"""
|
||||
CREATOR = 'creator'
|
||||
@@ -103,6 +102,8 @@ class ChatMember(TelegramObject):
|
||||
""":obj:`str`: 'left'"""
|
||||
MEMBER = 'member'
|
||||
""":obj:`str`: 'member'"""
|
||||
RESTRICTED = 'restricted'
|
||||
""":obj:`str`: 'restricted'"""
|
||||
|
||||
def __init__(self, user, status, until_date=None, can_be_edited=None,
|
||||
can_change_info=None, can_post_messages=None, can_edit_messages=None,
|
||||
|
||||
@@ -47,6 +47,7 @@ class ChosenInlineResult(TelegramObject):
|
||||
callback queries and can be used to edit the message.
|
||||
query (:obj:`str`): The query that was used to obtain the result.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
|
||||
@@ -14,8 +14,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/].
|
||||
"""
|
||||
Constants in the Telegram network.
|
||||
"""Constants in the Telegram network.
|
||||
|
||||
The following constants were extracted from the
|
||||
`Telegram Bots FAQ <https://core.telegram.org/bots/faq>`_.
|
||||
@@ -37,6 +36,7 @@ The following constant have been found by experimentation:
|
||||
Attributes:
|
||||
MAX_MESSAGE_ENTITIES (:obj:`int`): 100 (Beyond this cap telegram will simply ignore further
|
||||
formatting styles)
|
||||
|
||||
"""
|
||||
|
||||
MAX_MESSAGE_LENGTH = 4096
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
from .botan import Botan
|
||||
|
||||
__all__ = ['Botan']
|
||||
@@ -1,43 +0,0 @@
|
||||
import logging
|
||||
|
||||
from future.moves.urllib.parse import quote
|
||||
from future.moves.urllib.error import HTTPError, URLError
|
||||
from future.moves.urllib.request import urlopen, Request
|
||||
|
||||
logging.getLogger(__name__).addHandler(logging.NullHandler())
|
||||
|
||||
|
||||
class Botan(object):
|
||||
"""This class helps to send incoming events to your botan analytics account.
|
||||
See more: https://github.com/botanio/sdk#botan-sdk
|
||||
"""
|
||||
|
||||
token = ''
|
||||
url_template = 'https://api.botan.io/track?token={token}' \
|
||||
'&uid={uid}&name={name}&src=python-telegram-bot'
|
||||
|
||||
def __init__(self, token):
|
||||
self.token = token
|
||||
self.logger = logging.getLogger(__name__)
|
||||
|
||||
def track(self, message, event_name='event'):
|
||||
try:
|
||||
uid = message.chat_id
|
||||
except AttributeError:
|
||||
self.logger.warn('No chat_id in message')
|
||||
return False
|
||||
data = message.to_json()
|
||||
try:
|
||||
url = self.url_template.format(
|
||||
token=str(self.token), uid=str(uid), name=quote(event_name))
|
||||
request = Request(
|
||||
url, data=data.encode(), headers={'Content-Type': 'application/json'})
|
||||
urlopen(request)
|
||||
return True
|
||||
except HTTPError as error:
|
||||
self.logger.warn('Botan track error ' + str(error.code) + ':' + error.read().decode(
|
||||
'utf-8'))
|
||||
return False
|
||||
except URLError as error:
|
||||
self.logger.warn('Botan track error ' + str(error.reason))
|
||||
return False
|
||||
@@ -18,7 +18,7 @@
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""Extensions over the Telegram Bot API to facilitate bot making"""
|
||||
|
||||
from .dispatcher import Dispatcher
|
||||
from .dispatcher import Dispatcher, DispatcherHandlerStop, run_async
|
||||
from .jobqueue import JobQueue, Job
|
||||
from .updater import Updater
|
||||
from .callbackqueryhandler import CallbackQueryHandler
|
||||
@@ -42,4 +42,5 @@ __all__ = ('Dispatcher', 'JobQueue', 'Job', 'Updater', 'CallbackQueryHandler',
|
||||
'ChosenInlineResultHandler', 'CommandHandler', 'Handler', 'InlineQueryHandler',
|
||||
'MessageHandler', 'BaseFilter', 'Filters', 'RegexHandler', 'StringCommandHandler',
|
||||
'StringRegexHandler', 'TypeHandler', 'ConversationHandler',
|
||||
'PreCheckoutQueryHandler', 'ShippingQueryHandler', 'MessageQueue', 'DelayQueue')
|
||||
'PreCheckoutQueryHandler', 'ShippingQueryHandler', 'MessageQueue', 'DelayQueue',
|
||||
'DispatcherHandlerStop', 'run_async')
|
||||
|
||||
@@ -16,7 +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/].
|
||||
""" This module contains the CallbackQueryHandler class """
|
||||
"""This module contains the CallbackQueryHandler class."""
|
||||
|
||||
import re
|
||||
|
||||
@@ -27,8 +27,8 @@ from .handler import Handler
|
||||
|
||||
|
||||
class CallbackQueryHandler(Handler):
|
||||
"""
|
||||
Handler class to handle Telegram callback queries. Optionally based on a regex.
|
||||
"""Handler class to handle Telegram callback queries. Optionally based on a regex.
|
||||
|
||||
Read the documentation of the ``re`` module for more information.
|
||||
|
||||
Attributes:
|
||||
@@ -79,6 +79,7 @@ class CallbackQueryHandler(Handler):
|
||||
``user_data`` will be passed to the callback function. Default is ``False``.
|
||||
pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called
|
||||
``chat_data`` will be passed to the callback function. Default is ``False``.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -105,16 +106,15 @@ class CallbackQueryHandler(Handler):
|
||||
self.pass_groupdict = pass_groupdict
|
||||
|
||||
def check_update(self, update):
|
||||
"""
|
||||
Determines whether an update should be passed to this handlers :attr:`callback`.
|
||||
"""Determines whether an update should be passed to this handlers :attr:`callback`.
|
||||
|
||||
Args:
|
||||
update (:class:`telegram.Update`): Incoming telegram update.
|
||||
|
||||
Returns:
|
||||
:obj:`bool`
|
||||
"""
|
||||
|
||||
"""
|
||||
if isinstance(update, Update) and update.callback_query:
|
||||
if self.pattern:
|
||||
if update.callback_query.data:
|
||||
@@ -124,14 +124,13 @@ class CallbackQueryHandler(Handler):
|
||||
return True
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
"""
|
||||
Send the update to the :attr:`callback`.
|
||||
"""Send the update to the :attr:`callback`.
|
||||
|
||||
Args:
|
||||
update (:class:`telegram.Update`): Incoming telegram update.
|
||||
dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that originated the Update.
|
||||
"""
|
||||
|
||||
"""
|
||||
optional_args = self.collect_optional_args(dispatcher, update)
|
||||
if self.pattern:
|
||||
match = re.match(self.pattern, update.callback_query.data)
|
||||
|
||||
@@ -16,7 +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/].
|
||||
""" This module contains the ChosenInlineResultHandler class """
|
||||
"""This module contains the ChosenInlineResultHandler class."""
|
||||
|
||||
from .handler import Handler
|
||||
from telegram import Update
|
||||
@@ -24,8 +24,7 @@ from telegram.utils.deprecate import deprecate
|
||||
|
||||
|
||||
class ChosenInlineResultHandler(Handler):
|
||||
"""
|
||||
Handler class to handle Telegram updates that contain a chosen inline result.
|
||||
"""Handler class to handle Telegram updates that contain a chosen inline result.
|
||||
|
||||
Attributes:
|
||||
callback (:obj:`callable`): The callback function for this handler.
|
||||
@@ -60,6 +59,7 @@ class ChosenInlineResultHandler(Handler):
|
||||
``user_data`` will be passed to the callback function. Default is ``False``.
|
||||
pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called
|
||||
``chat_data`` will be passed to the callback function. Default is ``False``.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -76,27 +76,25 @@ class ChosenInlineResultHandler(Handler):
|
||||
pass_chat_data=pass_chat_data)
|
||||
|
||||
def check_update(self, update):
|
||||
"""
|
||||
Determines whether an update should be passed to this handlers :attr:`callback`.
|
||||
"""Determines whether an update should be passed to this handlers :attr:`callback`.
|
||||
|
||||
Args:
|
||||
update (:class:`telegram.Update`): Incoming telegram update.
|
||||
|
||||
Returns:
|
||||
:obj:`bool`
|
||||
"""
|
||||
|
||||
"""
|
||||
return isinstance(update, Update) and update.chosen_inline_result
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
"""
|
||||
Send the update to the :attr:`callback`.
|
||||
"""Send the update to the :attr:`callback`.
|
||||
|
||||
Args:
|
||||
update (:class:`telegram.Update`): Incoming telegram update.
|
||||
dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that originated the Update.
|
||||
"""
|
||||
|
||||
"""
|
||||
optional_args = self.collect_optional_args(dispatcher, update)
|
||||
|
||||
return self.callback(dispatcher.bot, update, **optional_args)
|
||||
|
||||
@@ -16,7 +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/].
|
||||
""" This module contains the CommandHandler class """
|
||||
"""This module contains the CommandHandler class."""
|
||||
import warnings
|
||||
|
||||
from future.utils import string_types
|
||||
@@ -26,10 +26,10 @@ from telegram import Update
|
||||
|
||||
|
||||
class CommandHandler(Handler):
|
||||
"""
|
||||
Handler class to handle Telegram commands. Commands are Telegram messages
|
||||
that start with ``/``, optionally followed by an ``@`` and the bot's
|
||||
name and/or some additional text.
|
||||
"""Handler class to handle Telegram commands.
|
||||
|
||||
Commands are Telegram messages that start with ``/``, optionally followed by an ``@`` and the
|
||||
bot's name and/or some additional text.
|
||||
|
||||
Attributes:
|
||||
command (:obj:`str` | List[:obj:`str`]): The command or list of commands this handler
|
||||
@@ -84,6 +84,7 @@ class CommandHandler(Handler):
|
||||
``user_data`` will be passed to the callback function. Default is ``False``.
|
||||
pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called
|
||||
``chat_data`` will be passed to the callback function. Default is ``False``.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -119,22 +120,21 @@ class CommandHandler(Handler):
|
||||
'instead. More info: https://git.io/vPTbc.')
|
||||
|
||||
def check_update(self, update):
|
||||
"""
|
||||
Determines whether an update should be passed to this handlers :attr:`callback`.
|
||||
"""Determines whether an update should be passed to this handlers :attr:`callback`.
|
||||
|
||||
Args:
|
||||
update (:class:`telegram.Update`): Incoming telegram update.
|
||||
|
||||
Returns:
|
||||
:obj:`bool`
|
||||
"""
|
||||
|
||||
"""
|
||||
if (isinstance(update, Update)
|
||||
and (update.message or update.edited_message and self.allow_edited)):
|
||||
message = update.message or update.edited_message
|
||||
|
||||
if message.text:
|
||||
command = message.text[1:].split(' ')[0].split('@')
|
||||
if message.text and message.text.startswith('/') and len(message.text) > 1:
|
||||
command = message.text[1:].split(None, 1)[0].split('@')
|
||||
command.append(
|
||||
message.bot.username) # in case the command was send without a username
|
||||
|
||||
@@ -145,7 +145,7 @@ class CommandHandler(Handler):
|
||||
else:
|
||||
res = self.filters(message)
|
||||
|
||||
return res and (message.text.startswith('/') and command[0].lower() in self.command
|
||||
return res and (command[0].lower() in self.command
|
||||
and command[1].lower() == message.bot.username.lower())
|
||||
else:
|
||||
return False
|
||||
@@ -154,14 +154,13 @@ class CommandHandler(Handler):
|
||||
return False
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
"""
|
||||
Send the update to the :attr:`callback`.
|
||||
"""Send the update to the :attr:`callback`.
|
||||
|
||||
Args:
|
||||
update (:class:`telegram.Update`): Incoming telegram update.
|
||||
dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that originated the Update.
|
||||
"""
|
||||
|
||||
"""
|
||||
optional_args = self.collect_optional_args(dispatcher, update)
|
||||
|
||||
message = update.message or update.edited_message
|
||||
|
||||
@@ -16,7 +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/].
|
||||
""" This module contains the ConversationHandler """
|
||||
"""This module contains the ConversationHandler."""
|
||||
|
||||
import logging
|
||||
|
||||
@@ -110,8 +110,8 @@ class ConversationHandler(Handler):
|
||||
|
||||
Raises:
|
||||
ValueError
|
||||
"""
|
||||
|
||||
"""
|
||||
END = -1
|
||||
""":obj:`int`: Used as a constant to return when a conversation is ended."""
|
||||
|
||||
@@ -203,8 +203,8 @@ class ConversationHandler(Handler):
|
||||
|
||||
Returns:
|
||||
:obj:`bool`
|
||||
"""
|
||||
|
||||
"""
|
||||
# Ignore messages in channels
|
||||
if (not isinstance(update, Update) or update.channel_post or self.per_chat
|
||||
and (update.inline_query or update.chosen_inline_result) or self.per_message
|
||||
@@ -285,14 +285,13 @@ class ConversationHandler(Handler):
|
||||
return True
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
"""
|
||||
Send the update to the callback for the current state and Handler
|
||||
"""Send the update to the callback for the current state and Handler
|
||||
|
||||
Args:
|
||||
update (:class:`telegram.Update`): Incoming telegram update.
|
||||
dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that originated the Update.
|
||||
"""
|
||||
|
||||
"""
|
||||
new_state = self.current_handler.handle_update(update, dispatcher)
|
||||
|
||||
self.update_state(new_state, self.current_conversation)
|
||||
|
||||
+96
-81
@@ -39,15 +39,15 @@ DEFAULT_GROUP = 0
|
||||
|
||||
|
||||
def run_async(func):
|
||||
"""
|
||||
Function decorator that will run the function in a new thread.
|
||||
will run :attr:`telegram.ext.Dispatcher.run_async`.
|
||||
"""Function decorator that will run the function in a new thread.
|
||||
|
||||
Will run :attr:`telegram.ext.Dispatcher.run_async`.
|
||||
|
||||
Using this decorator is only possible when only a single Dispatcher exist in the system.
|
||||
|
||||
Note:
|
||||
Use this decorator to run handlers asynchronously.
|
||||
"""
|
||||
Note: Use this decorator to run handlers asynchronously.
|
||||
|
||||
"""
|
||||
@wraps(func)
|
||||
def async_func(*args, **kwargs):
|
||||
return Dispatcher.get_instance().run_async(func, *args, **kwargs)
|
||||
@@ -55,9 +55,13 @@ def run_async(func):
|
||||
return async_func
|
||||
|
||||
|
||||
class DispatcherHandlerStop(Exception):
|
||||
"""Raise this in handler to prevent execution any other handler (even in different group)."""
|
||||
pass
|
||||
|
||||
|
||||
class Dispatcher(object):
|
||||
"""
|
||||
This class dispatches all kinds of updates to its registered handlers.
|
||||
"""This class dispatches all kinds of updates to its registered handlers.
|
||||
|
||||
Attributes:
|
||||
bot (:class:`telegram.Bot`): The bot object that should be passed to the handlers.
|
||||
@@ -74,6 +78,7 @@ class Dispatcher(object):
|
||||
instance to pass onto handler callbacks.
|
||||
workers (:obj:`int`, optional): Number of maximum concurrent worker threads for the
|
||||
``@run_async`` decorator. defaults to 4.
|
||||
|
||||
"""
|
||||
|
||||
__singleton_lock = Lock()
|
||||
@@ -113,12 +118,6 @@ class Dispatcher(object):
|
||||
else:
|
||||
self._set_singleton(None)
|
||||
|
||||
@classmethod
|
||||
def _reset_singleton(cls):
|
||||
# NOTE: This method was added mainly for test_updater benefit and specifically pypy. Never
|
||||
# call it in production code.
|
||||
cls.__singleton_semaphore.release()
|
||||
|
||||
def _init_async_threads(self, base_name, workers):
|
||||
base_name = '{}_'.format(base_name) if base_name else ''
|
||||
|
||||
@@ -134,16 +133,15 @@ class Dispatcher(object):
|
||||
|
||||
@classmethod
|
||||
def get_instance(cls):
|
||||
"""
|
||||
Get the singleton instance of this class.
|
||||
"""Get the singleton instance of this class.
|
||||
|
||||
Returns:
|
||||
:class:`telegram.ext.Dispatcher`
|
||||
|
||||
Raises:
|
||||
RuntimeError
|
||||
"""
|
||||
|
||||
"""
|
||||
if cls.__singleton is not None:
|
||||
return cls.__singleton()
|
||||
else:
|
||||
@@ -162,10 +160,13 @@ class Dispatcher(object):
|
||||
break
|
||||
|
||||
promise.run()
|
||||
if isinstance(promise.exception, DispatcherHandlerStop):
|
||||
self.logger.warning(
|
||||
'DispatcherHandlerStop is not supported with async functions; func: %s',
|
||||
promise.pooled_function.__name__)
|
||||
|
||||
def run_async(self, func, *args, **kwargs):
|
||||
"""
|
||||
Queue a function (with given args/kwargs) to be run asynchronously.
|
||||
"""Queue a function (with given args/kwargs) to be run asynchronously.
|
||||
|
||||
Args:
|
||||
func (:obj:`callable`): The function to run in the thread.
|
||||
@@ -182,14 +183,20 @@ class Dispatcher(object):
|
||||
self.__async_queue.put(promise)
|
||||
return promise
|
||||
|
||||
def start(self):
|
||||
"""
|
||||
Thread target of thread 'dispatcher'. Runs in background and processes
|
||||
the update queue.
|
||||
"""
|
||||
def start(self, ready=None):
|
||||
"""Thread target of thread 'dispatcher'.
|
||||
|
||||
Runs in background and processes the update queue.
|
||||
|
||||
Args:
|
||||
ready (:obj:`threading.Event`, optional): If specified, the event will be set once the
|
||||
dispatcher is ready.
|
||||
|
||||
"""
|
||||
if self.running:
|
||||
self.logger.warning('already running')
|
||||
if ready is not None:
|
||||
ready.set()
|
||||
return
|
||||
|
||||
if self.__exception_event.is_set():
|
||||
@@ -201,6 +208,9 @@ class Dispatcher(object):
|
||||
self.running = True
|
||||
self.logger.debug('Dispatcher started')
|
||||
|
||||
if ready is not None:
|
||||
ready.set()
|
||||
|
||||
while 1:
|
||||
try:
|
||||
# Pop update from update queue.
|
||||
@@ -221,10 +231,7 @@ class Dispatcher(object):
|
||||
self.logger.debug('Dispatcher thread stopped')
|
||||
|
||||
def stop(self):
|
||||
"""
|
||||
Stops the thread.
|
||||
"""
|
||||
|
||||
"""Stops the thread."""
|
||||
if self.running:
|
||||
self.__stop_event.set()
|
||||
while self.running:
|
||||
@@ -251,64 +258,71 @@ class Dispatcher(object):
|
||||
return self.running or bool(self.__async_threads)
|
||||
|
||||
def process_update(self, update):
|
||||
"""
|
||||
Processes a single update.
|
||||
"""Processes a single update.
|
||||
|
||||
Args:
|
||||
update (:obj:`str` | :class:`telegram.Update`): The update to process.
|
||||
"""
|
||||
update (:obj:`str` | :class:`telegram.Update` | :class:`telegram.TelegramError`):
|
||||
The update to process.
|
||||
|
||||
"""
|
||||
# An error happened while polling
|
||||
if isinstance(update, TelegramError):
|
||||
self.dispatch_error(None, update)
|
||||
try:
|
||||
self.dispatch_error(None, update)
|
||||
except Exception:
|
||||
self.logger.exception('An uncaught error was raised while handling the error')
|
||||
return
|
||||
|
||||
else:
|
||||
for group in self.groups:
|
||||
for handler in self.handlers[group]:
|
||||
try:
|
||||
if handler.check_update(update):
|
||||
handler.handle_update(update, self)
|
||||
break
|
||||
# Dispatch any errors
|
||||
except TelegramError as te:
|
||||
self.logger.warn('A TelegramError was raised while processing the '
|
||||
'Update.')
|
||||
for group in self.groups:
|
||||
try:
|
||||
for handler in (x for x in self.handlers[group] if x.check_update(update)):
|
||||
handler.handle_update(update, self)
|
||||
break
|
||||
|
||||
try:
|
||||
self.dispatch_error(update, te)
|
||||
except Exception:
|
||||
self.logger.exception('An uncaught error was raised while '
|
||||
'handling the error')
|
||||
finally:
|
||||
break
|
||||
# Stop processing with any other handler.
|
||||
except DispatcherHandlerStop:
|
||||
self.logger.debug('Stopping further handlers due to DispatcherHandlerStop')
|
||||
break
|
||||
|
||||
# Errors should not stop the thread
|
||||
except Exception:
|
||||
self.logger.exception('An uncaught error was raised while '
|
||||
'processing the update')
|
||||
break
|
||||
# Dispatch any error.
|
||||
except TelegramError as te:
|
||||
self.logger.warning('A TelegramError was raised while processing the Update')
|
||||
|
||||
try:
|
||||
self.dispatch_error(update, te)
|
||||
except DispatcherHandlerStop:
|
||||
self.logger.debug('Error handler stopped further handlers')
|
||||
break
|
||||
except Exception:
|
||||
self.logger.exception('An uncaught error was raised while handling the error')
|
||||
|
||||
# Errors should not stop the thread.
|
||||
except Exception:
|
||||
self.logger.exception('An uncaught error was raised while processing the update')
|
||||
|
||||
def add_handler(self, handler, group=DEFAULT_GROUP):
|
||||
"""
|
||||
Register a handler.
|
||||
"""Register a handler.
|
||||
|
||||
TL;DR: Order and priority counts. 0 or 1 handlers per group will be
|
||||
used.
|
||||
TL;DR: Order and priority counts. 0 or 1 handlers per group will be used.
|
||||
|
||||
A handler must be an instance of a subclass of :class:`telegram.ext.Handler`. All handlers
|
||||
are organized in groups with a numeric value. The default group is 0. All groups will be
|
||||
evaluated for handling an update, but only 0 or 1 handler per group will be used.
|
||||
evaluated for handling an update, but only 0 or 1 handler per group will be used. If
|
||||
:class:`telegram.DispatcherHandlerStop` is raised from one of the handlers, no further
|
||||
handlers (regardless of the group) will be called.
|
||||
|
||||
The priority/order of handlers is determined as follows:
|
||||
|
||||
* Priority of the group (lower group number == higher priority)
|
||||
* The first handler in a group which should handle an update will be
|
||||
used. Other handlers from the group will not be used. The order in
|
||||
which handlers were added to the group defines the priority.
|
||||
* The first handler in a group which should handle an update (see
|
||||
:attr:`telegram.ext.Handler.check_update`) will be used. Other handlers from the
|
||||
group will not be used. The order in which handlers were added to the group defines the
|
||||
priority.
|
||||
|
||||
Args:
|
||||
handler (:class:`telegram.ext.Handler`): A Handler instance.
|
||||
group (:obj:`int`, optional): The group identifier. Default is 0.
|
||||
|
||||
"""
|
||||
|
||||
if not isinstance(handler, Handler):
|
||||
@@ -324,14 +338,13 @@ class Dispatcher(object):
|
||||
self.handlers[group].append(handler)
|
||||
|
||||
def remove_handler(self, handler, group=DEFAULT_GROUP):
|
||||
"""
|
||||
Remove a handler from the specified group
|
||||
"""Remove a handler from the specified group.
|
||||
|
||||
Args:
|
||||
handler (:class:`telegram.ext.Handler`): A Handler instance.
|
||||
group (:obj:`object`, optional): The group identifier. Default is 0.
|
||||
"""
|
||||
|
||||
"""
|
||||
if handler in self.handlers[group]:
|
||||
self.handlers[group].remove(handler)
|
||||
if not self.handlers[group]:
|
||||
@@ -339,35 +352,37 @@ class Dispatcher(object):
|
||||
self.groups.remove(group)
|
||||
|
||||
def add_error_handler(self, callback):
|
||||
"""
|
||||
Registers an error handler in the Dispatcher.
|
||||
"""Registers an error handler in the Dispatcher.
|
||||
|
||||
Args:
|
||||
handler (:obj:`callable`): A function that takes ``Bot, Update, TelegramError`` as
|
||||
callback (:obj:`callable`): A function that takes ``Bot, Update, TelegramError`` as
|
||||
arguments.
|
||||
"""
|
||||
|
||||
"""
|
||||
self.error_handlers.append(callback)
|
||||
|
||||
def remove_error_handler(self, callback):
|
||||
"""
|
||||
Removes an error handler.
|
||||
"""Removes an error handler.
|
||||
|
||||
Args:
|
||||
handler (:obj:`callable`): The error handler to remove.
|
||||
"""
|
||||
callback (:obj:`callable`): The error handler to remove.
|
||||
|
||||
"""
|
||||
if callback in self.error_handlers:
|
||||
self.error_handlers.remove(callback)
|
||||
|
||||
def dispatch_error(self, update, error):
|
||||
"""
|
||||
Dispatches an error.
|
||||
"""Dispatches an error.
|
||||
|
||||
Args:
|
||||
update (:obj:`str` | :class:`telegram.Update`): The update that caused the error
|
||||
update (:obj:`str` | :class:`telegram.Update` | None): The update that caused the error
|
||||
error (:class:`telegram.TelegramError`): The Telegram error that was raised.
|
||||
"""
|
||||
|
||||
for callback in self.error_handlers:
|
||||
callback(self.bot, update, error)
|
||||
"""
|
||||
if self.error_handlers:
|
||||
for callback in self.error_handlers:
|
||||
callback(self.bot, update, error)
|
||||
|
||||
else:
|
||||
self.logger.exception(
|
||||
'No error handlers are registered, logging exception...', exc_info=error)
|
||||
|
||||
+50
-19
@@ -16,14 +16,13 @@
|
||||
#
|
||||
# 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 Filters for use with the MessageHandler class """
|
||||
"""This module contains the Filters for use with the MessageHandler class."""
|
||||
from telegram import Chat
|
||||
from future.utils import string_types
|
||||
|
||||
|
||||
class BaseFilter(object):
|
||||
"""
|
||||
Base class for all Message Filters
|
||||
"""Base class for all Message Filters.
|
||||
|
||||
Subclassing from this class filters to be combined using bitwise operators:
|
||||
|
||||
@@ -55,6 +54,7 @@ class BaseFilter(object):
|
||||
|
||||
Attributes:
|
||||
name (:obj:`str`): Name for this filter. Defaults to the type of filter.
|
||||
|
||||
"""
|
||||
|
||||
name = None
|
||||
@@ -78,14 +78,14 @@ class BaseFilter(object):
|
||||
return self.name
|
||||
|
||||
def filter(self, message):
|
||||
"""
|
||||
This method must be overwritten.
|
||||
"""This method must be overwritten.
|
||||
|
||||
Args:
|
||||
message (:class:`telegram.Message`): The message that is tested.
|
||||
|
||||
Returns:
|
||||
:obj:`bool`
|
||||
|
||||
"""
|
||||
|
||||
raise NotImplementedError
|
||||
@@ -96,6 +96,7 @@ class InvertedFilter(BaseFilter):
|
||||
|
||||
Args:
|
||||
f: The filter to invert.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, f):
|
||||
@@ -115,6 +116,7 @@ class MergedFilter(BaseFilter):
|
||||
base_filter: Filter 1 of the merged filter
|
||||
and_filter: Optional filter to "and" with base_filter. Mutually exclusive with or_filter.
|
||||
or_filter: Optional filter to "or" with base_filter. Mutually exclusive with and_filter.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, base_filter, and_filter=None, or_filter=None):
|
||||
@@ -134,12 +136,12 @@ class MergedFilter(BaseFilter):
|
||||
|
||||
|
||||
class Filters(object):
|
||||
"""
|
||||
Predefined filters for use with the `filter` argument of :class:`telegram.ext.MessageHandler`.
|
||||
"""Predefined filters for use as the `filter` argument of :class:`telegram.ext.MessageHandler`.
|
||||
|
||||
Examples:
|
||||
Use ``MessageHandler(Filters.video, callback_method)`` to filter all video
|
||||
messages. Use ``MessageHandler(Filters.contact, callback_method)`` for all contacts. etc.
|
||||
|
||||
"""
|
||||
|
||||
class _All(BaseFilter):
|
||||
@@ -260,12 +262,12 @@ class Filters(object):
|
||||
""":obj:`Filter`: Messages that contain :class:`telegram.Venue`."""
|
||||
|
||||
class _StatusUpdate(BaseFilter):
|
||||
"""
|
||||
Subset for messages containing a status update.
|
||||
"""Subset for messages containing a status update.
|
||||
|
||||
Examples:
|
||||
Use these filters like: ``Filters.status_update.new_chat_member`` etc. Or use just
|
||||
Use these filters like: ``Filters.status_update.new_chat_members`` etc. Or use just
|
||||
``Filters.status_update`` for all status update messages.
|
||||
|
||||
"""
|
||||
|
||||
class _NewChatMembers(BaseFilter):
|
||||
@@ -333,7 +335,7 @@ class Filters(object):
|
||||
|
||||
migrate = _Migrate()
|
||||
""":obj:`Filter`: Messages that contain :attr:`telegram.Message.migrate_from_chat_id` or
|
||||
:attr: `telegram.Message.migrate_from_chat_id`."""
|
||||
:attr: `telegram.Message.migrate_to_chat_id`."""
|
||||
|
||||
class _PinnedMessage(BaseFilter):
|
||||
name = 'Filters.status_update.pinned_message'
|
||||
@@ -353,6 +355,33 @@ class Filters(object):
|
||||
self.migrate(message) or self.pinned_message(message))
|
||||
|
||||
status_update = _StatusUpdate()
|
||||
"""Subset for messages containing a status update.
|
||||
|
||||
Examples:
|
||||
Use these filters like: ``Filters.status_update.new_chat_member`` etc. Or use just
|
||||
``Filters.status_update`` for all status update messages.
|
||||
|
||||
Attributes:
|
||||
chat_created (:obj:`Filter`): Messages that contain
|
||||
:attr:`telegram.Message.group_chat_created`,
|
||||
:attr:`telegram.Message.supergroup_chat_created` or
|
||||
:attr:`telegram.Message.channel_chat_created`.
|
||||
delete_chat_photo (:obj:`Filter`): Messages that contain
|
||||
:attr:`telegram.Message.delete_chat_photo`.
|
||||
left_chat_member (:obj:`Filter`): Messages that contain
|
||||
:attr:`telegram.Message.left_chat_member`.
|
||||
migrate (:obj:`Filter`): Messages that contain
|
||||
:attr:`telegram.Message.migrate_from_chat_id` or
|
||||
:attr: `telegram.Message.migrate_from_chat_id`.
|
||||
new_chat_members (:obj:`Filter`): Messages that contain
|
||||
:attr:`telegram.Message.new_chat_member`.
|
||||
new_chat_photo (:obj:`Filter`): Messages that contain
|
||||
:attr:`telegram.Message.new_chat_photo`.
|
||||
new_chat_title (:obj:`Filter`): Messages that contain
|
||||
:attr:`telegram.Message.new_chat_title`.
|
||||
pinned_message (:obj:`Filter`): Messages that contain
|
||||
:attr:`telegram.Message.pinned_message`.
|
||||
"""
|
||||
|
||||
class _Forwarded(BaseFilter):
|
||||
name = 'Filters.forwarded'
|
||||
@@ -383,6 +412,7 @@ class Filters(object):
|
||||
Args:
|
||||
entity_type: Entity type to check for. All types can be found as constants
|
||||
in :class:`telegram.MessageEntity`.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, entity_type):
|
||||
@@ -411,8 +441,7 @@ class Filters(object):
|
||||
""":obj:`Filter`: Messages sent in a group chat."""
|
||||
|
||||
class user(BaseFilter):
|
||||
"""
|
||||
Filters messages to allow only those which are from specified user ID.
|
||||
"""Filters messages to allow only those which are from specified user ID.
|
||||
|
||||
Examples:
|
||||
``MessageHandler(Filters.user(1234), callback_method)``
|
||||
@@ -424,6 +453,7 @@ class Filters(object):
|
||||
|
||||
Raises:
|
||||
ValueError: If chat_id and username are both present, or neither is.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, user_id=None, username=None):
|
||||
@@ -449,8 +479,7 @@ class Filters(object):
|
||||
message.from_user.username in self.usernames)
|
||||
|
||||
class chat(BaseFilter):
|
||||
"""
|
||||
Filters messages to allow only those which are from specified chat ID.
|
||||
"""Filters messages to allow only those which are from specified chat ID.
|
||||
|
||||
Examples:
|
||||
``MessageHandler(Filters.chat(-1234), callback_method)``
|
||||
@@ -462,6 +491,7 @@ class Filters(object):
|
||||
|
||||
Raises:
|
||||
ValueError: If chat_id and username are both present, or neither is.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, chat_id=None, username=None):
|
||||
@@ -504,10 +534,10 @@ class Filters(object):
|
||||
""":obj:`Filter`: Messages that confirm a :class:`telegram.SuccessfulPayment`."""
|
||||
|
||||
class language(BaseFilter):
|
||||
"""
|
||||
Filters messages to only allow those which are from users with a certain language code.
|
||||
Note that according to telegrams documentation, every single user does not have the
|
||||
language_code attribute.
|
||||
"""Filters messages to only allow those which are from users with a certain language code.
|
||||
|
||||
Note: According to telegrams documentation, every single user does not have the
|
||||
`language_code` attribute.
|
||||
|
||||
Examples:
|
||||
``MessageHandler(Filters.language("en"), callback_method)``
|
||||
@@ -516,6 +546,7 @@ class Filters(object):
|
||||
lang (:obj:`str` | List[:obj:`str`]): Which language code(s) to allow through. This
|
||||
will be matched using ``.startswith`` meaning that 'en' will match both 'en_US'
|
||||
and 'en_GB'.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, lang):
|
||||
|
||||
@@ -16,14 +16,11 @@
|
||||
#
|
||||
# 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 base class for handlers as used by the
|
||||
Dispatcher """
|
||||
"""This module contains the base class for handlers as used by the Dispatcher."""
|
||||
|
||||
|
||||
class Handler(object):
|
||||
"""
|
||||
The base class for all update handlers. You can create your own handlers by inheriting from
|
||||
this class.
|
||||
"""The base class for all update handlers. Create custom handlers by inheriting from it.
|
||||
|
||||
Attributes:
|
||||
callback (:obj:`callable`): The callback function for this handler.
|
||||
@@ -58,6 +55,7 @@ class Handler(object):
|
||||
``user_data`` will be passed to the callback function. Default is ``False``.
|
||||
pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called
|
||||
``chat_data`` will be passed to the callback function. Default is ``False``.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -82,6 +80,7 @@ class Handler(object):
|
||||
|
||||
Returns:
|
||||
:obj:`bool`
|
||||
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@@ -101,12 +100,11 @@ class Handler(object):
|
||||
raise NotImplementedError
|
||||
|
||||
def collect_optional_args(self, dispatcher, update=None):
|
||||
"""
|
||||
Prepares the optional arguments that are the same for all types of
|
||||
handlers.
|
||||
"""Prepares the optional arguments that are the same for all types of handlers.
|
||||
|
||||
Args:
|
||||
dispatcher (:class:`telegram.ext.Dispatcher`): The dispatcher.
|
||||
|
||||
"""
|
||||
optional_args = dict()
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ class InlineQueryHandler(Handler):
|
||||
pass_job_queue (:obj:`bool`): Optional. Determines whether ``job_queue`` will be passed to
|
||||
the callback function.
|
||||
pattern (:obj:`str` | :obj:`Pattern`): Optional. Regex pattern to test
|
||||
:attr:`telegram.CallbackQuery.data` against.
|
||||
:attr:`telegram.InlineQuery.query` against.
|
||||
pass_groups (:obj:`bool`): Optional. Determines whether ``groups`` will be passed to the
|
||||
callback function.
|
||||
pass_groupdict (:obj:`bool`): Optional. Determines whether ``groupdict``. will be passed to
|
||||
@@ -67,7 +67,7 @@ class InlineQueryHandler(Handler):
|
||||
:class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater`
|
||||
which can be used to schedule new jobs. Default is ``False``.
|
||||
pattern (:obj:`str` | :obj:`Pattern`, optional): Regex pattern. If not ``None``,
|
||||
``re.match`` is used on :attr:`telegram.CallbackQuery.data` to determine if an update
|
||||
``re.match`` is used on :attr:`telegram.InlineQuery.query` to determine if an update
|
||||
should be handled by this handler.
|
||||
pass_groups (:obj:`bool`, optional): If the callback should be passed the result of
|
||||
``re.match(pattern, data).groups()`` as a keyword argument called ``groups``.
|
||||
|
||||
+27
-53
@@ -35,8 +35,7 @@ class Days(object):
|
||||
|
||||
|
||||
class JobQueue(object):
|
||||
"""
|
||||
This class allows you to periodically perform tasks with the bot.
|
||||
"""This class allows you to periodically perform tasks with the bot.
|
||||
|
||||
Attributes:
|
||||
queue (:obj:`PriorityQueue`): The queue that holds the Jobs.
|
||||
@@ -48,6 +47,7 @@ class JobQueue(object):
|
||||
Deprecated:
|
||||
prevent_autostart (:obj:`bool`, optional): Thread does not start during initialisation.
|
||||
Use `start` method instead.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, bot, prevent_autostart=None):
|
||||
@@ -65,8 +65,7 @@ class JobQueue(object):
|
||||
self._running = False
|
||||
|
||||
def put(self, job, next_t=None):
|
||||
"""
|
||||
Queue a new job.
|
||||
"""Queue a new job.
|
||||
|
||||
Note:
|
||||
This method is deprecated. Please use: :attr:`run_once`, :attr:`run_daily`
|
||||
@@ -87,6 +86,7 @@ class JobQueue(object):
|
||||
* :obj:`datetime.time` will be interpreted as a specific time at which the job
|
||||
should run. This could be either today or, if the time has already passed,
|
||||
tomorrow.
|
||||
|
||||
"""
|
||||
|
||||
warnings.warn("'JobQueue.put' is being deprecated, use 'JobQueue.run_once', "
|
||||
@@ -125,8 +125,7 @@ class JobQueue(object):
|
||||
self._set_next_peek(next_t)
|
||||
|
||||
def run_once(self, callback, when, context=None, name=None):
|
||||
"""
|
||||
Creates a new ``Job`` that runs once and adds it to the queue.
|
||||
"""Creates a new ``Job`` that runs once and adds it to the queue.
|
||||
|
||||
Args:
|
||||
callback (:obj:`callable`): The callback function that should be executed by the new
|
||||
@@ -155,15 +154,14 @@ class JobQueue(object):
|
||||
Returns:
|
||||
:class:`telegram.ext.Job`: The new ``Job`` instance that has been added to the job
|
||||
queue.
|
||||
"""
|
||||
|
||||
"""
|
||||
job = Job(callback, repeat=False, context=context, name=name, job_queue=self)
|
||||
self._put(job, next_t=when)
|
||||
return job
|
||||
|
||||
def run_repeating(self, callback, interval, first=None, context=None, name=None):
|
||||
"""
|
||||
Creates a new ``Job`` that runs once and adds it to the queue.
|
||||
"""Creates a new ``Job`` that runs once and adds it to the queue.
|
||||
|
||||
Args:
|
||||
callback (:obj:`callable`): The callback function that should be executed by the new
|
||||
@@ -196,6 +194,7 @@ class JobQueue(object):
|
||||
Returns:
|
||||
:class:`telegram.ext.Job`: The new ``Job`` instance that has been added to the job
|
||||
queue.
|
||||
|
||||
"""
|
||||
|
||||
job = Job(callback,
|
||||
@@ -208,8 +207,7 @@ class JobQueue(object):
|
||||
return job
|
||||
|
||||
def run_daily(self, callback, time, days=Days.EVERY_DAY, context=None, name=None):
|
||||
"""
|
||||
Creates a new ``Job`` that runs once and adds it to the queue.
|
||||
"""Creates a new ``Job`` that runs once and adds it to the queue.
|
||||
|
||||
Args:
|
||||
callback (:obj:`callable`): The callback function that should be executed by the new
|
||||
@@ -227,6 +225,7 @@ class JobQueue(object):
|
||||
Returns:
|
||||
:class:`telegram.ext.Job`: The new ``Job`` instance that has been added to the job
|
||||
queue.
|
||||
|
||||
"""
|
||||
|
||||
job = Job(callback,
|
||||
@@ -250,9 +249,7 @@ class JobQueue(object):
|
||||
self.__tick.set()
|
||||
|
||||
def tick(self):
|
||||
"""
|
||||
Run all jobs that are due and re-enqueue them with their interval.
|
||||
"""
|
||||
"""Run all jobs that are due and re-enqueue them with their interval."""
|
||||
|
||||
now = time.time()
|
||||
|
||||
@@ -300,9 +297,7 @@ class JobQueue(object):
|
||||
self.logger.debug('Dropping non-repeating or removed job %s', job.name)
|
||||
|
||||
def start(self):
|
||||
"""
|
||||
Starts the job_queue thread.
|
||||
"""
|
||||
"""Starts the job_queue thread."""
|
||||
|
||||
self.__start_lock.acquire()
|
||||
|
||||
@@ -319,8 +314,8 @@ class JobQueue(object):
|
||||
"""
|
||||
Thread target of thread ``job_queue``. Runs in background and performs ticks on the job
|
||||
queue.
|
||||
"""
|
||||
|
||||
"""
|
||||
while self._running:
|
||||
# self._next_peek may be (re)scheduled during self.tick() or self.put()
|
||||
with self.__next_peek_lock:
|
||||
@@ -339,9 +334,7 @@ class JobQueue(object):
|
||||
self.logger.debug('%s thread stopped', self.__class__.__name__)
|
||||
|
||||
def stop(self):
|
||||
"""
|
||||
Stops the thread.
|
||||
"""
|
||||
"""Stops the thread."""
|
||||
|
||||
with self.__start_lock:
|
||||
self._running = False
|
||||
@@ -351,16 +344,13 @@ class JobQueue(object):
|
||||
self.__thread.join()
|
||||
|
||||
def jobs(self):
|
||||
"""
|
||||
Returns a tuple of all jobs that are currently in the ``JobQueue``
|
||||
"""
|
||||
"""Returns a tuple of all jobs that are currently in the ``JobQueue``."""
|
||||
|
||||
return tuple(job[1] for job in self.queue.queue if job)
|
||||
|
||||
|
||||
class Job(object):
|
||||
"""
|
||||
This class encapsulates a Job
|
||||
"""This class encapsulates a Job.
|
||||
|
||||
Attributes:
|
||||
callback (:obj:`callable`): The callback function that should be executed by the new job.
|
||||
@@ -383,8 +373,9 @@ class Job(object):
|
||||
name (:obj:`str`, optional): The name of the new job. Defaults to ``callback.__name__``.
|
||||
days (Tuple[:obj:`int`], optional): Defines on which days of the week the job should run.
|
||||
Defaults to ``Days.EVERY_DAY``
|
||||
job_queue (class:`telegram.ext.JobQueue`, optional): The ``JobQueue`` this job belongs to.
|
||||
job_queue (:class:`telegram.ext.JobQueue`, optional): The ``JobQueue`` this job belongs to.
|
||||
Only optional for backward compatibility with ``JobQueue.put()``.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -415,9 +406,7 @@ class Job(object):
|
||||
self._enabled.set()
|
||||
|
||||
def run(self, bot):
|
||||
"""
|
||||
Executes the callback function.
|
||||
"""
|
||||
"""Executes the callback function."""
|
||||
|
||||
self.callback(bot, self)
|
||||
|
||||
@@ -425,24 +414,19 @@ class Job(object):
|
||||
"""
|
||||
Schedules this job for removal from the ``JobQueue``. It will be removed without executing
|
||||
its callback function again.
|
||||
|
||||
"""
|
||||
|
||||
self._remove.set()
|
||||
|
||||
@property
|
||||
def removed(self):
|
||||
"""
|
||||
:obj:`bool`: Whether this job is due to be removed.
|
||||
"""
|
||||
|
||||
""":obj:`bool`: Whether this job is due to be removed."""
|
||||
return self._remove.is_set()
|
||||
|
||||
@property
|
||||
def enabled(self):
|
||||
"""
|
||||
:obj:`bool`: Whether this job is enabled.
|
||||
"""
|
||||
|
||||
""":obj:`bool`: Whether this job is enabled."""
|
||||
return self._enabled.is_set()
|
||||
|
||||
@enabled.setter
|
||||
@@ -457,8 +441,8 @@ class Job(object):
|
||||
"""
|
||||
:obj:`int` | :obj:`float` | :obj:`datetime.timedelta`: Optional. The interval in which the
|
||||
job will run.
|
||||
"""
|
||||
|
||||
"""
|
||||
return self._interval
|
||||
|
||||
@interval.setter
|
||||
@@ -474,10 +458,7 @@ class Job(object):
|
||||
|
||||
@property
|
||||
def interval_seconds(self):
|
||||
"""
|
||||
:obj:`int`: The interval for this job in seconds.
|
||||
"""
|
||||
|
||||
""":obj:`int`: The interval for this job in seconds."""
|
||||
if isinstance(self.interval, datetime.timedelta):
|
||||
return self.interval.total_seconds()
|
||||
else:
|
||||
@@ -485,10 +466,7 @@ class Job(object):
|
||||
|
||||
@property
|
||||
def repeat(self):
|
||||
"""
|
||||
:obj:`bool`: Optional. If this job should be periodically execute its callback function.
|
||||
"""
|
||||
|
||||
""":obj:`bool`: Optional. If this job should periodically execute its callback function."""
|
||||
return self._repeat
|
||||
|
||||
@repeat.setter
|
||||
@@ -499,9 +477,7 @@ class Job(object):
|
||||
|
||||
@property
|
||||
def days(self):
|
||||
"""
|
||||
Tuple[:obj:`int`]: Optional. Defines on which days of the week the job should run.
|
||||
"""
|
||||
"""Tuple[:obj:`int`]: Optional. Defines on which days of the week the job should run."""
|
||||
|
||||
return self._days
|
||||
|
||||
@@ -521,9 +497,7 @@ class Job(object):
|
||||
|
||||
@property
|
||||
def job_queue(self):
|
||||
"""
|
||||
:class:`telegram.ext.JobQueue`: Optional. The ``JobQueue`` this job belongs to.
|
||||
"""
|
||||
""":class:`telegram.ext.JobQueue`: Optional. The ``JobQueue`` this job belongs to."""
|
||||
|
||||
return self._job_queue
|
||||
|
||||
|
||||
@@ -17,16 +17,15 @@
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
# TODO: Remove allow_edited
|
||||
""" This module contains the MessageHandler class """
|
||||
"""This module contains the MessageHandler class."""
|
||||
import warnings
|
||||
|
||||
from .handler import Handler
|
||||
from telegram import Update
|
||||
from .handler import Handler
|
||||
|
||||
|
||||
class MessageHandler(Handler):
|
||||
"""
|
||||
Handler class to handle telegram messages. They might contain text, media or status updates.
|
||||
"""Handler class to handle telegram messages. They might contain text, media or status updates.
|
||||
|
||||
Attributes:
|
||||
filters (:obj:`Filter`): Only allow updates with these Filters. See
|
||||
@@ -86,6 +85,7 @@ class MessageHandler(Handler):
|
||||
|
||||
Raises:
|
||||
ValueError
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -125,21 +125,20 @@ class MessageHandler(Handler):
|
||||
'instead. More info: https://git.io/vPTbc.')
|
||||
|
||||
def _is_allowed_update(self, update):
|
||||
return any([(self.message_updates and update.message),
|
||||
(self.edited_updates and update.edited_message),
|
||||
(self.channel_post_updates and update.channel_post)])
|
||||
return any([self.message_updates and update.message,
|
||||
self.edited_updates and (update.edited_message or update.edited_channel_post),
|
||||
self.channel_post_updates and update.channel_post])
|
||||
|
||||
def check_update(self, update):
|
||||
"""
|
||||
Determines whether an update should be passed to this handlers :attr:`callback`.
|
||||
"""Determines whether an update should be passed to this handlers :attr:`callback`.
|
||||
|
||||
Args:
|
||||
update (:class:`telegram.Update`): Incoming telegram update.
|
||||
|
||||
Returns:
|
||||
:obj:`bool`
|
||||
"""
|
||||
|
||||
"""
|
||||
if isinstance(update, Update) and self._is_allowed_update(update):
|
||||
|
||||
if not self.filters:
|
||||
@@ -158,14 +157,13 @@ class MessageHandler(Handler):
|
||||
return res
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
"""
|
||||
Send the update to the :attr:`callback`.
|
||||
"""Send the update to the :attr:`callback`.
|
||||
|
||||
Args:
|
||||
update (:class:`telegram.Update`): Incoming telegram update.
|
||||
dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that originated the Update.
|
||||
"""
|
||||
|
||||
"""
|
||||
optional_args = self.collect_optional_args(dispatcher, update)
|
||||
|
||||
return self.callback(dispatcher.bot, update, **optional_args)
|
||||
|
||||
@@ -19,7 +19,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/]
|
||||
"""A throughput-limiting message processor for Telegram bots"""
|
||||
"""A throughput-limiting message processor for Telegram bots."""
|
||||
from telegram.utils import promise
|
||||
|
||||
import functools
|
||||
@@ -44,9 +44,7 @@ else:
|
||||
|
||||
|
||||
class DelayQueueError(RuntimeError):
|
||||
"""
|
||||
Indicates processing errors.
|
||||
"""
|
||||
"""Indicates processing errors."""
|
||||
pass
|
||||
|
||||
|
||||
@@ -78,6 +76,7 @@ class DelayQueue(threading.Thread):
|
||||
creation; if ``False``, should be started manually by `start` method. Defaults to True.
|
||||
name (:obj:`str`, optional): Thread's name. Defaults to ``'DelayQueue-N'``, where N is
|
||||
sequential number of object created.
|
||||
|
||||
"""
|
||||
|
||||
_instcnt = 0 # instance counter
|
||||
@@ -105,7 +104,8 @@ class DelayQueue(threading.Thread):
|
||||
def run(self):
|
||||
"""
|
||||
Do not use the method except for unthreaded testing purposes, the method normally is
|
||||
automatically called by autostart argument .
|
||||
automatically called by autostart argument.
|
||||
|
||||
"""
|
||||
|
||||
times = [] # used to store each callable processing time
|
||||
@@ -134,14 +134,14 @@ class DelayQueue(threading.Thread):
|
||||
self.exc_route(exc) # to prevent thread exit
|
||||
|
||||
def stop(self, timeout=None):
|
||||
"""
|
||||
Used to gently stop processor and shutdown its thread.
|
||||
"""Used to gently stop processor and shutdown its thread.
|
||||
|
||||
Args:
|
||||
timeout (:obj:`float`): Indicates maximum time to wait for processor to stop and its
|
||||
thread to exit. If timeout exceeds and processor has not stopped, method silently
|
||||
returns. :attr:`is_alive` could be used afterwards to check the actual status.
|
||||
``timeout`` set to None, blocks until processor is shut down. Defaults to None.
|
||||
|
||||
"""
|
||||
|
||||
self.__exit_req = True # gently request
|
||||
@@ -153,19 +153,20 @@ class DelayQueue(threading.Thread):
|
||||
"""
|
||||
Dummy exception handler which re-raises exception in thread. Could be possibly overwritten
|
||||
by subclasses.
|
||||
|
||||
"""
|
||||
|
||||
raise exc
|
||||
|
||||
def __call__(self, func, *args, **kwargs):
|
||||
"""
|
||||
Used to process callbacks in throughput-limiting thread through queue.
|
||||
"""Used to process callbacks in throughput-limiting thread through queue.
|
||||
|
||||
Args:
|
||||
func (:obj:`callable`): The actual function (or any callable) that is processed through
|
||||
queue.
|
||||
*args (:obj:`list`): Variable-length `func` arguments.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword-arguments to `func`.
|
||||
|
||||
"""
|
||||
|
||||
if not self.is_alive() or self.__exit_req:
|
||||
@@ -202,6 +203,7 @@ class MessageQueue(object):
|
||||
autostart (:obj:`bool`, optional): If True, processors are started immediately after
|
||||
object's creation; if ``False``, should be started manually by :attr:`start` method.
|
||||
Defaults to ``True``.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -224,9 +226,7 @@ class MessageQueue(object):
|
||||
autostart=autostart)
|
||||
|
||||
def start(self):
|
||||
"""
|
||||
Method is used to manually start the ``MessageQueue`` processing.
|
||||
"""
|
||||
"""Method is used to manually start the ``MessageQueue`` processing."""
|
||||
self._all_delayq.start()
|
||||
self._group_delayq.start()
|
||||
|
||||
@@ -258,6 +258,7 @@ class MessageQueue(object):
|
||||
|
||||
Returns:
|
||||
:obj:`callable`: Used as ``promise`` argument.
|
||||
|
||||
"""
|
||||
|
||||
if not is_group_msg: # ignore middle group delay
|
||||
@@ -268,8 +269,7 @@ class MessageQueue(object):
|
||||
|
||||
|
||||
def queuedmessage(method):
|
||||
"""
|
||||
A decorator to be used with :attr:`telegram.Bot` send* methods.
|
||||
"""A decorator to be used with :attr:`telegram.Bot` send* methods.
|
||||
|
||||
Note:
|
||||
As it probably wouldn't be a good idea to make this decorator a property, it has been coded
|
||||
@@ -297,6 +297,7 @@ def queuedmessage(method):
|
||||
Returns:
|
||||
``telegram.utils.promise.Promise``: In case call is queued or original method's return
|
||||
value if it's not.
|
||||
|
||||
"""
|
||||
|
||||
@functools.wraps(method)
|
||||
|
||||
@@ -16,15 +16,14 @@
|
||||
#
|
||||
# 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 PreCheckoutQueryHandler class """
|
||||
"""This module contains the PreCheckoutQueryHandler class."""
|
||||
|
||||
from telegram import Update
|
||||
from .handler import Handler
|
||||
|
||||
|
||||
class PreCheckoutQueryHandler(Handler):
|
||||
"""
|
||||
Handler class to handle Telegram PreCheckout callback queries.
|
||||
"""Handler class to handle Telegram PreCheckout callback queries.
|
||||
|
||||
Attributes:
|
||||
callback (:obj:`callable`): The callback function for this handler.
|
||||
@@ -59,6 +58,7 @@ class PreCheckoutQueryHandler(Handler):
|
||||
``user_data`` will be passed to the callback function. Default is ``False``.
|
||||
pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called
|
||||
``chat_data`` will be passed to the callback function. Default is ``False``.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -75,26 +75,24 @@ class PreCheckoutQueryHandler(Handler):
|
||||
pass_chat_data=pass_chat_data)
|
||||
|
||||
def check_update(self, update):
|
||||
"""
|
||||
Determines whether an update should be passed to this handlers :attr:`callback`.
|
||||
"""Determines whether an update should be passed to this handlers :attr:`callback`.
|
||||
|
||||
Args:
|
||||
update (:class:`telegram.Update`): Incoming telegram update.
|
||||
|
||||
Returns:
|
||||
:obj:`bool`
|
||||
"""
|
||||
|
||||
"""
|
||||
return isinstance(update, Update) and update.pre_checkout_query
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
"""
|
||||
Send the update to the :attr:`callback`.
|
||||
"""Send the update to the :attr:`callback`.
|
||||
|
||||
Args:
|
||||
update (:class:`telegram.Update`): Incoming telegram update.
|
||||
dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that originated the Update.
|
||||
"""
|
||||
|
||||
"""
|
||||
optional_args = self.collect_optional_args(dispatcher, update)
|
||||
return self.callback(dispatcher.bot, update, **optional_args)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
# TODO: Remove allow_edited
|
||||
""" This module contains the RegexHandler class """
|
||||
"""This module contains the RegexHandler class."""
|
||||
|
||||
import re
|
||||
import warnings
|
||||
@@ -29,11 +29,11 @@ from .handler import Handler
|
||||
|
||||
|
||||
class RegexHandler(Handler):
|
||||
"""
|
||||
Handler class to handle Telegram updates based on a regex. It uses a
|
||||
regular expression to check text messages. Read the documentation of the
|
||||
``re`` module for more information. The ``re.match`` function is used to
|
||||
determine if an update should be handled by this handler.
|
||||
"""Handler class to handle Telegram updates based on a regex.
|
||||
|
||||
It uses a regular expression to check text messages. Read the documentation of the ``re``
|
||||
module for more information. The ``re.match`` function is used to determine if an update should
|
||||
be handled by this handler.
|
||||
|
||||
Attributes:
|
||||
pattern (:obj:`str` | :obj:`Pattern`): The regex pattern.
|
||||
@@ -91,6 +91,7 @@ class RegexHandler(Handler):
|
||||
|
||||
Raises:
|
||||
ValueError
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -133,32 +134,32 @@ class RegexHandler(Handler):
|
||||
self.edited_updates = edited_updates
|
||||
|
||||
def check_update(self, update):
|
||||
"""
|
||||
Determines whether an update should be passed to this handlers :attr:`callback`.
|
||||
"""Determines whether an update should be passed to this handlers :attr:`callback`.
|
||||
|
||||
Args:
|
||||
update (:class:`telegram.Update`): Incoming telegram update.
|
||||
|
||||
Returns:
|
||||
:obj:`bool`
|
||||
|
||||
"""
|
||||
if not isinstance(update, Update) and not update.effective_message:
|
||||
return False
|
||||
if any([(self.message_updates and update.message),
|
||||
(self.edited_updates and update.edited_message),
|
||||
(self.channel_post_updates and update.channel_post)]) and \
|
||||
if any([self.message_updates and update.message,
|
||||
self.edited_updates and (update.edited_message or update.edited_channel_post),
|
||||
self.channel_post_updates and update.channel_post]) and \
|
||||
update.effective_message.text:
|
||||
match = re.match(self.pattern, update.effective_message.text)
|
||||
return bool(match)
|
||||
return False
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
"""
|
||||
Send the update to the :attr:`callback`.
|
||||
"""Send the update to the :attr:`callback`.
|
||||
|
||||
Args:
|
||||
update (:class:`telegram.Update`): Incoming telegram update.
|
||||
dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that originated the Update.
|
||||
|
||||
"""
|
||||
|
||||
optional_args = self.collect_optional_args(dispatcher, update)
|
||||
|
||||
@@ -16,15 +16,14 @@
|
||||
#
|
||||
# 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 ShippingQueryHandler class """
|
||||
"""This module contains the ShippingQueryHandler class."""
|
||||
|
||||
from telegram import Update
|
||||
from .handler import Handler
|
||||
|
||||
|
||||
class ShippingQueryHandler(Handler):
|
||||
"""
|
||||
Handler class to handle Telegram shipping callback queries.
|
||||
"""Handler class to handle Telegram shipping callback queries.
|
||||
|
||||
Attributes:
|
||||
callback (:obj:`callable`): The callback function for this handler.
|
||||
@@ -59,6 +58,7 @@ class ShippingQueryHandler(Handler):
|
||||
``user_data`` will be passed to the callback function. Default is ``False``.
|
||||
pass_chat_data (:obj:`bool`, optional): If set to ``True``, a keyword argument called
|
||||
``chat_data`` will be passed to the callback function. Default is ``False``.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -75,26 +75,24 @@ class ShippingQueryHandler(Handler):
|
||||
pass_chat_data=pass_chat_data)
|
||||
|
||||
def check_update(self, update):
|
||||
"""
|
||||
Determines whether an update should be passed to this handlers :attr:`callback`.
|
||||
"""Determines whether an update should be passed to this handlers :attr:`callback`.
|
||||
|
||||
Args:
|
||||
update (:class:`telegram.Update`): Incoming telegram update.
|
||||
|
||||
Returns:
|
||||
:obj:`bool`
|
||||
"""
|
||||
|
||||
"""
|
||||
return isinstance(update, Update) and update.shipping_query
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
"""
|
||||
Send the update to the :attr:`callback`.
|
||||
"""Send the update to the :attr:`callback`.
|
||||
|
||||
Args:
|
||||
update (:class:`telegram.Update`): Incoming telegram update.
|
||||
dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that originated the Update.
|
||||
"""
|
||||
|
||||
"""
|
||||
optional_args = self.collect_optional_args(dispatcher, update)
|
||||
return self.callback(dispatcher.bot, update, **optional_args)
|
||||
|
||||
@@ -16,7 +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/].
|
||||
""" This module contains the StringCommandHandler class """
|
||||
"""This module contains the StringCommandHandler class."""
|
||||
|
||||
from future.utils import string_types
|
||||
|
||||
@@ -24,9 +24,7 @@ from .handler import Handler
|
||||
|
||||
|
||||
class StringCommandHandler(Handler):
|
||||
"""
|
||||
Handler class to handle string commands. Commands are string updates
|
||||
that start with ``/``.
|
||||
"""Handler class to handle string commands. Commands are string updates that start with ``/``.
|
||||
|
||||
Note:
|
||||
This handler is not used to handle Telegram :attr:`telegram.Update`, but strings manually
|
||||
@@ -60,6 +58,7 @@ class StringCommandHandler(Handler):
|
||||
``job_queue`` will be passed to the callback function. It will be a
|
||||
class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater`
|
||||
which can be used to schedule new jobs. Default is ``False``.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -74,26 +73,26 @@ class StringCommandHandler(Handler):
|
||||
self.pass_args = pass_args
|
||||
|
||||
def check_update(self, update):
|
||||
"""
|
||||
Determines whether an update should be passed to this handlers :attr:`callback`.
|
||||
"""Determines whether an update should be passed to this handlers :attr:`callback`.
|
||||
|
||||
Args:
|
||||
update (:obj:`str`): An incomming command.
|
||||
|
||||
Returns:
|
||||
:obj:`bool`
|
||||
|
||||
"""
|
||||
|
||||
return (isinstance(update, string_types) and update.startswith('/')
|
||||
and update[1:].split(' ')[0] == self.command)
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
"""
|
||||
Send the update to the :attr:`callback`.
|
||||
"""Send the update to the :attr:`callback`.
|
||||
|
||||
Args:
|
||||
update (:obj:`str`): An incomming command.
|
||||
dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that originated the command.
|
||||
|
||||
"""
|
||||
|
||||
optional_args = self.collect_optional_args(dispatcher)
|
||||
|
||||
@@ -16,7 +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/].
|
||||
""" This module contains the StringRegexHandler class """
|
||||
"""This module contains the StringRegexHandler class."""
|
||||
|
||||
import re
|
||||
|
||||
@@ -26,11 +26,10 @@ from .handler import Handler
|
||||
|
||||
|
||||
class StringRegexHandler(Handler):
|
||||
"""
|
||||
Handler class to handle string updates based on a regex. It uses a
|
||||
regular expression to check update content. Read the documentation of the
|
||||
``re`` module for more information. The ``re.match`` function is used to
|
||||
determine if an update should be handled by this handler.
|
||||
"""Handler class to handle string updates based on a regex which checks the update content.
|
||||
|
||||
Read the documentation of the ``re`` module for more information. The ``re.match`` function is
|
||||
used to determine if an update should be handled by this handler.
|
||||
|
||||
Note:
|
||||
This handler is not used to handle Telegram :attr:`telegram.Update`, but strings manually
|
||||
@@ -67,6 +66,7 @@ class StringRegexHandler(Handler):
|
||||
``job_queue`` will be passed to the callback function. It will be a
|
||||
:class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater`
|
||||
which can be used to schedule new jobs. Default is ``False``.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -87,27 +87,25 @@ class StringRegexHandler(Handler):
|
||||
self.pass_groupdict = pass_groupdict
|
||||
|
||||
def check_update(self, update):
|
||||
"""
|
||||
Determines whether an update should be passed to this handlers :attr:`callback`.
|
||||
"""Determines whether an update should be passed to this handlers :attr:`callback`.
|
||||
|
||||
Args:
|
||||
update (:obj:`str`): An incomming command.
|
||||
|
||||
Returns:
|
||||
:obj:`bool`
|
||||
"""
|
||||
|
||||
"""
|
||||
return isinstance(update, string_types) and bool(re.match(self.pattern, update))
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
"""
|
||||
Send the update to the :attr:`callback`.
|
||||
"""Send the update to the :attr:`callback`.
|
||||
|
||||
Args:
|
||||
update (:obj:`str`): An incomming command.
|
||||
dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that originated the command.
|
||||
"""
|
||||
|
||||
"""
|
||||
optional_args = self.collect_optional_args(dispatcher)
|
||||
match = re.match(self.pattern, update)
|
||||
|
||||
|
||||
@@ -16,14 +16,13 @@
|
||||
#
|
||||
# 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 TypeHandler class """
|
||||
"""This module contains the TypeHandler class."""
|
||||
|
||||
from .handler import Handler
|
||||
|
||||
|
||||
class TypeHandler(Handler):
|
||||
"""
|
||||
Handler class to handle updates of custom types.
|
||||
"""Handler class to handle updates of custom types.
|
||||
|
||||
Attributes:
|
||||
type (:obj:`type`): The ``type`` of updates this handler should process.
|
||||
@@ -51,6 +50,7 @@ class TypeHandler(Handler):
|
||||
``job_queue`` will be passed to the callback function. It will be a
|
||||
:class:`telegram.ext.JobQueue` instance created by the :class:`telegram.ext.Updater`
|
||||
which can be used to schedule new jobs. Default is ``False``.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, type, callback, strict=False, pass_update_queue=False,
|
||||
@@ -61,14 +61,14 @@ class TypeHandler(Handler):
|
||||
self.strict = strict
|
||||
|
||||
def check_update(self, update):
|
||||
"""
|
||||
Determines whether an update should be passed to this handlers :attr:`callback`.
|
||||
"""Determines whether an update should be passed to this handlers :attr:`callback`.
|
||||
|
||||
Args:
|
||||
update (:class:`telegram.Update`): Incoming telegram update.
|
||||
|
||||
Returns:
|
||||
:obj:`bool`
|
||||
|
||||
"""
|
||||
|
||||
if not self.strict:
|
||||
@@ -77,14 +77,13 @@ class TypeHandler(Handler):
|
||||
return type(update) is self.type
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
"""
|
||||
Send the update to the :attr:`callback`.
|
||||
"""Send the update to the :attr:`callback`.
|
||||
|
||||
Args:
|
||||
update (:class:`telegram.Update`): Incoming telegram update.
|
||||
dispatcher (:class:`telegram.ext.Dispatcher`): Dispatcher that originated the Update.
|
||||
"""
|
||||
|
||||
"""
|
||||
optional_args = self.collect_optional_args(dispatcher)
|
||||
|
||||
return self.callback(dispatcher.bot, update, **optional_args)
|
||||
|
||||
+28
-18
@@ -16,8 +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/].
|
||||
"""This module contains the class Updater, which tries to make creating
|
||||
Telegram bots intuitive."""
|
||||
"""This module contains the class Updater, which tries to make creating Telegram bots intuitive."""
|
||||
|
||||
import logging
|
||||
import os
|
||||
@@ -70,14 +69,17 @@ class Updater(object):
|
||||
user_sig_handler (:obj:`function`, optional): Takes ``signum, frame`` as positional
|
||||
arguments. This will be called when a signal is received, defaults are (SIGINT,
|
||||
SIGTERM, SIGABRT) setable with :attr:`idle`.
|
||||
request_kwargs (:obj:`dict`, optional): Keyword args to control the creation of a request
|
||||
object (ignored if `bot` argument is used).
|
||||
request_kwargs (:obj:`dict`, optional): Keyword args to control the creation of a
|
||||
`telegram.utils.request.Request` object (ignored if `bot` argument is used). The
|
||||
request_kwargs are very useful for the advanced users who would like to control the
|
||||
default timeouts and/or control the proxy used for http communication.
|
||||
|
||||
Note:
|
||||
You must supply either a :attr:`bot` or a :attr:`token` argument.
|
||||
|
||||
Raises:
|
||||
ValueError: If both :attr:`token` and :attr:`bot` are passed or none of them.
|
||||
|
||||
"""
|
||||
|
||||
_request = None
|
||||
@@ -95,8 +97,16 @@ class Updater(object):
|
||||
if (token is not None) and (bot is not None):
|
||||
raise ValueError('`token` and `bot` are mutually exclusive')
|
||||
|
||||
self.logger = logging.getLogger(__name__)
|
||||
|
||||
con_pool_size = workers + 4
|
||||
|
||||
if bot is not None:
|
||||
self.bot = bot
|
||||
if bot.request.con_pool_size < con_pool_size:
|
||||
self.logger.warning(
|
||||
'Connection pool of Request object is smaller than optimal value (%s)',
|
||||
con_pool_size)
|
||||
else:
|
||||
# we need a connection pool the size of:
|
||||
# * for each of the workers
|
||||
@@ -107,7 +117,7 @@ class Updater(object):
|
||||
if request_kwargs is None:
|
||||
request_kwargs = {}
|
||||
if 'con_pool_size' not in request_kwargs:
|
||||
request_kwargs['con_pool_size'] = workers + 4
|
||||
request_kwargs['con_pool_size'] = con_pool_size
|
||||
self._request = Request(**request_kwargs)
|
||||
self.bot = Bot(token, base_url, request=self._request)
|
||||
self.user_sig_handler = user_sig_handler
|
||||
@@ -121,7 +131,6 @@ class Updater(object):
|
||||
workers=workers,
|
||||
exception_event=self.__exception_event)
|
||||
self.last_update_id = 0
|
||||
self.logger = logging.getLogger(__name__)
|
||||
self.running = False
|
||||
self.is_idle = False
|
||||
self.httpd = None
|
||||
@@ -152,8 +161,7 @@ class Updater(object):
|
||||
bootstrap_retries=0,
|
||||
read_latency=2.,
|
||||
allowed_updates=None):
|
||||
"""
|
||||
Starts polling updates from Telegram.
|
||||
"""Starts polling updates from Telegram.
|
||||
|
||||
Args:
|
||||
poll_interval (:obj:`float`, optional): Time to wait between polling updates from
|
||||
@@ -178,6 +186,7 @@ class Updater(object):
|
||||
|
||||
Returns:
|
||||
:obj:`Queue`: The update queue that can be filled from the main thread.
|
||||
|
||||
"""
|
||||
|
||||
if network_delay is not None:
|
||||
@@ -190,10 +199,13 @@ class Updater(object):
|
||||
|
||||
# Create & start threads
|
||||
self.job_queue.start()
|
||||
self._init_thread(self.dispatcher.start, "dispatcher")
|
||||
dispatcher_ready = Event()
|
||||
self._init_thread(self.dispatcher.start, "dispatcher", ready=dispatcher_ready)
|
||||
self._init_thread(self._start_polling, "updater", poll_interval, timeout,
|
||||
read_latency, bootstrap_retries, clean, allowed_updates)
|
||||
|
||||
dispatcher_ready.wait()
|
||||
|
||||
# Return the update queue so the main thread can insert updates
|
||||
return self.update_queue
|
||||
|
||||
@@ -222,8 +234,8 @@ class Updater(object):
|
||||
key (:obj:`str`, optional): Path to the SSL key file.
|
||||
clean (:obj:`bool`, optional): Whether to clean any pending updates on Telegram servers
|
||||
before actually starting the webhook. Default is ``False``.
|
||||
bootstrap_retries (Optional[int[): Whether the bootstrapping phase of the `Updater`
|
||||
will retry on failures on the Telegram server.
|
||||
bootstrap_retries (:obj:`int`, optional): Whether the bootstrapping phase of the
|
||||
`Updater` will retry on failures on the Telegram server.
|
||||
|
||||
* < 0 - retry indefinitely
|
||||
* 0 - no retries (default)
|
||||
@@ -236,6 +248,7 @@ class Updater(object):
|
||||
|
||||
Returns:
|
||||
:obj:`Queue`: The update queue that can be filled from the main thread.
|
||||
|
||||
"""
|
||||
|
||||
with self.__lock:
|
||||
@@ -252,7 +265,7 @@ class Updater(object):
|
||||
return self.update_queue
|
||||
|
||||
def _start_polling(self, poll_interval, timeout, read_latency, bootstrap_retries, clean,
|
||||
allowed_updates):
|
||||
allowed_updates): # pragma: no cover
|
||||
# """
|
||||
# Thread target of thread 'updater'. Runs in background, pulls
|
||||
# updates from Telegram and inserts them in the update queue of the
|
||||
@@ -397,9 +410,7 @@ class Updater(object):
|
||||
updates = self.bot.get_updates(updates[-1].update_id + 1)
|
||||
|
||||
def stop(self):
|
||||
"""
|
||||
Stops the polling/webhook thread, the dispatcher and the job queue.
|
||||
"""
|
||||
"""Stops the polling/webhook thread, the dispatcher and the job queue."""
|
||||
|
||||
self.job_queue.stop()
|
||||
with self.__lock:
|
||||
@@ -447,15 +458,14 @@ class Updater(object):
|
||||
os._exit(1)
|
||||
|
||||
def idle(self, stop_signals=(SIGINT, SIGTERM, SIGABRT)):
|
||||
"""
|
||||
Blocks until one of the signals are received and stops the updater.
|
||||
"""Blocks until one of the signals are received and stops the updater.
|
||||
|
||||
Args:
|
||||
stop_signals (:obj:`iterable`): Iterable containing signals from the signal module that
|
||||
should be subscribed to. Updater.stop() will be called on receiving one of those
|
||||
signals. Defaults to (``SIGINT``, ``SIGTERM``, ``SIGABRT``).
|
||||
"""
|
||||
|
||||
"""
|
||||
for sig in stop_signals:
|
||||
signal(sig, self.signal_handler)
|
||||
|
||||
|
||||
@@ -22,8 +22,7 @@ from telegram import TelegramObject
|
||||
|
||||
|
||||
class Audio(TelegramObject):
|
||||
"""
|
||||
This object represents an audio file to be treated as music by the Telegram clients.
|
||||
"""This object represents an audio file to be treated as music by the Telegram clients.
|
||||
|
||||
Attributes:
|
||||
file_id (:obj:`str`): Unique identifier for this file.
|
||||
@@ -43,6 +42,7 @@ class Audio(TelegramObject):
|
||||
mime_type (:obj:`str`, optional): MIME type of the file as defined by sender.
|
||||
file_size (:obj:`int`, optional): File size.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
|
||||
@@ -24,8 +24,7 @@ from telegram import TelegramObject
|
||||
|
||||
|
||||
class ChatPhoto(TelegramObject):
|
||||
"""
|
||||
This object represents a chat photo.
|
||||
"""This object represents a chat photo.
|
||||
|
||||
Attributes:
|
||||
small_file_id (:obj:`str`): Unique file identifier of small (160x160) chat photo.
|
||||
@@ -38,6 +37,7 @@ class ChatPhoto(TelegramObject):
|
||||
can be used only for photo download.
|
||||
bot (:class:`telegram.Bot`, optional): The Bot to use for instance methods
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, small_file_id, big_file_id, bot=None, **kwargs):
|
||||
|
||||
@@ -22,8 +22,7 @@ from telegram import TelegramObject
|
||||
|
||||
|
||||
class Contact(TelegramObject):
|
||||
"""
|
||||
This object represents a phone contact.
|
||||
"""This object represents a phone contact.
|
||||
|
||||
Attributes:
|
||||
phone_number (:obj:`str`): Contact's phone number.
|
||||
@@ -37,6 +36,7 @@ class Contact(TelegramObject):
|
||||
last_name (:obj:`str`, optional): Contact's last name.
|
||||
user_id (:obj:`int`, optional): Contact's user identifier in Telegram.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, phone_number, first_name, last_name=None, user_id=None, **kwargs):
|
||||
|
||||
@@ -22,8 +22,7 @@ from telegram import PhotoSize, TelegramObject
|
||||
|
||||
|
||||
class Document(TelegramObject):
|
||||
"""
|
||||
This object represents a general file (as opposed to photos, voice messages and audio files).
|
||||
"""This object represents a general file (as opposed to photos, voice messages and audio files).
|
||||
|
||||
Attributes:
|
||||
file_id (:obj:`str`): Unique file identifier.
|
||||
@@ -39,8 +38,8 @@ class Document(TelegramObject):
|
||||
mime_type (:obj:`str`, optional): MIME type of the file as defined by sender.
|
||||
file_size (:obj:`int`, optional): File size.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
"""
|
||||
|
||||
"""
|
||||
_id_keys = ('file_id',)
|
||||
|
||||
def __init__(self,
|
||||
|
||||
@@ -44,6 +44,7 @@ class File(TelegramObject):
|
||||
file_path (:obj:`str`, optional): File path. Use :attr:`download` to get the file.
|
||||
bot (:obj:`telegram.Bot`, optional): Bot to use with shortcut method.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, file_id, bot=None, file_size=None, file_path=None, **kwargs):
|
||||
@@ -85,8 +86,8 @@ class File(TelegramObject):
|
||||
|
||||
Raises:
|
||||
ValueError: If both ``custom_path`` and ``out`` are passed.
|
||||
"""
|
||||
|
||||
"""
|
||||
if custom_path is not None and out is not None:
|
||||
raise ValueError('custom_path and out are mutually exclusive')
|
||||
|
||||
|
||||
+10
-18
@@ -40,8 +40,7 @@ FILE_TYPES = ('audio', 'document', 'photo', 'sticker', 'video', 'voice', 'certif
|
||||
|
||||
|
||||
class InputFile(object):
|
||||
"""
|
||||
This object represents a Telegram InputFile.
|
||||
"""This object represents a Telegram InputFile.
|
||||
|
||||
Attributes:
|
||||
data (:obj:`dict`): Data containing an inputfile.
|
||||
@@ -51,6 +50,7 @@ class InputFile(object):
|
||||
|
||||
Raises:
|
||||
TelegramError
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, data):
|
||||
@@ -88,28 +88,22 @@ class InputFile(object):
|
||||
|
||||
@property
|
||||
def headers(self):
|
||||
"""
|
||||
:obj:`dict`: Headers.
|
||||
"""
|
||||
""":obj:`dict`: Headers."""
|
||||
|
||||
return {'User-agent': USER_AGENT, 'Content-type': self.content_type}
|
||||
|
||||
@property
|
||||
def content_type(self):
|
||||
"""
|
||||
:obj:`str`: Content type
|
||||
"""
|
||||
|
||||
""":obj:`str`: Content type"""
|
||||
return 'multipart/form-data; boundary=%s' % self.boundary
|
||||
|
||||
def to_form(self):
|
||||
"""
|
||||
Transform the inputfile to multipart/form data.
|
||||
"""Transform the inputfile to multipart/form data.
|
||||
|
||||
Returns:
|
||||
:obj:`str`
|
||||
"""
|
||||
|
||||
"""
|
||||
form = []
|
||||
form_boundary = '--' + self.boundary
|
||||
|
||||
@@ -148,16 +142,15 @@ class InputFile(object):
|
||||
|
||||
@staticmethod
|
||||
def is_image(stream):
|
||||
"""
|
||||
Check if the content file is an image by analyzing its headers.
|
||||
"""Check if the content file is an image by analyzing its headers.
|
||||
|
||||
Args:
|
||||
stream (:obj:`str`): A str representing the content of a file.
|
||||
|
||||
Returns:
|
||||
:obj:`str`: The str mime-type of an image.
|
||||
"""
|
||||
|
||||
"""
|
||||
image = imghdr.what(None, stream)
|
||||
if image:
|
||||
return 'image/%s' % image
|
||||
@@ -166,16 +159,15 @@ class InputFile(object):
|
||||
|
||||
@staticmethod
|
||||
def is_inputfile(data):
|
||||
"""
|
||||
Check if the request is a file request.
|
||||
"""Check if the request is a file request.
|
||||
|
||||
Args:
|
||||
data (Dict[:obj:`str`, :obj:`str`]): A dict of (str, str) key/value pairs.
|
||||
|
||||
Returns:
|
||||
:obj:`bool`
|
||||
"""
|
||||
|
||||
"""
|
||||
if data:
|
||||
file_type = [i for i in iter(data) if i in FILE_TYPES]
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2017
|
||||
# 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/].
|
||||
"""Base class for Telegram InputMedia Objects."""
|
||||
|
||||
from telegram import TelegramObject
|
||||
|
||||
|
||||
class InputMedia(TelegramObject):
|
||||
"""Base class for Telegram InputMedia Objects.
|
||||
|
||||
See :class:`telegram.InputMediaPhoto` and :class:`telegram.InputMediaVideo` for
|
||||
detailed use.
|
||||
|
||||
"""
|
||||
pass
|
||||
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2017
|
||||
# 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 InputMediaPhoto."""
|
||||
from telegram import InputMedia, PhotoSize
|
||||
|
||||
|
||||
class InputMediaPhoto(InputMedia):
|
||||
"""Represents a photo to be sent.
|
||||
|
||||
Attributes:
|
||||
type (:obj:`str`): ``photo``.
|
||||
media (:obj:`str`): File to send. Pass a file_id to send a file that exists on the
|
||||
Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the
|
||||
Internet. Lastly you can pass an existing :class:`telegram.PhotoSize` object to send.
|
||||
caption (:obj:`str`): Optional. Caption of the photo to be sent, 0-200 characters.
|
||||
|
||||
Args:
|
||||
media (:obj:`str`): File to send. Pass a file_id to send a file that exists on the
|
||||
Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the
|
||||
Internet. Lastly you can pass an existing :class:`telegram.PhotoSize` object to send.
|
||||
caption (:obj:`str`, optional ): Caption of the photo to be sent, 0-200 characters.
|
||||
|
||||
Note:
|
||||
At the moment using a new file is not yet supported.
|
||||
"""
|
||||
|
||||
# TODO: Make InputMediaPhoto, InputMediaVideo and send_media_group work with new files
|
||||
|
||||
def __init__(self, media, caption=None):
|
||||
self.type = 'photo'
|
||||
|
||||
if isinstance(media, PhotoSize):
|
||||
self.media = media.file_id
|
||||
elif hasattr(media, 'read'):
|
||||
raise ValueError(
|
||||
'Sending files is not supported (yet). Use file_id, url or PhotoSize')
|
||||
else:
|
||||
self.media = media
|
||||
|
||||
if caption:
|
||||
self.caption = caption
|
||||
@@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2017
|
||||
# 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 InputMediaPhoto."""
|
||||
from telegram import InputMedia, Video
|
||||
|
||||
|
||||
class InputMediaVideo(InputMedia):
|
||||
"""Represents a video to be sent.
|
||||
|
||||
Attributes:
|
||||
type (:obj:`str`): ``video``.
|
||||
media (:obj:`str`): File to send. Pass a file_id to send a file that exists on the Telegram
|
||||
servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet.
|
||||
Lastly you can pass an existing :class:`telegram.Video` object to send.
|
||||
caption (:obj:`str`): Optional. Caption of the video to be sent, 0-200 characters.
|
||||
width (:obj:`int`): Optional. Video width.
|
||||
height (:obj:`int`): Optional. Video height.
|
||||
duration (:obj:`int`): Optional. Video duration.
|
||||
|
||||
Args:
|
||||
media (:obj:`str`): File to send. Pass a file_id to send a file that exists on the Telegram
|
||||
servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet.
|
||||
Lastly you can pass an existing :class:`telegram.Video` object to send.
|
||||
caption (:obj:`str`, optional): Caption of the video to be sent, 0-200 characters.
|
||||
width (:obj:`int`, optional): Video width.
|
||||
height (:obj:`int`, optional): Video height.
|
||||
duration (:obj:`int`, optional): Video duration.
|
||||
|
||||
Note:
|
||||
When using a :class:`telegram.Video` for the :attr:`media` attribute. It will take the
|
||||
width, height and duration from that video, unless otherwise specified with the optional
|
||||
arguments.
|
||||
At the moment using a new file is not yet supported.
|
||||
"""
|
||||
|
||||
# TODO: Make InputMediaPhoto, InputMediaVideo and send_media_group work with new files
|
||||
|
||||
def __init__(self, media, caption=None, width=None, height=None, duration=None):
|
||||
self.type = 'video'
|
||||
|
||||
if isinstance(media, Video):
|
||||
self.media = media.file_id
|
||||
self.width = media.width
|
||||
self.height = media.height
|
||||
self.duration = media.duration
|
||||
elif hasattr(media, 'read'):
|
||||
raise ValueError('Sending files is not supported (yet). Use file_id, url or Video')
|
||||
else:
|
||||
self.media = media
|
||||
|
||||
if caption:
|
||||
self.caption = caption
|
||||
if width:
|
||||
self.width = width
|
||||
if height:
|
||||
self.height = height
|
||||
if duration:
|
||||
self.duration = duration
|
||||
@@ -22,8 +22,7 @@ from telegram import TelegramObject
|
||||
|
||||
|
||||
class Location(TelegramObject):
|
||||
"""
|
||||
This object represents a point on the map.
|
||||
"""This object represents a point on the map.
|
||||
|
||||
Attributes:
|
||||
longitude (:obj:`float`): Longitude as defined by sender.
|
||||
@@ -33,6 +32,7 @@ class Location(TelegramObject):
|
||||
longitude (:obj:`float`): Longitude as defined by sender.
|
||||
latitude (:obj:`float`): Latitude as defined by sender.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, longitude, latitude, **kwargs):
|
||||
|
||||
@@ -22,8 +22,7 @@ from telegram import TelegramObject
|
||||
|
||||
|
||||
class PhotoSize(TelegramObject):
|
||||
"""
|
||||
This object represents one size of a photo or a file/sticker thumbnail.
|
||||
"""This object represents one size of a photo or a file/sticker thumbnail.
|
||||
|
||||
Attributes:
|
||||
file_id (:obj:`str`): Unique identifier for this file.
|
||||
@@ -37,6 +36,7 @@ class PhotoSize(TelegramObject):
|
||||
height (:obj:`int`): Photo height.
|
||||
file_size (:obj:`int`, optional): File size.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, file_id, width, height, file_size=None, **kwargs):
|
||||
|
||||
@@ -22,8 +22,7 @@ from telegram import PhotoSize, TelegramObject
|
||||
|
||||
|
||||
class Sticker(TelegramObject):
|
||||
"""
|
||||
This object represents a sticker.
|
||||
"""This object represents a sticker.
|
||||
|
||||
Attributes:
|
||||
file_id (:obj:`str`): Unique identifier for this file.
|
||||
@@ -50,6 +49,7 @@ class Sticker(TelegramObject):
|
||||
position where the mask should be placed.
|
||||
file_size (:obj:`int`, optional): File size.
|
||||
**kwargs (obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -96,8 +96,7 @@ class Sticker(TelegramObject):
|
||||
|
||||
|
||||
class StickerSet(TelegramObject):
|
||||
"""
|
||||
This object represents a sticker set.
|
||||
"""This object represents a sticker set.
|
||||
|
||||
Attributes:
|
||||
name (:obj:`str`): Sticker set name.
|
||||
@@ -110,6 +109,7 @@ class StickerSet(TelegramObject):
|
||||
title (:obj:`str`): Sticker set title.
|
||||
contains_masks (:obj:`bool`): True, if the sticker set contains masks.
|
||||
stickers (List[:class:`telegram.Sticker`]): List of all set stickers.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, name, title, contains_masks, stickers, bot=None, **kwargs):
|
||||
@@ -140,8 +140,7 @@ class StickerSet(TelegramObject):
|
||||
|
||||
|
||||
class MaskPosition(TelegramObject):
|
||||
"""
|
||||
This object describes the position on faces where a mask should be placed by default.
|
||||
"""This object describes the position on faces where a mask should be placed by default.
|
||||
|
||||
Attributes:
|
||||
point (:obj:`str`): The part of the face relative to which the mask should be placed.
|
||||
@@ -164,8 +163,8 @@ class MaskPosition(TelegramObject):
|
||||
size, from top to bottom. For example, 1.0 will place the mask just below the default
|
||||
mask position.
|
||||
scale (:obj:`float`): Mask scaling coefficient. For example, 2.0 means double size.
|
||||
"""
|
||||
|
||||
"""
|
||||
FOREHEAD = 'forehead'
|
||||
""":obj:`str`: 'forehead'"""
|
||||
EYES = 'eyes'
|
||||
|
||||
@@ -22,8 +22,7 @@ from telegram import TelegramObject, Location
|
||||
|
||||
|
||||
class Venue(TelegramObject):
|
||||
"""
|
||||
This object represents a venue.
|
||||
"""This object represents a venue.
|
||||
|
||||
Attributes:
|
||||
location (:class:`telegram.Location`): Venue location.
|
||||
@@ -37,6 +36,7 @@ class Venue(TelegramObject):
|
||||
address (:obj:`str`): Address of the venue.
|
||||
foursquare_id (:obj:`str`, optional): Foursquare identifier of the venue.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, location, title, address, foursquare_id=None, **kwargs):
|
||||
|
||||
@@ -22,8 +22,7 @@ from telegram import PhotoSize, TelegramObject
|
||||
|
||||
|
||||
class Video(TelegramObject):
|
||||
"""
|
||||
This object represents a video file.
|
||||
"""This object represents a video file.
|
||||
|
||||
Attributes:
|
||||
file_id (:obj:`str`): Unique identifier for this file.
|
||||
@@ -43,6 +42,7 @@ class Video(TelegramObject):
|
||||
mime_type (:obj:`str`, optional): Mime type of a file as defined by sender.
|
||||
file_size (:obj:`int`, optional): File size.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
|
||||
@@ -22,8 +22,7 @@ from telegram import PhotoSize, TelegramObject
|
||||
|
||||
|
||||
class VideoNote(TelegramObject):
|
||||
"""
|
||||
This object represents a video message (available in Telegram apps as of v.4.0).
|
||||
"""This object represents a video message (available in Telegram apps as of v.4.0).
|
||||
|
||||
Attributes:
|
||||
file_id (:obj:`str`): Unique identifier for this file.
|
||||
@@ -39,6 +38,7 @@ class VideoNote(TelegramObject):
|
||||
thumb (:class:`telegram.PhotoSize`, optional): Video thumbnail.
|
||||
file_size (:obj:`int`, optional): File size.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, file_id, length, duration, thumb=None, file_size=None, **kwargs):
|
||||
|
||||
@@ -22,8 +22,7 @@ from telegram import TelegramObject
|
||||
|
||||
|
||||
class Voice(TelegramObject):
|
||||
"""
|
||||
This object represents a voice note.
|
||||
"""This object represents a voice note.
|
||||
|
||||
Attributes:
|
||||
file_id (:obj:`str`): Unique identifier for this file.
|
||||
@@ -37,6 +36,7 @@ class Voice(TelegramObject):
|
||||
mime_type (:obj:`str`, optional): MIME type of the file as defined by sender.
|
||||
file_size (:obj:`int`, optional): File size.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, file_id, duration, mime_type=None, file_size=None, **kwargs):
|
||||
|
||||
@@ -41,6 +41,7 @@ class ForceReply(ReplyMarkup):
|
||||
original message.
|
||||
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, force_reply=True, selective=False, **kwargs):
|
||||
@@ -48,10 +49,3 @@ class ForceReply(ReplyMarkup):
|
||||
self.force_reply = bool(force_reply)
|
||||
# Optionals
|
||||
self.selective = bool(selective)
|
||||
|
||||
@classmethod
|
||||
def de_json(cls, data, bot):
|
||||
if not data:
|
||||
return None
|
||||
|
||||
return cls(**data)
|
||||
|
||||
@@ -22,8 +22,7 @@ from telegram import TelegramObject
|
||||
|
||||
|
||||
class Animation(TelegramObject):
|
||||
"""
|
||||
This object represents an animation file to be displayed in the message containing a game.
|
||||
"""This object represents an animation file to be displayed in the message containing a game.
|
||||
|
||||
Attributes:
|
||||
file_id (:obj:`str`): Unique file identifier.
|
||||
@@ -39,6 +38,7 @@ class Animation(TelegramObject):
|
||||
file_name (:obj:`str`, optional): Original animation filename as defined by sender.
|
||||
mime_type (:obj:`str`, optional): MIME type of the file as defined by sender.
|
||||
file_size (:obj:`int`, optional): File size.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
|
||||
@@ -22,6 +22,4 @@ from telegram import TelegramObject
|
||||
|
||||
|
||||
class CallbackGame(TelegramObject):
|
||||
"""
|
||||
A placeholder, currently holds no information. Use BotFather to set up your game.
|
||||
"""
|
||||
"""A placeholder, currently holds no information. Use BotFather to set up your game."""
|
||||
|
||||
@@ -54,6 +54,7 @@ class Game(TelegramObject):
|
||||
appear in text, such as usernames, URLs, bot commands, etc.
|
||||
animation (:class:`telegram.Animation`, optional): Animation that will be displayed in the
|
||||
game message in chats. Upload via BotFather.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -68,7 +69,7 @@ class Game(TelegramObject):
|
||||
self.description = description
|
||||
self.photo = photo
|
||||
self.text = text
|
||||
self.text_entities = text_entities
|
||||
self.text_entities = text_entities or list()
|
||||
self.animation = animation
|
||||
|
||||
@classmethod
|
||||
@@ -88,13 +89,13 @@ class Game(TelegramObject):
|
||||
data = super(Game, self).to_dict()
|
||||
|
||||
data['photo'] = [p.to_dict() for p in self.photo]
|
||||
data['text_entities'] = [x.to_dict() for x in self.text_entities]
|
||||
if self.text_entities:
|
||||
data['text_entities'] = [x.to_dict() for x in self.text_entities]
|
||||
|
||||
return data
|
||||
|
||||
def parse_text_entity(self, entity):
|
||||
"""
|
||||
Returns the text from a given :class:`telegram.MessageEntity`.
|
||||
"""Returns the text from a given :class:`telegram.MessageEntity`.
|
||||
|
||||
Note:
|
||||
This method is present because Telegram calculates the offset and length in
|
||||
@@ -107,8 +108,8 @@ class Game(TelegramObject):
|
||||
|
||||
Returns:
|
||||
:obj:`str`: The text of the given entity.
|
||||
"""
|
||||
|
||||
"""
|
||||
# Is it a narrow build, if so we don't need to convert
|
||||
if sys.maxunicode == 0xffff:
|
||||
return self.text[entity.offset:entity.offset + entity.length]
|
||||
@@ -137,8 +138,8 @@ class Game(TelegramObject):
|
||||
Returns:
|
||||
Dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
|
||||
the text that belongs to them, calculated based on UTF-16 codepoints.
|
||||
"""
|
||||
|
||||
"""
|
||||
if types is None:
|
||||
types = MessageEntity.ALL_TYPES
|
||||
|
||||
|
||||
@@ -22,8 +22,7 @@ from telegram import TelegramObject, User
|
||||
|
||||
|
||||
class GameHighScore(TelegramObject):
|
||||
"""
|
||||
This object represents one row of the high scores table for a game.
|
||||
"""This object represents one row of the high scores table for a game.
|
||||
|
||||
Attributes:
|
||||
position (:obj:`int`): Position in high score table for the game.
|
||||
@@ -34,6 +33,7 @@ class GameHighScore(TelegramObject):
|
||||
position (:obj:`int`): Position in high score table for the game.
|
||||
user (:class:`telegram.User`): User.
|
||||
score (:obj:`int`): Score.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, position, user, score):
|
||||
|
||||
@@ -16,15 +16,13 @@
|
||||
#
|
||||
# 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
|
||||
InlineKeyboardButton"""
|
||||
"""This module contains an object that represents a Telegram InlineKeyboardButton."""
|
||||
|
||||
from telegram import TelegramObject
|
||||
|
||||
|
||||
class InlineKeyboardButton(TelegramObject):
|
||||
"""
|
||||
This object represents one button of an inline keyboard.
|
||||
"""This object represents one button of an inline keyboard.
|
||||
|
||||
Note:
|
||||
You must use exactly one of the optional fields. Mind that :attr:`callback_game` is not
|
||||
@@ -67,6 +65,7 @@ class InlineKeyboardButton(TelegramObject):
|
||||
pay (:obj:`bool`, optional): Specify True, to send a Pay button. This type of button must
|
||||
always be the ``first`` button in the first row.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -88,23 +87,3 @@ class InlineKeyboardButton(TelegramObject):
|
||||
self.switch_inline_query_current_chat = switch_inline_query_current_chat
|
||||
self.callback_game = callback_game
|
||||
self.pay = pay
|
||||
|
||||
@classmethod
|
||||
def de_json(cls, data, bot):
|
||||
data = super(InlineKeyboardButton, cls).de_json(data, bot)
|
||||
|
||||
if not data:
|
||||
return None
|
||||
|
||||
return cls(**data)
|
||||
|
||||
@classmethod
|
||||
def de_list(cls, data, bot):
|
||||
if not data:
|
||||
return []
|
||||
|
||||
inline_keyboards = list()
|
||||
for inline_keyboard in data:
|
||||
inline_keyboards.append(cls.de_json(inline_keyboard, bot))
|
||||
|
||||
return inline_keyboards
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a Telegram InlineKeyboardMarkup."""
|
||||
|
||||
from telegram import ReplyMarkup, InlineKeyboardButton
|
||||
from telegram import ReplyMarkup
|
||||
|
||||
|
||||
class InlineKeyboardMarkup(ReplyMarkup):
|
||||
@@ -33,26 +33,13 @@ class InlineKeyboardMarkup(ReplyMarkup):
|
||||
inline_keyboard (List[List[:class:`telegram.InlineKeyboardButton`]]): Array of button rows,
|
||||
each represented by an Array of InlineKeyboardButton objects.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, inline_keyboard, **kwargs):
|
||||
# Required
|
||||
self.inline_keyboard = inline_keyboard
|
||||
|
||||
@classmethod
|
||||
def de_json(cls, data, bot):
|
||||
data = super(InlineKeyboardMarkup, cls).de_json(data, bot)
|
||||
|
||||
if not data:
|
||||
return None
|
||||
|
||||
data['inline_keyboard'] = [
|
||||
InlineKeyboardButton.de_list(inline_keyboard, bot)
|
||||
for inline_keyboard in data['inline_keyboard']
|
||||
]
|
||||
|
||||
return cls(**data)
|
||||
|
||||
def to_dict(self):
|
||||
data = super(InlineKeyboardMarkup, self).to_dict()
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a Telegram InlineQuery"""
|
||||
"""This module contains an object that represents a Telegram InlineQuery."""
|
||||
|
||||
from telegram import TelegramObject, User, Location
|
||||
|
||||
@@ -47,6 +47,7 @@ class InlineQuery(TelegramObject):
|
||||
offset (:obj:`str`): Offset of the results to be returned, can be controlled by the bot.
|
||||
bot (:class:`telegram.Bot`, optional): The Bot to use for instance methods.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, id, from_user, query, offset, location=None, bot=None, **kwargs):
|
||||
@@ -83,10 +84,9 @@ class InlineQuery(TelegramObject):
|
||||
return data
|
||||
|
||||
def answer(self, *args, **kwargs):
|
||||
"""
|
||||
Shortcut for::
|
||||
"""Shortcut for::
|
||||
|
||||
bot.answer_inline_query(update.inline_query.id, *args, **kwargs)
|
||||
bot.answer_inline_query(update.inline_query.id, *args, **kwargs)
|
||||
|
||||
Args:
|
||||
results (List[:class:`telegram.InlineQueryResult`]): A list of results for the inline
|
||||
@@ -106,6 +106,6 @@ class InlineQuery(TelegramObject):
|
||||
switch_pm_parameter (:obj:`str`, optional): Deep-linking parameter for the /start
|
||||
message sent to the bot when user presses the switch button. 1-64 characters,
|
||||
only A-Z, a-z, 0-9, _ and - are allowed.
|
||||
"""
|
||||
|
||||
"""
|
||||
return self.bot.answer_inline_query(self.id, *args, **kwargs)
|
||||
|
||||
@@ -16,14 +16,13 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains the classes that represent Telegram InlineQueryResult"""
|
||||
"""This module contains the classes that represent Telegram InlineQueryResult."""
|
||||
|
||||
from telegram import TelegramObject
|
||||
|
||||
|
||||
class InlineQueryResult(TelegramObject):
|
||||
"""
|
||||
Baseclass for the InlineQueryResult* classes.
|
||||
"""Baseclass for the InlineQueryResult* classes.
|
||||
|
||||
Attributes:
|
||||
type (:obj:`str`): Type of the result.
|
||||
@@ -33,6 +32,7 @@ class InlineQueryResult(TelegramObject):
|
||||
type (:obj:`str`): Type of the result.
|
||||
id (:obj:`str`): Unique identifier for this result, 1-64 Bytes.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, type, id, **kwargs):
|
||||
|
||||
@@ -16,10 +16,9 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains the classes that represent Telegram
|
||||
InlineQueryResultArticle"""
|
||||
"""This module contains the classes that represent Telegram InlineQueryResultArticle."""
|
||||
|
||||
from telegram import InlineQueryResult, InlineKeyboardMarkup, InputMessageContent
|
||||
from telegram import InlineQueryResult
|
||||
|
||||
|
||||
class InlineQueryResultArticle(InlineQueryResult):
|
||||
@@ -56,6 +55,7 @@ class InlineQueryResultArticle(InlineQueryResult):
|
||||
thumb_width (:obj:`int`, optional): Thumbnail width.
|
||||
thumb_height (:obj:`int`, optional): Thumbnail height.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -91,16 +91,3 @@ class InlineQueryResultArticle(InlineQueryResult):
|
||||
self.thumb_width = thumb_width
|
||||
if thumb_height:
|
||||
self.thumb_height = thumb_height
|
||||
|
||||
@classmethod
|
||||
def de_json(cls, data, bot):
|
||||
data = super(InlineQueryResultArticle, cls).de_json(data, bot)
|
||||
|
||||
if not data:
|
||||
return None
|
||||
|
||||
data['reply_markup'] = InlineKeyboardMarkup.de_json(data.get('reply_markup'), bot)
|
||||
data['input_message_content'] = InputMessageContent.de_json(
|
||||
data.get('input_message_content'), bot)
|
||||
|
||||
return cls(**data)
|
||||
|
||||
@@ -16,10 +16,9 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains the classes that represent Telegram
|
||||
InlineQueryResultAudio"""
|
||||
"""This module contains the classes that represent Telegram InlineQueryResultAudio."""
|
||||
|
||||
from telegram import InlineQueryResult, InlineKeyboardMarkup, InputMessageContent
|
||||
from telegram import InlineQueryResult
|
||||
|
||||
|
||||
class InlineQueryResultAudio(InlineQueryResult):
|
||||
@@ -53,6 +52,7 @@ class InlineQueryResultAudio(InlineQueryResult):
|
||||
input_message_content (:class:`telegram.InputMessageContent`, optional): Content of the
|
||||
message to be sent instead of the audio.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -82,16 +82,3 @@ class InlineQueryResultAudio(InlineQueryResult):
|
||||
self.reply_markup = reply_markup
|
||||
if input_message_content:
|
||||
self.input_message_content = input_message_content
|
||||
|
||||
@classmethod
|
||||
def de_json(cls, data, bot):
|
||||
data = super(InlineQueryResultAudio, cls).de_json(data, bot)
|
||||
|
||||
if not data:
|
||||
return None
|
||||
|
||||
data['reply_markup'] = InlineKeyboardMarkup.de_json(data.get('reply_markup'), bot)
|
||||
data['input_message_content'] = InputMessageContent.de_json(
|
||||
data.get('input_message_content'), bot)
|
||||
|
||||
return cls(**data)
|
||||
|
||||
@@ -16,10 +16,9 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains the classes that represent Telegram
|
||||
InlineQueryResultCachedAudio"""
|
||||
"""This module contains the classes that represent Telegram InlineQueryResultCachedAudio."""
|
||||
|
||||
from telegram import InlineQueryResult, InlineKeyboardMarkup, InputMessageContent
|
||||
from telegram import InlineQueryResult
|
||||
|
||||
|
||||
class InlineQueryResultCachedAudio(InlineQueryResult):
|
||||
@@ -47,6 +46,7 @@ class InlineQueryResultCachedAudio(InlineQueryResult):
|
||||
input_message_content (:class:`telegram.InputMessageContent`, optional): Content of the
|
||||
message to be sent instead of the audio.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -67,16 +67,3 @@ class InlineQueryResultCachedAudio(InlineQueryResult):
|
||||
self.reply_markup = reply_markup
|
||||
if input_message_content:
|
||||
self.input_message_content = input_message_content
|
||||
|
||||
@classmethod
|
||||
def de_json(cls, data, bot):
|
||||
data = super(InlineQueryResultCachedAudio, cls).de_json(data, bot)
|
||||
|
||||
if not data:
|
||||
return None
|
||||
|
||||
data['reply_markup'] = InlineKeyboardMarkup.de_json(data.get('reply_markup'), bot)
|
||||
data['input_message_content'] = InputMessageContent.de_json(
|
||||
data.get('input_message_content'), bot)
|
||||
|
||||
return cls(**data)
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains the classes that represent Telegram InlineQueryResultCachedDocument"""
|
||||
"""This module contains the classes that represent Telegram InlineQueryResultCachedDocument."""
|
||||
|
||||
from telegram import InlineQueryResult, InlineKeyboardMarkup, InputMessageContent
|
||||
from telegram import InlineQueryResult
|
||||
|
||||
|
||||
class InlineQueryResultCachedDocument(InlineQueryResult):
|
||||
@@ -50,6 +50,7 @@ class InlineQueryResultCachedDocument(InlineQueryResult):
|
||||
input_message_content (:class:`telegram.InputMessageContent`, optional): Content of the
|
||||
message to be sent instead of the file.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -75,16 +76,3 @@ class InlineQueryResultCachedDocument(InlineQueryResult):
|
||||
self.reply_markup = reply_markup
|
||||
if input_message_content:
|
||||
self.input_message_content = input_message_content
|
||||
|
||||
@classmethod
|
||||
def de_json(cls, data, bot):
|
||||
data = super(InlineQueryResultCachedDocument, cls).de_json(data, bot)
|
||||
|
||||
if not data:
|
||||
return None
|
||||
|
||||
data['reply_markup'] = InlineKeyboardMarkup.de_json(data.get('reply_markup'), bot)
|
||||
data['input_message_content'] = InputMessageContent.de_json(
|
||||
data.get('input_message_content'), bot)
|
||||
|
||||
return cls(**data)
|
||||
|
||||
@@ -16,10 +16,9 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains the classes that represent Telegram
|
||||
InlineQueryResultCachedGif"""
|
||||
"""This module contains the classes that represent Telegram InlineQueryResultCachedGif."""
|
||||
|
||||
from telegram import InlineQueryResult, InlineKeyboardMarkup, InputMessageContent
|
||||
from telegram import InlineQueryResult
|
||||
|
||||
|
||||
class InlineQueryResultCachedGif(InlineQueryResult):
|
||||
@@ -50,6 +49,7 @@ class InlineQueryResultCachedGif(InlineQueryResult):
|
||||
input_message_content (:class:`telegram.InputMessageContent`, optional): Content of the
|
||||
message to be sent instead of the gif.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -73,16 +73,3 @@ class InlineQueryResultCachedGif(InlineQueryResult):
|
||||
self.reply_markup = reply_markup
|
||||
if input_message_content:
|
||||
self.input_message_content = input_message_content
|
||||
|
||||
@classmethod
|
||||
def de_json(cls, data, bot):
|
||||
data = super(InlineQueryResultCachedGif, cls).de_json(data, bot)
|
||||
|
||||
if not data:
|
||||
return None
|
||||
|
||||
data['reply_markup'] = InlineKeyboardMarkup.de_json(data.get('reply_markup'), bot)
|
||||
data['input_message_content'] = InputMessageContent.de_json(
|
||||
data.get('input_message_content'), bot)
|
||||
|
||||
return cls(**data)
|
||||
|
||||
@@ -16,10 +16,9 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains the classes that represent Telegram
|
||||
InlineQueryResultMpeg4Gif"""
|
||||
"""This module contains the classes that represent Telegram InlineQueryResultMpeg4Gif."""
|
||||
|
||||
from telegram import InlineQueryResult, InlineKeyboardMarkup, InputMessageContent
|
||||
from telegram import InlineQueryResult
|
||||
|
||||
|
||||
class InlineQueryResultCachedMpeg4Gif(InlineQueryResult):
|
||||
@@ -50,6 +49,7 @@ class InlineQueryResultCachedMpeg4Gif(InlineQueryResult):
|
||||
input_message_content (:class:`telegram.InputMessageContent`, optional): Content of the
|
||||
message to be sent instead of the MPEG-4 file.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -73,16 +73,3 @@ class InlineQueryResultCachedMpeg4Gif(InlineQueryResult):
|
||||
self.reply_markup = reply_markup
|
||||
if input_message_content:
|
||||
self.input_message_content = input_message_content
|
||||
|
||||
@classmethod
|
||||
def de_json(cls, data, bot):
|
||||
data = super(InlineQueryResultCachedMpeg4Gif, cls).de_json(data, bot)
|
||||
|
||||
if not data:
|
||||
return None
|
||||
|
||||
data['reply_markup'] = InlineKeyboardMarkup.de_json(data.get('reply_markup'), bot)
|
||||
data['input_message_content'] = InputMessageContent.de_json(
|
||||
data.get('input_message_content'), bot)
|
||||
|
||||
return cls(**data)
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains the classes that represent Telegram InlineQueryResultPhoto"""
|
||||
|
||||
from telegram import InlineQueryResult, InlineKeyboardMarkup, InputMessageContent
|
||||
from telegram import InlineQueryResult
|
||||
|
||||
|
||||
class InlineQueryResultCachedPhoto(InlineQueryResult):
|
||||
@@ -51,6 +51,7 @@ class InlineQueryResultCachedPhoto(InlineQueryResult):
|
||||
input_message_content (:class:`telegram.InputMessageContent`, optional): Content of the
|
||||
message to be sent instead of the photo.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -77,16 +78,3 @@ class InlineQueryResultCachedPhoto(InlineQueryResult):
|
||||
self.reply_markup = reply_markup
|
||||
if input_message_content:
|
||||
self.input_message_content = input_message_content
|
||||
|
||||
@classmethod
|
||||
def de_json(cls, data, bot):
|
||||
data = super(InlineQueryResultCachedPhoto, cls).de_json(data, bot)
|
||||
|
||||
if not data:
|
||||
return None
|
||||
|
||||
data['reply_markup'] = InlineKeyboardMarkup.de_json(data.get('reply_markup'), bot)
|
||||
data['input_message_content'] = InputMessageContent.de_json(
|
||||
data.get('input_message_content'), bot)
|
||||
|
||||
return cls(**data)
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains the classes that represent Telegram InlineQueryResultCachedSticker"""
|
||||
"""This module contains the classes that represent Telegram InlineQueryResultCachedSticker."""
|
||||
|
||||
from telegram import InlineQueryResult, InlineKeyboardMarkup, InputMessageContent
|
||||
from telegram import InlineQueryResult
|
||||
|
||||
|
||||
class InlineQueryResultCachedSticker(InlineQueryResult):
|
||||
@@ -44,6 +44,7 @@ class InlineQueryResultCachedSticker(InlineQueryResult):
|
||||
input_message_content (:class:`telegram.InputMessageContent`, optional): Content of the
|
||||
message to be sent instead of the sticker.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -61,16 +62,3 @@ class InlineQueryResultCachedSticker(InlineQueryResult):
|
||||
self.reply_markup = reply_markup
|
||||
if input_message_content:
|
||||
self.input_message_content = input_message_content
|
||||
|
||||
@classmethod
|
||||
def de_json(cls, data, bot):
|
||||
data = super(InlineQueryResultCachedSticker, cls).de_json(data, bot)
|
||||
|
||||
if not data:
|
||||
return None
|
||||
|
||||
data['reply_markup'] = InlineKeyboardMarkup.de_json(data.get('reply_markup'), bot)
|
||||
data['input_message_content'] = InputMessageContent.de_json(
|
||||
data.get('input_message_content'), bot)
|
||||
|
||||
return cls(**data)
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains the classes that represent Telegram InlineQueryResultCachedVideo"""
|
||||
"""This module contains the classes that represent Telegram InlineQueryResultCachedVideo."""
|
||||
|
||||
from telegram import InlineQueryResult, InlineKeyboardMarkup, InputMessageContent
|
||||
from telegram import InlineQueryResult
|
||||
|
||||
|
||||
class InlineQueryResultCachedVideo(InlineQueryResult):
|
||||
@@ -51,6 +51,7 @@ class InlineQueryResultCachedVideo(InlineQueryResult):
|
||||
input_message_content (:class:`telegram.InputMessageContent`, optional): Content of the
|
||||
message to be sent instead of the video.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -76,16 +77,3 @@ class InlineQueryResultCachedVideo(InlineQueryResult):
|
||||
self.reply_markup = reply_markup
|
||||
if input_message_content:
|
||||
self.input_message_content = input_message_content
|
||||
|
||||
@classmethod
|
||||
def de_json(cls, data, bot):
|
||||
data = super(InlineQueryResultCachedVideo, cls).de_json(data, bot)
|
||||
|
||||
if not data:
|
||||
return None
|
||||
|
||||
data['reply_markup'] = InlineKeyboardMarkup.de_json(data.get('reply_markup'), bot)
|
||||
data['input_message_content'] = InputMessageContent.de_json(
|
||||
data.get('input_message_content'), bot)
|
||||
|
||||
return cls(**data)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user