2015-07-07 21:50:36 +02:00
|
|
|
#!/usr/bin/env python
|
2015-07-08 00:54:00 +02:00
|
|
|
# encoding: utf-8
|
2015-07-07 21:50:36 +02:00
|
|
|
|
|
|
|
"""A library that provides a Python interface to the Telegram Bots API"""
|
|
|
|
|
|
|
|
import json
|
|
|
|
import requests
|
|
|
|
|
|
|
|
from telegram import (User, Message, Update)
|
|
|
|
|
|
|
|
|
|
|
|
class Bot(object):
|
|
|
|
def __init__(self,
|
|
|
|
token,
|
|
|
|
base_url=None):
|
|
|
|
|
|
|
|
if base_url is None:
|
|
|
|
self.base_url = 'https://api.telegram.org/bot%s' % token
|
|
|
|
else:
|
|
|
|
self.base_url = base_url + token
|
|
|
|
|
|
|
|
def getMe(self):
|
2015-07-08 00:54:00 +02:00
|
|
|
"""A simple method for testing your bot's auth token.
|
2015-07-07 21:50:36 +02:00
|
|
|
|
2015-07-08 00:54:00 +02:00
|
|
|
Returns:
|
|
|
|
A telegram.User instance representing that bot if the
|
|
|
|
credentials are valid, None otherwise.
|
|
|
|
"""
|
2015-07-07 21:50:36 +02:00
|
|
|
url = '%s/getMe' % (self.base_url)
|
|
|
|
|
|
|
|
json_data = self._requestUrl(url, 'GET')
|
|
|
|
data = self._parseAndCheckTelegram(json_data.content)
|
|
|
|
|
|
|
|
return User.newFromJsonDict(data)
|
|
|
|
|
|
|
|
def sendMessage(self,
|
|
|
|
chat_id,
|
|
|
|
text,
|
|
|
|
disable_web_page_preview=None,
|
|
|
|
reply_to_message_id=None,
|
|
|
|
reply_markup=None):
|
2015-07-08 00:54:00 +02:00
|
|
|
"""Use this method to send text messages.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
chat_id:
|
|
|
|
Unique identifier for the message recipient — telegram.User or
|
|
|
|
telegram.GroupChat id.
|
|
|
|
text:
|
|
|
|
Text of the message to be sent.
|
|
|
|
disable_web_page_preview:
|
|
|
|
Disables link previews for links in this message. [Optional]
|
|
|
|
reply_to_message_id:
|
|
|
|
If the message is a reply, ID of the original message. [Optional]
|
|
|
|
reply_markup:
|
|
|
|
Additional interface options. A JSON-serialized object for a custom
|
|
|
|
reply keyboard, instructions to hide keyboard or to force a reply
|
|
|
|
from the user. [Optional]
|
|
|
|
Returns:
|
|
|
|
A telegram.Message instance representing the message posted.
|
|
|
|
"""
|
2015-07-07 21:50:36 +02:00
|
|
|
|
|
|
|
url = '%s/sendMessage' % (self.base_url)
|
|
|
|
|
|
|
|
data = {'chat_id': chat_id,
|
|
|
|
'text': text}
|
|
|
|
if disable_web_page_preview:
|
|
|
|
data['disable_web_page_preview'] = disable_web_page_preview
|
|
|
|
if reply_to_message_id:
|
|
|
|
data['reply_to_message_id'] = reply_to_message_id
|
|
|
|
if reply_markup:
|
|
|
|
data['reply_markup'] = reply_markup
|
|
|
|
|
|
|
|
json_data = self._requestUrl(url, 'POST', data=data)
|
|
|
|
data = self._parseAndCheckTelegram(json_data.content)
|
|
|
|
|
|
|
|
return Message.newFromJsonDict(data)
|
|
|
|
|
|
|
|
def forwardMessage(self,
|
|
|
|
chat_id,
|
|
|
|
from_chat_id,
|
|
|
|
message_id):
|
2015-07-08 00:54:00 +02:00
|
|
|
"""Use this method to forward messages of any kind.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
chat_id:
|
|
|
|
Unique identifier for the message recipient — User or GroupChat id.
|
|
|
|
from_chat_id:
|
|
|
|
Unique identifier for the chat where the original message was sent
|
|
|
|
— User or GroupChat id.
|
|
|
|
message_id:
|
|
|
|
Unique message identifier.
|
|
|
|
Returns:
|
|
|
|
A telegram.Message instance representing the message forwarded.
|
|
|
|
"""
|
2015-07-07 21:50:36 +02:00
|
|
|
|
|
|
|
url = '%s/forwardMessage' % (self.base_url)
|
|
|
|
|
|
|
|
data = {}
|
|
|
|
if chat_id:
|
|
|
|
data['chat_id'] = chat_id
|
|
|
|
if from_chat_id:
|
|
|
|
data['from_chat_id'] = from_chat_id
|
|
|
|
if message_id:
|
|
|
|
data['message_id'] = message_id
|
|
|
|
|
|
|
|
json_data = self._requestUrl(url, 'POST', data=data)
|
|
|
|
data = self._parseAndCheckTelegram(json_data.content)
|
|
|
|
|
|
|
|
return Message.newFromJsonDict(data)
|
|
|
|
|
|
|
|
def sendPhoto(self,
|
|
|
|
chat_id,
|
|
|
|
photo,
|
|
|
|
caption=None,
|
|
|
|
reply_to_message_id=None,
|
|
|
|
reply_markup=None):
|
2015-07-08 00:54:00 +02:00
|
|
|
"""Use this method to send photos.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
chat_id:
|
|
|
|
Unique identifier for the message recipient — User or GroupChat id.
|
|
|
|
photo:
|
|
|
|
Photo to send. You can either pass a file_id as String to resend a
|
|
|
|
photo that is already on the Telegram servers, or upload a new
|
|
|
|
photo using multipart/form-data.
|
|
|
|
caption:
|
|
|
|
Photo caption (may also be used when resending photos by file_id).
|
|
|
|
[Optional]
|
|
|
|
reply_to_message_id:
|
|
|
|
If the message is a reply, ID of the original message. [Optional]
|
|
|
|
reply_markup:
|
|
|
|
Additional interface options. A JSON-serialized object for a custom
|
|
|
|
reply keyboard, instructions to hide keyboard or to force a reply
|
|
|
|
from the user. [Optional]
|
|
|
|
Returns:
|
|
|
|
A telegram.Message instance representing the message posted.
|
|
|
|
"""
|
2015-07-07 21:50:36 +02:00
|
|
|
|
|
|
|
url = '%s/sendPhoto' % (self.base_url)
|
|
|
|
|
|
|
|
data = {'chat_id': chat_id,
|
|
|
|
'photo': photo}
|
2015-07-07 23:46:32 +02:00
|
|
|
|
2015-07-07 21:50:36 +02:00
|
|
|
if caption:
|
|
|
|
data['caption'] = caption
|
|
|
|
if reply_to_message_id:
|
|
|
|
data['reply_to_message_id'] = reply_to_message_id
|
|
|
|
if reply_markup:
|
|
|
|
data['reply_markup'] = reply_markup
|
|
|
|
|
|
|
|
json_data = self._requestUrl(url, 'POST', data=data)
|
|
|
|
data = self._parseAndCheckTelegram(json_data.content)
|
|
|
|
|
|
|
|
return Message.newFromJsonDict(data)
|
|
|
|
|
2015-07-08 01:10:43 +02:00
|
|
|
def sendAudio(self,
|
|
|
|
chat_id,
|
|
|
|
audio,
|
|
|
|
reply_to_message_id=None,
|
|
|
|
reply_markup=None):
|
|
|
|
"""Use this method to send audio files, if you want Telegram clients to
|
|
|
|
display the file as a playable voice message. For this to work, your
|
|
|
|
audio must be in an .ogg file encoded with OPUS (other formats may be
|
|
|
|
sent as telegram.Document).
|
|
|
|
|
|
|
|
Args:
|
|
|
|
chat_id:
|
|
|
|
Unique identifier for the message recipient — User or GroupChat id.
|
|
|
|
audio:
|
|
|
|
Audio file to send. You can either pass a file_id as String to
|
|
|
|
resend an audio that is already on the Telegram servers, or upload
|
|
|
|
a new audio file using multipart/form-data.
|
|
|
|
reply_to_message_id:
|
|
|
|
If the message is a reply, ID of the original message. [Optional]
|
|
|
|
reply_markup:
|
|
|
|
Additional interface options. A JSON-serialized object for a
|
|
|
|
custom reply keyboard, instructions to hide keyboard or to force a
|
|
|
|
reply from the user. [Optional]
|
|
|
|
Returns:
|
|
|
|
A telegram.Message instance representing the message posted.
|
|
|
|
"""
|
|
|
|
|
2015-07-07 21:50:36 +02:00
|
|
|
url = '%s/sendAudio' % (self.base_url)
|
|
|
|
|
2015-07-08 01:10:43 +02:00
|
|
|
data = {'chat_id': chat_id,
|
|
|
|
'audio': audio}
|
|
|
|
|
|
|
|
if reply_to_message_id:
|
|
|
|
data['reply_to_message_id'] = reply_to_message_id
|
|
|
|
if reply_markup:
|
|
|
|
data['reply_markup'] = reply_markup
|
|
|
|
|
|
|
|
json_data = self._requestUrl(url, 'POST', data=data)
|
|
|
|
data = self._parseAndCheckTelegram(json_data.content)
|
|
|
|
|
|
|
|
return Message.newFromJsonDict(data)
|
|
|
|
|
2015-07-08 02:12:51 +02:00
|
|
|
def sendDocument(self,
|
|
|
|
chat_id,
|
|
|
|
document,
|
|
|
|
reply_to_message_id=None,
|
|
|
|
reply_markup=None):
|
|
|
|
"""Use this method to send general files.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
chat_id:
|
|
|
|
Unique identifier for the message recipient — User or GroupChat id.
|
|
|
|
document:
|
|
|
|
File to send. You can either pass a file_id as String to resend a
|
|
|
|
file that is already on the Telegram servers, or upload a new file
|
|
|
|
using multipart/form-data.
|
|
|
|
reply_to_message_id:
|
|
|
|
If the message is a reply, ID of the original message. [Optional]
|
|
|
|
reply_markup:
|
|
|
|
Additional interface options. A JSON-serialized object for a
|
|
|
|
custom reply keyboard, instructions to hide keyboard or to force a
|
|
|
|
reply from the user. [Optional]
|
|
|
|
Returns:
|
|
|
|
A telegram.Message instance representing the message posted.
|
|
|
|
"""
|
|
|
|
|
2015-07-07 21:50:36 +02:00
|
|
|
url = '%s/sendDocument' % (self.base_url)
|
|
|
|
|
2015-07-08 02:12:51 +02:00
|
|
|
data = {'chat_id': chat_id,
|
|
|
|
'document': document}
|
|
|
|
|
|
|
|
if reply_to_message_id:
|
|
|
|
data['reply_to_message_id'] = reply_to_message_id
|
|
|
|
if reply_markup:
|
|
|
|
data['reply_markup'] = reply_markup
|
|
|
|
|
|
|
|
json_data = self._requestUrl(url, 'POST', data=data)
|
|
|
|
data = self._parseAndCheckTelegram(json_data.content)
|
|
|
|
|
|
|
|
return Message.newFromJsonDict(data)
|
|
|
|
|
2015-07-08 04:52:12 +02:00
|
|
|
def sendSticker(self,
|
|
|
|
chat_id,
|
|
|
|
sticker,
|
|
|
|
reply_to_message_id=None,
|
|
|
|
reply_markup=None):
|
2015-07-08 14:17:18 +02:00
|
|
|
"""Use this method to send .webp stickers.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
chat_id:
|
|
|
|
Unique identifier for the message recipient — User or GroupChat id.
|
|
|
|
sticker:
|
|
|
|
Sticker to send. You can either pass a file_id as String to resend
|
|
|
|
a sticker that is already on the Telegram servers, or upload a new
|
|
|
|
sticker using multipart/form-data.
|
|
|
|
reply_to_message_id:
|
|
|
|
If the message is a reply, ID of the original message. [Optional]
|
|
|
|
reply_markup:
|
|
|
|
Additional interface options. A JSON-serialized object for a
|
|
|
|
custom reply keyboard, instructions to hide keyboard or to force a
|
|
|
|
reply from the user. [Optional]
|
|
|
|
Returns:
|
|
|
|
A telegram.Message instance representing the message posted.
|
|
|
|
"""
|
2015-07-08 04:52:12 +02:00
|
|
|
|
2015-07-07 21:50:36 +02:00
|
|
|
url = '%s/sendSticker' % (self.base_url)
|
|
|
|
|
2015-07-08 04:52:12 +02:00
|
|
|
data = {'chat_id': chat_id,
|
|
|
|
'sticker': sticker}
|
|
|
|
|
|
|
|
if reply_to_message_id:
|
|
|
|
data['reply_to_message_id'] = reply_to_message_id
|
|
|
|
if reply_markup:
|
|
|
|
data['reply_markup'] = reply_markup
|
|
|
|
|
|
|
|
json_data = self._requestUrl(url, 'POST', data=data)
|
|
|
|
data = self._parseAndCheckTelegram(json_data.content)
|
|
|
|
|
|
|
|
return Message.newFromJsonDict(data)
|
|
|
|
|
2015-07-08 14:17:18 +02:00
|
|
|
def sendVideo(self,
|
|
|
|
chat_id,
|
|
|
|
video,
|
|
|
|
reply_to_message_id=None,
|
|
|
|
reply_markup=None):
|
|
|
|
"""Use this method to send video files, Telegram clients support mp4
|
|
|
|
videos (other formats may be sent as telegram.Document).
|
|
|
|
|
|
|
|
Args:
|
|
|
|
chat_id:
|
|
|
|
Unique identifier for the message recipient — User or GroupChat id.
|
|
|
|
video:
|
|
|
|
Video to send. You can either pass a file_id as String to resend a
|
|
|
|
video that is already on the Telegram servers, or upload a new
|
|
|
|
video file using multipart/form-data.
|
|
|
|
reply_to_message_id:
|
|
|
|
If the message is a reply, ID of the original message. [Optional]
|
|
|
|
reply_markup:
|
|
|
|
Additional interface options. A JSON-serialized object for a
|
|
|
|
custom reply keyboard, instructions to hide keyboard or to force a
|
|
|
|
reply from the user. [Optional]
|
|
|
|
Returns:
|
|
|
|
A telegram.Message instance representing the message posted.
|
|
|
|
"""
|
|
|
|
|
2015-07-07 21:50:36 +02:00
|
|
|
url = '%s/sendVideo' % (self.base_url)
|
|
|
|
|
2015-07-08 14:17:18 +02:00
|
|
|
data = {'chat_id': chat_id,
|
|
|
|
'video': video}
|
|
|
|
|
|
|
|
if reply_to_message_id:
|
|
|
|
data['reply_to_message_id'] = reply_to_message_id
|
|
|
|
if reply_markup:
|
|
|
|
data['reply_markup'] = reply_markup
|
|
|
|
|
|
|
|
json_data = self._requestUrl(url, 'POST', data=data)
|
|
|
|
data = self._parseAndCheckTelegram(json_data.content)
|
|
|
|
|
|
|
|
return Message.newFromJsonDict(data)
|
|
|
|
|
2015-07-07 21:50:36 +02:00
|
|
|
def sendLocation(self):
|
|
|
|
url = '%s/sendLocation' % (self.base_url)
|
|
|
|
|
|
|
|
def sendChatAction(self):
|
|
|
|
url = '%s/sendChatAction' % (self.base_url)
|
|
|
|
|
|
|
|
def getUserProfilePhotos(self):
|
|
|
|
url = '%s/getUserProfilePhotos' % (self.base_url)
|
|
|
|
|
|
|
|
def getUpdates(self,
|
|
|
|
offset=None,
|
|
|
|
limit=100,
|
|
|
|
timeout=0):
|
|
|
|
|
|
|
|
url = '%s/getUpdates' % (self.base_url)
|
|
|
|
|
|
|
|
data = {}
|
|
|
|
if offset:
|
|
|
|
data['offset'] = offset
|
|
|
|
if limit:
|
|
|
|
data['limit'] = limit
|
|
|
|
if timeout:
|
|
|
|
data['timeout'] = timeout
|
|
|
|
|
|
|
|
json_data = self._requestUrl(url, 'POST', data=data)
|
|
|
|
data = self._parseAndCheckTelegram(json_data.content)
|
|
|
|
|
|
|
|
return [Update.newFromJsonDict(x) for x in data]
|
|
|
|
|
|
|
|
def setWebhook(self):
|
|
|
|
url = '%s/setWebhook' % (self.base_url)
|
|
|
|
|
|
|
|
def _requestUrl(self,
|
|
|
|
url,
|
|
|
|
method,
|
|
|
|
data=None):
|
2015-07-08 00:54:00 +02:00
|
|
|
"""Request an URL.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
url:
|
|
|
|
The web location we want to retrieve.
|
|
|
|
method:
|
|
|
|
Either POST or GET.
|
|
|
|
data:
|
|
|
|
A dict of (str, unicode) key/value pairs.
|
|
|
|
Returns:
|
|
|
|
A JSON object.
|
|
|
|
"""
|
2015-07-07 21:50:36 +02:00
|
|
|
|
|
|
|
if method == 'POST':
|
2015-07-08 00:54:00 +02:00
|
|
|
if 'photo' in data and isinstance(data['photo'], file):
|
2015-07-07 23:46:32 +02:00
|
|
|
try:
|
|
|
|
photo = data.pop('photo')
|
|
|
|
|
|
|
|
return requests.post(
|
|
|
|
url,
|
|
|
|
data=data,
|
|
|
|
files={'photo': photo}
|
|
|
|
)
|
|
|
|
except requests.RequestException as e:
|
|
|
|
pass
|
2015-07-08 01:10:43 +02:00
|
|
|
if 'audio' in data and isinstance(data['audio'], file):
|
|
|
|
try:
|
|
|
|
audio = data.pop('audio')
|
|
|
|
|
|
|
|
return requests.post(
|
|
|
|
url,
|
|
|
|
data=data,
|
|
|
|
files={'audio': audio}
|
|
|
|
)
|
|
|
|
except requests.RequestException as e:
|
|
|
|
pass
|
2015-07-08 02:12:51 +02:00
|
|
|
if 'document' in data and isinstance(data['document'], file):
|
|
|
|
try:
|
|
|
|
document = data.pop('document')
|
|
|
|
|
|
|
|
return requests.post(
|
|
|
|
url,
|
|
|
|
data=data,
|
|
|
|
files={'document': document}
|
|
|
|
)
|
|
|
|
except requests.RequestException as e:
|
|
|
|
pass
|
2015-07-07 23:46:32 +02:00
|
|
|
else:
|
|
|
|
try:
|
|
|
|
return requests.post(
|
|
|
|
url,
|
|
|
|
data=data
|
|
|
|
)
|
|
|
|
except requests.RequestException as e:
|
|
|
|
pass
|
2015-07-07 21:50:36 +02:00
|
|
|
if method == 'GET':
|
|
|
|
try:
|
|
|
|
return requests.get(url)
|
|
|
|
except requests.RequestException as e:
|
|
|
|
pass # raise TelegramError(str(e))
|
|
|
|
return 0
|
|
|
|
|
|
|
|
def _parseAndCheckTelegram(self,
|
|
|
|
json_data):
|
|
|
|
|
|
|
|
try:
|
|
|
|
data = json.loads(json_data)
|
|
|
|
except ValueError:
|
|
|
|
pass
|
|
|
|
|
|
|
|
return data['result']
|