Skip to content

Commit 2c7fb98

Browse files
author
Pietro Albini
committed
Add the Chat.admins dynamic attribute
This new attribute returns the list of the administrators of the group chat, fetching it from a new API introduced by the Bot API 2.1 update. Issue: GH-64
1 parent e8050c3 commit 2c7fb98

File tree

3 files changed

+88
-0
lines changed

3 files changed

+88
-0
lines changed

botogram/objects/chats.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,22 @@ class Chat(BaseObject, mixins.ChatMixin):
9393
}
9494
_check_equality_ = "id"
9595

96+
def _to_user(self):
97+
"""Convert this Chat object to an User object"""
98+
if self.type != "private":
99+
raise TypeError("This method works only on private chats!")
100+
101+
# Be sure to cache the instance
102+
if not hasattr(self, "_cache_user"):
103+
self._cache_user = User({
104+
"id": self.id,
105+
"first_name": self.first_name,
106+
"last_name": self.last_name,
107+
"username": self.username,
108+
}, self._api)
109+
110+
return self._cache_user
111+
96112
@property
97113
def name(self):
98114
"""Get the full name of the chat"""
@@ -107,6 +123,27 @@ def name(self):
107123

108124
return result
109125

126+
@property
127+
def admins(self):
128+
"""Get a list of the admins of the chat"""
129+
# If this is a private chat, return the current user since Telegram
130+
# doesn't support `getChatAdministrators` for private chats
131+
if self.type == "private":
132+
return [self._to_user()]
133+
elif self.type == "channel":
134+
raise TypeError("Not available on channels")
135+
136+
# Be sure to cache the list of the admins
137+
if not hasattr(self, "_cache_admins"):
138+
members = self._api.call("getChatAdministrators",
139+
{"chat_id": self.id},
140+
expect=multiple(ChatMember))
141+
self._cache_admins = tuple(member.user for member in members)
142+
143+
# The list of admins is saved as a tuple, so it's not mutable, but it's
144+
# returned as a list (the tuple thing is an implementation detail)
145+
return list(self._cache_admins)
146+
110147
def leave(self):
111148
"""Leave this chat"""
112149
if self.type not in ("group", "supergroup"):
@@ -122,6 +159,19 @@ def leave(self):
122159
raise
123160

124161

162+
class ChatMember(BaseObject):
163+
"""Telegram API representation of a chat member
164+
165+
https://core.telegram.org/bots/api#chatmember
166+
"""
167+
168+
required = {
169+
"user": User,
170+
"status": str,
171+
}
172+
_check_equality_ = "user"
173+
174+
125175
class UserProfilePhotos(BaseObject):
126176
"""Telegram API representation of an user's profile photos
127177

docs/api/telegram.rst

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,43 @@ about its business.
370370

371371
.. versionadded:: 0.2
372372

373+
.. py:attribute:: admins
374+
375+
The list of the administrators of the group (or supergroup), represented
376+
as a list of :py:class:`~botogram.User`. If the chat is a private chat, a
377+
list containing only the chat partner is returned. Instead, a
378+
``TypeError`` is raised if the chat is a channel.
379+
380+
Please remember the content of this attribute is fetched from Telegram
381+
the first time you access it (so it might be slow), but it's cached right
382+
after, so the following accesses will involve no network communication.
383+
384+
.. code-block:: python
385+
:emphasize-lines: 14,15,16
386+
387+
# This hook bans a member of the group if an admin replies to one of
388+
# its messages with "#ban"
389+
390+
@bot.process_message
391+
def ban_users(chat, message):
392+
# Allow only groups
393+
if message.type not in ("group", "supergroup"):
394+
return
395+
396+
# Allow only replies with text in the reply
397+
if message.text is None or message.reply_to_message is None:
398+
return
399+
400+
# Allow only admins to ban people
401+
if message.sender not in chat.admins:
402+
return
403+
404+
# Match the text and ban the original message sender
405+
if message.text == "#ban":
406+
chat.ban(message.reply_to_message.sender)
407+
408+
.. versionadded:: 0.3
409+
373410
.. py:method:: leave()
374411
375412
Kick the bot from this chat. This method is available only on groups and

docs/changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ New features
4747

4848
* Added new attribute :py:attr:`botogram.Message.pinned_message`
4949
* Added new attribute :py:attr:`botogram.Sticker.emoji`
50+
* Added new attribute :py:attr:`botogram.Chat.admins`
5051
* Added new method :py:meth:`botogram.Chat.leave`
5152
* Every method which sends something to a chat now returns the sent
5253
:py:class:`~botogram.Message`

0 commit comments

Comments
 (0)