Chrunos commited on
Commit
0efafe8
·
verified ·
1 Parent(s): a1b5d59

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +82 -4
app.py CHANGED
@@ -1,5 +1,7 @@
1
  from fastapi import FastAPI, HTTPException, status
 
2
  import instaloader
 
3
  import os
4
  import time
5
  import logging
@@ -169,13 +171,26 @@ async def get_stories(username: str):
169
  try:
170
  for story in L.get_stories(userids=[profile.userid]):
171
  for item in story.get_items():
172
- stories.append({
 
173
  "id": str(item.mediaid),
174
  "url": item.url,
175
  "type": "video" if item.is_video else "image",
176
  "timestamp": item.date_utc.isoformat(),
177
- "views": item.view_count if item.is_video else None,
178
- })
 
 
 
 
 
 
 
 
 
 
 
 
179
  except instaloader.exceptions.QueryReturnedNotFoundException:
180
  logger.error("Stories not found")
181
  raise HTTPException(
@@ -198,4 +213,67 @@ async def get_stories(username: str):
198
 
199
  except Exception as e:
200
  logger.error(f"Critical failure: {str(e)}")
201
- raise
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  from fastapi import FastAPI, HTTPException, status
2
+ from fastapi.responses import StreamingResponse
3
  import instaloader
4
+ import requests
5
  import os
6
  import time
7
  import logging
 
171
  try:
172
  for story in L.get_stories(userids=[profile.userid]):
173
  for item in story.get_items():
174
+ # Create a story dict with safe attribute access
175
+ story_data = {
176
  "id": str(item.mediaid),
177
  "url": item.url,
178
  "type": "video" if item.is_video else "image",
179
  "timestamp": item.date_utc.isoformat(),
180
+ }
181
+
182
+ # Only try to add view_count if it's a video and the attribute exists
183
+ if item.is_video:
184
+ try:
185
+ # Safely check if view_count attribute exists
186
+ if hasattr(item, 'view_count'):
187
+ story_data["views"] = item.view_count
188
+ except AttributeError:
189
+ # Skip adding views if the attribute doesn't exist
190
+ pass
191
+
192
+ stories.append(story_data)
193
+
194
  except instaloader.exceptions.QueryReturnedNotFoundException:
195
  logger.error("Stories not found")
196
  raise HTTPException(
 
213
 
214
  except Exception as e:
215
  logger.error(f"Critical failure: {str(e)}")
216
+ raise
217
+
218
+ @app.get("/download/{url:path}")
219
+ @handle_instagram_errors
220
+ async def download_media(url: str):
221
+ """Download and proxy media content"""
222
+ logger.info(f"Download request for: {url}")
223
+
224
+ try:
225
+ # Basic validation to prevent arbitrary URL access
226
+ if not url.startswith(("https://instagram", "https://scontent")):
227
+ raise HTTPException(
228
+ status_code=status.HTTP_400_BAD_REQUEST,
229
+ detail="Invalid URL format"
230
+ )
231
+
232
+ # Random delay to avoid detection patterns
233
+ time.sleep(random.uniform(1.0, 3.0))
234
+
235
+ # Configure headers to mimic a browser
236
+ headers = {
237
+ "User-Agent": random.choice(USER_AGENTS),
238
+ "Accept": "*/*",
239
+ "Accept-Language": "en-US,en;q=0.9",
240
+ "Referer": "https://www.instagram.com/",
241
+ "Sec-Fetch-Dest": "empty",
242
+ "Sec-Fetch-Mode": "cors",
243
+ "Sec-Fetch-Site": "cross-site",
244
+ }
245
+
246
+ # Request the media with a session
247
+ response = requests.get(url, headers=headers, stream=True, timeout=30)
248
+ response.raise_for_status()
249
+
250
+ # Determine content type from response or URL
251
+ if "Content-Type" in response.headers:
252
+ content_type = response.headers["Content-Type"]
253
+ elif url.endswith((".jpg", ".jpeg")):
254
+ content_type = "image/jpeg"
255
+ elif url.endswith(".mp4"):
256
+ content_type = "video/mp4"
257
+ else:
258
+ content_type = "application/octet-stream"
259
+
260
+ logger.info(f"Media downloaded successfully: {content_type}")
261
+
262
+ # Stream the response back
263
+ return StreamingResponse(
264
+ response.iter_content(chunk_size=8192),
265
+ media_type=content_type,
266
+ headers={
267
+ "Content-Disposition": f"attachment; filename={url.split('/')[-1]}",
268
+ "Cache-Control": "no-cache, no-store, must-revalidate",
269
+ "Pragma": "no-cache",
270
+ "Expires": "0",
271
+ }
272
+ )
273
+
274
+ except requests.exceptions.RequestException as e:
275
+ logger.error(f"Download failed: {str(e)}")
276
+ raise HTTPException(
277
+ status_code=status.HTTP_502_BAD_GATEWAY,
278
+ detail="Failed to download media"
279
+ )