Skip to content

Commit 5ca93b2

Browse files
committed
Add follower and following count methods
Add PartialUser follower and following count methods.
1 parent b350ca1 commit 5ca93b2

File tree

3 files changed

+69
-14
lines changed

3 files changed

+69
-14
lines changed

docs/changelog.rst

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ Master
44
======
55
- TwitchIO
66
- Additions
7-
- Added :func:`~twitchio.Chatter.is_vip` property to Chatter
7+
- Added :attr:`~twitchio.Chatter.is_vip` property to Chatter
8+
- New PartialUser methods
9+
- :func:`~twitchio.PartialUser.fetch_follower_count` to fetch total follower count of a User
10+
- :func:`~twitchio.PartialUser.fetch_following_count` to fetch total following count of a User
11+
812
- Bug fixes
913
- Fix whispers that were not able to be parsed
1014

@@ -106,7 +110,7 @@ Massive documentation updates
106110
- Fix bug where # prefixed channel names and capitals in initial_channels would not trigger :func:`~twitchio.Client.event_ready`
107111
- Adjusted join channel rate limit handling
108112
- :func:`twitchio.PartialUser.create_clip` has been fixed by converting bool to string in http request
109-
- :func:`~twitchio.Client.fetch_cheermotes` color attribute corrected
113+
- :attr:`~twitchio.Client.fetch_cheermotes` color attribute corrected
110114
- :func:`twitchio.PartialUser.fetch_channel_teams` returns empty list if no teams found rather than unhandled error
111115
- Fix :class:`twitchio.CustomRewardRedemption` so :func:`twitchio.CustomReward.get_redemptions` returns correctly
112116

@@ -134,13 +138,13 @@ Massive documentation updates
134138

135139
- TwitchIO
136140
- Loosen aiohttp requirements to allow 3.8.1
137-
- :class:`twitchio.Stream` was missing from ``__all__``. It is now available in the twitchio namespace.
141+
- :class:`~twitchio.Stream` was missing from ``__all__``. It is now available in the twitchio namespace.
138142
- Added ``.status``, ``.reason`` and ``.extra`` to :class:`HTTPException`
139143
- Fix ``Message._timestamp`` value when tag is not provided by twitch
140-
- Fix :func:`twitchio.Client.wait_for_ready`
141-
- Remove loop= parameter inside :func:`twitchio.Client.wait_for` for 3.10 compatibility
142-
- Add ``is_broadcaster`` check to :class:`twitchio.PartialChatter`. This is accessible as ``Context.author.is_broadcaster``
143-
- :func:`twitchio.PartialUser.fetch_follow` will now return ``None`` if the FollowEvent does not exists
144+
- Fix :func:`~twitchio.Client.wait_for_ready`
145+
- Remove loop= parameter inside :func:`~twitchio.Client.wait_for` for 3.10 compatibility
146+
- Add :attr:`~twitchio.Chatter.is_broadcaster` check to :class:`~twitchio.PartialChatter`. This is accessible as ``Context.author.is_broadcaster``
147+
- :func:`~twitchio.PartialUser.fetch_follow` will now return ``None`` if the FollowEvent does not exists
144148
- TwitchIO will now correctly handle error raised when only the prefix is typed in chat
145149
- Fix paginate logic in :func:`TwitchHTTP.request`
146150

twitchio/http.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -778,15 +778,17 @@ async def delete_unfollow_channel(self, token: str, from_id: str, to_id: str):
778778
Route("DELETE", "users/follows", query=[("from_id", from_id), ("to_id", to_id)], token=token)
779779
)
780780

781-
async def get_users(self, ids: List[int], logins: List[str], token: str = None):
781+
async def get_users(self, ids: List[int], logins: List[str], token: Optional[str] = None):
782782
q = []
783783
if ids:
784784
q.extend(("id", id) for id in ids)
785785
if logins:
786786
q.extend(("login", login) for login in logins)
787787
return await self.request(Route("GET", "users", query=q, token=token))
788788

789-
async def get_user_follows(self, from_id: str = None, to_id: str = None, token: str = None):
789+
async def get_user_follows(
790+
self, from_id: Optional[str] = None, to_id: Optional[str] = None, token: Optional[str] = None
791+
):
790792
return await self.request(
791793
Route(
792794
"GET",
@@ -1069,3 +1071,17 @@ async def delete_ban_timeout_user(
10691071
):
10701072
q = [("broadcaster_id", broadcaster_id), ("moderator_id", moderator_id), ("user_id", user_id)]
10711073
return await self.request(Route("DELETE", "moderation/bans", query=q, token=token))
1074+
1075+
async def get_follow_count(
1076+
self, from_id: Optional[str] = None, to_id: Optional[str] = None, token: Optional[str] = None
1077+
):
1078+
return await self.request(
1079+
Route(
1080+
"GET",
1081+
"users/follows",
1082+
query=[x for x in [("from_id", from_id), ("to_id", to_id)] if x[1] is not None],
1083+
token=token,
1084+
),
1085+
full_body=True,
1086+
paginate=False,
1087+
)

twitchio/user.py

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ async def fetch_stream_key(self, token: str):
474474
data = await self._http.get_stream_key(token, str(self.id))
475475
return data
476476

477-
async def fetch_following(self, token: str = None) -> List["FollowEvent"]:
477+
async def fetch_following(self, token: Optional[str] = None) -> List["FollowEvent"]:
478478
"""|coro|
479479
480480
Fetches a list of users that this user is following.
@@ -493,7 +493,7 @@ async def fetch_following(self, token: str = None) -> List["FollowEvent"]:
493493
data = await self._http.get_user_follows(token=token, from_id=str(self.id))
494494
return [FollowEvent(self._http, d, from_=self) for d in data]
495495

496-
async def fetch_followers(self, token: str = None):
496+
async def fetch_followers(self, token: Optional[str] = None):
497497
"""|coro|
498498
499499
Fetches a list of users that are following this user.
@@ -509,10 +509,10 @@ async def fetch_followers(self, token: str = None):
509509
"""
510510
from .models import FollowEvent
511511

512-
data = await self._http.get_user_follows(to_id=str(self.id))
512+
data = await self._http.get_user_follows(token=token, to_id=str(self.id))
513513
return [FollowEvent(self._http, d, to=self) for d in data]
514514

515-
async def fetch_follow(self, to_user: "PartialUser", token: str = None):
515+
async def fetch_follow(self, to_user: "PartialUser", token: Optional[str] = None):
516516
"""|coro|
517517
518518
Check if a user follows another user or when they followed a user.
@@ -531,9 +531,44 @@ async def fetch_follow(self, to_user: "PartialUser", token: str = None):
531531
raise TypeError(f"to_user must be a PartialUser not {type(to_user)}")
532532
from .models import FollowEvent
533533

534-
data = await self._http.get_user_follows(from_id=str(self.id), to_id=str(to_user.id))
534+
data = await self._http.get_user_follows(token=token, from_id=str(self.id), to_id=str(to_user.id))
535535
return FollowEvent(self._http, data[0]) if data else None
536536

537+
async def fetch_follower_count(self, token: Optional[str] = None) -> int:
538+
"""|coro|
539+
540+
Fetches a list of users that are following this user.
541+
542+
Parameters
543+
-----------
544+
token: Optional[:class:`str`]
545+
An oauth token to use instead of the bots token
546+
547+
Returns
548+
--------
549+
:class:`int`
550+
"""
551+
552+
data = await self._http.get_follow_count(token=token, to_id=str(self.id))
553+
return data["total"]
554+
555+
async def fetch_following_count(self, token: Optional[str] = None) -> int:
556+
"""|coro|
557+
558+
Fetches a list of users that this user is following.
559+
560+
Parameters
561+
-----------
562+
token: Optional[:class:`str`]
563+
An oauth token to use instead of the bots token
564+
565+
Returns
566+
--------
567+
:class:`int`
568+
"""
569+
data = await self._http.get_follow_count(token=token, from_id=str(self.id))
570+
return data["total"]
571+
537572
async def follow(self, userid: int, token: str, *, notifications=False):
538573
"""|coro|
539574

0 commit comments

Comments
 (0)