Chrunos commited on
Commit
172aea3
·
verified ·
1 Parent(s): b71ab68

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +72 -120
app.py CHANGED
@@ -1,9 +1,10 @@
1
- import streamlit as st
 
2
  import instaloader
3
  import os
4
  from dotenv import load_dotenv
5
  import re
6
- import requests
7
 
8
  # Load environment variables
9
  load_dotenv()
@@ -12,13 +13,27 @@ load_dotenv()
12
  INSTAGRAM_USERNAME = os.getenv('INSTAGRAM_USERNAME')
13
  INSTAGRAM_PASSWORD = os.getenv('INSTAGRAM_PASSWORD')
14
 
15
- def clean_url(url):
 
 
 
 
 
 
 
 
 
 
 
 
16
  """Clean Instagram URL and extract shortcode"""
17
  try:
18
  cleaned_url = url.split('?')[0].split('#')[0].strip('/')
19
  patterns = [
20
  r'instagram.com/reel/([A-Za-z0-9_-]+)',
21
  r'instagram.com/p/([A-Za-z0-9_-]+)',
 
 
22
  r'/([A-Za-z0-9_-]{11})[/]?$'
23
  ]
24
 
@@ -32,132 +47,69 @@ def clean_url(url):
32
  return segments[-1]
33
 
34
  return None
35
- except Exception as e:
36
- st.error(f"Error cleaning URL: {str(e)}")
37
  return None
38
 
39
- def download_file(url, path):
40
- """Download file from URL with progress bar"""
41
- try:
42
- response = requests.get(url, stream=True)
43
- response.raise_for_status()
44
-
45
- file_size = int(response.headers.get('content-length', 0))
46
- progress_bar = st.progress(0)
47
-
48
- with open(path, 'wb') as f:
49
- if file_size == 0:
50
- f.write(response.content)
51
- else:
52
- downloaded = 0
53
- for chunk in response.iter_content(chunk_size=8192):
54
- if chunk:
55
- f.write(chunk)
56
- downloaded += len(chunk)
57
- progress = int((downloaded / file_size) * 100)
58
- progress_bar.progress(progress)
59
-
60
- return True
61
- except Exception as e:
62
- st.error(f"Download error: {str(e)}")
63
- return False
64
-
65
- def download_reel(url):
66
- """Download Instagram reel"""
67
- if not url:
68
- return None, "Please enter a URL"
69
-
70
- shortcode = clean_url(url)
71
- if not shortcode:
72
- return None, "Could not extract valid shortcode from URL"
73
-
74
- st.info(f"Extracted shortcode: {shortcode}")
75
-
76
- loader = instaloader.Instaloader(
77
- download_videos=True,
78
- download_video_thumbnails=False,
79
- download_geotags=False,
80
- download_comments=False,
81
- save_metadata=False,
82
- compress_json=False
83
- )
84
 
 
 
 
85
  try:
86
- if INSTAGRAM_USERNAME and INSTAGRAM_PASSWORD:
87
- st.info(f"Logging in as {INSTAGRAM_USERNAME}...")
88
- loader.login(INSTAGRAM_USERNAME, INSTAGRAM_PASSWORD)
89
- st.success("Login successful!")
90
- else:
91
- return None, "Missing Instagram credentials"
92
-
93
- download_path = os.path.join('reels', shortcode)
94
- os.makedirs(download_path, exist_ok=True)
 
 
 
 
 
 
 
 
 
95
 
96
- st.info("Fetching post metadata...")
 
 
97
  post = instaloader.Post.from_shortcode(loader.context, shortcode)
98
 
 
 
99
  if post.is_video:
100
- video_url = post.video_url
101
- video_path = os.path.join(download_path, f"{shortcode}.mp4")
102
- st.info("Starting download...")
103
-
104
- if download_file(video_url, video_path):
105
- if os.path.exists(video_path):
106
- size = os.path.getsize(video_path)
107
- if size > 0:
108
- return video_path, f"Download successful! Size: {size/1024/1024:.2f} MB"
109
- else:
110
- return None, "Download failed: File is empty"
111
- else:
112
- return None, "Download failed: File not created"
113
- else:
114
- return None, "Failed to download video file"
115
  else:
116
- return None, "Post is not a video"
117
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  except instaloader.exceptions.InstaloaderException as e:
119
- return None, f"Instagram error: {str(e)}"
120
  except Exception as e:
121
- return None, f"Unexpected error: {str(e)}"
122
-
123
- def main():
124
- st.set_page_config(
125
- page_title="Instagram Reel Downloader",
126
- page_icon="📱",
127
- initial_sidebar_state="collapsed"
128
- )
129
-
130
- st.title('📱 Instagram Reel Downloader')
131
-
132
- st.markdown("""
133
- ### Instructions:
134
- 1. Enter the Instagram reel URL
135
- 2. Click 'Download Reel'
136
- 3. After successful download, click 'Download Video' button to save the file
137
- """)
138
-
139
- # Input for Reel URL
140
- url = st.text_input('Enter the Instagram Reel URL',
141
- placeholder='https://www.instagram.com/reel/XXXXXXXXXXXX')
142
-
143
- # Download button
144
- if st.button('Download Reel', type='primary'):
145
- if url:
146
- with st.spinner('Processing...'):
147
- file_path, message = download_reel(url)
148
- st.write(message)
149
-
150
- # If download was successful, show download button
151
- if file_path and os.path.exists(file_path):
152
- with open(file_path, 'rb') as file:
153
- st.download_button(
154
- label="Download Video",
155
- data=file,
156
- file_name=os.path.basename(file_path),
157
- mime="video/mp4"
158
- )
159
- else:
160
- st.warning('Please enter a URL.')
161
 
162
- if __name__ == "__main__":
163
- main()
 
 
1
+ from fastapi import FastAPI, HTTPException
2
+ from pydantic import BaseModel
3
  import instaloader
4
  import os
5
  from dotenv import load_dotenv
6
  import re
7
+ from typing import Optional, List
8
 
9
  # Load environment variables
10
  load_dotenv()
 
13
  INSTAGRAM_USERNAME = os.getenv('INSTAGRAM_USERNAME')
14
  INSTAGRAM_PASSWORD = os.getenv('INSTAGRAM_PASSWORD')
15
 
16
+ app = FastAPI()
17
+
18
+ class DownloadRequest(BaseModel):
19
+ url: str
20
+
21
+ class DownloadResponse(BaseModel):
22
+ success: bool
23
+ message: str
24
+ urls: Optional[List[str]] = None
25
+ type: Optional[str] = None
26
+ shortcode: Optional[str] = None
27
+
28
+ def clean_url(url: str) -> Optional[str]:
29
  """Clean Instagram URL and extract shortcode"""
30
  try:
31
  cleaned_url = url.split('?')[0].split('#')[0].strip('/')
32
  patterns = [
33
  r'instagram.com/reel/([A-Za-z0-9_-]+)',
34
  r'instagram.com/p/([A-Za-z0-9_-]+)',
35
+ r'instagram.com/stories/([A-Za-z0-9_-]+)',
36
+ r'instagram.com/tv/([A-Za-z0-9_-]+)',
37
  r'/([A-Za-z0-9_-]{11})[/]?$'
38
  ]
39
 
 
47
  return segments[-1]
48
 
49
  return None
50
+ except Exception:
 
51
  return None
52
 
53
+ @app.get('/')
54
+ def main():
55
+ return {"appStatus": "running"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
 
57
+
58
+ @app.post("/api/download", response_model=DownloadResponse)
59
+ async def download_media(request: DownloadRequest):
60
  try:
61
+ # Extract shortcode
62
+ shortcode = clean_url(request.url)
63
+ if not shortcode:
64
+ raise HTTPException(status_code=400, detail="Invalid URL format")
65
+
66
+ # Initialize loader
67
+ loader = instaloader.Instaloader(
68
+ download_videos=True,
69
+ download_video_thumbnails=False,
70
+ download_geotags=False,
71
+ download_comments=False,
72
+ save_metadata=False,
73
+ compress_json=False
74
+ )
75
+
76
+ # Login
77
+ if not all([INSTAGRAM_USERNAME, INSTAGRAM_PASSWORD]):
78
+ raise HTTPException(status_code=500, detail="Missing Instagram credentials")
79
 
80
+ loader.login(INSTAGRAM_USERNAME, INSTAGRAM_PASSWORD)
81
+
82
+ # Get post
83
  post = instaloader.Post.from_shortcode(loader.context, shortcode)
84
 
85
+ urls = []
86
+
87
  if post.is_video:
88
+ media_type = "video"
89
+ urls.append(post.video_url)
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  else:
91
+ media_type = "image"
92
+ if post.typename == "GraphSidecar":
93
+ # Multiple images
94
+ for node in post.get_sidecar_nodes():
95
+ urls.append(node.display_url)
96
+ else:
97
+ # Single image
98
+ urls.append(post.url)
99
+
100
+ return DownloadResponse(
101
+ success=True,
102
+ message="Media URLs retrieved successfully",
103
+ urls=urls,
104
+ type=media_type,
105
+ shortcode=shortcode
106
+ )
107
+
108
  except instaloader.exceptions.InstaloaderException as e:
109
+ raise HTTPException(status_code=400, detail=str(e))
110
  except Exception as e:
111
+ raise HTTPException(status_code=500, detail=str(e))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
 
113
+ @app.get("/api/health")
114
+ async def health_check():
115
+ return {"status": "healthy"}