Skip to content

Commit a84fa7b

Browse files
committed
added followers() and followings() to Mobile.py
1 parent 0c1f497 commit a84fa7b

13 files changed

+253
-4
lines changed

ensta/Mobile.py

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
import datetime
99
import json
1010
from .parser.ProfileParser import parse_profile
11-
from .structures import Profile, StoryLink
11+
from .parser.FollowersParser import parse_followers
12+
from .parser.FollowingsParser import parse_followings
13+
from .structures import Profile, StoryLink, Followers, Followings
1214
from .Direct import Direct
1315
from ensta.Utils import time_id, fb_uploader
1416

@@ -699,3 +701,72 @@ def unlike(self, media_id: str) -> bool:
699701
"Unable to unlike media. Maybe try using another account, switch "
700702
"to a different network, or use reputed proxies."
701703
)
704+
705+
def followers(self, identifier: str, next_cursor: str | int | None = None) -> Followers:
706+
"""
707+
Get followers list of an account
708+
:param: identifier: Username or UserID (UserID Recommended)
709+
:return: Followers Object
710+
"""
711+
712+
next_cursor: str = str(next_cursor) if next_cursor is not None else None
713+
user_id: str = self.profile(identifier).user_id
714+
max_id_line: str = f"&max_id={next_cursor}" if next_cursor is not None else ""
715+
716+
response: Response = self.session.get(
717+
url=f"https://i.instagram.com/api/v1/friendships/{user_id}/followers/?enable_groups=true{max_id_line}"
718+
)
719+
720+
try:
721+
response_dict: dict = response.json()
722+
723+
if response_dict.get("status", "") != "ok":
724+
raise NetworkError(
725+
"Response status was not ok.\n"
726+
f"Response Dict: {response_dict}"
727+
)
728+
729+
return parse_followers(response_dict)
730+
731+
except JSONDecodeError:
732+
raise NetworkError(
733+
"Unable to get followers list. Make sure either the account is public or you're "
734+
"already following the target user. Also, make sure the user hasn't blocked or "
735+
"restricted you. Try using another account, switch "
736+
"to a different network, or use reputed proxies."
737+
)
738+
739+
def followings(self, identifier: str, next_cursor: str | int | None = None) -> Followings:
740+
"""
741+
Get followings list of an account
742+
:param: identifier: Username or UserID (UserID Recommended)
743+
:return: Followings Object
744+
"""
745+
746+
next_cursor: str = str(next_cursor) if next_cursor is not None else None
747+
user_id: str = self.profile(identifier).user_id
748+
max_id_line: str = f"&max_id={next_cursor}" if next_cursor is not None else ""
749+
750+
response: Response = self.session.get(
751+
url=f"https://i.instagram.com/api/v1/friendships/{user_id}/following/?enable_groups=true"
752+
f"&includes_hashtags=true{max_id_line}"
753+
)
754+
755+
try:
756+
response_dict: dict = response.json()
757+
758+
if response_dict.get("status", "") != "ok":
759+
raise NetworkError(
760+
"Response status was not ok.\n"
761+
f"Response Dict: {response_dict}"
762+
)
763+
764+
return parse_followings(response_dict)
765+
766+
except JSONDecodeError:
767+
raise NetworkError(
768+
"Unable to get followings list. Make sure either the account is public or you're "
769+
"already following the target user. Also, make sure the user hasn't blocked or "
770+
"restricted you. Try using another account, switch "
771+
"to a different network, or use reputed proxies."
772+
)

ensta/parser/FollowersListParser.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
from ensta.structures.Follower import Follower
2+
3+
4+
def parse_followers_list(items: list[dict]) -> list[Follower]:
5+
6+
followers = list()
7+
8+
for item in items:
9+
10+
followers.append(
11+
Follower(
12+
user_id=str(item.get("pk")),
13+
username=item.get("username"),
14+
full_name=item.get("full_name"),
15+
is_private=item.get("is_private"),
16+
fbid_v2=item.get("fbid_v2"),
17+
third_party_downloads_enabled=item.get("third_party_downloads_enabled"),
18+
profile_picture_id=item.get("profile_pic_id"),
19+
profile_picture_url=item.get("profile_pic_url"),
20+
is_verified=item.get("is_verified"),
21+
has_anonymous_profile_picture=item.get("has_anonymous_profile_picture"),
22+
latest_reel_media=item.get("latest_reel_media")
23+
)
24+
)
25+
26+
return followers

ensta/parser/FollowersParser.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from ensta.structures.Followers import Followers
2+
from ensta.structures.Follower import Follower
3+
from .FollowersListParser import parse_followers_list
4+
5+
6+
def parse_followers(information: dict) -> Followers:
7+
8+
followers_list: list[Follower] = parse_followers_list(information.get("users"))
9+
10+
return Followers(
11+
list=followers_list,
12+
next_cursor=information.get("next_max_id"),
13+
big_list=information.get("big_list"),
14+
list_length=information.get("page_size"),
15+
has_more=information.get("has_more"),
16+
should_limit_list_of_followers=information.get("should_limit_list_of_followers"),
17+
use_clickable_see_more=information.get("use_clickable_see_more"),
18+
show_spam_follow_request_tab=information.get("show_spam_follow_request_tab")
19+
)

ensta/parser/FollowingsListParser.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from ensta.structures.Following import Following
2+
3+
4+
def parse_followings_list(items: list[dict]) -> list[Following]:
5+
6+
followings = list()
7+
8+
for item in items:
9+
10+
followings.append(
11+
Following(
12+
user_id=str(item.get("pk")),
13+
username=item.get("username"),
14+
full_name=item.get("full_name"),
15+
is_private=item.get("is_private"),
16+
fbid_v2=item.get("fbid_v2"),
17+
third_party_downloads_enabled=item.get("third_party_downloads_enabled"),
18+
profile_picture_id=item.get("profile_pic_id"),
19+
profile_picture_url=item.get("profile_pic_url"),
20+
is_verified=item.get("is_verified"),
21+
has_anonymous_profile_picture=item.get("has_anonymous_profile_picture"),
22+
latest_reel_media=item.get("latest_reel_media"),
23+
is_favorite=item.get("is_favorite")
24+
)
25+
)
26+
27+
return followings

ensta/parser/FollowingsParser.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from ensta.structures.Followings import Followings
2+
from ensta.structures.Following import Following
3+
from .FollowingsListParser import parse_followings_list
4+
5+
6+
def parse_followings(information: dict) -> Followings:
7+
8+
followings_list: list[Following] = parse_followings_list(information.get("users"))
9+
10+
return Followings(
11+
list=followings_list,
12+
next_cursor=information.get("next_max_id"),
13+
big_list=information.get("big_list"),
14+
list_length=information.get("page_size"),
15+
hashtag_count=information.get("hashtag_count"),
16+
has_more=information.get("has_more"),
17+
should_limit_list_of_followers=information.get("should_limit_list_of_followers"),
18+
use_clickable_see_more=information.get("use_clickable_see_more"),
19+
)

ensta/parser/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
from .BiographyLinkParser import parse_biography_link
22
from .ProfileParser import parse_profile
3+
from .FollowersParser import parse_followers
4+
from .FollowingsParser import parse_followings
5+
from .FollowersListParser import parse_followers_list
6+
from .FollowingsListParser import parse_followings_list

ensta/structures/Follower.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from dataclasses import dataclass
2+
3+
4+
@dataclass
5+
class Follower:
6+
7+
"""
8+
Stores single follower information e.g. - Full Name, Username, Profile Picture Url, etc.
9+
"""
10+
11+
user_id: str
12+
username: str
13+
full_name: str
14+
is_private: bool
15+
fbid_v2: str
16+
third_party_downloads_enabled: int
17+
profile_picture_id: str
18+
profile_picture_url: str
19+
is_verified: bool
20+
has_anonymous_profile_picture: bool
21+
latest_reel_media: int

ensta/structures/Followers.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from dataclasses import dataclass
2+
from .Follower import Follower
3+
4+
5+
@dataclass
6+
class Followers:
7+
8+
"""
9+
Stores fetched followers information e.g. - List, Next Cursor, List Length, etc.
10+
"""
11+
12+
list: list[Follower]
13+
next_cursor: int
14+
big_list: bool
15+
list_length: int
16+
has_more: bool
17+
should_limit_list_of_followers: bool
18+
use_clickable_see_more: bool
19+
show_spam_follow_request_tab: bool

ensta/structures/Following.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from dataclasses import dataclass
2+
3+
4+
@dataclass
5+
class Following:
6+
7+
"""
8+
Stores single following information e.g. - Full Name, Username, Profile Picture Url, etc.
9+
"""
10+
11+
user_id: str
12+
username: str
13+
full_name: str
14+
is_private: bool
15+
fbid_v2: str
16+
third_party_downloads_enabled: int
17+
profile_picture_id: str
18+
profile_picture_url: str
19+
is_verified: bool
20+
has_anonymous_profile_picture: bool
21+
latest_reel_media: int
22+
is_favorite: bool

ensta/structures/Followings.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from dataclasses import dataclass
2+
from .Following import Following
3+
4+
5+
@dataclass
6+
class Followings:
7+
8+
"""
9+
Stores fetched followings information e.g. - List, Next Cursor, List Length, etc.
10+
"""
11+
12+
list: list[Following]
13+
next_cursor: int
14+
big_list: bool
15+
list_length: int
16+
hashtag_count: int
17+
has_more: bool
18+
should_limit_list_of_followers: bool
19+
use_clickable_see_more: bool

0 commit comments

Comments
 (0)