From d03a394075454c2e7cb3aaf421349d6f27112835 Mon Sep 17 00:00:00 2001 From: leandrotoledo Date: Fri, 21 Aug 2015 14:49:07 -0300 Subject: [PATCH] Refactoring, improving the design of existing message class and adding docstrings --- telegram/__init__.py | 2 +- telegram/message.py | 319 +++++++++++++++++++++++-------------------- tests/test_bot.py | 5 +- 3 files changed, 175 insertions(+), 151 deletions(-) diff --git a/telegram/__init__.py b/telegram/__init__.py index dcc3e6c08..4dc2ea57e 100644 --- a/telegram/__init__.py +++ b/telegram/__init__.py @@ -22,7 +22,6 @@ __version__ = '2.7.1' from .base import TelegramObject from .user import User -from .message import Message from .update import Update from .groupchat import GroupChat from .photosize import PhotoSize @@ -43,6 +42,7 @@ from .inputfile import InputFile from .error import TelegramError from .nullhandler import NullHandler from .emoji import Emoji +from .message import Message from .bot import Bot __all__ = ['Bot', 'Emoji', 'TelegramError', 'InputFile', 'ReplyMarkup', diff --git a/telegram/message.py b/telegram/message.py index 770ec0acf..f50c2377f 100644 --- a/telegram/message.py +++ b/telegram/message.py @@ -1,4 +1,6 @@ #!/usr/bin/env python +# pylint: disable=too-many-instance-attributes +# pylint: disable=too-many-arguments,too-many-branches # # A library that provides a Python interface to the Telegram Bot API # Copyright (C) 2015 Leandro Toledo de Souza @@ -16,251 +18,272 @@ # 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 Message""" -from telegram import TelegramObject from datetime import datetime from time import mktime +from telegram import (Audio, Contact, Document, GroupChat, Location, PhotoSize, + Sticker, TelegramObject, User, Video, Voice) + class Message(TelegramObject): + """This object represents a Telegram Message. + + Note: + * In Python `from` is a reserved word, use `from_user` instead. + + Attributes: + message_id (int): + from_user (:class:`telegram.User`): + date (:class:`datetime.datetime`): + forward_from (:class:`telegram.User`): + forward_date (:class:`datetime.datetime`): + reply_to_message (:class:`telegram.Message`): + text (str): + audio (:class:`telegram.Audio`): + document (:class:`telegram.Document`): + photo (List[:class:`telegram.PhotoSize`]): + sticker (:class:`telegram.Sticker`): + video (:class:`telegram.Video`): + voice (:class:`telegram.Voice`): + caption (str): + contact (:class:`telegram.Contact`): + location (:class:`telegram.Location`): + new_chat_participant (:class:`telegram.User`): + left_chat_participant (:class:`telegram.User`): + new_chat_title (str): + new_chat_photo (List[:class:`telegram.PhotoSize`]): + delete_chat_photo (bool): + group_chat_created (bool): + + Args: + message_id (int): + from_user (:class:`telegram.User`): + date (:class:`datetime.datetime`): + chat (:class:`telegram.User` or :class:`telegram.GroupChat`): + **kwargs: Arbitrary keyword arguments. + + Keyword Args: + forward_from (Optional[:class:`telegram.User`]): + forward_date (Optional[:class:`datetime.datetime`]): + reply_to_message (Optional[:class:`telegram.Message`]): + text (Optional[str]): + audio (Optional[:class:`telegram.Audio`]): + document (Optional[:class:`telegram.Document`]): + photo (Optional[List[:class:`telegram.PhotoSize`]]): + sticker (Optional[:class:`telegram.Sticker`]): + video (Optional[:class:`telegram.Video`]): + voice (Optional[:class:`telegram.Voice`]): + caption (Optional[str]): + contact (Optional[:class:`telegram.Contact`]): + location (Optional[:class:`telegram.Location`]): + new_chat_participant (Optional[:class:`telegram.User`]): + left_chat_participant (Optional[:class:`telegram.User`]): + new_chat_title (Optional[str]): + new_chat_photo (Optional[List[:class:`telegram.PhotoSize`]): + delete_chat_photo (Optional[bool]): + group_chat_created (Optional[bool]): + """ + def __init__(self, message_id, from_user, date, chat, - forward_from=None, - forward_date=None, - reply_to_message=None, - text=None, - audio=None, - document=None, - photo=None, - sticker=None, - video=None, - voice=None, - caption=None, - contact=None, - location=None, - new_chat_participant=None, - left_chat_participant=None, - new_chat_title=None, - new_chat_photo=None, - delete_chat_photo=None, - group_chat_created=None): + **kwargs): self.message_id = message_id self.from_user = from_user self.date = date self.chat = chat - self.forward_from = forward_from - self.forward_date = forward_date - self.reply_to_message = reply_to_message - self.text = text - self.audio = audio - self.document = document - self.photo = photo - self.sticker = sticker - self.video = video - self.voice = voice - self.caption = caption - self.contact = contact - self.location = location - self.new_chat_participant = new_chat_participant - self.left_chat_participant = left_chat_participant - self.new_chat_title = new_chat_title - self.new_chat_photo = new_chat_photo - self.delete_chat_photo = delete_chat_photo - self.group_chat_created = group_chat_created + self.forward_from = kwargs.get('forward_from') + self.forward_date = kwargs.get('forward_date') + self.reply_to_message = kwargs.get('reply_to_message') + self.text = kwargs.get('text') + self.audio = kwargs.get('audio') + self.document = kwargs.get('document') + self.photo = kwargs.get('photo') + self.sticker = kwargs.get('sticker') + self.video = kwargs.get('video') + self.voice = kwargs.get('voice') + self.caption = kwargs.get('caption') + self.contact = kwargs.get('contact') + self.location = kwargs.get('location') + self.new_chat_participant = kwargs.get('new_chat_participant') + self.left_chat_participant = kwargs.get('left_chat_participant') + self.new_chat_title = kwargs.get('new_chat_title') + self.new_chat_photo = kwargs.get('new_chat_photo') + self.delete_chat_photo = kwargs.get('delete_chat_photo') + self.group_chat_created = kwargs.get('group_chat_created') @property def chat_id(self): + """int: Short for :attr:`Message.chat.id`""" return self.chat.id @staticmethod def de_json(data): - if 'from' in data: # from is a reserved word, use from_user instead. - from telegram import User - from_user = User.de_json(data['from']) - else: - from_user = None + """ + Args: + data (str): - if 'date' in data: - date = datetime.fromtimestamp(data['date']) - else: - date = None + Returns: + telegram.Message: + """ + message = dict() - if 'chat' in data: - if 'first_name' in data['chat']: - from telegram import User - chat = User.de_json(data['chat']) - if 'title' in data['chat']: - from telegram import GroupChat - chat = GroupChat.de_json(data['chat']) - else: - chat = None + message['message_id'] = int(data['message_id']) + message['from_user'] = User.de_json(data['from']) + message['date'] = datetime.fromtimestamp(data['date']) + + if 'first_name' in data['chat']: + message['chat'] = User.de_json(data['chat']) + elif 'title' in data['chat']: + message['chat'] = GroupChat.de_json(data['chat']) if 'forward_from' in data: - from telegram import User - forward_from = User.de_json(data['forward_from']) - else: - forward_from = None + message['forward_from'] = User.de_json(data['forward_from']) if 'forward_date' in data: - forward_date = datetime.fromtimestamp(data['forward_date']) - else: - forward_date = None + message['forward_date'] = \ + datetime.fromtimestamp(data['forward_date']) + + message['text'] = data.get('text', '') if 'reply_to_message' in data: - reply_to_message = Message.de_json(data['reply_to_message']) - else: - reply_to_message = None + message['reply_to_message'] = \ + Message.de_json(data['reply_to_message']) if 'audio' in data: - from telegram import Audio - audio = Audio.de_json(data['audio']) - else: - audio = None + message['audio'] = Audio.de_json(data['audio']) if 'document' in data: - from telegram import Document - document = Document.de_json(data['document']) - else: - document = None + message['document'] = Document.de_json(data['document']) if 'photo' in data: - from telegram import PhotoSize - photo = [PhotoSize.de_json(x) for x in data['photo']] - else: - photo = None + message['photo'] = [PhotoSize.de_json(x) for x in data['photo']] if 'sticker' in data: - from telegram import Sticker - sticker = Sticker.de_json(data['sticker']) - else: - sticker = None + message['sticker'] = Sticker.de_json(data['sticker']) if 'video' in data: - from telegram import Video - video = Video.de_json(data['video']) - else: - video = None + message['video'] = Video.de_json(data['video']) if 'voice' in data: - from telegram import Voice - voice = Voice.de_json(data['voice']) - else: - voice = None + message['voice'] = Voice.de_json(data['voice']) + + message['caption'] = data.get('caption', '') if 'contact' in data: - from telegram import Contact - contact = Contact.de_json(data['contact']) - else: - contact = None + message['contact'] = Contact.de_json(data['contact']) if 'location' in data: - from telegram import Location - location = Location.de_json(data['location']) - else: - location = None + message['location'] = Location.de_json(data['location']) if 'new_chat_participant' in data: - from telegram import User - new_chat_participant = User.de_json(data['new_chat_participant']) - else: - new_chat_participant = None + message['new_chat_participant'] = \ + User.de_json(data['new_chat_participant']) if 'left_chat_participant' in data: - from telegram import User - left_chat_participant = User.de_json(data['left_chat_participant']) - else: - left_chat_participant = None + message['left_chat_participant'] = \ + User.de_json(data['left_chat_participant']) + + message['new_chat_title'] = data.get('new_chat_title', '') if 'new_chat_photo' in data: - from telegram import PhotoSize - new_chat_photo = \ + message['new_chat_photo'] = \ [PhotoSize.de_json(x) for x in data['new_chat_photo']] - else: - new_chat_photo = None - return Message(message_id=data.get('message_id', None), - from_user=from_user, - date=date, - chat=chat, - forward_from=forward_from, - forward_date=forward_date, - reply_to_message=reply_to_message, - text=data.get('text', ''), - audio=audio, - document=document, - photo=photo, - sticker=sticker, - video=video, - voice=voice, - caption=data.get('caption', ''), - contact=contact, - location=location, - new_chat_participant=new_chat_participant, - left_chat_participant=left_chat_participant, - new_chat_title=data.get('new_chat_title', None), - new_chat_photo=new_chat_photo, - delete_chat_photo=data.get('delete_chat_photo', None), - group_chat_created=data.get('group_chat_created', None)) + message['delete_chat_photo'] = \ + bool(data.get('delete_chat_photo', False)) + + message['group_chat_created'] = \ + bool(data.get('group_chat_created', False)) + + return Message(**message) def to_dict(self): + """ + Returns: + dict: + """ data = {'message_id': self.message_id, 'from': self.from_user.to_dict(), + 'date': self._totimestamp(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.to_dict() + + if self.forward_date: + data['forward_date'] = self._totimestamp(self.forward_date) + if self.reply_to_message: data['reply_to_message'] = self.reply_to_message.to_dict() + if self.text: data['text'] = self.text + if self.audio: data['audio'] = self.audio.to_dict() + if self.document: data['document'] = self.document.to_dict() + if self.photo: data['photo'] = [p.to_dict() for p in self.photo] + if self.sticker: data['sticker'] = self.sticker.to_dict() + if self.video: data['video'] = self.video.to_dict() + if self.voice: data['voice'] = self.voice.to_dict() + if self.caption: data['caption'] = self.caption + if self.contact: data['contact'] = self.contact.to_dict() + if self.location: data['location'] = self.location.to_dict() + if self.new_chat_participant: data['new_chat_participant'] = self.new_chat_participant.to_dict() + if self.left_chat_participant: data['left_chat_participant'] = \ self.left_chat_participant.to_dict() + if self.new_chat_title: data['new_chat_title'] = self.new_chat_title + if self.new_chat_photo: data['new_chat_photo'] = [p.to_dict() for p in self.new_chat_photo] + if self.delete_chat_photo: data['delete_chat_photo'] = self.delete_chat_photo + if self.group_chat_created: data['group_chat_created'] = self.group_chat_created + return data @staticmethod - def _totimestamp(dt): - return int(mktime(dt.timetuple())) + def _totimestamp(dt_obj): + """ + Args: + dt_obj (:class:`datetime.datetime`): + + Returns: + int: + """ + try: + # Python 3.3+ + return int(dt_obj.timestamp()) + except AttributeError: + # Python 3 (< 3.3) and Python 2 + return int(mktime(dt_obj.timetuple())) diff --git a/tests/test_bot.py b/tests/test_bot.py index b44808c68..fcc266ea3 100644 --- a/tests/test_bot.py +++ b/tests/test_bot.py @@ -62,8 +62,9 @@ class BotTest(unittest.TestCase): '''Test the telegram.Bot getUpdates method''' print('Testing getUpdates') updates = self._bot.getUpdates() - self.assertTrue(self.is_json(updates[0].to_json())) - self.assertIsInstance(updates[0], telegram.Update) + if updates: + self.assertTrue(self.is_json(updates[0].to_json())) + self.assertIsInstance(updates[0], telegram.Update) def testForwardMessage(self): '''Test the telegram.Bot forwardMessage method'''