Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 94ed4cb

Browse files
jsmnbomtsnoam
authored andcommitted
Bot api 3.1 (python-telegram-bot#698) + minor improvements
- Added all the new and shiny features from API 3.1. - Not API 3.1 changes: - Use future.utils.string_types for string isinstance checks. - Stall between retries of test_set_webhook_get_webhook_info() & test_delete_webhook().
1 parent cbafdc2 commit 94ed4cb

File tree

11 files changed

+596
-73
lines changed

11 files changed

+596
-73
lines changed

CHANGES.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22
Changes
33
=======
44

5+
**DATE TBD**
6+
*WIP 6.2.0*
7+
- Improved filters for user_id/username/chat.
8+
- Internal restructure of files.
9+
- Improved unitests.
10+
- Fully support Bot API 3.1.
11+
512
**2017-06-18**
613

714
*Released 6.1.0*

telegram/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
from .base import TelegramObject
2222
from .user import User
23+
from .files.chatphoto import ChatPhoto
2324
from .chat import Chat
2425
from .chatmember import ChatMember
2526
from .files.photosize import PhotoSize
@@ -119,5 +120,5 @@
119120
'MAX_FILESIZE_DOWNLOAD', 'MAX_FILESIZE_UPLOAD', 'MAX_MESSAGES_PER_SECOND_PER_CHAT',
120121
'MAX_MESSAGES_PER_SECOND', 'MAX_MESSAGES_PER_MINUTE_PER_GROUP', 'WebhookInfo', 'Animation',
121122
'Game', 'GameHighScore', 'VideoNote', 'LabeledPrice', 'SuccessfulPayment', 'ShippingOption',
122-
'ShippingAddress', 'PreCheckoutQuery', 'OrderInfo', 'Invoice', 'ShippingQuery'
123+
'ShippingAddress', 'PreCheckoutQuery', 'OrderInfo', 'Invoice', 'ShippingQuery', 'ChatPhoto'
123124
]

telegram/bot.py

Lines changed: 390 additions & 5 deletions
Large diffs are not rendered by default.

telegram/chat.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
# along with this program. If not, see [http://www.gnu.org/licenses/].
2020
"""This module contains an object that represents a Telegram Chat."""
2121

22-
from telegram import TelegramObject
22+
from telegram import TelegramObject, ChatPhoto
2323

2424

2525
class Chat(TelegramObject):
@@ -33,14 +33,13 @@ class Chat(TelegramObject):
3333
first_name (str): First name of the other party in a private chat
3434
last_name (str): Last name of the other party in a private chat
3535
all_members_are_administrators (bool): True if group has 'All Members Are Administrators'
36+
photo (Optional[`telegram.ChatPhoto`]): Chat photo. Returned only in getChat.
37+
description (str): Description, for supergroups and channel chats. Returned
38+
only in getChat.
39+
invite_link (str): Chat invite link, for supergroups and channel chats. Returned
40+
only in getChat.
3641
3742
Args:
38-
id (int):
39-
type (str):
40-
title (Optional[str]):
41-
username(Optional[str]):
42-
first_name(Optional[str]):
43-
last_name(Optional[str]):
4443
bot (Optional[telegram.Bot]): The Bot to use for instance methods
4544
**kwargs (dict): Arbitrary keyword arguments.
4645
@@ -59,6 +58,9 @@ def __init__(self,
5958
last_name=None,
6059
all_members_are_administrators=None,
6160
bot=None,
61+
photo=None,
62+
description=None,
63+
invite_link=None,
6264
**kwargs):
6365
# Required
6466
self.id = int(id)
@@ -69,6 +71,9 @@ def __init__(self,
6971
self.first_name = first_name
7072
self.last_name = last_name
7173
self.all_members_are_administrators = all_members_are_administrators
74+
self.photo = photo
75+
self.description = description
76+
self.invite_link = invite_link
7277

7378
self.bot = bot
7479
self._id_attrs = (self.id,)
@@ -86,6 +91,8 @@ def de_json(data, bot):
8691
if not data:
8792
return None
8893

94+
data['photo'] = ChatPhoto.de_json(data.get('photo'), bot)
95+
8996
return Chat(bot=bot, **data)
9097

9198
def send_action(self, *args, **kwargs):

telegram/chatmember.py

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"""This module contains an object that represents a Telegram ChatMember."""
2020

2121
from telegram import User, TelegramObject
22+
from telegram.utils.helpers import to_timestamp, from_timestamp
2223

2324

2425
class ChatMember(TelegramObject):
@@ -28,10 +29,39 @@ class ChatMember(TelegramObject):
2829
user (:class:`telegram.User`): Information about the user.
2930
status (str): The member's status in the chat. Can be 'creator', 'administrator', 'member',
3031
'left' or 'kicked'.
32+
until_date (Optional[:class:`datetime.datetime`]): Restricted and kicked only. Date when
33+
restrictions will be lifted for this user.
34+
can_be_edited (Optional[boolean]): Administrators only. True, if the bot is allowed to
35+
edit administrator privileges of that user
36+
can_change_info (Optional[boolean]): Administrators only. True, if the administrator can
37+
change the chat title, photo and other settings
38+
can_post_messages (Optional[boolean]): Administrators only. True, if the administrator can
39+
post in the channel, channels only
40+
can_edit_messages (Optional[boolean]): Administrators only. True, if the administrator can
41+
edit messages of other users, channels only
42+
can_delete_messages (Optional[boolean]): Administrators only. True, if the administrator
43+
can delete messages of other user
44+
can_invite_users (Optional[boolean]): Administrators only. True, if the administrator can
45+
invite new users to the chat
46+
can_restrict_members (Optional[boolean]): Administrators only. True, if the administrator
47+
can restrict, ban or unban chat members
48+
can_pin_messages (Optional[boolean]): Administrators only. True, if the administrator can
49+
pin messages, supergroups only
50+
can_promote_members (Optional[boolean]): Administrators only. True, if the administrator
51+
can add new administrators with a subset of his own privileges or demote administrators
52+
that he has promoted, directly or indirectly (promoted by administrators that were
53+
appointed by the user)
54+
can_send_messages (Optional[boolean]): Restricted only. True, if the user can send text
55+
messages, contacts, locations and venues
56+
can_send_media_messages (Optional[boolean]): Restricted only. True, if the user can send
57+
audios, documents, photos, videos, video notes and voice notes,
58+
implies can_send_messages
59+
can_send_other_messages (Optional[boolean]): Restricted only. True, if the user can send
60+
animations, games, stickers and use inline bots, implies can_send_media_messages
61+
can_add_web_page_previews (Optional[boolean]): Restricted only. True, if user may add
62+
web page previews to his messages, implies can_send_media_messages
3163
3264
Args:
33-
user (:class:`telegram.User`):
34-
status (str):
3565
**kwargs (dict): Arbitrary keyword arguments.
3666
3767
"""
@@ -41,10 +71,30 @@ class ChatMember(TelegramObject):
4171
LEFT = 'left'
4272
KICKED = 'kicked'
4373

44-
def __init__(self, user, status, **kwargs):
74+
def __init__(self, user, status, until_date=None, can_be_edited=None,
75+
can_change_info=None, can_post_messages=None, can_edit_messages=None,
76+
can_delete_messages=None, can_invite_users=None,
77+
can_restrict_members=None, can_pin_messages=None,
78+
can_promote_members=None, can_send_messages=None,
79+
can_send_media_messages=None, can_send_other_messages=None,
80+
can_add_web_page_previews=None, **kwargs):
4581
# Required
4682
self.user = user
4783
self.status = status
84+
self.until_date = until_date
85+
self.can_be_edited = can_be_edited
86+
self.can_change_info = can_change_info
87+
self.can_post_messages = can_post_messages
88+
self.can_edit_messages = can_edit_messages
89+
self.can_delete_messages = can_delete_messages
90+
self.can_invite_users = can_invite_users
91+
self.can_restrict_members = can_restrict_members
92+
self.can_pin_messages = can_pin_messages
93+
self.can_promote_members = can_promote_members
94+
self.can_send_messages = can_send_messages
95+
self.can_send_media_messages = can_send_media_messages
96+
self.can_send_other_messages = can_send_other_messages
97+
self.can_add_web_page_previews = can_add_web_page_previews
4898

4999
self._id_attrs = (self.user, self.status)
50100

@@ -64,5 +114,17 @@ def de_json(data, bot):
64114
data = super(ChatMember, ChatMember).de_json(data, bot)
65115

66116
data['user'] = User.de_json(data.get('user'), bot)
117+
data['until_date'] = from_timestamp(data.get('until_date', None))
67118

68119
return ChatMember(**data)
120+
121+
def to_dict(self):
122+
"""
123+
Returns:
124+
dict:
125+
"""
126+
data = super(ChatMember, self).to_dict()
127+
128+
data['until_date'] = to_timestamp(self.until_date)
129+
130+
return data

telegram/ext/commandhandler.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
""" This module contains the CommandHandler class """
2020
import warnings
2121

22+
from future.utils import string_types
23+
2224
from .handler import Handler
2325
from telegram import Update
2426

@@ -80,12 +82,8 @@ def __init__(self,
8082
pass_job_queue=pass_job_queue,
8183
pass_user_data=pass_user_data,
8284
pass_chat_data=pass_chat_data)
83-
try:
84-
_str = basestring # Python 2
85-
except NameError:
86-
_str = str # Python 3
8785

88-
if isinstance(command, _str):
86+
if isinstance(command, string_types):
8987
self.command = [command.lower()]
9088
else:
9189
self.command = [x.lower() for x in command]

telegram/ext/filters.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,7 @@
1818
# along with this program. If not, see [http://www.gnu.org/licenses/].
1919
""" This module contains the Filters for use with the MessageHandler class """
2020
from telegram import Chat
21-
22-
try:
23-
str_type = base_string
24-
except NameError:
25-
str_type = str
21+
from future.utils import string_types
2622

2723

2824
class BaseFilter(object):
@@ -383,7 +379,7 @@ def __init__(self, user_id=None, username=None):
383379
self.user_ids = user_id
384380
if username is None:
385381
self.usernames = username
386-
elif isinstance(username, str_type):
382+
elif isinstance(username, string_types):
387383
self.usernames = [username.replace('@', '')]
388384
else:
389385
self.usernames = [user.replace('@', '') for user in username]
@@ -420,7 +416,7 @@ def __init__(self, chat_id=None, username=None):
420416
self.chat_ids = chat_id
421417
if username is None:
422418
self.usernames = username
423-
elif isinstance(username, str_type):
419+
elif isinstance(username, string_types):
424420
self.usernames = [username.replace('@', '')]
425421
else:
426422
self.usernames = [chat.replace('@', '') for chat in username]
@@ -460,7 +456,7 @@ class language(BaseFilter):
460456
"""
461457

462458
def __init__(self, lang):
463-
if isinstance(lang, str_type):
459+
if isinstance(lang, string_types):
464460
self.lang = [lang]
465461
else:
466462
self.lang = lang

telegram/files/chatphoto.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#!/usr/bin/env python
2+
#
3+
# A library that provides a Python interface to the Telegram Bot API
4+
# Copyright (C) 2015-2017
5+
# Leandro Toledo de Souza <[email protected]>
6+
#
7+
# This program is free software: you can redistribute it and/or modify
8+
# it under the terms of the GNU Lesser Public License as published by
9+
# the Free Software Foundation, either version 3 of the License, or
10+
# (at your option) any later version.
11+
#
12+
# This program is distributed in the hope that it will be useful,
13+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
# GNU Lesser Public License for more details.
16+
#
17+
# You should have received a copy of the GNU Lesser Public License
18+
# along with this program. If not, see [http://www.gnu.org/licenses/].
19+
"""This module contains an object that represents a Telegram ChatPhoto."""
20+
21+
from telegram import TelegramObject
22+
23+
24+
class ChatPhoto(TelegramObject):
25+
""" This object represents a Telegram ChatPhoto
26+
27+
Attributes:
28+
small_file_id (str): Unique file identifier of small (160x160) chat photo. This file_id
29+
can be used only for photo download.
30+
big_file_id (str): Unique file identifier of big (640x640) chat photo. This file_id
31+
can be used only for photo download.
32+
33+
Args:
34+
bot (Optional[telegram.Bot]): The Bot to use for instance methods
35+
**kwargs (dict): Arbitrary keyword arguments.
36+
37+
"""
38+
def __init__(self, small_file_id, big_file_id, bot=None, **kwargs):
39+
self.small_file_id = small_file_id
40+
self.big_file_id = big_file_id
41+
42+
@staticmethod
43+
def de_json(data, bot):
44+
"""
45+
Args:
46+
data (dict):
47+
bot (telegram.Bot):
48+
49+
Returns:
50+
telegram.ChatPhoto:
51+
"""
52+
if not data:
53+
return None
54+
55+
return ChatPhoto(bot=bot, **data)

telegram/message.py

Lines changed: 7 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,12 @@
1919
# along with this program. If not, see [http://www.gnu.org/licenses/].
2020
"""This module contains an object that represents a Telegram Message."""
2121
import sys
22-
from datetime import datetime
23-
from time import mktime
2422

2523
from telegram import (Audio, Contact, Document, Chat, Location, PhotoSize, Sticker, TelegramObject,
2624
User, Video, Voice, Venue, MessageEntity, Game, Invoice, SuccessfulPayment,
2725
VideoNote)
2826
from telegram.utils.deprecate import warn_deprecate_obj
29-
from telegram.utils.helpers import escape_html, escape_markdown
27+
from telegram.utils.helpers import escape_html, escape_markdown, to_timestamp, from_timestamp
3028

3129

3230
class Message(TelegramObject):
@@ -215,14 +213,14 @@ def de_json(data, bot):
215213
data = super(Message, Message).de_json(data, bot)
216214

217215
data['from_user'] = User.de_json(data.get('from'), bot)
218-
data['date'] = Message._fromtimestamp(data['date'])
216+
data['date'] = from_timestamp(data['date'])
219217
data['chat'] = Chat.de_json(data.get('chat'), bot)
220218
data['entities'] = MessageEntity.de_list(data.get('entities'), bot)
221219
data['forward_from'] = User.de_json(data.get('forward_from'), bot)
222220
data['forward_from_chat'] = Chat.de_json(data.get('forward_from_chat'), bot)
223-
data['forward_date'] = Message._fromtimestamp(data.get('forward_date'))
221+
data['forward_date'] = from_timestamp(data.get('forward_date'))
224222
data['reply_to_message'] = Message.de_json(data.get('reply_to_message'), bot)
225-
data['edit_date'] = Message._fromtimestamp(data.get('edit_date'))
223+
data['edit_date'] = from_timestamp(data.get('edit_date'))
226224
data['audio'] = Audio.de_json(data.get('audio'), bot)
227225
data['document'] = Document.de_json(data.get('document'), bot)
228226
data['game'] = Game.de_json(data.get('game'), bot)
@@ -259,12 +257,12 @@ def to_dict(self):
259257

260258
# Required
261259
data['from'] = data.pop('from_user', None)
262-
data['date'] = self._totimestamp(self.date)
260+
data['date'] = to_timestamp(self.date)
263261
# Optionals
264262
if self.forward_date:
265-
data['forward_date'] = self._totimestamp(self.forward_date)
263+
data['forward_date'] = to_timestamp(self.forward_date)
266264
if self.edit_date:
267-
data['edit_date'] = self._totimestamp(self.edit_date)
265+
data['edit_date'] = to_timestamp(self.edit_date)
268266
if self.photo:
269267
data['photo'] = [p.to_dict() for p in self.photo]
270268
if self.entities:
@@ -277,39 +275,6 @@ def to_dict(self):
277275

278276
return data
279277

280-
@staticmethod
281-
def _fromtimestamp(unixtime):
282-
"""
283-
Args:
284-
unixtime (int):
285-
286-
Returns:
287-
datetime.datetime:
288-
"""
289-
if not unixtime:
290-
return None
291-
292-
return datetime.fromtimestamp(unixtime)
293-
294-
@staticmethod
295-
def _totimestamp(dt_obj):
296-
"""
297-
Args:
298-
dt_obj (:class:`datetime.datetime`):
299-
300-
Returns:
301-
int:
302-
"""
303-
if not dt_obj:
304-
return None
305-
306-
try:
307-
# Python 3.3+
308-
return int(dt_obj.timestamp())
309-
except AttributeError:
310-
# Python 3 (< 3.3) and Python 2
311-
return int(mktime(dt_obj.timetuple()))
312-
313278
def _quote(self, kwargs):
314279
"""Modify kwargs for replying with or without quoting"""
315280

0 commit comments

Comments
 (0)