Skip to content

Commit ebe7bea

Browse files
author
Pietro Albini
committed
Add support for fetching an user's avatar
This commit adds support for obtaining the current avatar for an user with the botogram.User.avatar attribute. Because executing a request for every User object when 99% of the times you don't need the avatar really kills performances, the content of the attribute is dynamically loaded the first time you access it.
1 parent 99f24a0 commit ebe7bea

File tree

3 files changed

+93
-1
lines changed

3 files changed

+93
-1
lines changed

botogram/objects/__init__.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,25 @@ class User(BaseObject, mixins.ChatMixin):
2525
"username": str,
2626
}
2727

28+
@property
29+
@mixins._require_api
30+
def avatar(self):
31+
"""Get the avatar of the user"""
32+
# This is lazy loaded and cached, so it won't affect performances if
33+
# you don't need avatars
34+
if not hasattr(self, "_avatar"):
35+
avatars = self._api.call("getUserProfilePhotos", {
36+
"user_id": self.id,
37+
"limit": 1,
38+
}, expect=UserProfilePhotos)
39+
40+
# If the user has no avatars just use None
41+
self._avatar = None
42+
if len(avatars.photos):
43+
self._avatar = avatars.photos[0] # Take the most recent one
44+
45+
return self._avatar
46+
2847

2948
class Chat(BaseObject, mixins.ChatMixin):
3049
"""Telegram API representation of a chat
@@ -234,7 +253,7 @@ class UserProfilePhotos(BaseObject):
234253

235254
required = {
236255
"total_count": int,
237-
"photos": multiple(multiple(PhotoSize)),
256+
"photos": multiple(Photo),
238257
}
239258

240259

docs/api/telegram.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,18 @@ Available Classes
6262

6363
*This attribute can be None if it's not provided by Telegram.*
6464

65+
.. py:attribute:: avatar
66+
67+
This attribute contains the user's avatar, represented as a
68+
:py:class:`~botogram.Photo` object. If the user has no avatar, this
69+
attribute will be ``None``.
70+
71+
In order to improve performances, this attribute's content is dynamically
72+
requested to Telegram the first time you access it, so there will be some
73+
delay.
74+
75+
.. versionadded:: 0.2
76+
6577
.. py:method:: send(message, [preview=True, reply_to=None, syntax=None, extra=None])
6678
6779
Send the textual *message* to the user. You may optionally stop clients

tests/test_objects.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,67 @@
1010
import botogram.objects
1111

1212

13+
def test_user_avatar(api, mock_req):
14+
mock_req({
15+
"getUserProfilePhotos": {
16+
"ok": True,
17+
"result": {
18+
"total_count": 1,
19+
"photos": [
20+
[
21+
{
22+
"file_id": "aaaaaa",
23+
"width": 50,
24+
"height": 50,
25+
"file_size": 128,
26+
},
27+
{
28+
"file_id": "bbbbbb",
29+
"width": 25,
30+
"height": 25,
31+
"file_size": 64,
32+
},
33+
],
34+
],
35+
},
36+
},
37+
})
38+
39+
# First of all, make sure the API wrapper is required to fetch avatars
40+
user = botogram.objects.User({"id": 123, "first_name": "Bob"})
41+
with pytest.raises(RuntimeError):
42+
user.avatar # Access the avatar without an API wrapper
43+
44+
# Now use an API
45+
user = botogram.objects.User({"id": 123, "first_name": "Bob"}, api)
46+
47+
# Be sure the avatar isn't loaded yet
48+
assert not hasattr(user, "_avatar")
49+
50+
# Now fetch the avatar
51+
avatar = user.avatar
52+
assert avatar.file_id == "aaaaaa"
53+
54+
# And be sure it's cached
55+
assert hasattr(user, "_avatar")
56+
assert user._avatar == avatar
57+
58+
59+
def test_user_avatar_with_no_photos(api, mock_req):
60+
mock_req({
61+
"getUserProfilePhotos": {
62+
"ok": True,
63+
"result": {
64+
"total_count": 0,
65+
"photos": [],
66+
},
67+
},
68+
})
69+
70+
user = botogram.objects.User({"id": 123, "first_name": "Bob"}, api)
71+
assert user.avatar is None
72+
73+
1374
def test_photo_object():
1475
# The Photo object is custom-made, so it's better to ensure all it's
1576
# working as expected

0 commit comments

Comments
 (0)