mirror of
https://github.com/python-telegram-bot/python-telegram-bot.git
synced 2026-06-20 08:05:27 +00:00
Compare commits
219 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6479e15578 | |||
| 5dd3a660e3 | |||
| e2a651afc8 | |||
| 33512ffd2e | |||
| c2c5452829 | |||
| 9aa5522694 | |||
| 9720f59d7e | |||
| 578627feca | |||
| 257b8321f8 | |||
| 4f2ea5b0f1 | |||
| 9a2d5e0410 | |||
| 1b7f83625c | |||
| da01601ff9 | |||
| 752b64769d | |||
| f3b75d95c4 | |||
| 36b98b0ab4 | |||
| 05b85d4334 | |||
| f27807552f | |||
| f3aca42e69 | |||
| ed49bdb19c | |||
| 9f3afa5fa2 | |||
| cdf36a20b7 | |||
| c5598b96bc | |||
| ca4351079f | |||
| 34059c951d | |||
| c7dbdce3dc | |||
| fe5ae8ed84 | |||
| a6b28b022a | |||
| 284f16b87b | |||
| 785245a57e | |||
| 1d905d567c | |||
| 4541476143 | |||
| 11a3de67ea | |||
| 90bf26c09b | |||
| b5b09884b1 | |||
| 35132271af | |||
| 44d7bad11c | |||
| ad5f009ce7 | |||
| 8fe6e13ff2 | |||
| ff39e2436e | |||
| 5b14b134dc | |||
| 5897affa07 | |||
| 9982f3c908 | |||
| 22142e7cbd | |||
| 4c8d1c9a5e | |||
| bef6651da0 | |||
| 8c2ee0b439 | |||
| bfb99a688a | |||
| d239f4ee62 | |||
| 2b930c221d | |||
| 2a1d40bd28 | |||
| 1d4464ddbd | |||
| 85b9236641 | |||
| e78d11a99b | |||
| cc73469dab | |||
| 853d823964 | |||
| 69bfb85298 | |||
| f267646828 | |||
| 6b7144bbab | |||
| f8b13440c1 | |||
| a1ade408b0 | |||
| 2954ca2bad | |||
| 34ebb7fe5a | |||
| 78094b796d | |||
| fb378775a4 | |||
| 264b9bd08c | |||
| d714da4b36 | |||
| e39afad321 | |||
| 0507378509 | |||
| 659ac52d92 | |||
| 924c241680 | |||
| ac59f2f37c | |||
| 86c8ebbfb7 | |||
| cd38bdbed5 | |||
| 975d193441 | |||
| 728ffa432d | |||
| 8ac66698b5 | |||
| c2c93f5d51 | |||
| fc9f36d4db | |||
| e69e99ce23 | |||
| 27b2fd64b7 | |||
| 4dee785fba | |||
| 4c7cc3a05b | |||
| 1bb5dd224b | |||
| bd96771a7a | |||
| 191e442e59 | |||
| 58dddfd9c3 | |||
| 68a7d9fa1b | |||
| 38f2064639 | |||
| 651119fd69 | |||
| 232a0b0286 | |||
| 48bcc3129a | |||
| 6a01164897 | |||
| 7f6b017ce2 | |||
| 09cb33f52d | |||
| 423251f66c | |||
| ed1785981d | |||
| a8fecc527d | |||
| c3984e1bf1 | |||
| 93bf21a0a4 | |||
| cbf93e1046 | |||
| a1a8628c75 | |||
| d5ce32c672 | |||
| 09ddc1b1a8 | |||
| c7cd379016 | |||
| 84f3bc0c79 | |||
| 92dc9b81ce | |||
| 8ead72e3ef | |||
| a37add39f4 | |||
| 71530f404d | |||
| 0cd7ecab50 | |||
| c5f9e53d44 | |||
| acf1541395 | |||
| 906a1b8d7d | |||
| a2fddbe85c | |||
| 68e87db909 | |||
| a7bfb0c3a1 | |||
| e76ee6bb57 | |||
| 65061f8a99 | |||
| dabbbcafcb | |||
| 1eb4b40dbf | |||
| 7167936692 | |||
| aa3ca38837 | |||
| b22c3cc5c0 | |||
| 2786252a51 | |||
| 3f30f74024 | |||
| 79fc3be9cd | |||
| 71c73bdc74 | |||
| 761547e71d | |||
| 10bdf8212c | |||
| 45936c9982 | |||
| fae1896232 | |||
| 2518ddac22 | |||
| 61fe438a8b | |||
| 960862ccb1 | |||
| 4e5f4582dd | |||
| 225bc24c2a | |||
| a5f9aa3171 | |||
| 78088f4f6a | |||
| 59fa717023 | |||
| 31cab0d1b4 | |||
| 7fafaa1ea3 | |||
| e367b8519d | |||
| b610316667 | |||
| 39832d2f6b | |||
| 5408c23e33 | |||
| 62dd3a33e6 | |||
| 3754cdafb2 | |||
| 305ff93018 | |||
| 29e0cc64e9 | |||
| a5671a8fb1 | |||
| f99b2f8f3b | |||
| c626044a30 | |||
| a68cf8d464 | |||
| de96cc87ea | |||
| ca5e3146c6 | |||
| 53a574bbbb | |||
| 5b8efe0c14 | |||
| d07a1c3f67 | |||
| 32a78722ae | |||
| 04feeeff55 | |||
| a1495956aa | |||
| 8dc10fc7b2 | |||
| 7ad92dcc65 | |||
| d1ddfaddf0 | |||
| b7c7612b3f | |||
| ade89772f4 | |||
| 67b98e3190 | |||
| e672625a41 | |||
| 8cab735342 | |||
| bfb4c63d60 | |||
| 01a5a1c5b3 | |||
| 1db1b76a7c | |||
| 976f34082f | |||
| 6b7788570c | |||
| 1f9d3163dd | |||
| 837e9d2964 | |||
| fab97df58a | |||
| d70fc48e94 | |||
| 36192912c2 | |||
| 34748ec228 | |||
| d5567cd9cd | |||
| 2463b4b9c8 | |||
| 7cf5009517 | |||
| 9b74625d4a | |||
| 4180c069b3 | |||
| 3a0f219783 | |||
| 3c889655c1 | |||
| c2b8c4bf95 | |||
| 8234321a20 | |||
| 5e2d96b47d | |||
| 551f6c556c | |||
| ae17eb3272 | |||
| 358dd795c7 | |||
| 151a441af7 | |||
| 1f67623615 | |||
| 8737b5de63 | |||
| f3b8a3a5e9 | |||
| 9e9309eb90 | |||
| e8a34d8eef | |||
| 34c62a633b | |||
| 868d9217bc | |||
| f7ede4baea | |||
| c3e07b1056 | |||
| 79bdfe4c5d | |||
| 46657afa95 | |||
| 79e065a730 | |||
| 9928a1eefc | |||
| 0e2c3666c0 | |||
| a996e8873f | |||
| 3244417f61 | |||
| 61596400e1 | |||
| be0f5bc519 | |||
| 921fbae2f3 | |||
| 2161681131 | |||
| 9d0e0386d9 | |||
| dc7a459511 | |||
| be675f0118 | |||
| 71e74da0a2 |
+4
-1
@@ -1,5 +1,8 @@
|
||||
[run]
|
||||
source = telegram
|
||||
omit = telegram/vendor/*
|
||||
|
||||
[report]
|
||||
omit = tests/
|
||||
omit =
|
||||
tests/
|
||||
telegram/vendor/*
|
||||
|
||||
@@ -85,6 +85,12 @@ Here's how to make a one-off code change.
|
||||
|
||||
$ make test
|
||||
|
||||
If you don't have ``make``, do:
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ nosetests -v
|
||||
|
||||
- To actually make the commit (this will trigger tests for yapf, lint and pep8 automatically):
|
||||
|
||||
.. code-block:: bash
|
||||
@@ -184,11 +190,11 @@ break the API classes. For example:
|
||||
.. code-block:: python
|
||||
|
||||
# GOOD
|
||||
def __init__(self, id, name, **kwargs):
|
||||
self.last_name = kwargs.get('last_name', '')
|
||||
def __init__(self, id, name, last_name=None, **kwargs):
|
||||
self.last_name = last_name
|
||||
|
||||
# BAD
|
||||
def __init__(self, id, name, last_name=''):
|
||||
def __init__(self, id, name, last_name=None):
|
||||
self.last_name = last_name
|
||||
|
||||
|
||||
|
||||
@@ -68,3 +68,9 @@ telegram.mp4
|
||||
telegram.ogg
|
||||
telegram.png
|
||||
telegram.webp
|
||||
|
||||
# original files from merges
|
||||
*.orig
|
||||
|
||||
# Exclude .exrc file for Vim
|
||||
.exrc
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[submodule "telegram/vendor/urllib3"]
|
||||
path = telegram/vendor/urllib3
|
||||
url = https://github.com/python-telegram-bot/urllib3.git
|
||||
branch = ptb
|
||||
@@ -1,5 +1,5 @@
|
||||
- repo: git://github.com/pre-commit/mirrors-yapf
|
||||
sha: v0.11.0
|
||||
- repo: git://github.com/python-telegram-bot/mirrors-yapf
|
||||
sha: v0.12.2
|
||||
hooks:
|
||||
- id: yapf
|
||||
files: ^(telegram|tests)/.*\.py$
|
||||
|
||||
+6
-2
@@ -4,15 +4,19 @@ python:
|
||||
- "3.3"
|
||||
- "3.4"
|
||||
- "3.5"
|
||||
- "3.6"
|
||||
- "pypy"
|
||||
- "pypy3"
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
install:
|
||||
- pip install coveralls
|
||||
- pip install -r requirements.txt
|
||||
- pip install -r requirements-dev.txt
|
||||
- if [[ $TRAVIS_PYTHON_VERSION != 'pypy'* ]]; then pip install ujson; fi
|
||||
script:
|
||||
- nosetests -v --with-flaky --no-flaky-report --with-coverage --cover-package=telegram/
|
||||
- if [ $TRAVIS_PYTHON_VERSION != 3.3 ] && [ $TRAVIS_PYTHON_VERSION != pypy3 ]; then pre-commit run --all-files; fi
|
||||
- nosetests -v --with-flaky --no-flaky-report --with-coverage --cover-package=telegram/ tests
|
||||
- if [[ $TRAVIS_PYTHON_VERSION == 3.5 ]]; then pre-commit run --all-files; fi
|
||||
after_success:
|
||||
coveralls
|
||||
|
||||
+24
-1
@@ -1,7 +1,14 @@
|
||||
Credits
|
||||
=======
|
||||
|
||||
``python-telegram-bot`` is written and maintained by `Leandro Toledo <https://github.com/leandrotoledo>`_.
|
||||
``python-telegram-bot`` was originally created by
|
||||
`Leandro Toledo <https://github.com/leandrotoledo>`_ and is now maintained by
|
||||
`Jannes Höke <https://github.com/jh0ker>`_ (`@jh0ker <https://t.me/jh0ker>`_ on Telegram) and
|
||||
`Noam Meltzer <https://github.com/tsnoam>`_.
|
||||
|
||||
We're vendoring urllib3 as part of ``python-telegram-bot`` which is distributed under the MIT
|
||||
license. For more info, full credits & license terms, the sources can be found here:
|
||||
`https://github.com/python-telegram-bot/urllib3`.
|
||||
|
||||
Contributors
|
||||
------------
|
||||
@@ -9,27 +16,43 @@ Contributors
|
||||
The following wonderful people contributed directly or indirectly to this project:
|
||||
|
||||
- `Avanatiker <https://github.com/Avanatiker>`_
|
||||
- `Anton Tagunov <https://github.com/anton-tagunov>`_
|
||||
- `Balduro <https://github.com/Balduro>`_
|
||||
- `bimmlerd <https://github.com/bimmlerd>`_
|
||||
- `d-qoi <https://github.com/d-qoi>`_
|
||||
- `daimajia <https://github.com/daimajia>`_
|
||||
- `Eli Gao <https://github.com/eligao>`_
|
||||
- `ErgoZ Riftbit Vaper <https://github.com/ergoz>`_
|
||||
- `Eugene Lisitsky <https://github.com/lisitsky>`_
|
||||
- `evgfilim1 <https://github.com/evgfilim1>`_
|
||||
- `franciscod <https://github.com/franciscod>`_
|
||||
- `Hugo Damer <https://github.com/HakimusGIT>`_
|
||||
- `Jacob Bom <https://github.com/bomjacob>`_
|
||||
- `JASON0916 <https://github.com/JASON0916>`_
|
||||
- `jh0ker <https://github.com/jh0ker>`_
|
||||
- `John Yong <https://github.com/whipermr5>`_
|
||||
- `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>`_
|
||||
- `Michael Elovskikh <https://github.com/wronglink>`_
|
||||
- `naveenvhegde <https://github.com/naveenvhegde>`_
|
||||
- `neurrone <https://github.com/neurrone>`_
|
||||
- `njittam <https://github.com/njittam>`_
|
||||
- `Noam Meltzer <https://github.com/tsnoam>`_
|
||||
- `Oleg Shlyazhko <https://github.com/ollmer>`_
|
||||
- `overquota <https://github.com/overquota>`_
|
||||
- `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>`_
|
||||
- `Shelomentsev D <https://github.com/shelomentsevd>`_
|
||||
- `sooyhwang <https://github.com/sooyhwang>`_
|
||||
- `thodnev <https://github.com/thodnev>`_
|
||||
- `Valentijn <https://github.com/Faalentijn>`_
|
||||
- `voider1 <https://github.com/voider1>`_
|
||||
- `wjt <https://github.com/wjt>`_
|
||||
|
||||
Please add yourself here alphabetically when you submit your first pull request.
|
||||
|
||||
+48
@@ -2,6 +2,54 @@
|
||||
Changes
|
||||
=======
|
||||
|
||||
**2017-05-19**
|
||||
|
||||
*Released 6.0.0*
|
||||
|
||||
- Add support for Bot API 2.3.1
|
||||
- Add support for ``deleteMessage`` API method
|
||||
- New, simpler API for ``JobQueue`` - https://github.com/python-telegram-bot/python-telegram-bot/pull/484
|
||||
- Download files into file-like objects - https://github.com/python-telegram-bot/python-telegram-bot/pull/459
|
||||
- Use vendor ``urllib3`` to address issues with timeouts
|
||||
- The default timeout for messages is now 5 seconds. For sending media, the default timeout is now 20 seconds.
|
||||
- String attributes that are not set are now ``None`` by default, instead of empty strings
|
||||
- Add ``text_markdown`` and ``text_html`` properties to ``Message`` - https://github.com/python-telegram-bot/python-telegram-bot/pull/507
|
||||
- Add support for Socks5 proxy - https://github.com/python-telegram-bot/python-telegram-bot/pull/518
|
||||
- Add support for filters in ``CommandHandler`` - https://github.com/python-telegram-bot/python-telegram-bot/pull/536
|
||||
- Add the ability to invert (not) filters - https://github.com/python-telegram-bot/python-telegram-bot/pull/552
|
||||
- Add ``Filters.group`` and ``Filters.private``
|
||||
- Compatibility with GAE via ``urllib3.contrib`` package - https://github.com/python-telegram-bot/python-telegram-bot/pull/583
|
||||
- Add equality rich comparision operators to telegram objects - https://github.com/python-telegram-bot/python-telegram-bot/pull/604
|
||||
- Several bugfixes and other improvements
|
||||
- Remove some deprecated code
|
||||
|
||||
**2017-04-17**
|
||||
|
||||
*Released 5.3.1*
|
||||
|
||||
- Hotfix release due to bug introduced by urllib3 version 1.21
|
||||
|
||||
**2016-12-11**
|
||||
|
||||
*Released 5.3*
|
||||
|
||||
- Implement API changes of November 21st (Bot API 2.3)
|
||||
- ``JobQueue`` now supports ``datetime.timedelta`` in addition to seconds
|
||||
- ``JobQueue`` now supports running jobs only on certain days
|
||||
- New ``Filters.reply`` filter
|
||||
- Bugfix for ``Message.edit_reply_markup``
|
||||
- Other bugfixes
|
||||
|
||||
**2016-10-25**
|
||||
|
||||
*Released 5.2*
|
||||
|
||||
- Implement API changes of October 3rd (games update)
|
||||
- Add ``Message.edit_*`` methods
|
||||
- Filters for the ``MessageHandler`` can now be combined using bitwise operators (``& and |``)
|
||||
- Add a way to save user- and chat-related data temporarily
|
||||
- Other bugfixes and improvements
|
||||
|
||||
**2016-09-24**
|
||||
|
||||
*Released 5.1*
|
||||
|
||||
+13
-6
@@ -16,7 +16,7 @@ We have made you a wrapper you can't refuse
|
||||
:alt: Supported python versions
|
||||
|
||||
.. image:: https://img.shields.io/badge/docs-latest-af1a97.svg
|
||||
:target: https://pythonhosted.org/python-telegram-bot/
|
||||
:target: https://python-telegram-bot.readthedocs.io/
|
||||
:alt: Documentation Status
|
||||
|
||||
.. image:: https://img.shields.io/pypi/l/python-telegram-bot.svg
|
||||
@@ -37,7 +37,7 @@ We have made you a wrapper you can't refuse
|
||||
|
||||
.. image:: http://isitmaintained.com/badge/resolution/python-telegram-bot/python-telegram-bot.svg
|
||||
:target: http://isitmaintained.com/project/python-telegram-bot/python-telegram-bot
|
||||
:alt: Average time to resolve an issue
|
||||
:alt: Median time to resolve an issue
|
||||
|
||||
.. image:: https://img.shields.io/badge/Telegram-Group-blue.svg
|
||||
:target: https://telegram.me/pythontelegrambotgroup
|
||||
@@ -84,7 +84,7 @@ make the development of bots easy and straightforward. These classes are contain
|
||||
Telegram API support
|
||||
====================
|
||||
|
||||
As of **28. May 2016**, all types and methods of the Telegram Bot API are supported.
|
||||
As of **4. Dec 2016**, all types and methods of the Telegram Bot API are supported.
|
||||
|
||||
==========
|
||||
Installing
|
||||
@@ -100,9 +100,16 @@ Or you can install from source with:
|
||||
|
||||
.. code:: shell
|
||||
|
||||
$ git clone https://github.com/python-telegram-bot/python-telegram-bot
|
||||
$ git clone https://github.com/python-telegram-bot/python-telegram-bot --recursive
|
||||
$ cd python-telegram-bot
|
||||
$ python setup.py install
|
||||
|
||||
In case you have a previously cloned local repository already, you should initialize the added urllib3 submodule before installing with:
|
||||
|
||||
.. code:: shell
|
||||
|
||||
$ git submodule update --init --recursive
|
||||
|
||||
===============
|
||||
Getting started
|
||||
===============
|
||||
@@ -115,7 +122,7 @@ Our Wiki contains a lot of resources to get you started with ``python-telegram-b
|
||||
Other references:
|
||||
|
||||
- `Telegram API documentation <https://core.telegram.org/bots/api>`_
|
||||
- `python-telegram-bot documentation <https://pythonhosted.org/python-telegram-bot/>`_
|
||||
- `python-telegram-bot documentation <https://python-telegram-bot.readthedocs.io/>`_
|
||||
|
||||
-------------------
|
||||
Learning by example
|
||||
@@ -161,7 +168,7 @@ If you want DEBUG logs instead:
|
||||
Documentation
|
||||
=============
|
||||
|
||||
``python-telegram-bot``'s documentation lives at `pythonhosted.org <https://pythonhosted.org/python-telegram-bot/>`_.
|
||||
``python-telegram-bot``'s documentation lives at `readthedocs.io <https://python-telegram-bot.readthedocs.io/>`_.
|
||||
|
||||
============
|
||||
Getting help
|
||||
|
||||
+13
-10
@@ -15,7 +15,7 @@
|
||||
import sys
|
||||
import os
|
||||
import shlex
|
||||
import telegram
|
||||
# import telegram
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
@@ -51,7 +51,7 @@ master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'Python Telegram Bot'
|
||||
copyright = u'2015-2016, Leandro Toledo'
|
||||
copyright = u'2015-2017, Leandro Toledo'
|
||||
author = u'Leandro Toledo'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
@@ -59,9 +59,9 @@ author = u'Leandro Toledo'
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = telegram.__version__[:3]
|
||||
version = '6.0' # telegram.__version__[:3]
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = telegram.__version__
|
||||
release = '6.0.0' # telegram.__version__
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
@@ -131,7 +131,7 @@ html_theme = 'sphinx_rtd_theme'
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
#html_logo = None
|
||||
html_logo = 'ptb-logo-orange.png'
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
@@ -209,14 +209,17 @@ htmlhelp_basename = 'PythonTelegramBotdoc'
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
'papersize': 'a4paper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
'preamble': r'''\setcounter{tocdepth}{2}
|
||||
\usepackage{enumitem}
|
||||
\setlistdepth{99}''',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#'figure_align': 'htbp',
|
||||
@@ -227,12 +230,12 @@ latex_elements = {
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, 'PythonTelegramBot.tex', u'Python Telegram Bot Documentation',
|
||||
u'Leandro Toledo', 'manual'),
|
||||
author, 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
#latex_logo = None
|
||||
latex_logo = 'ptb-logo_1024.png'
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
@@ -271,7 +274,7 @@ man_pages = [
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'PythonTelegramBot', u'Python Telegram Bot Documentation',
|
||||
author, 'PythonTelegramBot', 'Not just a Python wrapper around the Telegram Bot API',
|
||||
author, 'PythonTelegramBot', "We have made you a wrapper you can't refuse",
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
|
||||
@@ -6,12 +6,8 @@
|
||||
Welcome to Python Telegram Bot's documentation!
|
||||
===============================================
|
||||
|
||||
Contents:
|
||||
telegram
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
telegram
|
||||
|
||||
|
||||
Indices and tables
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
telegram
|
||||
========
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
telegram
|
||||
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 74 KiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 71 KiB |
@@ -0,0 +1,7 @@
|
||||
telegram.animation module
|
||||
=========================
|
||||
|
||||
.. automodule:: telegram.animation
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.callbackgame module
|
||||
============================
|
||||
|
||||
.. automodule:: telegram.callbackgame
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.callbackquery module
|
||||
=============================
|
||||
|
||||
.. automodule:: telegram.callbackquery
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.chatmember module
|
||||
==========================
|
||||
|
||||
.. automodule:: telegram.chatmember
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,17 @@
|
||||
telegram.contrib package
|
||||
========================
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
.. toctree::
|
||||
|
||||
telegram.contrib.botan
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. automodule:: telegram.contrib
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -1,7 +1,7 @@
|
||||
telegram.nullhandler module
|
||||
telegram.ext.filters module
|
||||
===========================
|
||||
|
||||
.. automodule:: telegram.nullhandler
|
||||
.. automodule:: telegram.ext.filters
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.ext.messagequeue module
|
||||
================================
|
||||
|
||||
.. automodule:: telegram.ext.messagequeue
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -10,11 +10,14 @@ Submodules
|
||||
telegram.ext.dispatcher
|
||||
telegram.ext.jobqueue
|
||||
telegram.ext.handler
|
||||
telegram.ext.callbackqueryhandler
|
||||
telegram.ext.choseninlineresulthandler
|
||||
telegram.ext.conversationhandler
|
||||
telegram.ext.commandhandler
|
||||
telegram.ext.inlinequeryhandler
|
||||
telegram.ext.messagehandler
|
||||
telegram.ext.messagequeue
|
||||
telegram.ext.filters
|
||||
telegram.ext.regexhandler
|
||||
telegram.ext.stringcommandhandler
|
||||
telegram.ext.stringregexhandler
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.file module
|
||||
====================
|
||||
|
||||
.. automodule:: telegram.file
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.game module
|
||||
====================
|
||||
|
||||
.. automodule:: telegram.game
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.gamehighscore module
|
||||
=============================
|
||||
|
||||
.. automodule:: telegram.gamehighscore
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.inlinekeyboardbutton module
|
||||
===========================
|
||||
====================================
|
||||
|
||||
.. automodule:: telegram.inlinekeyboardbutton
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.inlinekeyboardmarkup module
|
||||
==========================
|
||||
====================================
|
||||
|
||||
.. automodule:: telegram.inlinekeyboardmarkup
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.inlinequeryresultarticle module
|
||||
=================================
|
||||
========================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultarticle
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.inlinequeryresultaudio module
|
||||
=================================
|
||||
======================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultaudio
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.inlinequeryresultcachedaudio module
|
||||
=================================
|
||||
============================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultcachedaudio
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.inlinequeryresultcacheddocument module
|
||||
=================================
|
||||
===============================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultcacheddocument
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.inlinequeryresultcachedgif module
|
||||
=================================
|
||||
==========================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultcachedgif
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.inlinequeryresultcachedmpeg4gif module
|
||||
=================================
|
||||
===============================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultcachedmpeg4gif
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.inlinequeryresultcachedphoto module
|
||||
=================================
|
||||
============================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultcachedphoto
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.inlinequeryresultcachedsticker module
|
||||
=================================
|
||||
==============================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultcachedsticker
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.inlinequeryresultcachedvideo module
|
||||
=================================
|
||||
============================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultcachedvideo
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.inlinequeryresultcachedvoice module
|
||||
=================================
|
||||
============================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultcachedvoice
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.inlinequeryresultcontact module
|
||||
=================================
|
||||
========================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultcontact
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.inlinequeryresultdocument module
|
||||
=================================
|
||||
=========================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultdocument
|
||||
:members:
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inlinequeryresultgame module
|
||||
=====================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultgame
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.inlinequeryresultgif module
|
||||
=================================
|
||||
====================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultgif
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.inlinequeryresultlocation module
|
||||
=================================
|
||||
=========================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultlocation
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.inlinequeryresultmpeg4gif module
|
||||
=================================
|
||||
=========================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultmpeg4gif
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.inlinequeryresultphoto module
|
||||
=================================
|
||||
======================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultphoto
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.inlinequeryresultvenue module
|
||||
=================================
|
||||
======================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultvenue
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.inlinequeryresultvideo module
|
||||
=================================
|
||||
======================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultvideo
|
||||
:members:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
telegram.inlinequeryresultvoice module
|
||||
=================================
|
||||
======================================
|
||||
|
||||
.. automodule:: telegram.inlinequeryresultvoice
|
||||
:members:
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inputcontactmessagecontent module
|
||||
==========================================
|
||||
|
||||
.. automodule:: telegram.inputcontactmessagecontent
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inputlocationmessagecontent module
|
||||
===========================================
|
||||
|
||||
.. automodule:: telegram.inputlocationmessagecontent
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inputmessagecontent module
|
||||
===================================
|
||||
|
||||
.. automodule:: telegram.inputmessagecontent
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inputtextmessagecontent module
|
||||
=======================================
|
||||
|
||||
.. automodule:: telegram.inputtextmessagecontent
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.inputvenuemessagecontent module
|
||||
========================================
|
||||
|
||||
.. automodule:: telegram.inputvenuemessagecontent
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.keyboardbutton module
|
||||
==============================
|
||||
|
||||
.. automodule:: telegram.keyboardbutton
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.messageentity module
|
||||
=============================
|
||||
|
||||
.. automodule:: telegram.messageentity
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.parsemode module
|
||||
=========================
|
||||
|
||||
.. automodule:: telegram.parsemode
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -1,7 +0,0 @@
|
||||
telegram.replykeyboardhide module
|
||||
=================================
|
||||
|
||||
.. automodule:: telegram.replykeyboardhide
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.replykeyboardremove module
|
||||
===================================
|
||||
|
||||
.. automodule:: telegram.replykeyboardremove
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
+31
-13
@@ -6,14 +6,30 @@ Submodules
|
||||
|
||||
.. toctree::
|
||||
|
||||
telegram.contrib
|
||||
telegram.ext
|
||||
telegram.animation
|
||||
telegram.audio
|
||||
telegram.base
|
||||
telegram.bot
|
||||
telegram.ext
|
||||
telegram.inlinequery
|
||||
telegram.inlinequeryresult
|
||||
telegram.callbackgame
|
||||
telegram.callbackquery
|
||||
telegram.chat
|
||||
telegram.chataction
|
||||
telegram.chatmember
|
||||
telegram.choseninlineresult
|
||||
telegram.constants
|
||||
telegram.contact
|
||||
telegram.document
|
||||
telegram.error
|
||||
telegram.file
|
||||
telegram.forcereply
|
||||
telegram.game
|
||||
telegram.gamehighscore
|
||||
telegram.inlinekeyboardbutton
|
||||
telegram.inlinekeyboardmarkup
|
||||
telegram.inlinequery
|
||||
telegram.inlinequeryresult
|
||||
telegram.inlinequeryresultarticle
|
||||
telegram.inlinequeryresultaudio
|
||||
telegram.inlinequeryresultcachedaudio
|
||||
@@ -26,6 +42,7 @@ Submodules
|
||||
telegram.inlinequeryresultcachedvoice
|
||||
telegram.inlinequeryresultcontact
|
||||
telegram.inlinequeryresultdocument
|
||||
telegram.inlinequeryresultgame
|
||||
telegram.inlinequeryresultgif
|
||||
telegram.inlinequeryresultlocation
|
||||
telegram.inlinequeryresultmpeg4gif
|
||||
@@ -33,28 +50,29 @@ Submodules
|
||||
telegram.inlinequeryresultvenue
|
||||
telegram.inlinequeryresultvideo
|
||||
telegram.inlinequeryresultvoice
|
||||
telegram.choseninlineresult
|
||||
telegram.chataction
|
||||
telegram.contact
|
||||
telegram.document
|
||||
telegram.emoji
|
||||
telegram.error
|
||||
telegram.forcereply
|
||||
telegram.chat
|
||||
telegram.inputcontactmessagecontent
|
||||
telegram.inputfile
|
||||
telegram.inputlocationmessagecontent
|
||||
telegram.inputmessagecontent
|
||||
telegram.inputtextmessagecontent
|
||||
telegram.inputvenuemessagecontent
|
||||
telegram.keyboardbutton
|
||||
telegram.location
|
||||
telegram.message
|
||||
telegram.nullhandler
|
||||
telegram.messageentity
|
||||
telegram.parsemode
|
||||
telegram.photosize
|
||||
telegram.replykeyboardhide
|
||||
telegram.replykeyboardremove
|
||||
telegram.replykeyboardmarkup
|
||||
telegram.replymarkup
|
||||
telegram.sticker
|
||||
telegram.update
|
||||
telegram.user
|
||||
telegram.userprofilephotos
|
||||
telegram.venue
|
||||
telegram.video
|
||||
telegram.voice
|
||||
telegram.webhookinfo
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.venue module
|
||||
=====================
|
||||
|
||||
.. automodule:: telegram.venue
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -0,0 +1,7 @@
|
||||
telegram.webhookinfo module
|
||||
===========================
|
||||
|
||||
.. automodule:: telegram.webhookinfo
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
+6
-3
@@ -4,14 +4,17 @@ The examples in this folder are small bots meant to show you how a bot that is w
|
||||
|
||||
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.
|
||||
|
||||
### [`echobot2.py`](https://github.com/python-telegram-bot/python-telegram-bot/blob/v5.0/examples/echobot2.py)
|
||||
### [`echobot2.py`](https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/echobot2.py)
|
||||
This is probably the base for most of the bots made with `python-telegram-bot`. It simply replies to each text message with a message that contains the same text.
|
||||
|
||||
### [`timerbot.py`](https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/timerbot.py)
|
||||
This bot uses the [`JobQueue`](https://pythonhosted.org/python-telegram-bot/telegram.ext.jobqueue.html) class to send timed messages. The user sets a timer by using `/set` command with a specific time, for example `/set 30`. The bot then sets up a job to send a message to that user after 30 seconds. The user can also cancel the timer by sending `/unset`. To learn more about the `JobQueue`, read [this wiki article](https://github.com/python-telegram-bot/python-telegram-bot/wiki/Extensions-%E2%80%93-JobQueue).
|
||||
This bot uses the [`JobQueue`](https://python-telegram-bot.readthedocs.io/en/latest/telegram.ext.jobqueue.html) class to send timed messages. The user sets a timer by using `/set` command with a specific time, for example `/set 30`. The bot then sets up a job to send a message to that user after 30 seconds. The user can also cancel the timer by sending `/unset`. To learn more about the `JobQueue`, read [this wiki article](https://github.com/python-telegram-bot/python-telegram-bot/wiki/Extensions-%E2%80%93-JobQueue).
|
||||
|
||||
### [`conversationbot.py`](https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/conversationbot.py)
|
||||
A common task for a bot is to ask information from the user. In v5.0 of this library, we introduced the [`ConversationHandler`](https://pythonhosted.org/python-telegram-bot/telegram.ext.conversationhandler.html) for that exact purpose. This example uses it to retrieve user-information in a conversation-like style.
|
||||
A common task for a bot is to ask information from the user. In v5.0 of this library, we introduced the [`ConversationHandler`](https://python-telegram-bot.readthedocs.io/en/latest/telegram.ext.conversationhandler.html) for that exact purpose. This example uses it to retrieve user-information in a conversation-like style. To get a better understanding, take a look at the [state diagram](https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/conversationbot.png).
|
||||
|
||||
### [`conversationbot2.py`](https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/conversationbot2.py)
|
||||
A more complex example of a bot that uses the `ConversationHandler`. It is also more confusing. Good thing there is a [fancy state diagram](https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/conversationbot2.png) for this one, too!
|
||||
|
||||
### [`inlinekeyboard.py`](https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/inlinekeyboard.py)
|
||||
This example sheds some light on inline keyboards, callback queries and message editing.
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 82 KiB |
+25
-26
@@ -17,7 +17,7 @@ Press Ctrl-C on the command line or send a signal to the process to stop the
|
||||
bot.
|
||||
"""
|
||||
|
||||
from telegram import (ReplyKeyboardMarkup)
|
||||
from telegram import (ReplyKeyboardMarkup, ReplyKeyboardRemove)
|
||||
from telegram.ext import (Updater, CommandHandler, MessageHandler, Filters, RegexHandler,
|
||||
ConversationHandler)
|
||||
|
||||
@@ -35,11 +35,11 @@ GENDER, PHOTO, LOCATION, BIO = range(4)
|
||||
def start(bot, update):
|
||||
reply_keyboard = [['Boy', 'Girl', 'Other']]
|
||||
|
||||
bot.sendMessage(update.message.chat_id,
|
||||
text='Hi! My name is Professor Bot. I will hold a conversation with you. '
|
||||
'Send /cancel to stop talking to me.\n\n'
|
||||
'Are you a boy or a girl?',
|
||||
reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True))
|
||||
update.message.reply_text(
|
||||
'Hi! My name is Professor Bot. I will hold a conversation with you. '
|
||||
'Send /cancel to stop talking to me.\n\n'
|
||||
'Are you a boy or a girl?',
|
||||
reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True))
|
||||
|
||||
return GENDER
|
||||
|
||||
@@ -47,20 +47,20 @@ 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))
|
||||
bot.sendMessage(update.message.chat_id,
|
||||
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.')
|
||||
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())
|
||||
|
||||
return PHOTO
|
||||
|
||||
|
||||
def photo(bot, update):
|
||||
user = update.message.from_user
|
||||
photo_file = bot.getFile(update.message.photo[-1].file_id)
|
||||
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'))
|
||||
bot.sendMessage(update.message.chat_id, text='Gorgeous! Now, send me your location please, '
|
||||
'or send /skip if you don\'t want to.')
|
||||
update.message.reply_text('Gorgeous! Now, send me your location please, '
|
||||
'or send /skip if you don\'t want to.')
|
||||
|
||||
return LOCATION
|
||||
|
||||
@@ -68,8 +68,8 @@ 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)
|
||||
bot.sendMessage(update.message.chat_id, text='I bet you look great! Now, send me your '
|
||||
'location please, or send /skip.')
|
||||
update.message.reply_text('I bet you look great! Now, send me your location please, '
|
||||
'or send /skip.')
|
||||
|
||||
return LOCATION
|
||||
|
||||
@@ -79,8 +79,8 @@ def location(bot, update):
|
||||
user_location = update.message.location
|
||||
logger.info("Location of %s: %f / %f"
|
||||
% (user.first_name, user_location.latitude, user_location.longitude))
|
||||
bot.sendMessage(update.message.chat_id, text='Maybe I can visit you sometime! '
|
||||
'At last, tell me something about yourself.')
|
||||
update.message.reply_text('Maybe I can visit you sometime! '
|
||||
'At last, tell me something about yourself.')
|
||||
|
||||
return BIO
|
||||
|
||||
@@ -88,8 +88,8 @@ 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)
|
||||
bot.sendMessage(update.message.chat_id, text='You seem a bit paranoid! '
|
||||
'At last, tell me something about yourself.')
|
||||
update.message.reply_text('You seem a bit paranoid! '
|
||||
'At last, tell me something about yourself.')
|
||||
|
||||
return BIO
|
||||
|
||||
@@ -97,8 +97,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))
|
||||
bot.sendMessage(update.message.chat_id,
|
||||
text='Thank you! I hope we can talk again some day.')
|
||||
update.message.reply_text('Thank you! I hope we can talk again some day.')
|
||||
|
||||
return ConversationHandler.END
|
||||
|
||||
@@ -106,8 +105,8 @@ def bio(bot, update):
|
||||
def cancel(bot, update):
|
||||
user = update.message.from_user
|
||||
logger.info("User %s canceled the conversation." % user.first_name)
|
||||
bot.sendMessage(update.message.chat_id,
|
||||
text='Bye! I hope we can talk again some day.')
|
||||
update.message.reply_text('Bye! I hope we can talk again some day.',
|
||||
reply_markup=ReplyKeyboardRemove())
|
||||
|
||||
return ConversationHandler.END
|
||||
|
||||
@@ -130,13 +129,13 @@ def main():
|
||||
states={
|
||||
GENDER: [RegexHandler('^(Boy|Girl|Other)$', gender)],
|
||||
|
||||
PHOTO: [MessageHandler([Filters.photo], photo),
|
||||
PHOTO: [MessageHandler(Filters.photo, photo),
|
||||
CommandHandler('skip', skip_photo)],
|
||||
|
||||
LOCATION: [MessageHandler([Filters.location], location),
|
||||
LOCATION: [MessageHandler(Filters.location, location),
|
||||
CommandHandler('skip', skip_location)],
|
||||
|
||||
BIO: [MessageHandler([Filters.text], bio)]
|
||||
BIO: [MessageHandler(Filters.text, bio)]
|
||||
},
|
||||
|
||||
fallbacks=[CommandHandler('cancel', cancel)]
|
||||
@@ -150,7 +149,7 @@ def main():
|
||||
# Start the Bot
|
||||
updater.start_polling()
|
||||
|
||||
# Run the bot until the you presses Ctrl-C or the process receives SIGINT,
|
||||
# Run the bot until you press Ctrl-C or the process receives SIGINT,
|
||||
# SIGTERM or SIGABRT. This should be used most of the time, since
|
||||
# start_polling() is non-blocking and will stop the bot gracefully.
|
||||
updater.idle()
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 82 KiB |
@@ -0,0 +1,152 @@
|
||||
#!/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.
|
||||
"""
|
||||
This Bot uses the Updater class to handle the bot.
|
||||
|
||||
First, a few callback functions are defined. Then, those functions are passed to
|
||||
the Dispatcher and registered at their respective places.
|
||||
Then, the bot is started and runs until we press Ctrl-C on the command line.
|
||||
|
||||
Usage:
|
||||
Example of a bot-user conversation using ConversationHandler.
|
||||
Send /start to initiate the conversation.
|
||||
Press Ctrl-C on the command line or send a signal to the process to stop the
|
||||
bot.
|
||||
"""
|
||||
|
||||
from telegram import ReplyKeyboardMarkup
|
||||
from telegram.ext import (Updater, CommandHandler, MessageHandler, Filters, RegexHandler,
|
||||
ConversationHandler)
|
||||
|
||||
import logging
|
||||
|
||||
# Enable logging
|
||||
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||
level=logging.INFO)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
CHOOSING, TYPING_REPLY, TYPING_CHOICE = range(3)
|
||||
|
||||
reply_keyboard = [['Age', 'Favourite colour'],
|
||||
['Number of siblings', 'Something else...'],
|
||||
['Done']]
|
||||
markup = ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True)
|
||||
|
||||
|
||||
def facts_to_str(user_data):
|
||||
facts = list()
|
||||
|
||||
for key, value in user_data.items():
|
||||
facts.append('%s - %s' % (key, value))
|
||||
|
||||
return "\n".join(facts).join(['\n', '\n'])
|
||||
|
||||
|
||||
def start(bot, update):
|
||||
update.message.reply_text(
|
||||
"Hi! My name is Doctor Botter. I will hold a more complex conversation with you. "
|
||||
"Why don't you tell me something about yourself?",
|
||||
reply_markup=markup)
|
||||
|
||||
return CHOOSING
|
||||
|
||||
|
||||
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())
|
||||
|
||||
return TYPING_REPLY
|
||||
|
||||
|
||||
def custom_choice(bot, update):
|
||||
update.message.reply_text('Alright, please send me the category first, '
|
||||
'for example "Most impressive skill"')
|
||||
|
||||
return TYPING_CHOICE
|
||||
|
||||
|
||||
def received_information(bot, update, user_data):
|
||||
text = update.message.text
|
||||
category = user_data['choice']
|
||||
user_data[category] = text
|
||||
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)
|
||||
|
||||
return CHOOSING
|
||||
|
||||
|
||||
def done(bot, update, user_data):
|
||||
if 'choice' in 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))
|
||||
|
||||
user_data.clear()
|
||||
return ConversationHandler.END
|
||||
|
||||
|
||||
def error(bot, update, error):
|
||||
logger.warn('Update "%s" caused error "%s"' % (update, error))
|
||||
|
||||
|
||||
def main():
|
||||
# Create the Updater and pass it your bot's token.
|
||||
updater = Updater("TOKEN")
|
||||
|
||||
# Get the dispatcher to register handlers
|
||||
dp = updater.dispatcher
|
||||
|
||||
# Add conversation handler with the states GENDER, PHOTO, LOCATION and BIO
|
||||
conv_handler = ConversationHandler(
|
||||
entry_points=[CommandHandler('start', start)],
|
||||
|
||||
states={
|
||||
CHOOSING: [RegexHandler('^(Age|Favourite colour|Number of siblings)$',
|
||||
regular_choice,
|
||||
pass_user_data=True),
|
||||
RegexHandler('^Something else...$',
|
||||
custom_choice),
|
||||
],
|
||||
|
||||
TYPING_CHOICE: [MessageHandler(Filters.text,
|
||||
regular_choice,
|
||||
pass_user_data=True),
|
||||
],
|
||||
|
||||
TYPING_REPLY: [MessageHandler(Filters.text,
|
||||
received_information,
|
||||
pass_user_data=True),
|
||||
],
|
||||
},
|
||||
|
||||
fallbacks=[RegexHandler('^Done$', done, pass_user_data=True)]
|
||||
)
|
||||
|
||||
dp.add_handler(conv_handler)
|
||||
|
||||
# log all errors
|
||||
dp.add_error_handler(error)
|
||||
|
||||
# Start the Bot
|
||||
updater.start_polling()
|
||||
|
||||
# Run the bot until you press Ctrl-C or the process receives SIGINT,
|
||||
# SIGTERM or SIGABRT. This should be used most of the time, since
|
||||
# start_polling() is non-blocking and will stop the bot gracefully.
|
||||
updater.idle()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
+3
-5
@@ -20,7 +20,7 @@ def main():
|
||||
# get the first pending update_id, this is so we can skip over it in case
|
||||
# we get an "Unauthorized" exception.
|
||||
try:
|
||||
update_id = bot.getUpdates()[0].update_id
|
||||
update_id = bot.get_updates()[0].update_id
|
||||
except IndexError:
|
||||
update_id = None
|
||||
|
||||
@@ -39,14 +39,12 @@ def main():
|
||||
def echo(bot):
|
||||
global update_id
|
||||
# Request updates after the last update_id
|
||||
for update in bot.getUpdates(offset=update_id, timeout=10):
|
||||
# chat_id is required to reply to any message
|
||||
chat_id = update.message.chat_id
|
||||
for update in bot.get_updates(offset=update_id, timeout=10):
|
||||
update_id = update.update_id + 1
|
||||
|
||||
if update.message: # your bot can receive updates without messages
|
||||
# Reply to the message
|
||||
bot.sendMessage(chat_id=chat_id, text=update.message.text)
|
||||
update.message.reply_text(update.message.text)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -56,7 +56,7 @@ def main():
|
||||
dp.add_handler(CommandHandler("help", help))
|
||||
|
||||
# on noncommand i.e message - echo the message on Telegram
|
||||
dp.add_handler(MessageHandler([Filters.text], echo))
|
||||
dp.add_handler(MessageHandler(Filters.text, echo))
|
||||
|
||||
# log all errors
|
||||
dp.add_error_handler(error)
|
||||
@@ -64,7 +64,7 @@ def main():
|
||||
# Start the Bot
|
||||
updater.start_polling()
|
||||
|
||||
# Run the bot until the you presses Ctrl-C or the process receives SIGINT,
|
||||
# Run the bot until you press Ctrl-C or the process receives SIGINT,
|
||||
# SIGTERM or SIGABRT. This should be used most of the time, since
|
||||
# start_polling() is non-blocking and will stop the bot gracefully.
|
||||
updater.idle()
|
||||
|
||||
@@ -34,11 +34,11 @@ 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):
|
||||
bot.sendMessage(update.message.chat_id, text='Hi!')
|
||||
update.message.reply_text('Hi!')
|
||||
|
||||
|
||||
def help(bot, update):
|
||||
bot.sendMessage(update.message.chat_id, text='Help!')
|
||||
update.message.reply_text('Help!')
|
||||
|
||||
|
||||
def escape_markdown(text):
|
||||
@@ -68,11 +68,11 @@ def inlinequery(bot, update):
|
||||
"_%s_" % escape_markdown(query),
|
||||
parse_mode=ParseMode.MARKDOWN)))
|
||||
|
||||
bot.answerInlineQuery(update.inline_query.id, results=results)
|
||||
update.inline_query.answer(results)
|
||||
|
||||
|
||||
def error(bot, update, error):
|
||||
logger.warn('Update "%s" caused error "%s"' % (update, error))
|
||||
logger.warning('Update "%s" caused error "%s"' % (update, error))
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
@@ -20,19 +20,19 @@ def start(bot, update):
|
||||
|
||||
reply_markup = InlineKeyboardMarkup(keyboard)
|
||||
|
||||
bot.sendMessage(update.message.chat_id, text="Please choose:", reply_markup=reply_markup)
|
||||
update.message.reply_text('Please choose:', reply_markup=reply_markup)
|
||||
|
||||
|
||||
def button(bot, update):
|
||||
query = update.callback_query
|
||||
|
||||
bot.editMessageText(text="Selected option: %s" % query.data,
|
||||
chat_id=query.message.chat_id,
|
||||
message_id=query.message.message_id)
|
||||
bot.edit_message_text(text="Selected option: %s" % query.data,
|
||||
chat_id=query.message.chat_id,
|
||||
message_id=query.message.message_id)
|
||||
|
||||
|
||||
def help(bot, update):
|
||||
bot.sendMessage(update.message.chat_id, text="Use /start to test this bot.")
|
||||
update.message.reply_text("Use /start to test this bot.")
|
||||
|
||||
|
||||
def error(bot, update, error):
|
||||
|
||||
+24
-24
@@ -22,61 +22,58 @@ import logging
|
||||
|
||||
# Enable logging
|
||||
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||
level=logging.DEBUG)
|
||||
level=logging.INFO)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
timers = dict()
|
||||
|
||||
|
||||
# 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):
|
||||
bot.sendMessage(update.message.chat_id, text='Hi! Use /set <seconds> to ' 'set a timer')
|
||||
update.message.reply_text('Hi! Use /set <seconds> to set a timer')
|
||||
|
||||
|
||||
def alarm(bot, job):
|
||||
"""Function to send the alarm message"""
|
||||
bot.sendMessage(job.context, text='Beep!')
|
||||
bot.send_message(job.context, text='Beep!')
|
||||
|
||||
|
||||
def set(bot, update, args, job_queue):
|
||||
def set(bot, update, args, job_queue, chat_data):
|
||||
"""Adds a job to the queue"""
|
||||
chat_id = update.message.chat_id
|
||||
try:
|
||||
# args[0] should contain the time for the timer in seconds
|
||||
due = int(args[0])
|
||||
if due < 0:
|
||||
bot.sendMessage(chat_id, text='Sorry we can not go back to future!')
|
||||
update.message.reply_text('Sorry we can not go back to future!')
|
||||
return
|
||||
|
||||
# Add job to queue
|
||||
job = Job(alarm, due, repeat=False, context=chat_id)
|
||||
timers[chat_id] = job
|
||||
job_queue.put(job)
|
||||
job = job_queue.run_once(alarm, due, context=chat_id)
|
||||
chat_data['job'] = job
|
||||
|
||||
bot.sendMessage(chat_id, text='Timer successfully set!')
|
||||
update.message.reply_text('Timer successfully set!')
|
||||
|
||||
except (IndexError, ValueError):
|
||||
bot.sendMessage(chat_id, text='Usage: /set <seconds>')
|
||||
update.message.reply_text('Usage: /set <seconds>')
|
||||
|
||||
|
||||
def unset(bot, update, job_queue):
|
||||
def unset(bot, update, chat_data):
|
||||
"""Removes the job if the user changed their mind"""
|
||||
chat_id = update.message.chat_id
|
||||
|
||||
if chat_id not in timers:
|
||||
bot.sendMessage(chat_id, text='You have no active timer')
|
||||
if 'job' not in chat_data:
|
||||
update.message.reply_text('You have no active timer')
|
||||
return
|
||||
|
||||
job = timers[chat_id]
|
||||
job = chat_data['job']
|
||||
job.schedule_removal()
|
||||
del timers[chat_id]
|
||||
del chat_data['job']
|
||||
|
||||
bot.sendMessage(chat_id, text='Timer successfully unset!')
|
||||
update.message.reply_text('Timer successfully unset!')
|
||||
|
||||
|
||||
def error(bot, update, error):
|
||||
logger.warn('Update "%s" caused error "%s"' % (update, error))
|
||||
logger.warning('Update "%s" caused error "%s"' % (update, error))
|
||||
|
||||
|
||||
def main():
|
||||
@@ -88,8 +85,11 @@ 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, pass_args=True, pass_job_queue=True))
|
||||
dp.add_handler(CommandHandler("unset", unset, pass_job_queue=True))
|
||||
dp.add_handler(CommandHandler("set", set,
|
||||
pass_args=True,
|
||||
pass_job_queue=True,
|
||||
pass_chat_data=True))
|
||||
dp.add_handler(CommandHandler("unset", unset, pass_chat_data=True))
|
||||
|
||||
# log all errors
|
||||
dp.add_error_handler(error)
|
||||
@@ -97,9 +97,9 @@ def main():
|
||||
# Start the Bot
|
||||
updater.start_polling()
|
||||
|
||||
# Block until the you presses Ctrl-C or the process receives SIGINT,
|
||||
# SIGTERM or SIGABRT. This should be used most of the time, since
|
||||
# start_polling() is non-blocking and will stop the bot gracefully.
|
||||
# Block until you press Ctrl-C or the process receives SIGINT, SIGTERM or
|
||||
# SIGABRT. This should be used most of the time, since start_polling() is
|
||||
# non-blocking and will stop the bot gracefully.
|
||||
updater.idle()
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
future>=0.15.2
|
||||
urllib3>=1.10
|
||||
certifi
|
||||
|
||||
@@ -17,6 +17,13 @@ def requirements():
|
||||
return requirements_list
|
||||
|
||||
|
||||
packages = find_packages(exclude=['tests*'])
|
||||
packages.extend(['telegram.vendor.urllib3.urllib3',
|
||||
'telegram.vendor.urllib3.urllib3.packages', 'telegram.vendor.urllib3.urllib3.packages.ssl_match_hostname',
|
||||
'telegram.vendor.urllib3.urllib3.packages.backports', 'telegram.vendor.urllib3.urllib3.contrib',
|
||||
'telegram.vendor.urllib3.urllib3.util',
|
||||
])
|
||||
|
||||
with codecs.open('README.rst', 'r', 'utf-8') as fd:
|
||||
fn = os.path.join('telegram', 'version.py')
|
||||
with open(fn) as fh:
|
||||
@@ -30,12 +37,13 @@ with codecs.open('README.rst', 'r', 'utf-8') as fd:
|
||||
license='LGPLv3',
|
||||
url='https://python-telegram-bot.org/',
|
||||
keywords='python telegram bot api wrapper',
|
||||
description='Not just a Python wrapper around the Telegram Bot API',
|
||||
description="We have made you a wrapper you can't refuse",
|
||||
long_description=fd.read(),
|
||||
packages=find_packages(exclude=['tests*']),
|
||||
packages=packages,
|
||||
install_requires=requirements(),
|
||||
extras_require={
|
||||
'json': 'ujson',
|
||||
'socks': 'PySocks'
|
||||
},
|
||||
include_package_data=True,
|
||||
classifiers=[
|
||||
@@ -53,4 +61,5 @@ with codecs.open('README.rst', 'r', 'utf-8') as fd:
|
||||
'Programming Language :: Python :: 3.3',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
'Programming Language :: Python :: 3.6'
|
||||
],)
|
||||
|
||||
+32
-21
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# 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
|
||||
@@ -19,6 +19,10 @@
|
||||
"""A library that provides a Python interface to the Telegram Bot API"""
|
||||
|
||||
from sys import version_info
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'vendor', 'urllib3'))
|
||||
|
||||
from .base import TelegramObject
|
||||
from .user import User
|
||||
@@ -38,7 +42,7 @@ from .userprofilephotos import UserProfilePhotos
|
||||
from .keyboardbutton import KeyboardButton
|
||||
from .replymarkup import ReplyMarkup
|
||||
from .replykeyboardmarkup import ReplyKeyboardMarkup
|
||||
from .replykeyboardhide import ReplyKeyboardHide
|
||||
from .replykeyboardremove import ReplyKeyboardRemove, ReplyKeyboardHide
|
||||
from .forcereply import ForceReply
|
||||
from .error import TelegramError
|
||||
from .inputfile import InputFile
|
||||
@@ -46,6 +50,8 @@ from .file import File
|
||||
from .emoji import Emoji
|
||||
from .parsemode import ParseMode
|
||||
from .messageentity import MessageEntity
|
||||
from .animation import Animation
|
||||
from .game import Game
|
||||
from .message import Message
|
||||
from .inputmessagecontent import InputMessageContent
|
||||
from .callbackquery import CallbackQuery
|
||||
@@ -73,10 +79,13 @@ from .inlinequeryresultphoto import InlineQueryResultPhoto
|
||||
from .inlinequeryresultvenue import InlineQueryResultVenue
|
||||
from .inlinequeryresultvideo import InlineQueryResultVideo
|
||||
from .inlinequeryresultvoice import InlineQueryResultVoice
|
||||
from .inlinequeryresultgame import InlineQueryResultGame
|
||||
from .inputtextmessagecontent import InputTextMessageContent
|
||||
from .inputlocationmessagecontent import InputLocationMessageContent
|
||||
from .inputvenuemessagecontent import InputVenueMessageContent
|
||||
from .inputcontactmessagecontent import InputContactMessageContent
|
||||
from .webhookinfo import WebhookInfo
|
||||
from .gamehighscore import GameHighScore
|
||||
from .update import Update
|
||||
from .bot import Bot
|
||||
from .constants import (MAX_MESSAGE_LENGTH, MAX_CAPTION_LENGTH, SUPPORTED_WEBHOOK_PORTS,
|
||||
@@ -87,22 +96,24 @@ from .version import __version__ # flake8: noqa
|
||||
|
||||
__author__ = 'devs@python-telegram-bot.org'
|
||||
|
||||
__all__ = ['Audio', 'Bot', 'Chat', 'ChatMember', 'ChatAction', 'ChosenInlineResult',
|
||||
'CallbackQuery', 'Contact', 'Document', 'Emoji', 'File', 'ForceReply',
|
||||
'InlineKeyboardButton', 'InlineKeyboardMarkup', 'InlineQuery', 'InlineQueryResult',
|
||||
'InlineQueryResult', 'InlineQueryResultArticle', 'InlineQueryResultAudio',
|
||||
'InlineQueryResultCachedAudio', 'InlineQueryResultCachedDocument',
|
||||
'InlineQueryResultCachedGif', 'InlineQueryResultCachedMpeg4Gif',
|
||||
'InlineQueryResultCachedPhoto', 'InlineQueryResultCachedSticker',
|
||||
'InlineQueryResultCachedVideo', 'InlineQueryResultCachedVoice',
|
||||
'InlineQueryResultContact', 'InlineQueryResultDocument', 'InlineQueryResultGif',
|
||||
'InlineQueryResultLocation', 'InlineQueryResultMpeg4Gif', 'InlineQueryResultPhoto',
|
||||
'InlineQueryResultVenue', 'InlineQueryResultVideo', 'InlineQueryResultVoice',
|
||||
'InputContactMessageContent', 'InputFile', 'InputLocationMessageContent',
|
||||
'InputMessageContent', 'InputTextMessageContent', 'InputVenueMessageContent',
|
||||
'KeyboardButton', 'Location', 'Message', 'MessageEntity', 'ParseMode', 'PhotoSize',
|
||||
'ReplyKeyboardHide', 'ReplyKeyboardMarkup', 'ReplyMarkup', 'Sticker', 'TelegramError',
|
||||
'TelegramObject', 'Update', 'User', 'UserProfilePhotos', 'Venue', 'Video', 'Voice',
|
||||
'MAX_MESSAGE_LENGTH', 'MAX_CAPTION_LENGTH', 'SUPPORTED_WEBHOOK_PORTS',
|
||||
'MAX_FILESIZE_DOWNLOAD', 'MAX_FILESIZE_UPLOAD', 'MAX_MESSAGES_PER_SECOND_PER_CHAT',
|
||||
'MAX_MESSAGES_PER_SECOND', 'MAX_MESSAGES_PER_MINUTE_PER_GROUP']
|
||||
__all__ = [
|
||||
'Audio', 'Bot', 'Chat', 'ChatMember', 'ChatAction', 'ChosenInlineResult', 'CallbackQuery',
|
||||
'Contact', 'Document', 'Emoji', 'File', 'ForceReply', 'InlineKeyboardButton',
|
||||
'InlineKeyboardMarkup', 'InlineQuery', 'InlineQueryResult', 'InlineQueryResult',
|
||||
'InlineQueryResultArticle', 'InlineQueryResultAudio', 'InlineQueryResultCachedAudio',
|
||||
'InlineQueryResultCachedDocument', 'InlineQueryResultCachedGif',
|
||||
'InlineQueryResultCachedMpeg4Gif', 'InlineQueryResultCachedPhoto',
|
||||
'InlineQueryResultCachedSticker', 'InlineQueryResultCachedVideo',
|
||||
'InlineQueryResultCachedVoice', 'InlineQueryResultContact', 'InlineQueryResultDocument',
|
||||
'InlineQueryResultGif', 'InlineQueryResultLocation', 'InlineQueryResultMpeg4Gif',
|
||||
'InlineQueryResultPhoto', 'InlineQueryResultVenue', 'InlineQueryResultVideo',
|
||||
'InlineQueryResultVoice', 'InlineQueryResultGame', 'InputContactMessageContent', 'InputFile',
|
||||
'InputLocationMessageContent', 'InputMessageContent', 'InputTextMessageContent',
|
||||
'InputVenueMessageContent', 'KeyboardButton', 'Location', 'Message', 'MessageEntity',
|
||||
'ParseMode', 'PhotoSize', 'ReplyKeyboardRemove', 'ReplyKeyboardMarkup', 'ReplyMarkup',
|
||||
'Sticker', 'TelegramError', 'TelegramObject', 'Update', 'User', 'UserProfilePhotos', 'Venue',
|
||||
'Video', 'Voice', 'MAX_MESSAGE_LENGTH', 'MAX_CAPTION_LENGTH', 'SUPPORTED_WEBHOOK_PORTS',
|
||||
'MAX_FILESIZE_DOWNLOAD', 'MAX_FILESIZE_UPLOAD', 'MAX_MESSAGES_PER_SECOND_PER_CHAT',
|
||||
'MAX_MESSAGES_PER_SECOND', 'MAX_MESSAGES_PER_MINUTE_PER_GROUP', 'WebhookInfo', 'Animation',
|
||||
'Game', 'GameHighScore'
|
||||
]
|
||||
|
||||
@@ -14,5 +14,10 @@ def print_ver_info():
|
||||
print('future {0}'.format(future.__version__))
|
||||
print('Python {0}'.format(sys.version.replace('\n', ' ')))
|
||||
|
||||
# main
|
||||
print_ver_info()
|
||||
|
||||
def main():
|
||||
print_ver_info()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
#!/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 Animation."""
|
||||
from telegram import PhotoSize
|
||||
from telegram import TelegramObject
|
||||
|
||||
|
||||
class Animation(TelegramObject):
|
||||
"""This object represents a Telegram Animation.
|
||||
|
||||
Attributes:
|
||||
file_id (str): Unique file identifier.
|
||||
|
||||
Keyword Args:
|
||||
thumb (Optional[:class:`telegram.PhotoSize`]): Animation thumbnail as defined by sender.
|
||||
file_name (Optional[str]): Original animation filename as defined by sender.
|
||||
mime_type (Optional[str]): MIME type of the file as defined by sender.
|
||||
file_size (Optional[int]): File size.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
file_id,
|
||||
thumb=None,
|
||||
file_name=None,
|
||||
mime_type=None,
|
||||
file_size=None,
|
||||
**kwargs):
|
||||
self.file_id = file_id
|
||||
self.thumb = thumb
|
||||
self.file_name = file_name
|
||||
self.mime_type = mime_type
|
||||
self.file_size = file_size
|
||||
|
||||
self._id_attrs = (self.file_id,)
|
||||
|
||||
@staticmethod
|
||||
def de_json(data, bot):
|
||||
"""
|
||||
Args:
|
||||
data (dict):
|
||||
bot (telegram.Bot):
|
||||
|
||||
Returns:
|
||||
telegram.Game:
|
||||
"""
|
||||
if not data:
|
||||
return None
|
||||
|
||||
data = super(Animation, Animation).de_json(data, bot)
|
||||
|
||||
data['thumb'] = PhotoSize.de_json(data.get('thumb'), bot)
|
||||
|
||||
return Animation(**data)
|
||||
+18
-10
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# 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
|
||||
@@ -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 a object that represents a Telegram Audio."""
|
||||
"""This module contains an object that represents a Telegram Audio."""
|
||||
|
||||
from telegram import TelegramObject
|
||||
|
||||
@@ -35,24 +35,32 @@ class Audio(TelegramObject):
|
||||
Args:
|
||||
file_id (str):
|
||||
duration (int):
|
||||
**kwargs: Arbitrary keyword arguments.
|
||||
|
||||
Keyword Args:
|
||||
performer (Optional[str]):
|
||||
title (Optional[str]):
|
||||
mime_type (Optional[str]):
|
||||
file_size (Optional[int]):
|
||||
**kwargs: Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, file_id, duration, **kwargs):
|
||||
def __init__(self,
|
||||
file_id,
|
||||
duration,
|
||||
performer=None,
|
||||
title=None,
|
||||
mime_type=None,
|
||||
file_size=None,
|
||||
**kwargs):
|
||||
# Required
|
||||
self.file_id = str(file_id)
|
||||
self.duration = int(duration)
|
||||
# Optionals
|
||||
self.performer = kwargs.get('performer', '')
|
||||
self.title = kwargs.get('title', '')
|
||||
self.mime_type = str(kwargs.get('mime_type', ''))
|
||||
self.file_size = int(kwargs.get('file_size', 0))
|
||||
self.performer = performer
|
||||
self.title = title
|
||||
self.mime_type = mime_type
|
||||
self.file_size = file_size
|
||||
|
||||
self._id_attrs = (self.file_id,)
|
||||
|
||||
@staticmethod
|
||||
def de_json(data, bot):
|
||||
|
||||
+13
-3
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# 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
|
||||
@@ -28,8 +28,8 @@ from abc import ABCMeta
|
||||
|
||||
class TelegramObject(object):
|
||||
"""Base class for most telegram objects."""
|
||||
|
||||
__metaclass__ = ABCMeta
|
||||
_id_attrs = ()
|
||||
|
||||
def __str__(self):
|
||||
return str(self.to_dict())
|
||||
@@ -69,7 +69,7 @@ class TelegramObject(object):
|
||||
data = dict()
|
||||
|
||||
for key in iter(self.__dict__):
|
||||
if key == 'bot':
|
||||
if key in ('bot', '_id_attrs'):
|
||||
continue
|
||||
|
||||
value = self.__dict__[key]
|
||||
@@ -80,3 +80,13 @@ class TelegramObject(object):
|
||||
data[key] = value
|
||||
|
||||
return data
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, self.__class__):
|
||||
return self._id_attrs == other._id_attrs
|
||||
return super(TelegramObject, self).__eq__(other)
|
||||
|
||||
def __hash__(self):
|
||||
if self._id_attrs:
|
||||
return hash((self.__class__, self._id_attrs))
|
||||
return super(TelegramObject, self).__hash__()
|
||||
|
||||
+1023
-684
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,25 @@
|
||||
#!/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 CallbackGame."""
|
||||
|
||||
from telegram import TelegramObject
|
||||
|
||||
|
||||
class CallbackGame(TelegramObject):
|
||||
"""A placeholder, currently holds no information. Use BotFather to set up your game."""
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# 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
|
||||
@@ -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 a object that represents a Telegram
|
||||
CallbackQuery"""
|
||||
"""This module contains an object that represents a Telegram CallbackQuery"""
|
||||
|
||||
from telegram import TelegramObject, Message, User
|
||||
|
||||
@@ -25,14 +24,25 @@ from telegram import TelegramObject, Message, User
|
||||
class CallbackQuery(TelegramObject):
|
||||
"""This object represents a Telegram CallbackQuery."""
|
||||
|
||||
def __init__(self, id, from_user, data, bot=None, **kwargs):
|
||||
def __init__(self,
|
||||
id,
|
||||
from_user,
|
||||
chat_instance,
|
||||
message=None,
|
||||
data=None,
|
||||
inline_message_id=None,
|
||||
game_short_name=None,
|
||||
bot=None,
|
||||
**kwargs):
|
||||
# Required
|
||||
self.id = id
|
||||
self.from_user = from_user
|
||||
self.data = data
|
||||
self.chat_instance = chat_instance
|
||||
# Optionals
|
||||
self.message = kwargs.get('message')
|
||||
self.inline_message_id = kwargs.get('inline_message_id', '')
|
||||
self.message = message
|
||||
self.data = data
|
||||
self.inline_message_id = inline_message_id
|
||||
self.game_short_name = game_short_name
|
||||
|
||||
self.bot = bot
|
||||
|
||||
@@ -50,6 +60,8 @@ class CallbackQuery(TelegramObject):
|
||||
if not data:
|
||||
return None
|
||||
|
||||
data = super(CallbackQuery, CallbackQuery).de_json(data, bot)
|
||||
|
||||
data['from_user'] = User.de_json(data.get('from'), bot)
|
||||
data['message'] = Message.de_json(data.get('message'), bot)
|
||||
|
||||
@@ -69,3 +81,52 @@ class CallbackQuery(TelegramObject):
|
||||
def answer(self, *args, **kwargs):
|
||||
"""Shortcut for ``bot.answerCallbackQuery(update.callback_query.id, *args, **kwargs)``"""
|
||||
return self.bot.answerCallbackQuery(self.id, *args, **kwargs)
|
||||
|
||||
def edit_message_text(self, *args, **kwargs):
|
||||
"""
|
||||
Shortcut for either ``bot.editMessageText(chat_id=update.callback_query.message.chat_id, \
|
||||
message_id=update.callback_query.message.message_id, \
|
||||
*args, **kwargs)``
|
||||
or ``bot.editMessageText(inline_message_id=update.callback_query.inline_message_id, \
|
||||
*args, **kwargs)``
|
||||
"""
|
||||
if self.inline_message_id:
|
||||
return self.bot.edit_message_text(
|
||||
inline_message_id=self.inline_message_id, *args, **kwargs)
|
||||
else:
|
||||
return self.bot.edit_message_text(
|
||||
chat_id=self.message.chat_id, message_id=self.message.message_id, *args, **kwargs)
|
||||
|
||||
def edit_message_caption(self, *args, **kwargs):
|
||||
"""
|
||||
Shortcut for either
|
||||
``bot.editMessageCaption(chat_id=update.callback_query.message.chat_id, \
|
||||
message_id=update.callback_query.message.message_id, \
|
||||
*args, **kwargs)``
|
||||
or
|
||||
``bot.editMessageCaption(inline_message_id=update.callback_query.inline_message_id, \
|
||||
*args, **kwargs)``
|
||||
"""
|
||||
if self.inline_message_id:
|
||||
return self.bot.edit_message_caption(
|
||||
inline_message_id=self.inline_message_id, *args, **kwargs)
|
||||
else:
|
||||
return self.bot.edit_message_caption(
|
||||
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
|
||||
``bot.editMessageReplyMarkup(chat_id=update.callback_query.message.chat_id, \
|
||||
message_id=update.callback_query.message.message_id, \
|
||||
*args, **kwargs)``
|
||||
or
|
||||
``bot.editMessageReplyMarkup(inline_message_id=update.callback_query.inline_message_id, \
|
||||
*args, **kwargs)``
|
||||
"""
|
||||
if self.inline_message_id:
|
||||
return self.bot.edit_message_reply_markup(
|
||||
inline_message_id=self.inline_message_id, *args, **kwargs)
|
||||
else:
|
||||
return self.bot.edit_message_reply_markup(
|
||||
chat_id=self.message.chat_id, message_id=self.message.message_id, *args, **kwargs)
|
||||
|
||||
+25
-12
@@ -2,7 +2,7 @@
|
||||
# pylint: disable=C0103,W0622
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# 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
|
||||
@@ -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 a object that represents a Telegram Chat."""
|
||||
"""This module contains an object that represents a Telegram Chat."""
|
||||
|
||||
from telegram import TelegramObject
|
||||
|
||||
@@ -32,33 +32,46 @@ class Chat(TelegramObject):
|
||||
username (str): Username, for private chats and channels if available
|
||||
first_name (str): First name of the other party in a private chat
|
||||
last_name (str): Last name of the other party in a private chat
|
||||
all_members_are_administrators (bool): True if group has 'All Members Are Administrators'
|
||||
|
||||
Args:
|
||||
id (int):
|
||||
type (str):
|
||||
**kwargs: Arbitrary keyword arguments.
|
||||
|
||||
Keyword Args:
|
||||
type (Optional[str]):
|
||||
title (Optional[str]):
|
||||
username(Optional[str]):
|
||||
first_name(Optional[str]):
|
||||
last_name(Optional[str]):
|
||||
bot (Optional[Bot]): The Bot to use for instance methods
|
||||
"""
|
||||
**kwargs (dict): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
PRIVATE = 'private'
|
||||
GROUP = 'group'
|
||||
SUPERGROUP = 'supergroup'
|
||||
CHANNEL = 'channel'
|
||||
|
||||
def __init__(self, id, type, bot=None, **kwargs):
|
||||
def __init__(self,
|
||||
id,
|
||||
type,
|
||||
title=None,
|
||||
username=None,
|
||||
first_name=None,
|
||||
last_name=None,
|
||||
all_members_are_administrators=None,
|
||||
bot=None,
|
||||
**kwargs):
|
||||
# Required
|
||||
self.id = int(id)
|
||||
self.type = type
|
||||
# Optionals
|
||||
self.title = kwargs.get('title', '')
|
||||
self.username = kwargs.get('username', '')
|
||||
self.first_name = kwargs.get('first_name', '')
|
||||
self.last_name = kwargs.get('last_name', '')
|
||||
self.title = title
|
||||
self.username = username
|
||||
self.first_name = first_name
|
||||
self.last_name = last_name
|
||||
self.all_members_are_administrators = all_members_are_administrators
|
||||
|
||||
self.bot = bot
|
||||
self._id_attrs = (self.id,)
|
||||
|
||||
@staticmethod
|
||||
def de_json(data, bot):
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# pylint: disable=R0903
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# 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
|
||||
@@ -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 a object that represents a Telegram ChatAction."""
|
||||
"""This module contains an object that represents a Telegram ChatAction."""
|
||||
|
||||
|
||||
class ChatAction(object):
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# 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
|
||||
@@ -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 a object that represents a Telegram ChatMember."""
|
||||
"""This module contains an object that represents a Telegram ChatMember."""
|
||||
|
||||
from telegram import User, TelegramObject
|
||||
|
||||
@@ -32,8 +32,9 @@ class ChatMember(TelegramObject):
|
||||
Args:
|
||||
user (:class:`telegram.User`):
|
||||
status (str):
|
||||
"""
|
||||
**kwargs (dict): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
CREATOR = 'creator'
|
||||
ADMINISTRATOR = 'administrator'
|
||||
MEMBER = 'member'
|
||||
@@ -45,6 +46,8 @@ class ChatMember(TelegramObject):
|
||||
self.user = user
|
||||
self.status = status
|
||||
|
||||
self._id_attrs = (self.user, self.status)
|
||||
|
||||
@staticmethod
|
||||
def de_json(data, bot):
|
||||
"""
|
||||
@@ -58,6 +61,8 @@ class ChatMember(TelegramObject):
|
||||
if not data:
|
||||
return None
|
||||
|
||||
data = super(ChatMember, ChatMember).de_json(data, bot)
|
||||
|
||||
data['user'] = User.de_json(data.get('user'), bot)
|
||||
|
||||
return ChatMember(**data)
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
# pylint: disable=R0902,R0912,R0913
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015 Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
# 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
|
||||
@@ -17,7 +18,7 @@
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""
|
||||
This module contains a object that represents a Telegram ChosenInlineResult
|
||||
This module contains an object that represents a Telegram ChosenInlineResult
|
||||
"""
|
||||
|
||||
from telegram import TelegramObject, User, Location
|
||||
@@ -33,11 +34,16 @@ class ChosenInlineResult(TelegramObject):
|
||||
result_id (str):
|
||||
from_user (:class:`telegram.User`):
|
||||
query (str):
|
||||
location (:class:`telegram.Location`):
|
||||
inline_message_id (str):
|
||||
|
||||
Args:
|
||||
result_id (str):
|
||||
from_user (:class:`telegram.User`):
|
||||
query (str):
|
||||
location (Optional[:class:`telegram.Location`]):
|
||||
inline_message_id (Optional[str]):
|
||||
**kwargs (dict): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
@@ -56,6 +62,8 @@ class ChosenInlineResult(TelegramObject):
|
||||
self.location = location
|
||||
self.inline_message_id = inline_message_id
|
||||
|
||||
self._id_attrs = (self.result_id,)
|
||||
|
||||
@staticmethod
|
||||
def de_json(data, bot):
|
||||
"""
|
||||
@@ -69,6 +77,7 @@ class ChosenInlineResult(TelegramObject):
|
||||
if not data:
|
||||
return None
|
||||
|
||||
data = super(ChosenInlineResult, ChosenInlineResult).de_json(data, bot)
|
||||
# Required
|
||||
data['from_user'] = User.de_json(data.pop('from'), bot)
|
||||
# Optionals
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# python-telegram-bot - a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# Copyright (C) 2015-2017
|
||||
# by the python-telegram-bot contributors <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
@@ -32,6 +32,7 @@ Attributes:
|
||||
limit, but eventually you'll begin receiving 429 errors.
|
||||
MAX_MESSAGES_PER_SECOND (int)
|
||||
MAX_MESSAGES_PER_MINUTE_PER_GROUP (int)
|
||||
MAX_INLINE_QUERY_RESULTS (int)
|
||||
|
||||
The following constant have been found by experimentation:
|
||||
|
||||
@@ -52,3 +53,4 @@ MAX_MESSAGES_PER_SECOND_PER_CHAT = 1
|
||||
MAX_MESSAGES_PER_SECOND = 30
|
||||
MAX_MESSAGES_PER_MINUTE_PER_GROUP = 20
|
||||
MAX_MESSAGE_ENTITIES = 100
|
||||
MAX_INLINE_QUERY_RESULTS = 50
|
||||
|
||||
+9
-8
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# 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
|
||||
@@ -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 a object that represents a Telegram Contact."""
|
||||
"""This module contains an object that represents a Telegram Contact."""
|
||||
|
||||
from telegram import TelegramObject
|
||||
|
||||
@@ -33,20 +33,21 @@ class Contact(TelegramObject):
|
||||
Args:
|
||||
phone_number (str):
|
||||
first_name (str):
|
||||
**kwargs: Arbitrary keyword arguments.
|
||||
|
||||
Keyword Args:
|
||||
last_name (Optional[str]):
|
||||
user_id (Optional[int]):
|
||||
**kwargs: Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, phone_number, first_name, **kwargs):
|
||||
def __init__(self, phone_number, first_name, last_name=None, user_id=None, **kwargs):
|
||||
# Required
|
||||
self.phone_number = str(phone_number)
|
||||
self.first_name = first_name
|
||||
# Optionals
|
||||
self.last_name = kwargs.get('last_name', '')
|
||||
self.user_id = int(kwargs.get('user_id', 0))
|
||||
self.last_name = last_name
|
||||
self.user_id = user_id
|
||||
|
||||
self._id_attrs = (self.phone_number,)
|
||||
|
||||
@staticmethod
|
||||
def de_json(data, bot):
|
||||
|
||||
+21
-10
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# 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
|
||||
@@ -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 a object that represents a Telegram Document."""
|
||||
"""This module contains an object that represents a Telegram Document."""
|
||||
|
||||
from telegram import PhotoSize, TelegramObject
|
||||
|
||||
@@ -33,23 +33,32 @@ class Document(TelegramObject):
|
||||
|
||||
Args:
|
||||
file_id (str):
|
||||
**kwargs: Arbitrary keyword arguments.
|
||||
|
||||
Keyword Args:
|
||||
thumb (Optional[:class:`telegram.PhotoSize`]):
|
||||
file_name (Optional[str]):
|
||||
mime_type (Optional[str]):
|
||||
file_size (Optional[int]):
|
||||
**kwargs (dict): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, file_id, **kwargs):
|
||||
_id_keys = ('file_id',)
|
||||
|
||||
def __init__(self,
|
||||
file_id,
|
||||
thumb=None,
|
||||
file_name=None,
|
||||
mime_type=None,
|
||||
file_size=None,
|
||||
**kwargs):
|
||||
# Required
|
||||
self.file_id = str(file_id)
|
||||
# Optionals
|
||||
self.thumb = kwargs.get('thumb')
|
||||
self.file_name = kwargs.get('file_name', '')
|
||||
self.mime_type = str(kwargs.get('mime_type', ''))
|
||||
self.file_size = int(kwargs.get('file_size', 0))
|
||||
self.thumb = thumb
|
||||
self.file_name = file_name
|
||||
self.mime_type = mime_type
|
||||
self.file_size = file_size
|
||||
|
||||
self._id_attrs = (self.file_id,)
|
||||
|
||||
@staticmethod
|
||||
def de_json(data, bot):
|
||||
@@ -64,6 +73,8 @@ class Document(TelegramObject):
|
||||
if not data:
|
||||
return None
|
||||
|
||||
data = super(Document, Document).de_json(data, bot)
|
||||
|
||||
data['thumb'] = PhotoSize.de_json(data.get('thumb'), bot)
|
||||
|
||||
return Document(**data)
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@
|
||||
# pylint: disable=C0103,R0903,E0213
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# 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
|
||||
@@ -18,7 +18,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains a object that represents an Emoji.
|
||||
"""This module contains an object that represents an Emoji.
|
||||
|
||||
This module will be removed in the future.
|
||||
"""
|
||||
|
||||
+18
-8
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# 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
|
||||
@@ -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 a object that represents a Telegram Error."""
|
||||
"""This module contains an object that represents a Telegram Error."""
|
||||
|
||||
|
||||
def _lstrip_str(in_s, lstr):
|
||||
@@ -62,9 +62,7 @@ class TelegramError(Exception):
|
||||
|
||||
|
||||
class Unauthorized(TelegramError):
|
||||
|
||||
def __init__(self):
|
||||
super(Unauthorized, self).__init__('Unauthorized')
|
||||
pass
|
||||
|
||||
|
||||
class InvalidToken(TelegramError):
|
||||
@@ -94,8 +92,20 @@ class ChatMigrated(TelegramError):
|
||||
Args:
|
||||
new_chat_id (int):
|
||||
|
||||
Returns:
|
||||
"""
|
||||
super(ChatMigrated,
|
||||
self).__init__('Group migrated to supergroup. New chat id: {}'.format(new_chat_id))
|
||||
self.new_chat_id = new_chat_id
|
||||
|
||||
|
||||
class RetryAfter(TelegramError):
|
||||
|
||||
def __init__(self, retry_after):
|
||||
"""
|
||||
Args:
|
||||
retry_after (int):
|
||||
|
||||
"""
|
||||
super(ChatMigrated, self).__init__('Chat migrated')
|
||||
self.new_chat_id = new_chat_id
|
||||
super(RetryAfter,
|
||||
self).__init__('Flood control exceeded. Retry in {} seconds'.format(retry_after))
|
||||
self.retry_after = float(retry_after)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# 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
|
||||
@@ -26,7 +26,8 @@ from .choseninlineresulthandler import ChosenInlineResultHandler
|
||||
from .commandhandler import CommandHandler
|
||||
from .handler import Handler
|
||||
from .inlinequeryhandler import InlineQueryHandler
|
||||
from .messagehandler import MessageHandler, Filters
|
||||
from .messagehandler import MessageHandler
|
||||
from .filters import BaseFilter, Filters
|
||||
from .regexhandler import RegexHandler
|
||||
from .stringcommandhandler import StringCommandHandler
|
||||
from .stringregexhandler import StringRegexHandler
|
||||
@@ -35,5 +36,5 @@ from .conversationhandler import ConversationHandler
|
||||
|
||||
__all__ = ('Dispatcher', 'JobQueue', 'Job', 'Updater', 'CallbackQueryHandler',
|
||||
'ChosenInlineResultHandler', 'CommandHandler', 'Handler', 'InlineQueryHandler',
|
||||
'MessageHandler', 'Filters', 'RegexHandler', 'StringCommandHandler',
|
||||
'MessageHandler', 'BaseFilter', 'Filters', 'RegexHandler', 'StringCommandHandler',
|
||||
'StringRegexHandler', 'TypeHandler', 'ConversationHandler')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# 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
|
||||
@@ -23,7 +23,6 @@ import re
|
||||
from future.utils import string_types
|
||||
|
||||
from telegram import Update
|
||||
from telegram.utils.deprecate import deprecate
|
||||
from .handler import Handler
|
||||
|
||||
|
||||
@@ -39,7 +38,7 @@ class CallbackQueryHandler(Handler):
|
||||
pass_update_queue (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``update_queue`` will be passed to the callback function. It will be the ``Queue``
|
||||
instance used by the ``Updater`` and ``Dispatcher`` that contains new updates which can
|
||||
be used to insert updates. Default is ``False``.
|
||||
be used to insert updates. Default is ``False``.
|
||||
pass_job_queue (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``job_queue`` will be passed to the callback function. It will be a ``JobQueue``
|
||||
instance created by the ``Updater`` which can be used to schedule new jobs.
|
||||
@@ -52,6 +51,14 @@ class CallbackQueryHandler(Handler):
|
||||
pass_groupdict (optional[bool]): If the callback should be passed the
|
||||
result of ``re.match(pattern, data).groupdict()`` as a keyword
|
||||
argument called ``groupdict``. Default is ``False``
|
||||
pass_user_data (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``user_data`` will be passed to the callback function. It will be a ``dict`` you
|
||||
can use to keep any data related to the user that sent the update. For each update of
|
||||
the same user, it will be the same ``dict``. Default is ``False``.
|
||||
pass_chat_data (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``chat_data`` will be passed to the callback function. It will be a ``dict`` you
|
||||
can use to keep any data related to the chat that the update was sent in.
|
||||
For each update in the same chat, it will be the same ``dict``. Default is ``False``.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -60,9 +67,15 @@ class CallbackQueryHandler(Handler):
|
||||
pass_job_queue=False,
|
||||
pattern=None,
|
||||
pass_groups=False,
|
||||
pass_groupdict=False):
|
||||
pass_groupdict=False,
|
||||
pass_user_data=False,
|
||||
pass_chat_data=False):
|
||||
super(CallbackQueryHandler, self).__init__(
|
||||
callback, pass_update_queue=pass_update_queue, pass_job_queue=pass_job_queue)
|
||||
callback,
|
||||
pass_update_queue=pass_update_queue,
|
||||
pass_job_queue=pass_job_queue,
|
||||
pass_user_data=pass_user_data,
|
||||
pass_chat_data=pass_chat_data)
|
||||
|
||||
if isinstance(pattern, string_types):
|
||||
pattern = re.compile(pattern)
|
||||
@@ -81,7 +94,7 @@ class CallbackQueryHandler(Handler):
|
||||
return True
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
optional_args = self.collect_optional_args(dispatcher)
|
||||
optional_args = self.collect_optional_args(dispatcher, update)
|
||||
if self.pattern:
|
||||
match = re.match(self.pattern, update.callback_query.data)
|
||||
|
||||
@@ -91,8 +104,3 @@ class CallbackQueryHandler(Handler):
|
||||
optional_args['groupdict'] = match.groupdict()
|
||||
|
||||
return self.callback(dispatcher.bot, update, **optional_args)
|
||||
|
||||
# old non-PEP8 Handler methods
|
||||
m = "telegram.CallbackQueryHandler."
|
||||
checkUpdate = deprecate(check_update, m + "checkUpdate", m + "check_update")
|
||||
handleUpdate = deprecate(handle_update, m + "handleUpdate", m + "handle_update")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# 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
|
||||
@@ -35,22 +35,39 @@ class ChosenInlineResultHandler(Handler):
|
||||
pass_update_queue (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``update_queue`` will be passed to the callback function. It will be the ``Queue``
|
||||
instance used by the ``Updater`` and ``Dispatcher`` that contains new updates which can
|
||||
be used to insert updates. Default is ``False``.
|
||||
be used to insert updates. Default is ``False``.
|
||||
pass_job_queue (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``job_queue`` will be passed to the callback function. It will be a ``JobQueue``
|
||||
instance created by the ``Updater`` which can be used to schedule new jobs.
|
||||
Default is ``False``.
|
||||
pass_user_data (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``user_data`` will be passed to the callback function. It will be a ``dict`` you
|
||||
can use to keep any data related to the user that sent the update. For each update of
|
||||
the same user, it will be the same ``dict``. Default is ``False``.
|
||||
pass_chat_data (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``chat_data`` will be passed to the callback function. It will be a ``dict`` you
|
||||
can use to keep any data related to the chat that the update was sent in.
|
||||
For each update in the same chat, it will be the same ``dict``. Default is ``False``.
|
||||
"""
|
||||
|
||||
def __init__(self, callback, pass_update_queue=False, pass_job_queue=False):
|
||||
def __init__(self,
|
||||
callback,
|
||||
pass_update_queue=False,
|
||||
pass_job_queue=False,
|
||||
pass_user_data=False,
|
||||
pass_chat_data=False):
|
||||
super(ChosenInlineResultHandler, self).__init__(
|
||||
callback, pass_update_queue=pass_update_queue, pass_job_queue=pass_job_queue)
|
||||
callback,
|
||||
pass_update_queue=pass_update_queue,
|
||||
pass_job_queue=pass_job_queue,
|
||||
pass_user_data=pass_user_data,
|
||||
pass_chat_data=pass_chat_data)
|
||||
|
||||
def check_update(self, update):
|
||||
return isinstance(update, Update) and update.chosen_inline_result
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
optional_args = self.collect_optional_args(dispatcher)
|
||||
optional_args = self.collect_optional_args(dispatcher, update)
|
||||
|
||||
return self.callback(dispatcher.bot, update, **optional_args)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# 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
|
||||
@@ -17,10 +17,10 @@
|
||||
# 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 """
|
||||
import warnings
|
||||
|
||||
from .handler import Handler
|
||||
from telegram import Update
|
||||
from telegram.utils.deprecate import deprecate
|
||||
|
||||
|
||||
class CommandHandler(Handler):
|
||||
@@ -30,10 +30,15 @@ class CommandHandler(Handler):
|
||||
name and/or some additional text.
|
||||
|
||||
Args:
|
||||
command (str): The name of the command this handler should listen for.
|
||||
command (str|list): The name of the command or list of command this handler should
|
||||
listen for.
|
||||
callback (function): A function that takes ``bot, update`` as
|
||||
positional arguments. It will be called when the ``check_update``
|
||||
has determined that an update should be processed by this handler.
|
||||
filters (telegram.ext.BaseFilter): A filter inheriting from
|
||||
:class:`telegram.ext.filters.BaseFilter`. Standard filters can be found in
|
||||
:class:`telegram.ext.filters.Filters`. Filters can be combined using bitwise
|
||||
operators (& for and, | for or).
|
||||
allow_edited (Optional[bool]): If the handler should also accept edited messages.
|
||||
Default is ``False``
|
||||
pass_args (optional[bool]): If the handler should be passed the
|
||||
@@ -44,39 +49,84 @@ class CommandHandler(Handler):
|
||||
pass_update_queue (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``update_queue`` will be passed to the callback function. It will be the ``Queue``
|
||||
instance used by the ``Updater`` and ``Dispatcher`` that contains new updates which can
|
||||
be used to insert updates. Default is ``False``.
|
||||
be used to insert updates. Default is ``False``.
|
||||
pass_job_queue (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``job_queue`` will be passed to the callback function. It will be a ``JobQueue``
|
||||
instance created by the ``Updater`` which can be used to schedule new jobs.
|
||||
Default is ``False``.
|
||||
pass_user_data (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``user_data`` will be passed to the callback function. It will be a ``dict`` you
|
||||
can use to keep any data related to the user that sent the update. For each update of
|
||||
the same user, it will be the same ``dict``. Default is ``False``.
|
||||
pass_chat_data (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``chat_data`` will be passed to the callback function. It will be a ``dict`` you
|
||||
can use to keep any data related to the chat that the update was sent in.
|
||||
For each update in the same chat, it will be the same ``dict``. Default is ``False``.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
command,
|
||||
callback,
|
||||
filters=None,
|
||||
allow_edited=False,
|
||||
pass_args=False,
|
||||
pass_update_queue=False,
|
||||
pass_job_queue=False):
|
||||
pass_job_queue=False,
|
||||
pass_user_data=False,
|
||||
pass_chat_data=False):
|
||||
super(CommandHandler, self).__init__(
|
||||
callback, pass_update_queue=pass_update_queue, pass_job_queue=pass_job_queue)
|
||||
self.command = command
|
||||
callback,
|
||||
pass_update_queue=pass_update_queue,
|
||||
pass_job_queue=pass_job_queue,
|
||||
pass_user_data=pass_user_data,
|
||||
pass_chat_data=pass_chat_data)
|
||||
try:
|
||||
_str = basestring # Python 2
|
||||
except NameError:
|
||||
_str = str # Python 3
|
||||
|
||||
if isinstance(command, _str):
|
||||
self.command = [command]
|
||||
else:
|
||||
self.command = command
|
||||
self.filters = filters
|
||||
self.allow_edited = allow_edited
|
||||
self.pass_args = pass_args
|
||||
|
||||
# We put this up here instead of with the rest of checking code
|
||||
# in check_update since we don't wanna spam a ton
|
||||
if isinstance(self.filters, list):
|
||||
warnings.warn('Using a list of filters in MessageHandler is getting '
|
||||
'deprecated, please use bitwise operators (& and |) '
|
||||
'instead. More info: https://git.io/vPTbc.')
|
||||
|
||||
def check_update(self, update):
|
||||
if (isinstance(update, Update)
|
||||
and (update.message or update.edited_message and self.allow_edited)):
|
||||
message = update.message or update.edited_message
|
||||
|
||||
return (message.text and message.text.startswith('/')
|
||||
and message.text[1:].split(' ')[0].split('@')[0] == self.command)
|
||||
if message.text:
|
||||
command = message.text[1:].split(' ')[0].split('@')
|
||||
command.append(
|
||||
message.bot.username) # in case the command was send without a username
|
||||
|
||||
if self.filters is None:
|
||||
res = True
|
||||
elif isinstance(self.filters, list):
|
||||
res = any(func(message) for func in self.filters)
|
||||
else:
|
||||
res = self.filters(message)
|
||||
|
||||
return res and (message.text.startswith('/') and command[0] in self.command
|
||||
and command[1].lower() == message.bot.username.lower())
|
||||
else:
|
||||
return False
|
||||
|
||||
else:
|
||||
return False
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
optional_args = self.collect_optional_args(dispatcher)
|
||||
optional_args = self.collect_optional_args(dispatcher, update)
|
||||
|
||||
message = update.message or update.edited_message
|
||||
|
||||
@@ -84,8 +134,3 @@ class CommandHandler(Handler):
|
||||
optional_args['args'] = message.text.split()[1:]
|
||||
|
||||
return self.callback(dispatcher.bot, update, **optional_args)
|
||||
|
||||
# old non-PEP8 Handler methods
|
||||
m = "telegram.CommandHandler."
|
||||
checkUpdate = deprecate(check_update, m + "checkUpdate", m + "check_update")
|
||||
handleUpdate = deprecate(handle_update, m + "handleUpdate", m + "handle_update")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# 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
|
||||
@@ -21,13 +21,16 @@
|
||||
import logging
|
||||
|
||||
from telegram import Update
|
||||
from telegram.ext import Handler
|
||||
from telegram.ext import (Handler, CallbackQueryHandler, InlineQueryHandler,
|
||||
ChosenInlineResultHandler)
|
||||
from telegram.utils.promise import Promise
|
||||
|
||||
|
||||
class ConversationHandler(Handler):
|
||||
"""
|
||||
A handler to hold a conversation with a user by managing four collections of other handlers.
|
||||
A handler to hold a conversation with a single user by managing four collections of other
|
||||
handlers. Note that neither posts in Telegram Channels, nor group interactions with multiple
|
||||
users are managed by instances of this class.
|
||||
|
||||
The first collection, a ``list`` named ``entry_points``, is used to initiate the conversation,
|
||||
for example with a ``CommandHandler`` or ``RegexHandler``.
|
||||
@@ -85,7 +88,10 @@ class ConversationHandler(Handler):
|
||||
fallbacks,
|
||||
allow_reentry=False,
|
||||
run_async_timeout=None,
|
||||
timed_out_behavior=None):
|
||||
timed_out_behavior=None,
|
||||
per_chat=True,
|
||||
per_user=True,
|
||||
per_message=False):
|
||||
|
||||
self.entry_points = entry_points
|
||||
""":type: list[telegram.ext.Handler]"""
|
||||
@@ -103,43 +109,76 @@ class ConversationHandler(Handler):
|
||||
""":type: list[telegram.ext.Handler]"""
|
||||
|
||||
self.conversations = dict()
|
||||
""":type: dict[(int, int): str]"""
|
||||
self.per_user = per_user
|
||||
self.per_chat = per_chat
|
||||
self.per_message = per_message
|
||||
""":type: dict[tuple: object]"""
|
||||
|
||||
self.current_conversation = None
|
||||
self.current_handler = None
|
||||
|
||||
self.logger = logging.getLogger(__name__)
|
||||
|
||||
if not any((self.per_user, self.per_chat, self.per_message)):
|
||||
raise ValueError("'per_user', 'per_chat' and 'per_message' can't all be 'False'")
|
||||
|
||||
if self.per_message and not self.per_chat:
|
||||
logging.warning("If 'per_message=True' is used, 'per_chat=True' should also be used, "
|
||||
"since message IDs are not globally unique.")
|
||||
|
||||
all_handlers = list()
|
||||
all_handlers.extend(entry_points)
|
||||
all_handlers.extend(fallbacks)
|
||||
|
||||
for state_handlers in states.values():
|
||||
all_handlers.extend(state_handlers)
|
||||
|
||||
if self.per_message:
|
||||
for handler in all_handlers:
|
||||
if not isinstance(handler, CallbackQueryHandler):
|
||||
logging.warning("If 'per_message=True', all entry points and state handlers"
|
||||
" must be 'CallbackQueryHandler', since no other handlers "
|
||||
"have a message context.")
|
||||
else:
|
||||
for handler in all_handlers:
|
||||
if isinstance(handler, CallbackQueryHandler):
|
||||
logging.warning("If 'per_message=False', 'CallbackQueryHandler' will not be "
|
||||
"tracked for every message.")
|
||||
|
||||
if self.per_chat:
|
||||
for handler in all_handlers:
|
||||
if isinstance(handler, (InlineQueryHandler, ChosenInlineResultHandler)):
|
||||
logging.warning("If 'per_chat=True', 'InlineQueryHandler' can not be used, "
|
||||
"since inline queries have no chat context.")
|
||||
|
||||
def _get_key(self, update):
|
||||
chat = update.effective_chat
|
||||
user = update.effective_user
|
||||
|
||||
key = list()
|
||||
|
||||
if self.per_chat:
|
||||
key.append(chat.id)
|
||||
|
||||
if self.per_user:
|
||||
key.append(user.id)
|
||||
|
||||
if self.per_message:
|
||||
key.append(update.callback_query.inline_message_id
|
||||
or update.callback_query.message.message_id)
|
||||
|
||||
return tuple(key)
|
||||
|
||||
def check_update(self, update):
|
||||
|
||||
if not isinstance(update, Update):
|
||||
# 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
|
||||
and not update.callback_query or update.callback_query and self.per_chat
|
||||
and not update.callback_query.message):
|
||||
return False
|
||||
|
||||
user = None
|
||||
chat = None
|
||||
|
||||
if update.message:
|
||||
user = update.message.from_user
|
||||
chat = update.message.chat
|
||||
|
||||
elif update.edited_message:
|
||||
user = update.edited_message.from_user
|
||||
chat = update.edited_message.chat
|
||||
|
||||
elif update.inline_query:
|
||||
user = update.inline_query.from_user
|
||||
|
||||
elif update.chosen_inline_result:
|
||||
user = update.chosen_inline_result.from_user
|
||||
|
||||
elif update.callback_query:
|
||||
user = update.callback_query.from_user
|
||||
chat = update.callback_query.message.chat if update.callback_query.message else None
|
||||
|
||||
else:
|
||||
return False
|
||||
|
||||
key = (chat.id, user.id) if chat else (None, user.id)
|
||||
key = self._get_key(update)
|
||||
state = self.conversations.get(key)
|
||||
|
||||
# Resolve promises
|
||||
@@ -147,10 +186,16 @@ class ConversationHandler(Handler):
|
||||
self.logger.debug('waiting for promise...')
|
||||
|
||||
old_state, new_state = state
|
||||
new_state.result(timeout=self.run_async_timeout)
|
||||
error = False
|
||||
try:
|
||||
res = new_state.result(timeout=self.run_async_timeout)
|
||||
except Exception as exc:
|
||||
self.logger.exception("Promise function raised exception")
|
||||
self.logger.exception("{}".format(exc))
|
||||
error = True
|
||||
|
||||
if new_state.done.is_set():
|
||||
self.update_state(new_state.result(), key)
|
||||
if not error and new_state.done.is_set():
|
||||
self.update_state(res, key)
|
||||
state = self.conversations.get(key)
|
||||
|
||||
else:
|
||||
|
||||
+12
-19
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# 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
|
||||
@@ -24,6 +24,7 @@ from functools import wraps
|
||||
from threading import Thread, Lock, Event, current_thread, BoundedSemaphore
|
||||
from time import sleep
|
||||
from uuid import uuid4
|
||||
from collections import defaultdict
|
||||
|
||||
from queue import Queue, Empty
|
||||
|
||||
@@ -31,7 +32,6 @@ from future.builtins import range
|
||||
|
||||
from telegram import TelegramError
|
||||
from telegram.ext.handler import Handler
|
||||
from telegram.utils.deprecate import deprecate
|
||||
from telegram.utils.promise import Promise
|
||||
|
||||
logging.getLogger(__name__).addHandler(logging.NullHandler())
|
||||
@@ -84,6 +84,12 @@ class Dispatcher(object):
|
||||
self.bot = bot
|
||||
self.update_queue = update_queue
|
||||
self.job_queue = job_queue
|
||||
self.workers = workers
|
||||
|
||||
self.user_data = defaultdict(dict)
|
||||
""":type: dict[int, dict]"""
|
||||
self.chat_data = defaultdict(dict)
|
||||
""":type: dict[int, dict]"""
|
||||
|
||||
self.handlers = {}
|
||||
""":type: dict[int, list[Handler]"""
|
||||
@@ -105,8 +111,6 @@ class Dispatcher(object):
|
||||
else:
|
||||
self._set_singleton(None)
|
||||
|
||||
self._init_async_threads(uuid4(), workers)
|
||||
|
||||
@classmethod
|
||||
def _reset_singleton(cls):
|
||||
# NOTE: This method was added mainly for test_updater benefit and specifically pypy. Never
|
||||
@@ -154,11 +158,7 @@ class Dispatcher(object):
|
||||
len(self.__async_threads))
|
||||
break
|
||||
|
||||
try:
|
||||
promise.run()
|
||||
|
||||
except:
|
||||
self.logger.exception("run_async function raised exception")
|
||||
promise.run()
|
||||
|
||||
def run_async(self, func, *args, **kwargs):
|
||||
"""Queue a function (with given args/kwargs) to be run asynchronously.
|
||||
@@ -193,6 +193,7 @@ class Dispatcher(object):
|
||||
self.logger.error(msg)
|
||||
raise TelegramError(msg)
|
||||
|
||||
self._init_async_threads(uuid4(), self.workers)
|
||||
self.running = True
|
||||
self.logger.debug('Dispatcher started')
|
||||
|
||||
@@ -303,7 +304,7 @@ class Dispatcher(object):
|
||||
which handlers were added to the group defines the priority.
|
||||
|
||||
Args:
|
||||
handler (Handler): A Handler instance
|
||||
handler (telegram.ext.Handler): A Handler instance
|
||||
group (Optional[int]): The group identifier. Default is 0
|
||||
"""
|
||||
|
||||
@@ -324,7 +325,7 @@ class Dispatcher(object):
|
||||
Remove a handler from the specified group
|
||||
|
||||
Args:
|
||||
handler (Handler): A Handler instance
|
||||
handler (telegram.ext.Handler): A Handler instance
|
||||
group (optional[object]): The group identifier. Default is 0
|
||||
"""
|
||||
if handler in self.handlers[group]:
|
||||
@@ -366,11 +367,3 @@ class Dispatcher(object):
|
||||
|
||||
for callback in self.error_handlers:
|
||||
callback(self.bot, update, error)
|
||||
|
||||
# old non-PEP8 Dispatcher methods
|
||||
m = "telegram.dispatcher."
|
||||
addHandler = deprecate(add_handler, m + "AddHandler", m + "add_handler")
|
||||
removeHandler = deprecate(remove_handler, m + "removeHandler", m + "remove_handler")
|
||||
addErrorHandler = deprecate(add_error_handler, m + "addErrorHandler", m + "add_error_handler")
|
||||
removeErrorHandler = deprecate(remove_error_handler, m + "removeErrorHandler",
|
||||
m + "remove_error_handler")
|
||||
|
||||
@@ -0,0 +1,265 @@
|
||||
#!/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 the Filters for use with the MessageHandler class """
|
||||
from telegram import Chat
|
||||
|
||||
|
||||
class BaseFilter(object):
|
||||
"""Base class for all Message Filters
|
||||
|
||||
Subclassing from this class filters to be combined using bitwise operators:
|
||||
|
||||
And:
|
||||
|
||||
>>> (Filters.text & Filters.entity(MENTION))
|
||||
|
||||
Or:
|
||||
|
||||
>>> (Filters.audio | Filters.video)
|
||||
|
||||
Not:
|
||||
|
||||
>>> ~ Filters.command
|
||||
|
||||
Also works with more than two filters:
|
||||
|
||||
>>> (Filters.text & (Filters.entity(URL) | Filters.entity(TEXT_LINK)))
|
||||
>>> Filters.text & (~ Filters.forwarded)
|
||||
|
||||
If you want to create your own filters create a class inheriting from this class and implement
|
||||
a `filter` method that returns a boolean: `True` if the message should be handled, `False`
|
||||
otherwise. Note that the filters work only as class instances, not actual class objects
|
||||
(so remember to initialize your filter classes).
|
||||
"""
|
||||
|
||||
def __call__(self, message):
|
||||
return self.filter(message)
|
||||
|
||||
def __and__(self, other):
|
||||
return MergedFilter(self, and_filter=other)
|
||||
|
||||
def __or__(self, other):
|
||||
return MergedFilter(self, or_filter=other)
|
||||
|
||||
def __invert__(self):
|
||||
return InvertedFilter(self)
|
||||
|
||||
def filter(self, message):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class InvertedFilter(BaseFilter):
|
||||
"""Represents a filter that has been inverted.
|
||||
|
||||
Args:
|
||||
f: The filter to invert
|
||||
"""
|
||||
|
||||
def __init__(self, f):
|
||||
self.f = f
|
||||
|
||||
def filter(self, message):
|
||||
return not self.f(message)
|
||||
|
||||
def __str__(self):
|
||||
return "<telegram.ext.filters.InvertedFilter inverting {}>".format(self.f)
|
||||
|
||||
__repr__ = __str__
|
||||
|
||||
|
||||
class MergedFilter(BaseFilter):
|
||||
"""Represents a filter consisting of two other filters.
|
||||
|
||||
Args:
|
||||
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):
|
||||
self.base_filter = base_filter
|
||||
self.and_filter = and_filter
|
||||
self.or_filter = or_filter
|
||||
|
||||
def filter(self, message):
|
||||
if self.and_filter:
|
||||
return self.base_filter(message) and self.and_filter(message)
|
||||
elif self.or_filter:
|
||||
return self.base_filter(message) or self.or_filter(message)
|
||||
|
||||
def __str__(self):
|
||||
return ("<telegram.ext.filters.MergedFilter consisting of"
|
||||
" {} {} {}>").format(self.base_filter, "and" if self.and_filter else "or",
|
||||
self.and_filter or self.or_filter)
|
||||
|
||||
__repr__ = __str__
|
||||
|
||||
|
||||
class Filters(object):
|
||||
"""
|
||||
Predefined filters for use with the `filter` argument of :class:`telegram.ext.MessageHandler`.
|
||||
"""
|
||||
|
||||
class _All(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return True
|
||||
|
||||
all = _All()
|
||||
|
||||
class _Text(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.text and not message.text.startswith('/'))
|
||||
|
||||
text = _Text()
|
||||
|
||||
class _Command(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.text and message.text.startswith('/'))
|
||||
|
||||
class _Reply(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.reply_to_message)
|
||||
|
||||
reply = _Reply()
|
||||
|
||||
command = _Command()
|
||||
|
||||
class _Audio(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.audio)
|
||||
|
||||
audio = _Audio()
|
||||
|
||||
class _Document(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.document)
|
||||
|
||||
document = _Document()
|
||||
|
||||
class _Photo(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.photo)
|
||||
|
||||
photo = _Photo()
|
||||
|
||||
class _Sticker(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.sticker)
|
||||
|
||||
sticker = _Sticker()
|
||||
|
||||
class _Video(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.video)
|
||||
|
||||
video = _Video()
|
||||
|
||||
class _Voice(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.voice)
|
||||
|
||||
voice = _Voice()
|
||||
|
||||
class _Contact(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.contact)
|
||||
|
||||
contact = _Contact()
|
||||
|
||||
class _Location(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.location)
|
||||
|
||||
location = _Location()
|
||||
|
||||
class _Venue(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.venue)
|
||||
|
||||
venue = _Venue()
|
||||
|
||||
class _StatusUpdate(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.new_chat_member or message.left_chat_member
|
||||
or message.new_chat_title or message.new_chat_photo
|
||||
or message.delete_chat_photo or message.group_chat_created
|
||||
or message.supergroup_chat_created or message.channel_chat_created
|
||||
or message.migrate_to_chat_id or message.migrate_from_chat_id
|
||||
or message.pinned_message)
|
||||
|
||||
status_update = _StatusUpdate()
|
||||
|
||||
class _Forwarded(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.forward_date)
|
||||
|
||||
forwarded = _Forwarded()
|
||||
|
||||
class _Game(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return bool(message.game)
|
||||
|
||||
game = _Game()
|
||||
|
||||
class entity(BaseFilter):
|
||||
"""Filters messages to only allow those which have a :class:`telegram.MessageEntity`
|
||||
where their `type` matches `entity_type`.
|
||||
|
||||
Args:
|
||||
entity_type: Entity type to check for. All types can be found as constants
|
||||
in :class:`telegram.MessageEntity`.
|
||||
|
||||
Returns: function to use as filter
|
||||
"""
|
||||
|
||||
def __init__(self, entity_type):
|
||||
self.entity_type = entity_type
|
||||
|
||||
def filter(self, message):
|
||||
return any([entity.type == self.entity_type for entity in message.entities])
|
||||
|
||||
class _Private(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return message.chat.type == Chat.PRIVATE
|
||||
|
||||
private = _Private()
|
||||
|
||||
class _Group(BaseFilter):
|
||||
|
||||
def filter(self, message):
|
||||
return message.chat.type in [Chat.GROUP, Chat.SUPERGROUP]
|
||||
|
||||
group = _Group()
|
||||
+31
-15
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# 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
|
||||
@@ -19,8 +19,6 @@
|
||||
""" This module contains the base class for handlers as used by the
|
||||
Dispatcher """
|
||||
|
||||
from telegram.utils.deprecate import deprecate
|
||||
|
||||
|
||||
class Handler(object):
|
||||
"""
|
||||
@@ -34,17 +32,32 @@ class Handler(object):
|
||||
pass_update_queue (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``update_queue`` will be passed to the callback function. It will be the ``Queue``
|
||||
instance used by the ``Updater`` and ``Dispatcher`` that contains new updates which can
|
||||
be used to insert updates. Default is ``False``.
|
||||
be used to insert updates. Default is ``False``.
|
||||
pass_job_queue (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``job_queue`` will be passed to the callback function. It will be a ``JobQueue``
|
||||
instance created by the ``Updater`` which can be used to schedule new jobs.
|
||||
Default is ``False``.
|
||||
pass_user_data (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``user_data`` will be passed to the callback function. It will be a ``dict`` you
|
||||
can use to keep any data related to the user that sent the update. For each update of
|
||||
the same user, it will be the same ``dict``. Default is ``False``.
|
||||
pass_chat_data (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``chat_data`` will be passed to the callback function. It will be a ``dict`` you
|
||||
can use to keep any data related to the chat that the update was sent in.
|
||||
For each update in the same chat, it will be the same ``dict``. Default is ``False``.
|
||||
"""
|
||||
|
||||
def __init__(self, callback, pass_update_queue=False, pass_job_queue=False):
|
||||
def __init__(self,
|
||||
callback,
|
||||
pass_update_queue=False,
|
||||
pass_job_queue=False,
|
||||
pass_user_data=False,
|
||||
pass_chat_data=False):
|
||||
self.callback = callback
|
||||
self.pass_update_queue = pass_update_queue
|
||||
self.pass_job_queue = pass_job_queue
|
||||
self.pass_user_data = pass_user_data
|
||||
self.pass_chat_data = pass_chat_data
|
||||
|
||||
def check_update(self, update):
|
||||
"""
|
||||
@@ -69,30 +82,33 @@ class Handler(object):
|
||||
|
||||
Args:
|
||||
update (object): The update to be handled
|
||||
dispatcher (Dispatcher): The dispatcher to collect optional args
|
||||
dispatcher (telegram.ext.Dispatcher): The dispatcher to collect optional args
|
||||
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def collect_optional_args(self, dispatcher):
|
||||
def collect_optional_args(self, dispatcher, update=None):
|
||||
"""
|
||||
Prepares the optional arguments that are the same for all types of
|
||||
handlers
|
||||
|
||||
Args:
|
||||
dispatcher (Dispatcher):
|
||||
dispatcher (telegram.ext.Dispatcher):
|
||||
"""
|
||||
optional_args = dict()
|
||||
|
||||
if self.pass_update_queue:
|
||||
optional_args['update_queue'] = dispatcher.update_queue
|
||||
if self.pass_job_queue:
|
||||
optional_args['job_queue'] = dispatcher.job_queue
|
||||
if self.pass_user_data or self.pass_chat_data:
|
||||
chat = update.effective_chat
|
||||
user = update.effective_user
|
||||
|
||||
if self.pass_user_data:
|
||||
optional_args['user_data'] = dispatcher.user_data[user.id if user else None]
|
||||
|
||||
if self.pass_chat_data:
|
||||
optional_args['chat_data'] = dispatcher.chat_data[chat.id if chat else None]
|
||||
|
||||
return optional_args
|
||||
|
||||
# old non-PEP8 Handler methods
|
||||
m = "telegram.Handler."
|
||||
checkUpdate = deprecate(check_update, m + "checkUpdate", m + "check_update")
|
||||
handleUpdate = deprecate(handle_update, m + "handleUpdate", m + "handle_update")
|
||||
collectOptionalArgs = deprecate(collect_optional_args, m + "collectOptionalArgs",
|
||||
m + "collect_optional_args")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# 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
|
||||
@@ -38,7 +38,7 @@ class InlineQueryHandler(Handler):
|
||||
pass_update_queue (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``update_queue`` will be passed to the callback function. It will be the ``Queue``
|
||||
instance used by the ``Updater`` and ``Dispatcher`` that contains new updates which can
|
||||
be used to insert updates. Default is ``False``.
|
||||
be used to insert updates. Default is ``False``.
|
||||
pass_job_queue (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``job_queue`` will be passed to the callback function. It will be a ``JobQueue``
|
||||
instance created by the ``Updater`` which can be used to schedule new jobs.
|
||||
@@ -51,6 +51,14 @@ class InlineQueryHandler(Handler):
|
||||
pass_groupdict (optional[bool]): If the callback should be passed the
|
||||
result of ``re.match(pattern, query).groupdict()`` as a keyword
|
||||
argument called ``groupdict``. Default is ``False``
|
||||
pass_user_data (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``user_data`` will be passed to the callback function. It will be a ``dict`` you
|
||||
can use to keep any data related to the user that sent the update. For each update of
|
||||
the same user, it will be the same ``dict``. Default is ``False``.
|
||||
pass_chat_data (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``chat_data`` will be passed to the callback function. It will be a ``dict`` you
|
||||
can use to keep any data related to the chat that the update was sent in.
|
||||
For each update in the same chat, it will be the same ``dict``. Default is ``False``.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -59,9 +67,15 @@ class InlineQueryHandler(Handler):
|
||||
pass_job_queue=False,
|
||||
pattern=None,
|
||||
pass_groups=False,
|
||||
pass_groupdict=False):
|
||||
pass_groupdict=False,
|
||||
pass_user_data=False,
|
||||
pass_chat_data=False):
|
||||
super(InlineQueryHandler, self).__init__(
|
||||
callback, pass_update_queue=pass_update_queue, pass_job_queue=pass_job_queue)
|
||||
callback,
|
||||
pass_update_queue=pass_update_queue,
|
||||
pass_job_queue=pass_job_queue,
|
||||
pass_user_data=pass_user_data,
|
||||
pass_chat_data=pass_chat_data)
|
||||
|
||||
if isinstance(pattern, string_types):
|
||||
pattern = re.compile(pattern)
|
||||
@@ -80,7 +94,7 @@ class InlineQueryHandler(Handler):
|
||||
return True
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
optional_args = self.collect_optional_args(dispatcher)
|
||||
optional_args = self.collect_optional_args(dispatcher, update)
|
||||
if self.pattern:
|
||||
match = re.match(self.pattern, update.inline_query.query)
|
||||
|
||||
|
||||
+299
-45
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# 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
|
||||
@@ -20,25 +20,38 @@
|
||||
|
||||
import logging
|
||||
import time
|
||||
import warnings
|
||||
import datetime
|
||||
import weakref
|
||||
from numbers import Number
|
||||
from threading import Thread, Lock, Event
|
||||
from queue import PriorityQueue, Empty
|
||||
|
||||
|
||||
class Days(object):
|
||||
MON, TUE, WED, THU, FRI, SAT, SUN = range(7)
|
||||
EVERY_DAY = tuple(range(7))
|
||||
|
||||
|
||||
class JobQueue(object):
|
||||
"""This class allows you to periodically perform tasks with the bot.
|
||||
|
||||
Attributes:
|
||||
queue (PriorityQueue):
|
||||
bot (Bot):
|
||||
prevent_autostart (Optional[bool]): If ``True``, the job queue will not be started
|
||||
automatically. Defaults to ``False``
|
||||
bot (telegram.Bot):
|
||||
|
||||
Args:
|
||||
bot (Bot): The bot instance that should be passed to the jobs
|
||||
bot (telegram.Bot): The bot instance that should be passed to the jobs
|
||||
|
||||
Deprecated: 5.2
|
||||
prevent_autostart (Optional[bool]): Thread does not start during initialisation.
|
||||
Use `start` method instead.
|
||||
"""
|
||||
|
||||
def __init__(self, bot, prevent_autostart=False):
|
||||
def __init__(self, bot, prevent_autostart=None):
|
||||
if prevent_autostart is not None:
|
||||
warnings.warn("prevent_autostart is being deprecated, use `start` method instead.")
|
||||
|
||||
self.queue = PriorityQueue()
|
||||
self.bot = bot
|
||||
self.logger = logging.getLogger(self.__class__.__name__)
|
||||
@@ -51,38 +64,187 @@ class JobQueue(object):
|
||||
""":type: float"""
|
||||
self._running = False
|
||||
|
||||
if not prevent_autostart:
|
||||
self.logger.debug('Auto-starting %s', self.__class__.__name__)
|
||||
self.start()
|
||||
|
||||
def put(self, job, next_t=None):
|
||||
"""Queue a new job. If the JobQueue is not running, it will be started.
|
||||
"""Queue a new job.
|
||||
|
||||
Args:
|
||||
job (Job): The ``Job`` instance representing the new job
|
||||
next_t (Optional[float]): Time in seconds in which the job should be executed first.
|
||||
Defaults to ``job.interval``
|
||||
job (telegram.ext.Job): The ``Job`` instance representing the new job
|
||||
next_t (Optional[int, float, datetime.timedelta, datetime.datetime, datetime.time]):
|
||||
Time in or at which the job should run for the first time. This parameter will be
|
||||
interpreted depending on its type.
|
||||
``int`` or ``float`` will be interpreted as "seconds from now" in which the job
|
||||
should run.
|
||||
``datetime.timedelta`` will be interpreted as "time from now" in which the job
|
||||
should run.
|
||||
``datetime.datetime`` will be interpreted as a specific date and time at which the
|
||||
job should run.
|
||||
``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', "
|
||||
"'JobQueue.run_daily' or 'JobQueue.run_repeating' instead")
|
||||
if job.job_queue is None:
|
||||
job.job_queue = self
|
||||
self._put(job, next_t=next_t)
|
||||
|
||||
def _put(self, job, next_t=None, last_t=None):
|
||||
"""Queue a new job.
|
||||
|
||||
Args:
|
||||
job (telegram.ext.Job): The ``Job`` instance representing the new job
|
||||
next_t (Optional[int, float, datetime.timedelta, datetime.datetime, datetime.time]):
|
||||
Time in or at which the job should run for the first time. This parameter will be
|
||||
interpreted depending on its type.
|
||||
|
||||
* ``int`` or ``float`` will be interpreted as "seconds from now" in which the job
|
||||
should run.
|
||||
* ``datetime.timedelta`` will be interpreted as "time from now" in which the job
|
||||
should run.
|
||||
* ``datetime.datetime`` will be interpreted as a specific date and time at which
|
||||
the job should run.
|
||||
* ``datetime.time`` will be interpreted as a specific time of day at which the job
|
||||
should run. This could be either today or, if the time has already passed,
|
||||
tomorrow.
|
||||
last_t (Optional[float]): Timestamp of the time when ``job`` was scheduled for in the
|
||||
last ``put`` call. If provided, it will be used to calculate the next timestamp
|
||||
more accurately by accounting for the execution time of the job (and possibly
|
||||
others). If None, `now` will be assumed.
|
||||
|
||||
"""
|
||||
job.job_queue = self
|
||||
|
||||
if next_t is None:
|
||||
next_t = job.interval
|
||||
if next_t is None:
|
||||
raise ValueError('next_t is None')
|
||||
|
||||
now = time.time()
|
||||
next_t += now
|
||||
if isinstance(next_t, datetime.datetime):
|
||||
next_t = (next_t - datetime.datetime.now()).total_seconds()
|
||||
|
||||
elif isinstance(next_t, datetime.time):
|
||||
next_datetime = datetime.datetime.combine(datetime.date.today(), next_t)
|
||||
|
||||
if datetime.datetime.now().time() > next_t:
|
||||
next_datetime += datetime.timedelta(days=1)
|
||||
|
||||
next_t = (next_datetime - datetime.datetime.now()).total_seconds()
|
||||
|
||||
elif isinstance(next_t, datetime.timedelta):
|
||||
next_t = next_t.total_seconds()
|
||||
|
||||
next_t += last_t or time.time()
|
||||
|
||||
self.logger.debug('Putting job %s with t=%f', job.name, next_t)
|
||||
|
||||
self.queue.put((next_t, job))
|
||||
|
||||
# Wake up the loop if this job should be executed next
|
||||
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.
|
||||
|
||||
Args:
|
||||
callback (function): The callback function that should be executed by the new job. It
|
||||
should take two parameters ``bot`` and ``job``, where ``job`` is the ``Job``
|
||||
instance. It can be used to access it's ``context`` or change it to a repeating
|
||||
job.
|
||||
when (int, float, datetime.timedelta, datetime.datetime, datetime.time):
|
||||
Time in or at which the job should run. This parameter will be interpreted
|
||||
depending on its type.
|
||||
|
||||
* ``int`` or ``float`` will be interpreted as "seconds from now" in which the job
|
||||
should run.
|
||||
* ``datetime.timedelta`` will be interpreted as "time from now" in which the job
|
||||
should run.
|
||||
* ``datetime.datetime`` will be interpreted as a specific date and time at which
|
||||
the job should run.
|
||||
* ``datetime.time`` will be interpreted as a specific time of day at which the job
|
||||
should run. This could be either today or, if the time has already passed,
|
||||
tomorrow.
|
||||
|
||||
context (Optional[object]): Additional data needed for the callback function. Can be
|
||||
accessed through ``job.context`` in the callback. Defaults to ``None``
|
||||
name (Optional[str]): The name of the new job. Defaults to ``callback.__name__``
|
||||
|
||||
Returns:
|
||||
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.
|
||||
|
||||
Args:
|
||||
callback (function): The callback function that should be executed by the new job. It
|
||||
should take two parameters ``bot`` and ``job``, where ``job`` is the ``Job``
|
||||
instance. It can be used to access it's ``context``, terminate the job or change
|
||||
its interval.
|
||||
interval (int, float, datetime.timedelta): The interval in which the job will run.
|
||||
If it is an ``int`` or a ``float``, it will be interpreted as seconds.
|
||||
first (int, float, datetime.timedelta, datetime.datetime, datetime.time):
|
||||
|
||||
* ``int`` or ``float`` will be interpreted as "seconds from now" in which the job
|
||||
should run.
|
||||
* ``datetime.timedelta`` will be interpreted as "time from now" in which the job
|
||||
should run.
|
||||
* ``datetime.datetime`` will be interpreted as a specific date and time at which
|
||||
the job should run.
|
||||
* ``datetime.time`` will be interpreted as a specific time of day at which the job
|
||||
should run. This could be either today or, if the time has already passed,
|
||||
tomorrow.
|
||||
|
||||
Defaults to ``interval``
|
||||
context (Optional[object]): Additional data needed for the callback function. Can be
|
||||
accessed through ``job.context`` in the callback. Defaults to ``None``
|
||||
name (Optional[str]): The name of the new job. Defaults to ``callback.__name__``
|
||||
|
||||
Returns:
|
||||
Job: The new ``Job`` instance that has been added to the job queue.
|
||||
|
||||
"""
|
||||
job = Job(callback,
|
||||
interval=interval,
|
||||
repeat=True,
|
||||
context=context,
|
||||
name=name,
|
||||
job_queue=self)
|
||||
self._put(job, next_t=first)
|
||||
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.
|
||||
|
||||
Args:
|
||||
callback (function): The callback function that should be executed by the new job. It
|
||||
should take two parameters ``bot`` and ``job``, where ``job`` is the ``Job``
|
||||
instance. It can be used to access it's ``context`` or terminate the job.
|
||||
time (datetime.time): Time of day at which the job should run.
|
||||
days (Optional[tuple[int]]): Defines on which days of the week the job should run.
|
||||
Defaults to ``Days.EVERY_DAY``
|
||||
context (Optional[object]): Additional data needed for the callback function. Can be
|
||||
accessed through ``job.context`` in the callback. Defaults to ``None``
|
||||
name (Optional[str]): The name of the new job. Defaults to ``callback.__name__``
|
||||
|
||||
Returns:
|
||||
Job: The new ``Job`` instance that has been added to the job queue.
|
||||
|
||||
"""
|
||||
job = Job(callback,
|
||||
interval=datetime.timedelta(days=1),
|
||||
repeat=True,
|
||||
days=days,
|
||||
context=context,
|
||||
name=name,
|
||||
job_queue=self)
|
||||
self._put(job, next_t=time)
|
||||
return job
|
||||
|
||||
def _set_next_peek(self, t):
|
||||
"""
|
||||
Set next peek if not defined or `t` is before next peek.
|
||||
In case the next peek was set, also trigger the `self.__tick` event.
|
||||
|
||||
"""
|
||||
with self.__next_peek_lock:
|
||||
if not self._next_peek or self._next_peek > t:
|
||||
@@ -107,9 +269,9 @@ class JobQueue(object):
|
||||
self.logger.debug('Peeked at %s with t=%f', job.name, t)
|
||||
|
||||
if t > now:
|
||||
# we can get here in two conditions:
|
||||
# 1. At the second or later pass of the while loop, after we've already processed
|
||||
# the job(s) we were supposed to at this time.
|
||||
# We can get here in two conditions:
|
||||
# 1. At the second or later pass of the while loop, after we've already
|
||||
# processed the job(s) we were supposed to at this time.
|
||||
# 2. At the first iteration of the loop only if `self.put()` had triggered
|
||||
# `self.__tick` because `self._next_peek` wasn't set
|
||||
self.logger.debug("Next task isn't due yet. Finished!")
|
||||
@@ -117,25 +279,27 @@ class JobQueue(object):
|
||||
self._set_next_peek(t)
|
||||
break
|
||||
|
||||
if job._remove.is_set():
|
||||
if job.removed:
|
||||
self.logger.debug('Removing job %s', job.name)
|
||||
continue
|
||||
|
||||
if job.enabled:
|
||||
self.logger.debug('Running job %s', job.name)
|
||||
|
||||
try:
|
||||
job.run(self.bot)
|
||||
current_week_day = datetime.datetime.now().weekday()
|
||||
if any(day == current_week_day for day in job.days):
|
||||
self.logger.debug('Running job %s', job.name)
|
||||
job.run(self.bot)
|
||||
|
||||
except:
|
||||
self.logger.exception('An uncaught error was raised while executing job %s',
|
||||
job.name)
|
||||
|
||||
else:
|
||||
self.logger.debug('Skipping disabled job %s', job.name)
|
||||
|
||||
if job.repeat:
|
||||
self.put(job)
|
||||
if job.repeat and not job.removed:
|
||||
self._put(job, last_t=t)
|
||||
else:
|
||||
self.logger.debug('Dropping non-repeating or removed job %s', job.name)
|
||||
|
||||
def start(self):
|
||||
"""
|
||||
@@ -150,7 +314,6 @@ class JobQueue(object):
|
||||
self.__thread = Thread(target=self._main_loop, name="job_queue")
|
||||
self.__thread.start()
|
||||
self.logger.debug('%s thread started', self.__class__.__name__)
|
||||
|
||||
else:
|
||||
self.__start_lock.release()
|
||||
|
||||
@@ -163,7 +326,7 @@ class JobQueue(object):
|
||||
while self._running:
|
||||
# self._next_peek may be (re)scheduled during self.tick() or self.put()
|
||||
with self.__next_peek_lock:
|
||||
tmout = self._next_peek and self._next_peek - time.time()
|
||||
tmout = self._next_peek - time.time() if self._next_peek else None
|
||||
self._next_peek = None
|
||||
self.__tick.clear()
|
||||
|
||||
@@ -197,33 +360,58 @@ class Job(object):
|
||||
"""This class encapsulates a Job
|
||||
|
||||
Attributes:
|
||||
callback (function):
|
||||
interval (float):
|
||||
repeat (bool):
|
||||
name (str):
|
||||
callback (function): The function that the job executes when it's due
|
||||
interval (int, float, datetime.timedelta): The interval in which the job runs
|
||||
days (tuple[int]): A tuple of ``int`` values that determine on which days of the week the
|
||||
job runs
|
||||
repeat (bool): If the job runs periodically or only once
|
||||
name (str): The name of this job
|
||||
job_queue (JobQueue): The ``JobQueue`` this job belongs to
|
||||
enabled (bool): Boolean property that decides if this job is currently active
|
||||
|
||||
Args:
|
||||
callback (function): The callback function that should be executed by the Job. It should
|
||||
take two parameters ``bot`` and ``job``, where ``job`` is the ``Job`` instance. It
|
||||
can be used to terminate the job or modify its interval.
|
||||
interval (float): The interval in which this job should execute its callback function in
|
||||
seconds.
|
||||
interval (Optional[int, float, datetime.timedelta]): The interval in which the job will
|
||||
execute its callback function. ``int`` and ``float`` will be interpreted as seconds.
|
||||
If you don't set this value, you must set ``repeat=False`` and specify ``next_t`` when
|
||||
you put the job into the job queue.
|
||||
repeat (Optional[bool]): If this job should be periodically execute its callback function
|
||||
(``True``) or only once (``False``). Defaults to ``True``
|
||||
context (Optional[object]): Additional data needed for the callback function. Can be
|
||||
accessed through ``job.context`` in the callback. Defaults to ``None``
|
||||
days (Optional[tuple[int]]): Defines on which days of the week the job should run.
|
||||
Defaults to ``Days.EVERY_DAY``
|
||||
name (Optional[str]): The name of this job. Defaults to ``callback.__name__``
|
||||
job_queue (Optional[class:`telegram.ext.JobQueue`]): The ``JobQueue`` this job belongs to.
|
||||
Only optional for backward compatibility with ``JobQueue.put()``.
|
||||
|
||||
"""
|
||||
job_queue = None
|
||||
|
||||
def __init__(self, callback, interval, repeat=True, context=None):
|
||||
def __init__(self,
|
||||
callback,
|
||||
interval=None,
|
||||
repeat=True,
|
||||
context=None,
|
||||
days=Days.EVERY_DAY,
|
||||
name=None,
|
||||
job_queue=None):
|
||||
|
||||
self.callback = callback
|
||||
self.context = context
|
||||
self.name = name or callback.__name__
|
||||
|
||||
self._repeat = repeat
|
||||
self._interval = None
|
||||
self.interval = interval
|
||||
self.repeat = repeat
|
||||
self.context = context
|
||||
|
||||
self.name = callback.__name__
|
||||
self._days = None
|
||||
self.days = days
|
||||
|
||||
self._job_queue = weakref.proxy(job_queue) if job_queue is not None else None
|
||||
|
||||
self._remove = Event()
|
||||
self._enabled = Event()
|
||||
self._enabled.set()
|
||||
@@ -236,20 +424,86 @@ class Job(object):
|
||||
"""
|
||||
Schedules this job for removal from the ``JobQueue``. It will be removed without executing
|
||||
its callback function again.
|
||||
|
||||
"""
|
||||
self._remove.set()
|
||||
|
||||
def is_enabled(self):
|
||||
@property
|
||||
def removed(self):
|
||||
return self._remove.is_set()
|
||||
|
||||
@property
|
||||
def enabled(self):
|
||||
return self._enabled.is_set()
|
||||
|
||||
def set_enabled(self, status):
|
||||
@enabled.setter
|
||||
def enabled(self, status):
|
||||
if status:
|
||||
self._enabled.set()
|
||||
else:
|
||||
self._enabled.clear()
|
||||
|
||||
enabled = property(is_enabled, set_enabled)
|
||||
@property
|
||||
def interval(self):
|
||||
return self._interval
|
||||
|
||||
@interval.setter
|
||||
def interval(self, interval):
|
||||
if interval is None and self.repeat:
|
||||
raise ValueError("The 'interval' can not be 'None' when 'repeat' is set to 'True'")
|
||||
|
||||
if not (interval is None or isinstance(interval, (Number, datetime.timedelta))):
|
||||
raise ValueError("The 'interval' must be of type 'datetime.timedelta',"
|
||||
" 'int' or 'float'")
|
||||
|
||||
self._interval = interval
|
||||
|
||||
@property
|
||||
def interval_seconds(self):
|
||||
if isinstance(self.interval, datetime.timedelta):
|
||||
return self.interval.total_seconds()
|
||||
else:
|
||||
return self.interval
|
||||
|
||||
@property
|
||||
def repeat(self):
|
||||
return self._repeat
|
||||
|
||||
@repeat.setter
|
||||
def repeat(self, repeat):
|
||||
if self.interval is None and repeat:
|
||||
raise ValueError("'repeat' can not be set to 'True' when no 'interval' is set")
|
||||
self._repeat = repeat
|
||||
|
||||
@property
|
||||
def days(self):
|
||||
return self._days
|
||||
|
||||
@days.setter
|
||||
def days(self, days):
|
||||
if not isinstance(days, tuple):
|
||||
raise ValueError("The 'days' argument should be of type 'tuple'")
|
||||
|
||||
if not all(isinstance(day, int) for day in days):
|
||||
raise ValueError("The elements of the 'days' argument should be of type 'int'")
|
||||
|
||||
if not all(0 <= day <= 6 for day in days):
|
||||
raise ValueError("The elements of the 'days' argument should be from 0 up to and "
|
||||
"including 6")
|
||||
|
||||
self._days = days
|
||||
|
||||
@property
|
||||
def job_queue(self):
|
||||
""" :rtype: JobQueue """
|
||||
return self._job_queue
|
||||
|
||||
@job_queue.setter
|
||||
def job_queue(self, job_queue):
|
||||
# Property setter for backward compatibility with JobQueue.put()
|
||||
if not self._job_queue:
|
||||
self._job_queue = weakref.proxy(job_queue)
|
||||
else:
|
||||
raise RuntimeError("The 'job_queue' attribute can only be set once.")
|
||||
|
||||
def __lt__(self, other):
|
||||
return False
|
||||
|
||||
+63
-104
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2016
|
||||
# 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
|
||||
@@ -17,90 +17,10 @@
|
||||
# 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 MessageHandler class """
|
||||
import warnings
|
||||
|
||||
from .handler import Handler
|
||||
from telegram import Update
|
||||
from telegram.utils.deprecate import deprecate
|
||||
|
||||
|
||||
class Filters(object):
|
||||
"""
|
||||
Convenient namespace (class) & methods for the filter funcs of the
|
||||
MessageHandler class.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def text(message):
|
||||
return message.text and not message.text.startswith('/')
|
||||
|
||||
@staticmethod
|
||||
def command(message):
|
||||
return message.text and message.text.startswith('/')
|
||||
|
||||
@staticmethod
|
||||
def audio(message):
|
||||
return bool(message.audio)
|
||||
|
||||
@staticmethod
|
||||
def document(message):
|
||||
return bool(message.document)
|
||||
|
||||
@staticmethod
|
||||
def photo(message):
|
||||
return bool(message.photo)
|
||||
|
||||
@staticmethod
|
||||
def sticker(message):
|
||||
return bool(message.sticker)
|
||||
|
||||
@staticmethod
|
||||
def video(message):
|
||||
return bool(message.video)
|
||||
|
||||
@staticmethod
|
||||
def voice(message):
|
||||
return bool(message.voice)
|
||||
|
||||
@staticmethod
|
||||
def contact(message):
|
||||
return bool(message.contact)
|
||||
|
||||
@staticmethod
|
||||
def location(message):
|
||||
return bool(message.location)
|
||||
|
||||
@staticmethod
|
||||
def venue(message):
|
||||
return bool(message.venue)
|
||||
|
||||
@staticmethod
|
||||
def status_update(message):
|
||||
return bool(message.new_chat_member or message.left_chat_member or message.new_chat_title
|
||||
or message.new_chat_photo or message.delete_chat_photo
|
||||
or message.group_chat_created or message.supergroup_chat_created
|
||||
or message.channel_chat_created or message.migrate_to_chat_id
|
||||
or message.migrate_from_chat_id or message.pinned_message)
|
||||
|
||||
@staticmethod
|
||||
def forwarded(message):
|
||||
return bool(message.forward_date)
|
||||
|
||||
@staticmethod
|
||||
def entity(entity_type):
|
||||
"""Filters messages to only allow those which have a :class:`telegram.MessageEntity`
|
||||
where their `type` matches `entity_type`.
|
||||
|
||||
Args:
|
||||
entity_type: Entity type to check for. All types can be found as constants
|
||||
in :class:`telegram.MessageEntity`.
|
||||
|
||||
Returns: function to use as filter
|
||||
"""
|
||||
|
||||
def entities_filter(message):
|
||||
return any([entity.type == entity_type for entity in message.entities])
|
||||
|
||||
return entities_filter
|
||||
|
||||
|
||||
class MessageHandler(Handler):
|
||||
@@ -110,20 +30,33 @@ class MessageHandler(Handler):
|
||||
updates.
|
||||
|
||||
Args:
|
||||
filters (list[function]): A list of filter functions. Standard filters
|
||||
can be found in the Filters class above.
|
||||
| Each `function` takes ``Update`` as arg and returns ``bool``.
|
||||
| All messages that match at least one of those filters will be
|
||||
accepted. If ``bool(filters)`` evaluates to ``False``, messages are
|
||||
not filtered.
|
||||
filters (telegram.ext.BaseFilter): A filter inheriting from
|
||||
:class:`telegram.ext.filters.BaseFilter`. Standard filters can be found in
|
||||
:class:`telegram.ext.filters.Filters`. Filters can be combined using bitwise
|
||||
operators (& for and, | for or).
|
||||
callback (function): A function that takes ``bot, update`` as
|
||||
positional arguments. It will be called when the ``check_update``
|
||||
has determined that an update should be processed by this handler.
|
||||
allow_edited (Optional[bool]): If the handler should also accept edited messages.
|
||||
Default is ``False``
|
||||
pass_update_queue (optional[bool]): If the handler should be passed the
|
||||
update queue as a keyword argument called ``update_queue``. It can
|
||||
be used to insert updates. Default is ``False``
|
||||
pass_user_data (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``user_data`` will be passed to the callback function. It will be a ``dict`` you
|
||||
can use to keep any data related to the user that sent the update. For each update of
|
||||
the same user, it will be the same ``dict``. Default is ``False``.
|
||||
pass_chat_data (optional[bool]): If set to ``True``, a keyword argument called
|
||||
``chat_data`` will be passed to the callback function. It will be a ``dict`` you
|
||||
can use to keep any data related to the chat that the update was sent in.
|
||||
For each update in the same chat, it will be the same ``dict``. Default is ``False``.
|
||||
message_updates (Optional[bool]): Should "normal" message updates be handled? Default is
|
||||
``True``.
|
||||
allow_edited (Optional[bool]): If the handler should also accept edited messages.
|
||||
Default is ``False`` - Deprecated. use edited updates instead.
|
||||
channel_post_updates (Optional[bool]): Should channel posts updates be handled? Default is
|
||||
``True``.
|
||||
edited_updates (Optional[bool]): Should "edited" message updates be handled? Default is
|
||||
``False``.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -131,22 +64,54 @@ class MessageHandler(Handler):
|
||||
callback,
|
||||
allow_edited=False,
|
||||
pass_update_queue=False,
|
||||
pass_job_queue=False):
|
||||
pass_job_queue=False,
|
||||
pass_user_data=False,
|
||||
pass_chat_data=False,
|
||||
message_updates=True,
|
||||
channel_post_updates=True,
|
||||
edited_updates=False):
|
||||
if not message_updates and not channel_post_updates and not edited_updates:
|
||||
raise ValueError(
|
||||
'message_updates, channel_post_updates and edited_updates are all False')
|
||||
if allow_edited:
|
||||
warnings.warn('allow_edited is getting deprecated, please use edited_updates instead')
|
||||
edited_updates = allow_edited
|
||||
|
||||
super(MessageHandler, self).__init__(
|
||||
callback, pass_update_queue=pass_update_queue, pass_job_queue=pass_job_queue)
|
||||
callback,
|
||||
pass_update_queue=pass_update_queue,
|
||||
pass_job_queue=pass_job_queue,
|
||||
pass_user_data=pass_user_data,
|
||||
pass_chat_data=pass_chat_data)
|
||||
self.filters = filters
|
||||
self.allow_edited = allow_edited
|
||||
self.message_updates = message_updates
|
||||
self.channel_post_updates = channel_post_updates
|
||||
self.edited_updates = edited_updates
|
||||
|
||||
# We put this up here instead of with the rest of checking code
|
||||
# in check_update since we don't wanna spam a ton
|
||||
if isinstance(self.filters, list):
|
||||
warnings.warn('Using a list of filters in MessageHandler is getting '
|
||||
'deprecated, please use bitwise operators (& and |) '
|
||||
'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)])
|
||||
|
||||
def check_update(self, update):
|
||||
if (isinstance(update, Update)
|
||||
and (update.message or update.edited_message and self.allow_edited)):
|
||||
if isinstance(update, Update) and self._is_allowed_update(update):
|
||||
|
||||
if not self.filters:
|
||||
res = True
|
||||
|
||||
else:
|
||||
message = update.message or update.edited_message
|
||||
res = any(func(message) for func in self.filters)
|
||||
message = update.effective_message
|
||||
if isinstance(self.filters, list):
|
||||
res = any(func(message) for func in self.filters)
|
||||
else:
|
||||
res = self.filters(message)
|
||||
|
||||
else:
|
||||
res = False
|
||||
@@ -154,12 +119,6 @@ class MessageHandler(Handler):
|
||||
return res
|
||||
|
||||
def handle_update(self, update, dispatcher):
|
||||
optional_args = self.collect_optional_args(dispatcher)
|
||||
optional_args = self.collect_optional_args(dispatcher, update)
|
||||
|
||||
return self.callback(dispatcher.bot, update, **optional_args)
|
||||
|
||||
# old non-PEP8 Handler methods
|
||||
|
||||
m = "telegram.MessageHandler."
|
||||
checkUpdate = deprecate(check_update, m + "checkUpdate", m + "check_update")
|
||||
handleUpdate = deprecate(handle_update, m + "handleUpdate", m + "handle_update")
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user