Improving the design of existing Telegram classes and adding docstrings

This commit is contained in:
leandrotoledo 2015-08-21 23:15:29 -03:00
parent d03a394075
commit fdb5f2339c
21 changed files with 877 additions and 283 deletions

View file

@ -22,7 +22,6 @@ __version__ = '2.7.1'
from .base import TelegramObject
from .user import User
from .update import Update
from .groupchat import GroupChat
from .photosize import PhotoSize
from .audio import Audio
@ -38,11 +37,12 @@ from .replymarkup import ReplyMarkup
from .replykeyboardmarkup import ReplyKeyboardMarkup
from .replykeyboardhide import ReplyKeyboardHide
from .forcereply import ForceReply
from .inputfile import InputFile
from .error import TelegramError
from .inputfile import InputFile
from .nullhandler import NullHandler
from .emoji import Emoji
from .message import Message
from .update import Update
from .bot import Bot
__all__ = ['Bot', 'Emoji', 'TelegramError', 'InputFile', 'ReplyMarkup',

View file

@ -16,37 +16,83 @@
# 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"""
from telegram import TelegramObject
class Audio(TelegramObject):
"""This object represents a Telegram Audio.
Attributes:
file_id (str):
duration (int):
performer (str):
title (str):
mime_type (str):
file_size (int):
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]):
"""
def __init__(self,
file_id,
duration,
performer=None,
title=None,
mime_type=None,
file_size=None):
**kwargs):
# Required
self.file_id = file_id
self.duration = duration
self.performer = performer
self.title = title
self.mime_type = mime_type
self.file_size = file_size
self.duration = int(duration)
# Optionals
self.performer = kwargs.get('performer', '')
self.title = kwargs.get('title', '')
self.mime_type = kwargs.get('mime_type', '')
self.file_size = int(kwargs.get('file_size', 0))
@staticmethod
def de_json(data):
return Audio(file_id=data.get('file_id', None),
duration=data.get('duration', None),
performer=data.get('performer', None),
title=data.get('title', None),
mime_type=data.get('mime_type', None),
file_size=data.get('file_size', None))
"""
Args:
data (str):
Returns:
telegram.Audio:
"""
if not data:
return None
audio = dict()
# Required
audio['file_id'] = data['file_id']
audio['duration'] = data['duration']
# Optionals
audio['performer'] = data.get('performer')
audio['title'] = data.get('title')
audio['mime_type'] = data.get('mime_type')
audio['file_size'] = data.get('file_size', 0)
return Audio(**audio)
def to_dict(self):
data = {'file_id': self.file_id,
'duration': self.duration}
"""
Returns:
dict:
"""
data = dict()
# Required
data['file_id'] = self.file_id
data['duration'] = self.duration
# Optionals
if self.performer:
data['performer'] = self.performer
if self.title:
@ -55,4 +101,5 @@ class Audio(TelegramObject):
data['mime_type'] = self.mime_type
if self.file_size:
data['file_size'] = self.file_size
return data

View file

@ -41,4 +41,4 @@ class TelegramObject(object):
@abstractmethod
def to_dict(self):
return
return None

View file

@ -1,4 +1,5 @@
#!/usr/bin/env python
# pylint: disable=R0903
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015 Leandro Toledo de Souza <leandrotoeldodesouza@gmail.com>
@ -16,8 +17,12 @@
# 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"""
class ChatAction(object):
"""This object represents a Telegram ChatAction."""
TYPING = 'typing'
UPLOAD_PHOTO = 'upload_photo'
RECORD_VIDEO = 'upload_video'

View file

@ -16,33 +16,78 @@
# 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"""
from telegram import TelegramObject
class Contact(TelegramObject):
"""This object represents a Telegram Contact.
Attributes:
phone_number (str):
first_name (str):
last_name (str):
user_id (int):
Args:
phone_number (str):
first_name (str):
**kwargs: Arbitrary keyword arguments.
Keyword Args:
last_name (Optional[str]):
user_id (Optional[int]):
"""
def __init__(self,
phone_number,
first_name,
last_name=None,
user_id=None):
**kwargs):
# Required
self.phone_number = phone_number
self.first_name = first_name
self.last_name = last_name
self.user_id = user_id
# Optionals
self.last_name = kwargs.get('last_name', '')
self.user_id = int(kwargs.get('user_id', 0))
@staticmethod
def de_json(data):
return Contact(phone_number=data.get('phone_number', None),
first_name=data.get('first_name', None),
last_name=data.get('last_name', None),
user_id=data.get('user_id', None))
"""
Args:
data (str):
Returns:
telegram.Contact:
"""
if not data:
return None
contact = dict()
# Required
contact['phone_number'] = data['phone_number']
contact['first_name'] = data['first_name']
# Optionals
contact['last_name'] = data.get('last_name')
contact['user_id'] = data.get('user_id', 0)
return Contact(**contact)
def to_dict(self):
data = {'phone_number': self.phone_number,
'first_name': self.first_name}
"""
Returns:
dict:
"""
data = dict()
# Required
data['phone_number'] = self.phone_number
data['first_name'] = self.first_name
# Optionals
if self.last_name:
data['last_name'] = self.last_name
if self.user_id:
data['user_id'] = self.user_id
return data

View file

@ -16,39 +16,77 @@
# 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"""
from telegram import TelegramObject
from telegram import PhotoSize, TelegramObject
class Document(TelegramObject):
"""This object represents a Telegram Document.
Attributes:
file_id (str):
thumb (:class:`telegram.PhotoSize`):
file_name (str):
mime_type (str):
file_size (int):
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]):
"""
def __init__(self,
file_id,
thumb=None,
file_name=None,
mime_type=None,
file_size=None):
**kwargs):
# Required
self.file_id = file_id
self.thumb = thumb
self.file_name = file_name
self.mime_type = mime_type
self.file_size = file_size
# Optionals
self.thumb = kwargs.get('thumb')
self.file_name = kwargs.get('file_name', '')
self.mime_type = kwargs.get('mime_type', '')
self.file_size = int(kwargs.get('file_size', 0))
@staticmethod
def de_json(data):
if 'thumb' in data:
from telegram import PhotoSize
thumb = PhotoSize.de_json(data['thumb'])
else:
thumb = None
"""
Args:
data (str):
return Document(file_id=data.get('file_id', None),
thumb=thumb,
file_name=data.get('file_name', None),
mime_type=data.get('mime_type', None),
file_size=data.get('file_size', None))
Returns:
telegram.Document:
"""
if not data:
return None
document = dict()
# Required
document['file_id'] = data['file_id']
# Optionals
document['thumb'] = PhotoSize.de_json(data.get('thumb'))
document['file_name'] = data.get('file_name')
document['mime_type'] = data.get('mime_type')
document['file_size'] = data.get('file_size', 0)
return Document(**document)
def to_dict(self):
data = {'file_id': self.file_id}
"""
Returns:
dict:
"""
data = dict()
# Required
data['file_id'] = self.file_id
# Optionals
if self.thumb:
data['thumb'] = self.thumb.to_dict()
if self.file_name:
@ -57,4 +95,5 @@ class Document(TelegramObject):
data['mime_type'] = self.mime_type
if self.file_size:
data['file_size'] = self.file_size
return data

View file

@ -1,5 +1,6 @@
#!/usr/bin/env python
# flake8: noqa
# pylint: disable=C0103,C0301,R0903
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015 Leandro Toledo de Souza <leandrotoeldodesouza@gmail.com>
@ -17,8 +18,12 @@
# 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"""
class Emoji(object):
"""This object represents an Emoji."""
GRINNING_FACE_WITH_SMILING_EYES = b'\xF0\x9F\x98\x81'
FACE_WITH_TEARS_OF_JOY = b'\xF0\x9F\x98\x82'
SMILING_FACE_WITH_OPEN_MOUTH = b'\xF0\x9F\x98\x83'
@ -155,16 +160,26 @@ class Emoji(object):
SQUARED_SOS = b'\xF0\x9F\x86\x98'
SQUARED_UP_WITH_EXCLAMATION_MARK = b'\xF0\x9F\x86\x99'
SQUARED_VS = b'\xF0\x9F\x86\x9A'
REGIONAL_INDICATOR_SYMBOL_LETTER_D_PLUS_REGIONAL_INDICATOR_SYMBOL_LETTER_E = b'\xF0\x9F\x87\xA9\xF0\x9F\x87\xAA'
REGIONAL_INDICATOR_SYMBOL_LETTER_G_PLUS_REGIONAL_INDICATOR_SYMBOL_LETTER_B = b'\xF0\x9F\x87\xAC\xF0\x9F\x87\xA7'
REGIONAL_INDICATOR_SYMBOL_LETTER_C_PLUS_REGIONAL_INDICATOR_SYMBOL_LETTER_N = b'\xF0\x9F\x87\xA8\xF0\x9F\x87\xB3'
REGIONAL_INDICATOR_SYMBOL_LETTER_J_PLUS_REGIONAL_INDICATOR_SYMBOL_LETTER_P = b'\xF0\x9F\x87\xAF\xF0\x9F\x87\xB5'
REGIONAL_INDICATOR_SYMBOL_LETTER_K_PLUS_REGIONAL_INDICATOR_SYMBOL_LETTER_R = b'\xF0\x9F\x87\xB0\xF0\x9F\x87\xB7'
REGIONAL_INDICATOR_SYMBOL_LETTER_F_PLUS_REGIONAL_INDICATOR_SYMBOL_LETTER_R = b'\xF0\x9F\x87\xAB\xF0\x9F\x87\xB7'
REGIONAL_INDICATOR_SYMBOL_LETTER_E_PLUS_REGIONAL_INDICATOR_SYMBOL_LETTER_S = b'\xF0\x9F\x87\xAA\xF0\x9F\x87\xB8'
REGIONAL_INDICATOR_SYMBOL_LETTER_I_PLUS_REGIONAL_INDICATOR_SYMBOL_LETTER_T = b'\xF0\x9F\x87\xAE\xF0\x9F\x87\xB9'
REGIONAL_INDICATOR_SYMBOL_LETTER_U_PLUS_REGIONAL_INDICATOR_SYMBOL_LETTER_S = b'\xF0\x9F\x87\xBA\xF0\x9F\x87\xB8'
REGIONAL_INDICATOR_SYMBOL_LETTER_R_PLUS_REGIONAL_INDICATOR_SYMBOL_LETTER_U = b'\xF0\x9F\x87\xB7\xF0\x9F\x87\xBA'
REGIONAL_INDICATOR_SYMBOL_LETTER_D_PLUS_REGIONAL_INDICATOR_SYMBOL_LETTER_E\
= b'\xF0\x9F\x87\xA9\xF0\x9F\x87\xAA'
REGIONAL_INDICATOR_SYMBOL_LETTER_G_PLUS_REGIONAL_INDICATOR_SYMBOL_LETTER_B\
= b'\xF0\x9F\x87\xAC\xF0\x9F\x87\xA7'
REGIONAL_INDICATOR_SYMBOL_LETTER_C_PLUS_REGIONAL_INDICATOR_SYMBOL_LETTER_N\
= b'\xF0\x9F\x87\xA8\xF0\x9F\x87\xB3'
REGIONAL_INDICATOR_SYMBOL_LETTER_J_PLUS_REGIONAL_INDICATOR_SYMBOL_LETTER_P\
= b'\xF0\x9F\x87\xAF\xF0\x9F\x87\xB5'
REGIONAL_INDICATOR_SYMBOL_LETTER_K_PLUS_REGIONAL_INDICATOR_SYMBOL_LETTER_R\
= b'\xF0\x9F\x87\xB0\xF0\x9F\x87\xB7'
REGIONAL_INDICATOR_SYMBOL_LETTER_F_PLUS_REGIONAL_INDICATOR_SYMBOL_LETTER_R\
= b'\xF0\x9F\x87\xAB\xF0\x9F\x87\xB7'
REGIONAL_INDICATOR_SYMBOL_LETTER_E_PLUS_REGIONAL_INDICATOR_SYMBOL_LETTER_S\
= b'\xF0\x9F\x87\xAA\xF0\x9F\x87\xB8'
REGIONAL_INDICATOR_SYMBOL_LETTER_I_PLUS_REGIONAL_INDICATOR_SYMBOL_LETTER_T\
= b'\xF0\x9F\x87\xAE\xF0\x9F\x87\xB9'
REGIONAL_INDICATOR_SYMBOL_LETTER_U_PLUS_REGIONAL_INDICATOR_SYMBOL_LETTER_S\
= b'\xF0\x9F\x87\xBA\xF0\x9F\x87\xB8'
REGIONAL_INDICATOR_SYMBOL_LETTER_R_PLUS_REGIONAL_INDICATOR_SYMBOL_LETTER_U\
= b'\xF0\x9F\x87\xB7\xF0\x9F\x87\xBA'
SQUARED_KATAKANA_KOKO = b'\xF0\x9F\x88\x81'
SQUARED_KATAKANA_SA = b'\xF0\x9F\x88\x82'
SQUARED_CJK_UNIFIED_IDEOGRAPH_7121 = b'\xF0\x9F\x88\x9A'

View file

@ -16,11 +16,16 @@
# 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"""
class TelegramError(Exception):
"""Base class for Telegram errors."""
"""This object represents a Telegram Error."""
@property
def message(self):
'''Returns the first argument used to construct this error.'''
"""
Returns:
str:
"""
return self.args[0]

View file

@ -1,4 +1,5 @@
#!/usr/bin/env python
# pylint: disable=C0103,W0622
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015 Leandro Toledo de Souza <leandrotoeldodesouza@gmail.com>
@ -16,23 +17,59 @@
# 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 GroupChat"""
from telegram import TelegramObject
class GroupChat(TelegramObject):
"""This object represents a Telegram GroupChat.
Attributes:
id (int):
title (str):
Args:
id (int):
title (str):
"""
def __init__(self,
id,
title):
self.id = id
# Required
self.id = int(id)
self.title = title
@staticmethod
def de_json(data):
return GroupChat(id=data.get('id', None),
title=data.get('title', None))
"""
Args:
data (str):
Returns:
telegram.GroupChat:
"""
if not data:
return None
groupchat = dict()
# Required
groupchat['id'] = data['id']
groupchat['title'] = data['title']
return GroupChat(**groupchat)
def to_dict(self):
data = {'id': self.id,
'title': self.title}
"""
Returns:
dict:
"""
data = dict()
# Required
data['id'] = self.id
data['title'] = self.title
return data

View file

@ -1,4 +1,5 @@
#!/usr/bin/env python
# pylint: disable=W0622,E0611
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015 Leandro Toledo de Souza <leandrotoeldodesouza@gmail.com>
@ -16,6 +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 InputFile"""
try:
from email.generator import _make_boundary as choose_boundary
@ -29,7 +31,7 @@ import os
import sys
import imghdr
from .error import TelegramError
from telegram import TelegramError
DEFAULT_MIME_TYPE = 'application/octet-stream'
USER_AGENT = 'Python Telegram Bot' \
@ -37,6 +39,8 @@ USER_AGENT = 'Python Telegram Bot' \
class InputFile(object):
"""This object represents a Telegram InputFile."""
def __init__(self,
data):
self.data = data
@ -71,14 +75,26 @@ class InputFile(object):
@property
def headers(self):
"""
Returns:
str:
"""
return {'User-agent': USER_AGENT,
'Content-type': self.content_type}
@property
def content_type(self):
"""
Returns:
str:
"""
return 'multipart/form-data; boundary=%s' % self.boundary
def to_form(self):
"""
Returns:
str:
"""
form = []
form_boundary = '--' + self.boundary
@ -105,9 +121,14 @@ class InputFile(object):
form.append('--' + self.boundary + '--')
form.append('')
return self._parse(form)
return InputFile._parse(form)
def _parse(self, form):
@staticmethod
def _parse(form):
"""
Returns:
str:
"""
if sys.version_info > (3,):
# on Python 3 form needs to be byte encoded
encoded_form = []
@ -125,11 +146,10 @@ class InputFile(object):
"""Check if the content file is an image by analyzing its headers.
Args:
stream:
A str representing the content of a file.
stream (str): A str representing the content of a file.
Returns:
The str mimetype of an image.
str: The str mimetype of an image.
"""
image = imghdr.what(None, stream)
if image:
@ -142,8 +162,7 @@ class InputFile(object):
"""Check if the request is a file request.
Args:
data:
A dict of (str, unicode) key/value pairs
data (str): A dict of (str, unicode) key/value pairs
Returns:
bool

View file

@ -16,23 +16,57 @@
# 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 Location"""
from telegram import TelegramObject
class Location(TelegramObject):
"""This object represents a Telegram Sticker.
Attributes:
longitude (float):
latitude (float):
Args:
longitude (float):
latitude (float):
"""
def __init__(self,
longitude,
latitude):
self.longitude = longitude
self.latitude = latitude
# Required
self.longitude = float(longitude)
self.latitude = float(latitude)
@staticmethod
def de_json(data):
return Location(longitude=data.get('longitude', None),
latitude=data.get('latitude', None))
"""
Args:
data (str):
Returns:
telegram.Location:
"""
if not data:
return None
location = dict()
location['longitude'] = data['longitude']
location['latitude'] = data['latitude']
return Location(**location)
def to_dict(self):
data = {'longitude': self.longitude,
'latitude': self.latitude}
"""
Returns:
dict:
"""
data = dict()
data['longitude'] = self.longitude
data['latitude'] = self.latitude
return data

View file

@ -1,6 +1,5 @@
#!/usr/bin/env python
# pylint: disable=too-many-instance-attributes
# pylint: disable=too-many-arguments,too-many-branches
# pylint: disable=R0902,R0912,R0913
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015 Leandro Toledo de Souza <leandrotoeldodesouza@gmail.com>
@ -92,29 +91,31 @@ class Message(TelegramObject):
date,
chat,
**kwargs):
self.message_id = message_id
# Required
self.message_id = int(message_id)
self.from_user = from_user
self.date = date
self.chat = chat
# Optionals
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.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.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_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')
self.delete_chat_photo = bool(kwargs.get('delete_chat_photo', False))
self.group_chat_created = bool(kwargs.get('group_chat_created', False))
@property
def chat_id(self):
@ -130,75 +131,58 @@ class Message(TelegramObject):
Returns:
telegram.Message:
"""
if not data:
return None
message = dict()
message['message_id'] = int(data['message_id'])
# Required
message['message_id'] = 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:
message['forward_from'] = User.de_json(data['forward_from'])
if 'forward_date' in data:
message['forward_date'] = \
datetime.fromtimestamp(data['forward_date'])
message['text'] = data.get('text', '')
if 'reply_to_message' in data:
message['reply_to_message'] = \
Message.de_json(data['reply_to_message'])
if 'audio' in data:
message['audio'] = Audio.de_json(data['audio'])
if 'document' in data:
message['document'] = Document.de_json(data['document'])
if 'photo' in data:
message['photo'] = [PhotoSize.de_json(x) for x in data['photo']]
if 'sticker' in data:
message['sticker'] = Sticker.de_json(data['sticker'])
if 'video' in data:
message['video'] = Video.de_json(data['video'])
if 'voice' in data:
message['voice'] = Voice.de_json(data['voice'])
message['caption'] = data.get('caption', '')
if 'contact' in data:
message['contact'] = Contact.de_json(data['contact'])
if 'location' in data:
message['location'] = Location.de_json(data['location'])
if 'new_chat_participant' in data:
message['new_chat_participant'] = \
User.de_json(data['new_chat_participant'])
if 'left_chat_participant' in data:
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:
message['new_chat_photo'] = \
[PhotoSize.de_json(x) for x in data['new_chat_photo']]
# Optionals
if 'first_name' in data.get('chat', ''):
message['chat'] = User.de_json(data.get('chat'))
elif 'title' in data.get('chat', ''):
message['chat'] = GroupChat.de_json(data.get('chat'))
message['forward_from'] = \
User.de_json(data.get('forward_from'))
message['forward_date'] = \
Message._fromtimestamp(data.get('forward_date'))
message['reply_to_message'] = \
Message.de_json(data.get('reply_to_message'))
message['text'] = \
data.get('text')
message['audio'] = \
Audio.de_json(data.get('audio'))
message['document'] = \
Document.de_json(data.get('document'))
message['photo'] = \
[PhotoSize.de_json(x) for x in data.get('photo', [])]
message['sticker'] = \
Sticker.de_json(data.get('sticker'))
message['video'] = \
Video.de_json(data.get('video'))
message['voice'] = \
Voice.de_json(data.get('voice'))
message['caption'] = \
data.get('caption')
message['contact'] = \
Contact.de_json(data.get('contact'))
message['location'] = \
Location.de_json(data.get('location'))
message['new_chat_participant'] = \
User.de_json(data.get('new_chat_participant'))
message['left_chat_participant'] = \
User.de_json(data.get('left_chat_participant'))
message['new_chat_title'] = \
data.get('new_chat_title')
message['new_chat_photo'] = \
[PhotoSize.de_json(x) for x in data.get('new_chat_photo', [])]
message['delete_chat_photo'] = \
bool(data.get('delete_chat_photo', False))
data.get('delete_chat_photo')
message['group_chat_created'] = \
bool(data.get('group_chat_created', False))
data.get('group_chat_created')
return Message(**message)
@ -207,71 +191,70 @@ class Message(TelegramObject):
Returns:
dict:
"""
data = {'message_id': self.message_id,
'from': self.from_user.to_dict(),
'date': self._totimestamp(self.date),
'chat': self.chat.to_dict()}
data = dict()
# Required
data['message_id'] = self.message_id
data['from'] = self.from_user.to_dict()
data['date'] = self._totimestamp(self.date)
data['chat'] = self.chat.to_dict()
# Optionals
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 _fromtimestamp(unixtime):
"""
Args:
unixtime (int):
Returns:
datetime.datetime:
"""
if not unixtime:
return None
return datetime.fromtimestamp(unixtime)
@staticmethod
def _totimestamp(dt_obj):
"""
@ -281,6 +264,9 @@ class Message(TelegramObject):
Returns:
int:
"""
if not dt_obj:
return None
try:
# Python 3.3+
return int(dt_obj.timestamp())

View file

@ -16,10 +16,17 @@
# 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 logging NullHandler"""
import logging
class NullHandler(logging.Handler):
"""This object represents a logging NullHandler."""
def emit(self, record):
"""
Args:
record (str):
"""
pass

View file

@ -16,32 +16,78 @@
# 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 PhotoSize"""
from telegram import TelegramObject
class PhotoSize(TelegramObject):
"""This object represents a Telegram PhotoSize.
Attributes:
file_id (str):
width (int):
height (int):
file_size (int):
Args:
file_id (str):
width (int):
height (int):
**kwargs: Arbitrary keyword arguments.
Keyword Args:
file_size (Optional[int]):
"""
def __init__(self,
file_id,
width,
height,
file_size=None):
**kwargs):
# Required
self.file_id = file_id
self.width = width
self.height = height
self.file_size = file_size
self.width = int(width)
self.height = int(height)
# Optionals
self.file_size = int(kwargs.get('file_size', 0))
@staticmethod
def de_json(data):
return PhotoSize(file_id=data.get('file_id', None),
width=data.get('width', None),
height=data.get('height', None),
file_size=data.get('file_size', None))
"""
Args:
data (str):
Returns:
telegram.PhotoSize:
"""
if not data:
return None
photosize = dict()
# Required
photosize['file_id'] = data['file_id']
photosize['width'] = data['width']
photosize['height'] = data['height']
# Optionals
photosize['file_size'] = data.get('file_size', 0)
return PhotoSize(**photosize)
def to_dict(self):
data = {'file_id': self.file_id,
'width': self.width,
'height': self.height}
"""
Returns:
dict:
"""
data = dict()
# Required
data['file_id'] = self.file_id
data['width'] = self.width
data['height'] = self.height
# Optionals
if self.file_size:
data['file_size'] = self.file_size
return data

View file

@ -16,42 +16,84 @@
# 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 Sticker"""
from telegram import TelegramObject
from telegram import PhotoSize, TelegramObject
class Sticker(TelegramObject):
"""This object represents a Telegram Sticker.
Attributes:
file_id (str):
width (int):
height (int):
thumb (:class:`telegram.PhotoSize`):
file_size (int):
Args:
file_id (str):
width (int):
height (int):
**kwargs: Arbitrary keyword arguments.
Keyword Args:
thumb (Optional[:class:`telegram.PhotoSize`]):
file_size (Optional[int]):
"""
def __init__(self,
file_id,
width,
height,
thumb=None,
file_size=None):
**kwargs):
# Required
self.file_id = file_id
self.width = width
self.height = height
self.thumb = thumb
self.file_size = file_size
self.width = int(width)
self.height = int(height)
# Optionals
self.thumb = kwargs.get('thumb')
self.file_size = int(kwargs.get('file_size', 0))
@staticmethod
def de_json(data):
if 'thumb' in data:
from telegram import PhotoSize
thumb = PhotoSize.de_json(data['thumb'])
else:
thumb = None
"""
Args:
data (str):
return Sticker(file_id=data.get('file_id', None),
width=data.get('width', None),
height=data.get('height', None),
thumb=thumb,
file_size=data.get('file_size', None))
Returns:
telegram.Sticker:
"""
if not data:
return None
sticker = dict()
# Required
sticker['file_id'] = data['file_id']
sticker['width'] = data['width']
sticker['height'] = data['height']
# Optionals
sticker['thumb'] = PhotoSize.de_json(data['thumb'])
sticker['file_size'] = data.get('file_size', 0)
return Sticker(**sticker)
def to_dict(self):
data = {'file_id': self.file_id,
'width': self.width,
'height': self.height,
'thumb': self.thumb.to_dict()}
"""
Returns:
dict:
"""
data = dict()
# Required
data['file_id'] = self.file_id
data['width'] = self.width
data['height'] = self.height
# Optionals
if self.thumb:
data['thumb'] = self.thumb.to_dict()
if self.file_size:
data['file_size'] = self.file_size
return data

View file

@ -16,30 +16,60 @@
# 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 Update"""
from telegram import TelegramObject
from telegram import Message, TelegramObject
class Update(TelegramObject):
"""This object represents a Telegram Update.
Attributes:
update_id (int):
message (:class:`telegram.Message`):
Args:
update_id (int):
**kwargs: Arbitrary keyword arguments.
Keyword Args:
message (Optional[:class:`telegram.Message`]):
"""
def __init__(self,
update_id,
message=None):
**kwargs):
# Required
self.update_id = update_id
self.message = message
# Optionals
self.message = kwargs.get('message')
@staticmethod
def de_json(data):
if 'message' in data:
from telegram import Message
message = Message.de_json(data['message'])
else:
message = None
"""
Args:
data (str):
return Update(update_id=data.get('update_id', None),
message=message)
Returns:
telegram.Update:
"""
update = dict()
update['update_id'] = data['update_id']
update['message'] = Message.de_json(data['message'])
return Update(**update)
def to_dict(self):
data = {'update_id': self.update_id}
"""
Returns:
dict:
"""
data = dict()
# Required
data['update_id'] = self.update_id
# Optionals
if self.message:
data['message'] = self.message.to_dict()
return data

View file

@ -1,4 +1,5 @@
#!/usr/bin/env python
# pylint: disable=C0103,W0622
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015 Leandro Toledo de Souza <leandrotoeldodesouza@gmail.com>
@ -16,23 +17,44 @@
# 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 User"""
from telegram import TelegramObject
class User(TelegramObject):
"""This object represents a Telegram Sticker.
Attributes:
id (int):
first_name (str):
last_name (str):
username (str):
Args:
id (int):
first_name (str):
**kwargs: Arbitrary keyword arguments.
Keyword Args:
last_name (Optional[str]):
username (Optional[str]):
"""
def __init__(self,
id,
first_name,
last_name=None,
username=None):
self.id = id
**kwargs):
# Required
self.id = int(id)
self.first_name = first_name
self.last_name = last_name
self.username = username
# Optionals
self.last_name = kwargs.get('last_name', '')
self.username = kwargs.get('username', '')
@property
def name(self):
"""str: """
if self.username:
return '@%s' % self.username
if self.last_name:
@ -41,16 +63,41 @@ class User(TelegramObject):
@staticmethod
def de_json(data):
return User(id=data.get('id', None),
first_name=data.get('first_name', None),
last_name=data.get('last_name', None),
username=data.get('username', None))
"""
Args:
data (str):
Returns:
telegram.User:
"""
if not data:
return None
user = dict()
# Required
user['id'] = data['id']
user['first_name'] = data['first_name']
# Optionals
user['last_name'] = data.get('last_name')
user['username'] = data.get('username')
return User(**user)
def to_dict(self):
data = {'id': self.id,
'first_name': self.first_name}
"""
Returns:
dict:
"""
data = dict()
# Required
data['id'] = self.id
data['first_name'] = self.first_name
# Optionals
if self.last_name:
data['last_name'] = self.last_name
if self.username:
data['username'] = self.username
return data

View file

@ -16,36 +16,64 @@
# 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
UserProfilePhotos"""
from telegram import TelegramObject
from telegram import PhotoSize, TelegramObject
class UserProfilePhotos(TelegramObject):
"""This object represents a Telegram UserProfilePhotos.
Attributes:
total_count (int):
photos (List[List[:class:`telegram.PhotoSize`]]):
Args:
total_count (int):
photos (List[List[:class:`telegram.PhotoSize`]]):
"""
def __init__(self,
total_count,
photos):
self.total_count = total_count
# Required
self.total_count = int(total_count)
self.photos = photos
@staticmethod
def de_json(data):
if 'photos' in data:
from telegram import PhotoSize
photos = []
for photo in data['photos']:
photos.append([PhotoSize.de_json(x) for x in photo])
else:
photos = None
"""
Args:
data (str):
return UserProfilePhotos(total_count=data.get('total_count', None),
photos=photos)
Returns:
telegram.UserProfilePhotos:
"""
if not data:
return None
upf = dict()
# Required
upf['total_count'] = data['total_count']
upf['photos'] = []
for photo in data['photos']:
upf['photos'].append([PhotoSize.de_json(x) for x in photo])
return UserProfilePhotos(**upf)
def to_dict(self):
data = {}
if self.total_count:
data['total_count'] = self.total_count
if self.photos:
data['photos'] = []
for photo in self.photos:
data['photos'].append([x.to_dict() for x in photo])
"""
Returns:
dict:
"""
data = dict()
# Required
data['total_count'] = self.total_count
data['photos'] = []
for photo in self.photos:
data['photos'].append([x.to_dict() for x in photo])
return data

View file

@ -0,0 +1,74 @@
#!/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 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/].
import json
try:
from urllib.parse import urlencode
from urllib.request import urlopen, Request
from urllib.error import HTTPError, URLError
except ImportError:
from urllib import urlencode
from urllib2 import urlopen, Request
from urllib2 import HTTPError, URLError
DEFAULT_BASE_URL = \
'https://api.botan.io/track?token=%(token)&uid=%(uid)&name=%(name)'
USER_AGENT = 'Python Telegram Bot' \
' (https://github.com/leandrotoledo/python-telegram-bot)'
CONTENT_TYPE = 'application/json'
class Botan(Object):
def __init__(self,
token,
base_url=None):
self.token = token
if base_url is None:
self.base_url = DEFAULT_BASE_URL % {'token': self.token}
else:
self.base_url = base_url % {'token': self.token}
def track(self,
uid,
text,
name = 'Message'):
url = self.base_url % {'uid': uid,
'message': text,
'name': name}
self._post(url, message)
def _post(self,
url,
data):
headers = {'User-agent': USER_AGENT,
'Content-type': CONTENT_TYPE}
try:
request = Request(
url,
data=urlencode(data).encode(),
headers=headers
)
return urlopen(request).read()
except IOError as e:
raise TelegramError(str(e))
except HTTPError as e:
raise TelegramError(str(e))

View file

@ -16,52 +16,96 @@
# 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 Video"""
from telegram import TelegramObject
from telegram import PhotoSize, TelegramObject
class Video(TelegramObject):
"""This object represents a Telegram Video.
Attributes:
file_id (str):
width (int):
height (int):
duration (int):
thumb (:class:`telegram.PhotoSize`):
mime_type (str):
file_size (int):
Args:
file_id (str):
width (int):
height (int):
duration (int):
**kwargs: Arbitrary keyword arguments.
Keyword Args:
thumb (Optional[:class:`telegram.PhotoSize`]):
mime_type (Optional[str]):
file_size (Optional[int]):
"""
def __init__(self,
file_id,
width,
height,
duration,
thumb=None,
mime_type=None,
file_size=None):
**kwargs):
# Required
self.file_id = file_id
self.width = width
self.height = height
self.duration = duration
self.thumb = thumb
self.mime_type = mime_type
self.file_size = file_size
self.width = int(width)
self.height = int(height)
self.duration = int(duration)
# Optionals
self.thumb = kwargs.get('thumb')
self.mime_type = kwargs.get('mime_type', '')
self.file_size = int(kwargs.get('file_size', 0))
@staticmethod
def de_json(data):
if 'thumb' in data:
from telegram import PhotoSize
thumb = PhotoSize.de_json(data['thumb'])
else:
thumb = None
"""
Args:
data (str):
return Video(file_id=data.get('file_id', None),
width=data.get('width', None),
height=data.get('height', None),
duration=data.get('duration', None),
thumb=thumb,
mime_type=data.get('mime_type', None),
file_size=data.get('file_size', None))
Returns:
telegram.Video:
"""
if not data:
return None
video = dict()
# Required
video['file_id'] = data['file_id']
video['width'] = data['width']
video['height'] = data['height']
video['duration'] = data['duration']
# Optionals
video['thumb'] = PhotoSize.de_json(data.get('thumb'))
video['mime_type'] = data.get('mime_type')
video['file_size'] = data.get('file_size', 0)
return Video(**video)
def to_dict(self):
data = {'file_id': self.file_id,
'width': self.width,
'height': self.height,
'duration': self.duration}
"""
Returns:
dict:
"""
data = dict()
# Required
data['file_id'] = self.file_id
data['width'] = self.width
data['height'] = self.height
data['duration'] = self.duration
# Optionals
if self.thumb:
data['thumb'] = self.thumb.to_dict()
if self.mime_type:
data['mime_type'] = self.mime_type
if self.file_size:
data['file_size'] = self.file_size
return data

View file

@ -16,34 +16,78 @@
# 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 Voice"""
from telegram import TelegramObject
class Voice(TelegramObject):
"""This object represents a Telegram Voice.
Attributes:
file_id (str):
duration (int):
mime_type (str):
file_size (int):
Args:
file_id (str):
**kwargs: Arbitrary keyword arguments.
Keyword Args:
duration (Optional[int]):
mime_type (Optional[str]):
file_size (Optional[int]):
"""
def __init__(self,
file_id,
duration=None,
mime_type=None,
file_size=None):
**kwargs):
# Required
self.file_id = file_id
self.duration = duration
self.mime_type = mime_type
self.file_size = file_size
# Optionals
self.duration = int(kwargs.get('duration', 0))
self.mime_type = kwargs.get('mime_type', '')
self.file_size = int(kwargs.get('file_size', 0))
@staticmethod
def de_json(data):
return Voice(file_id=data.get('file_id', None),
duration=data.get('duration', None),
mime_type=data.get('mime_type', None),
file_size=data.get('file_size', None))
"""
Args:
data (str):
Returns:
telegram.Voice:
"""
if not data:
return None
voice = dict()
# Required
voice['file_id'] = data['file_id']
# Optionals
voice['duration'] = data.get('duration', 0)
voice['mime_type'] = data.get('mime_type')
voice['file_size'] = data.get('file_size', 0)
return Voice(**voice)
def to_dict(self):
data = {'file_id': self.file_id}
"""
Returns:
dict:
"""
data = dict()
# Required
data['file_id'] = self.file_id
# Optionals
if self.duration:
data['duration'] = self.duration
if self.mime_type:
data['mime_type'] = self.mime_type
if self.file_size:
data['file_size'] = self.file_size
return data