Chrunos commited on
Commit
fb41ea7
·
verified ·
1 Parent(s): 14f07fa

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +120 -72
app.py CHANGED
@@ -1,10 +1,9 @@
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,27 +12,13 @@ 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,69 +32,132 @@ def clean_url(url: str) -> Optional[str]:
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"}
 
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
  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
  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()