mirror of
https://github.com/python-telegram-bot/python-telegram-bot.git
synced 2026-06-21 08:35:28 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5dc1e4cac1 | |||
| 2cecca8324 | |||
| 109439022f | |||
| 59ff1b68b5 | |||
| fda1843593 | |||
| 9b6ccaf94b | |||
| ea1614631e | |||
| 6bcc8cdcfd | |||
| 9b3ce5069e | |||
| f2671ffff3 | |||
| 3974690b90 | |||
| 66b3f8bbd3 | |||
| 140e68dd20 | |||
| 46cf2c250e |
+19
-1
@@ -1 +1,19 @@
|
||||
* Leandro Toledo
|
||||
Credits
|
||||
=======
|
||||
|
||||
``python-telegram-bot`` is written and maintained by `Leandro Toledo <https://github.com/leandrotoledo>`_.
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
The following wonderful people contributed directly or indirectly to this project:
|
||||
|
||||
- `Avanatiker <https://github.com/Avanatiker>`_
|
||||
- `bimmlerd <https://github.com/bimmlerd>`_
|
||||
- `franciscod <https://github.com/franciscod>`_
|
||||
- `JASON0916 <https://github.com/JASON0916>`_
|
||||
- `JRoot3D <https://github.com/JRoot3D>`_
|
||||
- `sooyhwang <https://github.com/sooyhwang>`_
|
||||
- `wjt <https://github.com/wjt>`_
|
||||
|
||||
Please add yourself here alphabetically when you submit your first pull request.
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
2015-08-14
|
||||
Released 2.6.0
|
||||
Depreciation of require_authentication and clearCredentials methods
|
||||
Giving AUTHORS the proper credits for their contribution for this project
|
||||
Message.date and Message.forward_date are now datetime objects
|
||||
|
||||
|
||||
2015-08-12
|
||||
Released 2.5.3
|
||||
telegram.Bot now supports to be unpickled
|
||||
|
||||
|
||||
2015-08-11
|
||||
Released 2.5.2
|
||||
New changes from Telegram Bot API have been applied
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
How To Contribute
|
||||
=================
|
||||
|
||||
Every open source project lives from the generous help by contributors that sacrifice their time and ``python-telegram-bot`` is no different.
|
||||
|
||||
To make participation as pleasant as possible, this project adheres to the `Code of Conduct`_ by the Python Software Foundation.
|
||||
|
||||
Here are a few guidelines to get you started:
|
||||
|
||||
- Add yourself to the AUTHORS.rst_ file in an alphabetical fashion.
|
||||
Every contribution is valuable and shall be credited.
|
||||
- If your change is noteworthy, add an entry to the CHANGES_.
|
||||
- No contribution is too small; please submit as many fixes for typos and grammar bloopers as you can!
|
||||
- Don’t break backward compatibility.
|
||||
- *Always* add tests and docs for your code.
|
||||
This is a hard rule; patches with missing tests or documentation won’t be merged.
|
||||
If a feature is not tested or documented, it doesn’t exist.
|
||||
- Obey `PEP 8`_ and `PEP 257`_.
|
||||
- Follow `Google Python Style Guide`_ and `Google Python Style Docstrings`_.
|
||||
- Write `good commit messages`_.
|
||||
|
||||
.. note::
|
||||
If you have something great but aren’t sure whether it adheres -- or even can adhere -- to the rules above: **please submit a pull request anyway**!
|
||||
|
||||
In the best case, we can mold it into something, in the worst case the pull request gets politely closed.
|
||||
There’s absolutely nothing to fear.
|
||||
|
||||
Thank you for considering to contribute to ``python-telegram-bot``!
|
||||
If you have any question or concerns, feel free to reach out to me.
|
||||
|
||||
|
||||
.. _`PEP 8`: https://www.python.org/dev/peps/pep-0008/
|
||||
.. _`PEP 257`: https://www.python.org/dev/peps/pep-0257/
|
||||
.. _`good commit messages`: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
|
||||
.. _`Code of Conduct`: https://www.python.org/psf/codeofconduct/
|
||||
.. _`Google Python Style Guide`: https://google-styleguide.googlecode.com/svn/trunk/pyguide.html
|
||||
.. _`Google Python Style Docstrings`: http://sphinx-doc.org/latest/ext/example_google.html
|
||||
.. _CHANGES: https://github.com/leandrotoledo/python-telegram-bot/blob/master/CHANGES
|
||||
.. _AUTHORS.rst: https://github.com/leandrotoledo/python-telegram-bot/blob/master/AUTHORS.rst
|
||||
+16
-4
@@ -12,6 +12,10 @@ By `Leandro Toledo <leandrotoledodesouza@gmail.com>`_
|
||||
:target: https://pypi.python.org/pypi/python-telegram-bot
|
||||
:alt: PyPi Package Monthly Download
|
||||
|
||||
.. image:: https://readthedocs.org/projects/python-telegram-bot/badge/?version=latest
|
||||
:target: https://readthedocs.org/projects/python-telegram-bot/?badge=latest
|
||||
:alt: Documentation Status
|
||||
|
||||
.. image:: https://img.shields.io/github/license/leandrotoledo/python-telegram-bot.svg
|
||||
:target: http://www.gnu.org/licenses/lgpl-3.0.html
|
||||
:alt: LGPLv3 License
|
||||
@@ -44,13 +48,15 @@ Table of contents
|
||||
|
||||
- `Getting the code`_
|
||||
|
||||
- `Documentation`_
|
||||
- `Getting started`_
|
||||
|
||||
1. `API`_
|
||||
|
||||
2. `Logging`_
|
||||
|
||||
3. `Examples`_
|
||||
|
||||
4. `Documentation`_
|
||||
|
||||
- `License`_
|
||||
|
||||
@@ -134,9 +140,9 @@ To see other options available, run:
|
||||
|
||||
$ make help
|
||||
|
||||
================
|
||||
_`Documentation`
|
||||
================
|
||||
==================
|
||||
_`Getting started`
|
||||
==================
|
||||
|
||||
View the last release API documentation at: https://core.telegram.org/bots/api
|
||||
|
||||
@@ -239,6 +245,12 @@ Here follows some examples to help you to get your own Bot up to speed:
|
||||
|
||||
- `DevOps Reaction Bot <https://github.com/leandrotoledo/gae-devops-reaction-telegram-bot>`_ sends latest or random posts from `DevOps Reaction <http://devopsreactions.tumblr.com/>`_. Running on `Google App Engine <https://cloud.google.com/appengine>`_ (billing has to be enabled for fully Socket API support).
|
||||
|
||||
================
|
||||
_`Documentation`
|
||||
================
|
||||
|
||||
``python-telegram-bot``'s documentation lives at `Read the Docs <http://python-telegram-bot.readthedocs.org/en/latest/>`_.
|
||||
|
||||
==========
|
||||
_`License`
|
||||
==========
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
sphinx
|
||||
sphinx_rtd_theme
|
||||
sphinx-pypi-upload
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
[wheel]
|
||||
universal = 1
|
||||
|
||||
[upload_docs]
|
||||
[build_sphinx]
|
||||
source-dir = docs/source
|
||||
build-dir = docs/build
|
||||
all_files = 1
|
||||
|
||||
[upload_sphinx]
|
||||
upload-dir = docs/build/html
|
||||
|
||||
@@ -15,7 +15,7 @@ def read(*paths):
|
||||
|
||||
setup(
|
||||
name='python-telegram-bot',
|
||||
version='2.5.2',
|
||||
version='2.6.0',
|
||||
author='Leandro Toledo',
|
||||
author_email='leandrotoledodesouza@gmail.com',
|
||||
license='LGPLv3',
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
|
||||
__author__ = 'leandrotoledodesouza@gmail.com'
|
||||
__version__ = '2.5.2'
|
||||
__version__ = '2.6.0'
|
||||
|
||||
from .base import TelegramObject
|
||||
from .user import User
|
||||
|
||||
+33
-40
@@ -48,21 +48,39 @@ class Bot(TelegramObject):
|
||||
else:
|
||||
self.base_url = base_url + self.token
|
||||
|
||||
self.bot = None
|
||||
|
||||
self.log = logging.getLogger(__name__)
|
||||
|
||||
try:
|
||||
bot = self.getMe()
|
||||
def info(func):
|
||||
@functools.wraps(func)
|
||||
def decorator(self, *args, **kwargs):
|
||||
if not self.bot:
|
||||
self.getMe()
|
||||
|
||||
self.id = bot.id
|
||||
self.first_name = bot.first_name
|
||||
self.last_name = bot.last_name
|
||||
self.username = bot.username
|
||||
result = func(self, *args, **kwargs)
|
||||
return result
|
||||
return decorator
|
||||
|
||||
self.__auth = True
|
||||
@property
|
||||
@info
|
||||
def id(self):
|
||||
return self.bot.id
|
||||
|
||||
self.log.info('Starting bot %s' % self.name)
|
||||
except TelegramError:
|
||||
raise TelegramError({'message': 'Bad token'})
|
||||
@property
|
||||
@info
|
||||
def first_name(self):
|
||||
return self.bot.first_name
|
||||
|
||||
@property
|
||||
@info
|
||||
def last_name(self):
|
||||
return self.bot.last_name
|
||||
|
||||
@property
|
||||
@info
|
||||
def username(self):
|
||||
return self.bot.username
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
@@ -109,22 +127,6 @@ class Bot(TelegramObject):
|
||||
return Message.de_json(data)
|
||||
return decorator
|
||||
|
||||
def require_authentication(func):
|
||||
@functools.wraps(func)
|
||||
def decorator(self, *args, **kwargs):
|
||||
if not self.__auth:
|
||||
raise TelegramError({'message': "API must be authenticated."})
|
||||
|
||||
return func(self, *args, **kwargs)
|
||||
return decorator
|
||||
|
||||
@log
|
||||
@require_authentication
|
||||
def clearCredentials(self):
|
||||
"""Clear any credentials for this instance.
|
||||
"""
|
||||
self.__auth = False
|
||||
|
||||
@log
|
||||
def getMe(self):
|
||||
"""A simple method for testing your bot's auth token.
|
||||
@@ -138,11 +140,12 @@ class Bot(TelegramObject):
|
||||
json_data = self._requestUrl(url, 'GET')
|
||||
data = self._parseAndCheckTelegram(json_data)
|
||||
|
||||
return User.de_json(data)
|
||||
self.bot = User.de_json(data)
|
||||
|
||||
return self.bot
|
||||
|
||||
@log
|
||||
@message
|
||||
@require_authentication
|
||||
def sendMessage(self,
|
||||
chat_id,
|
||||
text,
|
||||
@@ -182,7 +185,6 @@ class Bot(TelegramObject):
|
||||
|
||||
@log
|
||||
@message
|
||||
@require_authentication
|
||||
def forwardMessage(self,
|
||||
chat_id,
|
||||
from_chat_id,
|
||||
@@ -216,7 +218,6 @@ class Bot(TelegramObject):
|
||||
|
||||
@log
|
||||
@message
|
||||
@require_authentication
|
||||
def sendPhoto(self,
|
||||
chat_id,
|
||||
photo,
|
||||
@@ -258,7 +259,6 @@ class Bot(TelegramObject):
|
||||
|
||||
@log
|
||||
@message
|
||||
@require_authentication
|
||||
def sendAudio(self,
|
||||
chat_id,
|
||||
audio,
|
||||
@@ -296,7 +296,6 @@ class Bot(TelegramObject):
|
||||
|
||||
@log
|
||||
@message
|
||||
@require_authentication
|
||||
def sendDocument(self,
|
||||
chat_id,
|
||||
document,
|
||||
@@ -331,7 +330,6 @@ class Bot(TelegramObject):
|
||||
|
||||
@log
|
||||
@message
|
||||
@require_authentication
|
||||
def sendSticker(self,
|
||||
chat_id,
|
||||
sticker,
|
||||
@@ -366,7 +364,6 @@ class Bot(TelegramObject):
|
||||
|
||||
@log
|
||||
@message
|
||||
@require_authentication
|
||||
def sendVideo(self,
|
||||
chat_id,
|
||||
video,
|
||||
@@ -414,7 +411,6 @@ class Bot(TelegramObject):
|
||||
|
||||
@log
|
||||
@message
|
||||
@require_authentication
|
||||
def sendLocation(self,
|
||||
chat_id,
|
||||
latitude,
|
||||
@@ -451,7 +447,6 @@ class Bot(TelegramObject):
|
||||
|
||||
@log
|
||||
@message
|
||||
@require_authentication
|
||||
def sendChatAction(self,
|
||||
chat_id,
|
||||
action):
|
||||
@@ -482,7 +477,6 @@ class Bot(TelegramObject):
|
||||
return url, data
|
||||
|
||||
@log
|
||||
@require_authentication
|
||||
def getUserProfilePhotos(self,
|
||||
user_id,
|
||||
offset=None,
|
||||
@@ -518,7 +512,6 @@ class Bot(TelegramObject):
|
||||
return UserProfilePhotos.de_json(data)
|
||||
|
||||
@log
|
||||
@require_authentication
|
||||
def getUpdates(self,
|
||||
offset=None,
|
||||
limit=100,
|
||||
@@ -565,7 +558,6 @@ class Bot(TelegramObject):
|
||||
return [Update.de_json(x) for x in data]
|
||||
|
||||
@log
|
||||
@require_authentication
|
||||
def setWebhook(self,
|
||||
webhook_url):
|
||||
"""Use this method to specify a url and receive incoming updates via an
|
||||
@@ -675,4 +667,5 @@ class Bot(TelegramObject):
|
||||
return data
|
||||
|
||||
def __reduce__(self):
|
||||
return (self.__class__, (self.token, self.base_url))
|
||||
return (self.__class__, (self.token,
|
||||
self.base_url.replace(self.token, '')))
|
||||
|
||||
+4
-15
@@ -26,8 +26,8 @@ except ImportError:
|
||||
from urllib2 import urlopen
|
||||
import mimetypes
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import imghdr
|
||||
|
||||
from .error import TelegramError
|
||||
|
||||
@@ -128,20 +128,9 @@ class InputFile(object):
|
||||
Returns:
|
||||
The str mimetype of an image.
|
||||
"""
|
||||
try:
|
||||
header = stream[:10]
|
||||
|
||||
if re.match(b'GIF8', header):
|
||||
return 'image/gif'
|
||||
|
||||
if re.match(b'\x89PNG', header):
|
||||
return 'image/png'
|
||||
|
||||
if re.match(b'\xff\xd8\xff\xe0\x00\x10JFIF', header) or \
|
||||
re.match(b'\xff\xd8\xff\xe1(.*){2}Exif', header):
|
||||
return 'image/jpeg'
|
||||
except IndexError as e:
|
||||
raise TelegramError(str(e))
|
||||
image = imghdr.what(None, stream)
|
||||
if image:
|
||||
return 'image/%s' % image
|
||||
|
||||
raise TelegramError({'message': 'Could not parse file content'})
|
||||
|
||||
|
||||
+31
-5
@@ -18,6 +18,8 @@
|
||||
|
||||
|
||||
from telegram import TelegramObject
|
||||
from datetime import datetime
|
||||
from time import mktime
|
||||
|
||||
|
||||
class Message(TelegramObject):
|
||||
@@ -79,6 +81,11 @@ class Message(TelegramObject):
|
||||
else:
|
||||
from_user = None
|
||||
|
||||
if 'date' in data:
|
||||
date = datetime.fromtimestamp(data['date'])
|
||||
else:
|
||||
date = None
|
||||
|
||||
if 'chat' in data:
|
||||
if 'first_name' in data['chat']:
|
||||
from telegram import User
|
||||
@@ -95,6 +102,11 @@ class Message(TelegramObject):
|
||||
else:
|
||||
forward_from = None
|
||||
|
||||
if 'forward_date' in data:
|
||||
forward_date = datetime.fromtimestamp(data['forward_date'])
|
||||
else:
|
||||
forward_date = None
|
||||
|
||||
if 'reply_to_message' in data:
|
||||
reply_to_message = Message.de_json(data['reply_to_message'])
|
||||
else:
|
||||
@@ -156,10 +168,10 @@ class Message(TelegramObject):
|
||||
|
||||
return Message(message_id=data.get('message_id', None),
|
||||
from_user=from_user,
|
||||
date=data.get('date', None),
|
||||
date=date,
|
||||
chat=chat,
|
||||
forward_from=forward_from,
|
||||
forward_date=data.get('forward_date', None),
|
||||
forward_date=forward_date,
|
||||
reply_to_message=reply_to_message,
|
||||
text=data.get('text', ''),
|
||||
audio=audio,
|
||||
@@ -180,12 +192,22 @@ class Message(TelegramObject):
|
||||
def to_dict(self):
|
||||
data = {'message_id': self.message_id,
|
||||
'from': self.from_user.to_dict(),
|
||||
'date': self.date,
|
||||
'chat': self.chat.to_dict()}
|
||||
try:
|
||||
# Python 3.3+ supports .timestamp()
|
||||
data['date'] = int(self.date.timestamp())
|
||||
|
||||
if self.forward_date:
|
||||
data['forward_date'] = int(self.forward_date.timestamp())
|
||||
except AttributeError:
|
||||
# _totimestamp() for Python 3 (< 3.3) and Python 2
|
||||
data['date'] = self._totimestamp(self.date)
|
||||
|
||||
if self.forward_date:
|
||||
data['forward_date'] = self._totimestamp(self.forward_date)
|
||||
|
||||
if self.forward_from:
|
||||
data['forward_from'] = self.forward_from
|
||||
if self.forward_date:
|
||||
data['forward_date'] = self.forward_date
|
||||
if self.reply_to_message:
|
||||
data['reply_to_message'] = self.reply_to_message
|
||||
if self.text:
|
||||
@@ -219,3 +241,7 @@ class Message(TelegramObject):
|
||||
if self.group_chat_created:
|
||||
data['group_chat_created'] = self.group_chat_created
|
||||
return data
|
||||
|
||||
@staticmethod
|
||||
def _totimestamp(dt):
|
||||
return int(mktime(dt.timetuple()))
|
||||
|
||||
+26
-2
@@ -21,6 +21,7 @@
|
||||
import os
|
||||
import telegram
|
||||
import unittest
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class BotTest(unittest.TestCase):
|
||||
@@ -44,6 +45,7 @@ class BotTest(unittest.TestCase):
|
||||
message = self._bot.sendMessage(chat_id=12173560,
|
||||
text='Моё судно на воздушной подушке полно угрей')
|
||||
self.assertEqual(u'Моё судно на воздушной подушке полно угрей', message.text)
|
||||
self.assertIsInstance(message.date, datetime)
|
||||
|
||||
def testGetUpdates(self):
|
||||
'''Test the telegram.Bot getUpdates method'''
|
||||
@@ -59,6 +61,7 @@ class BotTest(unittest.TestCase):
|
||||
message_id=138)
|
||||
self.assertEqual('Oi', message.text)
|
||||
self.assertEqual('leandrotoledo', message.forward_from.username)
|
||||
self.assertIsInstance(message.forward_date, datetime)
|
||||
|
||||
def testSendPhoto(self):
|
||||
'''Test the telegram.Bot sendPhoto method'''
|
||||
@@ -76,13 +79,27 @@ class BotTest(unittest.TestCase):
|
||||
chat_id=12173560)
|
||||
self.assertEqual('AgADAQADr6cxGzU8LQe6q0dMJD2rHYkP2ykABFymiQqJgjxRGGMAAgI', message.photo[0].file_id)
|
||||
|
||||
def testSendURLPhoto(self):
|
||||
def testSendJPGURLPhoto(self):
|
||||
'''Test the telegram.Bot sendPhoto method'''
|
||||
print('Testing sendPhoto - URL')
|
||||
print('Testing testSendJPGURLPhoto - URL')
|
||||
message = self._bot.sendPhoto(photo=str('http://dummyimage.com/600x400/000/fff.jpg&text=telegram'),
|
||||
chat_id=12173560)
|
||||
self.assertEqual(822, message.photo[0].file_size)
|
||||
|
||||
def testSendPNGURLPhoto(self):
|
||||
'''Test the telegram.Bot sendPhoto method'''
|
||||
print('Testing testSendPNGURLPhoto - URL')
|
||||
message = self._bot.sendPhoto(photo=str('http://dummyimage.com/600x400/000/fff.png&text=telegram'),
|
||||
chat_id=12173560)
|
||||
self.assertEqual(684, message.photo[0].file_size)
|
||||
|
||||
def testSendGIFURLPhoto(self):
|
||||
'''Test the telegram.Bot sendPhoto method'''
|
||||
print('Testing testSendGIFURLPhoto - URL')
|
||||
message = self._bot.sendPhoto(photo=str('http://dummyimage.com/600x400/000/fff.gif&text=telegram'),
|
||||
chat_id=12173560)
|
||||
self.assertEqual(684, message.photo[0].file_size)
|
||||
|
||||
def testSendAudio(self):
|
||||
'''Test the telegram.Bot sendAudio method'''
|
||||
print('Testing sendAudio - File')
|
||||
@@ -104,6 +121,13 @@ class BotTest(unittest.TestCase):
|
||||
chat_id=12173560)
|
||||
self.assertEqual(12948, message.document.file_size)
|
||||
|
||||
def testSendGIFURLDocument(self):
|
||||
'''Test the telegram.Bot sendDocument method'''
|
||||
print('Testing sendDocument - File')
|
||||
message = self._bot.sendPhoto(photo=str('http://dummyimage.com/600x400/000/fff.gif&text=telegram'),
|
||||
chat_id=12173560)
|
||||
self.assertEqual(684, message.photo[0].file_size)
|
||||
|
||||
def testResendDocument(self):
|
||||
'''Test the telegram.Bot sendDocument method'''
|
||||
print('Testing sendDocument - Resend')
|
||||
|
||||
Reference in New Issue
Block a user