Skip to content

Commit d5604e3

Browse files
committed
Get the users that likes a post
1 parent ff518e4 commit d5604e3

File tree

5 files changed

+103
-4
lines changed

5 files changed

+103
-4
lines changed

authentication_middleware.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from fastapi import Request
2+
from starlette.middleware.base import BaseHTTPMiddleware
3+
from starlette.responses import JSONResponse
4+
5+
class AuthenticationMiddleware(BaseHTTPMiddleware):
6+
def __init__(self, app, instagram_service):
7+
super().__init__(app)
8+
self.instagram_service = instagram_service
9+
10+
async def dispatch(self, request: Request, call_next):
11+
if request.url.path == "/v1/api/media_likers":
12+
username = request.query_params.get("username")
13+
if not username or not self.instagram_service.get_client(username):
14+
return JSONResponse(
15+
status_code=401,
16+
content={"message": "Authentication required. Please login first using the /v1/api/login endpoint."}
17+
)
18+
response = await call_next(request)
19+
return response

instagram_service.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from instagrapi import Client
2+
from instagrapi.types import UserShort
3+
from typing import Optional
4+
5+
class InstagramService:
6+
def __init__(self):
7+
self.clients = {}
8+
9+
def login(self, username: str, password: str) -> str:
10+
client = Client()
11+
client.login(username, password)
12+
self.clients[username] = client
13+
return username
14+
15+
def get_client(self, username: str) -> Optional[Client]:
16+
return self.clients.get(username)
17+
18+
def get_media_likers(self, username: str, media_id: str):
19+
client = self.get_client(username)
20+
if client:
21+
likers = client.media_likers(media_id)
22+
return [self.user_short_to_dict(liker) for liker in likers]
23+
else:
24+
return None
25+
26+
def user_short_to_dict(self, user_short: UserShort):
27+
return {
28+
"pk": user_short.pk,
29+
"username": user_short.username,
30+
"full_name": user_short.full_name,
31+
}
32+
33+
instagram_service = InstagramService()

main.py

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,41 @@
11
from fastapi import FastAPI, HTTPException, Query
22
from fastapi.responses import JSONResponse
33
from starlette.middleware import Middleware
4-
from middleware import TimeoutMiddleware
4+
from time_middleware import TimeoutMiddleware
55
from typing import Optional
6+
from pydantic import BaseModel
67

78
# Import the functions from the other scripts
89
from profile_data import retrieve_profile_info
910
from user_post import retrieve_post_metrics
1011
from media import get_post_details
1112

13+
# Import the Instagram service
14+
from instagram_service import instagram_service
15+
from authentication_middleware import AuthenticationMiddleware
16+
17+
class Credentials(BaseModel):
18+
username: str
19+
password: str
20+
1221
app = FastAPI(middleware=[
13-
Middleware(TimeoutMiddleware, timeout=600)
22+
Middleware(TimeoutMiddleware, timeout=600),
23+
Middleware(AuthenticationMiddleware, instagram_service=instagram_service)
1424
])
1525

26+
27+
@app.post('/v1/api/login')
28+
def login(credentials: Credentials):
29+
try:
30+
username = instagram_service.login(credentials.username, credentials.password)
31+
return JSONResponse(content={"meassege": "Login Successful", "username": username})
32+
except Exception as e:
33+
raise HTTPException(
34+
status_code=500,
35+
detail=str(e)
36+
)
37+
38+
1639
@app.get('/v1/api/profile')
1740
def profile_info(username: str = Query(..., description="Username of the profile to retrieve")):
1841
try:
@@ -30,8 +53,8 @@ def profile_info(username: str = Query(..., description="Username of the profile
3053
@app.get('/v1/api/user_posts')
3154
def user_posts(
3255
username: str = Query(..., description="Username to retrieve posts for"),
33-
from_date: Optional[str] = Query(None, description="Start date for post retrieval (YYYY-MM-DD)"),
34-
to_date: Optional[str] = Query(None, description="End date for post retrieval (YYYY-MM-DD)")
56+
from_date: Optional[str] = Query(None, description="Start date for post retrieval (YYYY-MM-DD), Optional"),
57+
to_date: Optional[str] = Query(None, description="End date for post retrieval (YYYY-MM-DD), Optional")
3558
):
3659
try:
3760
posts = retrieve_post_metrics(username, from_date, to_date)
@@ -57,6 +80,29 @@ def media_posts(url: str = Query(..., description="URL of the media to retrieve
5780
except Exception as e:
5881
raise HTTPException(status_code=500, detail=str(e))
5982

83+
84+
85+
@app.get('/v1/api/media_likers')
86+
def media_likers(
87+
media_id: str = Query(..., description="media_id = {post_id}_{owner_id} to retrieve likers for the post"),
88+
username: str = Query(..., description="Username of the logged-in user")
89+
):
90+
try:
91+
likers = instagram_service.get_media_likers(username, media_id)
92+
if not likers:
93+
raise HTTPException(
94+
status_code=404,
95+
detail="Likers for this media not found"
96+
)
97+
return JSONResponse(content=likers)
98+
except HTTPException as e:
99+
raise e
100+
except Exception as e:
101+
raise HTTPException(
102+
status_code=500,
103+
detail=str(e)
104+
)
105+
60106
if __name__ == '__main__':
61107
import uvicorn
62108
uvicorn.run(app, host="127.0.0.1", port=8000, log_level="debug")

profile_data.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ def retrieve_profile_info(username: str):
2424
# Access profile details
2525
profile_info = {
2626
'user_info':{
27+
'uniqueID': profile.userid,
2728
'Username': profile.username,
2829
'Full_Name': profile.full_name,
2930
'Followers': profile.followers,
File renamed without changes.

0 commit comments

Comments
 (0)