Conflicts:
	telegram/__init__.py
This commit is contained in:
ErgoZ 2015-09-10 20:42:56 +03:00
commit c8a14bf34d
14 changed files with 192 additions and 70 deletions

3
.gitignore vendored
View file

@ -58,3 +58,6 @@ docs/_build/
# PyBuilder
target/
.idea/
# Sublime Text 2
*.sublime*

View file

@ -9,6 +9,6 @@ python:
install:
- pip install coveralls
script:
coverage run tests/run.py
nosetests --with-coverage --cover-package telegram/
after_success:
coveralls

View file

@ -1,4 +1,4 @@
.PHONY: clean pep8 lint test coverage
.PHONY: clean pep8 lint test
clean:
rm -fr build
@ -14,7 +14,7 @@ lint:
pylint -E telegram
test:
python tests/run.py
nosetests
help:
@echo "Available targets:"

View file

@ -1,11 +1,5 @@
# There could be some unused imports
from inspect import getmembers, ismethod
import threading
import logging
import telegram
import time
from telegram import CommandHandlerWithHelp, CommandHandler
class ExampleCommandHandler(CommandHandlerWithHelp):
from telegram import CommandHandlerWithHelpAndFather, CommandHandler
class ExampleCommandHandler(CommandHandlerWithHelpAndFather):
"""This is an example how to use a CommandHandlerWithHelp or just a CommandHandler.
If You want to use a CommandHandler it is very easy.
@ -31,7 +25,7 @@ class ExampleCommandHandler(CommandHandlerWithHelp):
chat_id = update.message.chat.id
reply_to = update.message.message_id
message = "Sorry, I don't know how to do {command}.".format(command=update.message.text.split(' ')[0])
self.bot.sendMessage(chat_id, message, reply_to_message_id=reply_to)
self.bot.sendMessage(chat_id=chat_id, text=message, reply_to_message_id=reply_to)
# creates /test command. This code gets called when a telegram user enters /test
def command_test(self, update):
@ -39,7 +33,7 @@ class ExampleCommandHandler(CommandHandlerWithHelp):
chat_id = update.message.chat.id
reply_to = update.message.message_id
message = 'Yeah, the server is online!'
self.bot.sendMessage(chat_id, message, reply_to_message_id=reply_to)
self.bot.sendMessage(chat_id=chat_id, text=message, reply_to_message_id=reply_to)
# creates /parrot command
def command_parrot(self, update):
@ -50,7 +44,7 @@ class ExampleCommandHandler(CommandHandlerWithHelp):
message = update.message.text[len(send[0]):]
if len(send) == 1:
message = '...'
self.bot.sendMessage(chat_id, message, reply_to_message_id=reply_to)
self.bot.sendMessage(chat_id=chat_id, text=message, reply_to_message_id=reply_to)
# creates /p command
def command_p(self, update):
@ -67,7 +61,7 @@ class ExampleCommandHandler(CommandHandlerWithHelp):
chat_id = update.message.chat.id
reply_to = update.message.message_id
message = 'Yeah, this is another test'
self.bot.sendMessage(chat_id, message, reply_to_message_id=reply_to)
self.bot.sendMessage(chat_id=chat_id, text=message, reply_to_message_id=reply_to)
class Exampe2CommandHandler(CommandHandler):
@ -79,11 +73,15 @@ class Exampe2CommandHandler(CommandHandler):
chat_id = update.message.chat.id
reply_to = update.message.message_id
message = 'Yeah, the server is online!'
self.bot.sendMessage(chat_id, message, reply_to_message_id=reply_to)
self.bot.sendMessage(chat_id=chat_id, text=message, reply_to_message_id=reply_to)
if __name__ == '__main__':
import telegram
token = '' # use your own token here
import telegram as telegram
try:
from mytoken import token
except:
token = '' # use your own token here
print ('token = ', token)
Bot = telegram.Bot(token=token)
test_command_handler = ExampleCommandHandler(Bot)
test_command_handler.run()

View file

@ -46,10 +46,12 @@ from .parsemode import ParseMode
from .message import Message
from .update import Update
from .bot import Bot
from .command_handler import *
__all__ = ['Bot', 'Emoji', 'TelegramError', 'InputFile', 'ReplyMarkup',
'ForceReply', 'ReplyKeyboardHide', 'ReplyKeyboardMarkup',
'UserProfilePhotos', 'ChatAction', 'Location', 'Contact',
'Video', 'Sticker', 'Document', 'Audio', 'PhotoSize', 'GroupChat',
'Update', 'ParseMode', 'Message', 'User', 'TelegramObject', 'NullHandler',
'Voice']
'Voice', 'CommandHandler', 'CommandHandlerWithHelp',
'CommandHandlerWithFatherCommand', 'CommandHandlerWithHelpAndFather']

View file

@ -4,7 +4,10 @@ import logging
import telegram
import time
logger = logging.getLogger(__name__)
__all__ = ['CommandHandler', 'CommandHandlerWithHelp']
__all__ = ['CommandHandler', 'CommandHandlerWithHelp', 'CommandHandlerWithFatherCommand',
'CommandHandlerWithHelpAndFather']
class CommandHandler(object):
""" This handles incomming commands and gives an easy way to create commands.
@ -15,7 +18,8 @@ class CommandHandler(object):
"""
def __init__(self, bot):
self.bot = bot # a telegram bot
self.isValidCommand = None # a function that returns a boolean and takes one agrument an update. if False is returned the the comaand is not executed.
self.isValidCommand = None # a function that returns a boolean and takes one agrument an update.
# If False is returned the the command is not executed.
def _get_command_func(self, command):
if command[0] == '/':
@ -38,6 +42,7 @@ class CommandHandler(object):
The timeout on a thread. If a thread is alive after this period then try to join the thread in
the next loop.
"""
old_threads = []
while True:
time.sleep(sleep)
@ -82,7 +87,7 @@ class CommandHandler(object):
if username == bot_name:
command_func = self._get_command_func(command)
if command_func is not None:
self.bot.sendChatAction(update.message.chat.id,telegram.ChatAction.TYPING)
self.bot.sendChatAction(chat_id=update.message.chat.id, action=telegram.ChatAction.TYPING)
if self.isValidCommand is None or self.isValidCommand(update):
if make_thread:
t = threading.Thread(target=command_func, args=(update,))
@ -107,8 +112,9 @@ class CommandHandler(object):
"""
chat_id = update.message.chat.id
reply_to = update.message.message_id
message = "Sorry, the command was not authorised or valid: {command}.".format(command=update.message.text.split(' ')[0])
self.bot.sendMessage(chat_id, message, reply_to_message_id=reply_to)
message = "Sorry, the command was not authorised or valid: {command}.".format(
command=update.message.text.split(' ')[0])
self.bot.sendMessage(chat_id=chat_id, text=message, reply_to_message_id=reply_to)
def _command_not_found(self, update):
"""Inform the telegram user that the command was not found.
@ -119,7 +125,7 @@ class CommandHandler(object):
chat_id = update.message.chat.id
reply_to = update.message.message_id
message = "Sorry, I didn't understand the command: {command}.".format(command=update.message.text.split(' ')[0])
self.bot.sendMessage(chat_id, message, reply_to_message_id=reply_to)
self.bot.sendMessage(chat_id=chat_id, text=message, reply_to_message_id=reply_to)
class CommandHandlerWithHelp(CommandHandler):
@ -130,8 +136,23 @@ class CommandHandlerWithHelp(CommandHandler):
self._help_before_list = '' # text with information about the bot
self._help_after_list = '' # a footer
self._help_list_title = 'These are the commands:' # the title of the list
self._help_extra_message = 'These commands are only usefull to the developer.'
self.is_reply = True
self.command_start = self.command_help
self.skip_in_help = []
def command_helpextra(self,update):
""" The commands in here are only usefull to the developer of the bot"""
command_functions = [attr[1] for attr in getmembers(self, predicate=ismethod) if attr[0][:8] == 'command_' and
attr[0] in self.skip_in_help]
chat_id = update.message.chat.id
help_message = self._help_extra_message + '\n'
for command_function in command_functions:
if command_function.__doc__ is not None:
help_message += ' /' + command_function.__name__[8:] + ' - ' + command_function.__doc__ + '\n'
else:
help_message += ' /' + command_function.__name__[8:] + ' - ' + '\n'
self.bot.sendMessage(chat_id=chat_id, text=help_message)
def _generate_help(self):
""" Generate a string which can be send as a help file.
@ -141,17 +162,23 @@ class CommandHandlerWithHelp(CommandHandler):
command to the telegram user.
"""
command_functions = [attr[1] for attr in getmembers(self, predicate=ismethod) if attr[0][:8] == 'command_']
help_message = self._help_title + '\n\n'
help_message += self._help_before_list + '\n\n'
help_message += self._help_list_title + '\n'
help_message += self._generate_help_list()
help_message += '\n'
help_message += self._help_after_list
return help_message
def _generate_help_list(self):
command_functions = [attr[1] for attr in getmembers(self, predicate=ismethod) if attr[0][:8] == 'command_' and
attr[0] not in self.skip_in_help]
help_message = ''
for command_function in command_functions:
if command_function.__doc__ is not None:
help_message += ' /' + command_function.__name__[8:] + ' - ' + command_function.__doc__ + '\n'
else:
help_message += ' /' + command_function.__name__[8:] + ' - ' + '\n'
help_message += '\n'
help_message += self._help_after_list
return help_message
def _command_not_found(self, update):
@ -160,15 +187,45 @@ class CommandHandlerWithHelp(CommandHandler):
reply_to = update.message.message_id
message = 'Sorry, I did not understand the command: {command}. Please see /help for all available commands'
if self.is_reply:
self.bot.sendMessage(chat_id, message.format(command=update.message.text.split(' ')[0]),
self.bot.sendMessage(chat_id=chat_id, text=message.format(command=update.message.text.split(' ')[0]),
reply_to_message_id=reply_to)
else:
self.bot.sendMessage(chat_id, message.format(command=update.message.text.split(' ')[0]))
self.bot.sendMessage(chat_id=chat_id, text=message.format(command=update.message.text.split(' ')[0]))
def command_help(self, update):
""" The help file. """
chat_id = update.message.chat.id
reply_to = update.message.message_id
message = self._generate_help()
self.bot.sendMessage(chat_id, message, reply_to_message_id=reply_to)
self.bot.sendMessage(chat_id=chat_id, text=message, reply_to_message_id=reply_to)
class CommandHandlerWithFatherCommand(CommandHandler):
""" A class that creates some commands that are usefull when setting up the bot
"""
def __init__(self, bot):
super(CommandHandlerWithFatherCommand, self).__init__(bot)
self.skip_in_help = ['command_father']
def command_father(self, update):
"""Gives you the commands you need to setup this bot. in telegram.me/BotFather"""
chat_id = update.message.chat.id
self.bot.sendMessage(chat_id=chat_id, text='Send the following messages to telegram.me/BotFather')
self.bot.sendMessage(chat_id=chat_id, text='/setcommands')
self.bot.sendMessage(chat_id=chat_id, text='@' + self.bot.getMe()['username'])
commands = ''
command_functions = [attr[1] for attr in getmembers(self, predicate=ismethod) if attr[0][:8] == 'command_' and
attr[0] not in self.skip_in_help]
for command_function in command_functions:
if command_function.__doc__ is not None:
commands += command_function.__name__[8:] + ' - ' + command_function.__doc__ + '\n'
else:
commands += command_function.__name__[8:] + ' - ' + '\n'
self.bot.sendMessage(chat_id=chat_id, text=commands)
class CommandHandlerWithHelpAndFather(CommandHandlerWithFatherCommand, CommandHandlerWithHelp):
"""A class that combines CommandHandlerWithHelp and CommandHandlerWithFatherCommand.
"""
pass

View file

@ -55,6 +55,9 @@ class InputFile(object):
if 'photo' in data:
self.input_name = 'photo'
self.input_file = data.pop('photo')
if 'sticker' in data:
self.input_name = 'sticker'
self.input_file = data.pop('sticker')
if 'video' in data:
self.input_name = 'video'
self.input_file = data.pop('video')
@ -67,7 +70,7 @@ class InputFile(object):
if isinstance(self.input_file, file):
self.input_file_content = self.input_file.read()
if 'filename' in self.data:
if 'filename' in data:
self.filename = self.data.pop('filename')
else:
self.filename = os.path.basename(self.input_file.name)
@ -174,8 +177,8 @@ class InputFile(object):
bool
"""
if data:
file_types = ['audio', 'document', 'photo', 'video', 'voice',
'certificate']
file_types = ['audio', 'document', 'photo', 'sticker', 'video',
'voice', 'certificate']
file_type = [i for i in list(data.keys()) if i in file_types]
if file_type:

View file

@ -171,6 +171,12 @@ class Message(TelegramObject):
return Message(**data)
def __getitem__(self, item):
if item in self.__dict__.keys():
return self.__dict__[item]
elif item == 'chat_id':
return self.chat.id
def to_dict(self):
"""
Returns:

View file

@ -84,11 +84,14 @@ def post(url,
try:
if InputFile.is_inputfile(data):
data = InputFile(data)
request = Request(url, data=data.to_form(), headers=data.headers)
result = urlopen(request).read()
request = Request(url, data=data.to_form(),
headers=data.headers)
else:
result = urlopen(url, urlencode(data).encode()).read()
data = json.dumps(data)
request = Request(url, data=data.encode(),
headers={'Content-Type': 'application/json'})
result = urlopen(request).read()
except HTTPError as error:
message = _parse(error.read())
raise TelegramError(message)

View file

@ -1,28 +0,0 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015 Leandro Toledo de Souza <leandrotoeldodesouza@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
import os
import glob
import unittest
suite = unittest.TestSuite()
for test_file in glob.glob('tests/test_*.py'):
test_module = os.path.basename(test_file).replace('.py', '')
suite.addTest(unittest.defaultTestLoader.loadTestsFromName(test_module))
unittest.TextTestRunner().run(suite)

View file

@ -71,7 +71,7 @@ class AudioTest(BaseTest, unittest.TestCase):
message = self._bot.sendAudio(self._chat_id,
self.audio_file,
self.duration,
duration=self.duration,
performer=self.performer,
title=self.title,
mime_type=self.mime_type,
@ -107,6 +107,27 @@ class AudioTest(BaseTest, unittest.TestCase):
self.assertEqual(audio.mime_type, self.mime_type)
self.assertEqual(audio.file_size, self.file_size)
def test_send_audio_mp3_file_custom_filename(self):
"""Test telegram.Bot sendAudio method"""
print('Testing bot.sendAudio - MP3 File with custom filename')
message = self._bot.sendAudio(chat_id=self._chat_id,
audio=self.audio_file,
duration=self.duration,
performer=self.performer,
title=self.title,
filename='telegram_custom.mp3')
audio = message.audio
self.assertTrue(isinstance(audio.file_id, str))
self.assertNotEqual(audio.file_id, '')
self.assertEqual(audio.duration, self.duration)
self.assertEqual(audio.performer, self.performer)
self.assertEqual(audio.title, self.title)
self.assertEqual(audio.mime_type, self.mime_type)
self.assertEqual(audio.file_size, self.file_size)
def test_send_audio_resend(self):
"""Test telegram.Bot sendAudio method"""
print('Testing bot.sendAudio - Resend by file_id')
@ -123,7 +144,7 @@ class AudioTest(BaseTest, unittest.TestCase):
self.assertEqual(audio.duration, self.duration)
self.assertEqual(audio.performer, self.performer)
self.assertEqual(audio.title, self.title)
self.assertEqual(audio.mime_type, '')
self.assertEqual(audio.mime_type, self.mime_type)
self.assertEqual(audio.file_size, self.file_size)
def test_audio_de_json(self):

View file

@ -66,6 +66,23 @@ class DocumentTest(BaseTest, unittest.TestCase):
self.assertEqual(document.mime_type, self.mime_type)
self.assertEqual(document.file_size, self.file_size)
def test_send_document_png_file_with_custom_file_name(self):
"""Test telegram.Bot sendDocument method"""
print('Testing bot.sendDocument - PNG File with custom filename')
message = self._bot.sendDocument(self._chat_id,
self.document_file,
filename='telegram_custom.png')
document = message.document
self.assertTrue(isinstance(document.file_id, str))
self.assertNotEqual(document.file_id, '')
self.assertTrue(isinstance(document.thumb, telegram.PhotoSize))
self.assertEqual(document.file_name, 'telegram_custom.png')
self.assertEqual(document.mime_type, self.mime_type)
self.assertEqual(document.file_size, self.file_size)
def test_send_document_url_gif_file(self):
"""Test telegram.Bot sendDocument method"""
print('Testing bot.sendDocument - GIF File by URL')
@ -93,8 +110,8 @@ class DocumentTest(BaseTest, unittest.TestCase):
self.assertEqual(document.file_id, self.document_file_id)
self.assertTrue(isinstance(document.thumb, telegram.PhotoSize))
self.assertEqual(document.file_name, '')
self.assertEqual(document.mime_type, '')
self.assertEqual(document.file_name, self.file_name)
self.assertEqual(document.mime_type, self.mime_type)
self.assertEqual(document.file_size, self.file_size)
def test_document_de_json(self):

View file

@ -115,6 +115,29 @@ class VideoTest(BaseTest, unittest.TestCase):
self.assertEqual(message.caption, self.caption)
def test_send_video_mp4_file_with_custom_filename(self):
"""Test telegram.Bot sendVideo method"""
print('Testing bot.sendVideo - MP4 File with custom filename')
message = self._bot.sendVideo(chat_id=self._chat_id,
video=self.video_file,
duration=self.duration,
caption=self.caption,
filename='telegram_custom.mp4')
video = message.video
self.assertTrue(isinstance(video.file_id, str))
self.assertNotEqual(video.file_id, '')
self.assertEqual(video.width, 0)
self.assertEqual(video.height, 0)
self.assertEqual(video.duration, self.duration)
self.assertEqual(video.thumb, None)
self.assertEqual(video.mime_type, '')
self.assertEqual(video.file_size, self.file_size)
self.assertEqual(message.caption, self.caption)
def test_send_video_resend(self):
"""Test telegram.Bot sendVideo method"""
print('Testing bot.sendVideo - Resend by file_id')

View file

@ -93,6 +93,23 @@ class VoiceTest(BaseTest, unittest.TestCase):
self.assertEqual(voice.mime_type, self.mime_type)
self.assertEqual(voice.file_size, self.file_size)
def test_send_voice_ogg_file_with_custom_filename(self):
"""Test telegram.Bot sendVoice method"""
print('Testing bot.sendVoice - Ogg File with custom filename')
message = self._bot.sendVoice(chat_id=self._chat_id,
voice=self.voice_file,
duration=self.duration,
filename='telegram_custom.ogg')
voice = message.voice
self.assertTrue(isinstance(voice.file_id, str))
self.assertNotEqual(voice.file_id, '')
self.assertEqual(voice.duration, self.duration)
self.assertEqual(voice.mime_type, self.mime_type)
self.assertEqual(voice.file_size, self.file_size)
def test_send_voice_resend(self):
"""Test telegram.Bot sendVoice method"""
print('Testing bot.sendVoice - Resend by file_id')