nakas commited on
Commit
f3e8aa7
·
verified ·
1 Parent(s): 98e5133

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +324 -5
app.py CHANGED
@@ -1,17 +1,336 @@
 
 
 
1
  import subprocess
2
  import sys
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
  def download_playwright_browsers():
 
 
 
 
 
 
5
  try:
6
  print("Installing Playwright browsers...")
7
- result = subprocess.run([sys.executable, "-m", "playwright", "install", "chromium"],
8
- capture_output=True,
9
- text=True)
 
 
 
 
 
 
 
 
 
10
  print("Installation output:", result.stdout)
11
  if result.stderr:
12
  print("Installation errors:", result.stderr)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  except Exception as e:
14
- print(f"Error installing browsers: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
 
16
  if __name__ == "__main__":
17
- download_playwright_browsers()
 
 
 
 
 
1
+ import gradio as gr
2
+ import time
3
+ import os
4
  import subprocess
5
  import sys
6
+ from PIL import Image
7
+ import io
8
+ import base64
9
+ import logging
10
+ import traceback
11
+ from datetime import datetime
12
+
13
+ # Configure logging
14
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
15
+ logger = logging.getLogger(__name__)
16
+
17
+ # Create screenshots directory if it doesn't exist
18
+ os.makedirs('screenshots', exist_ok=True)
19
+
20
+ # Global variable to track browser installation
21
+ BROWSERS_INSTALLED = False
22
 
23
  def download_playwright_browsers():
24
+ """Download and install Playwright browsers"""
25
+ global BROWSERS_INSTALLED
26
+
27
+ if BROWSERS_INSTALLED:
28
+ return "Playwright browsers already installed."
29
+
30
  try:
31
  print("Installing Playwright browsers...")
32
+
33
+ # First install playwright itself if needed
34
+ subprocess.run([sys.executable, "-m", "pip", "install", "playwright==1.39.0"], check=True)
35
+
36
+ # Then install the browsers
37
+ result = subprocess.run(
38
+ [sys.executable, "-m", "playwright", "install", "chromium"],
39
+ check=True,
40
+ capture_output=True,
41
+ text=True
42
+ )
43
+
44
  print("Installation output:", result.stdout)
45
  if result.stderr:
46
  print("Installation errors:", result.stderr)
47
+
48
+ BROWSERS_INSTALLED = True
49
+ return "Playwright browsers installed successfully."
50
+ except Exception as e:
51
+ error_msg = f"Error installing browsers: {str(e)}"
52
+ print(error_msg)
53
+ return error_msg
54
+
55
+ def save_screenshot(name):
56
+ """Save a placeholder screenshot if we can't get a real one"""
57
+ try:
58
+ timestamp = int(time.time())
59
+ filename = f"screenshots/{name}_{timestamp}.png"
60
+
61
+ # Create a simple colored image as a placeholder
62
+ img = Image.new('RGB', (400, 300), color=(73, 109, 137))
63
+ img.save(filename)
64
+
65
+ logger.info(f"Saved placeholder screenshot: {filename}")
66
+ return filename
67
  except Exception as e:
68
+ logger.error(f"Error creating placeholder: {e}")
69
+ return None
70
+
71
+ def login_and_like_posts(username, password, max_likes):
72
+ """Main function to login to Instagram and like posts"""
73
+ status_updates = ["Starting Instagram Auto-Liker..."]
74
+ image_path = save_screenshot("start")
75
+
76
+ # First ensure browsers are installed
77
+ install_msg = download_playwright_browsers()
78
+ status_updates.append(install_msg)
79
+
80
+ try:
81
+ # Only import playwright after ensuring it's installed
82
+ from playwright.sync_api import sync_playwright
83
+
84
+ status_updates.append("Launching browser...")
85
+
86
+ with sync_playwright() as p:
87
+ browser = p.chromium.launch(
88
+ headless=True,
89
+ args=['--no-sandbox', '--disable-dev-shm-usage']
90
+ )
91
+
92
+ # Create a context with realistic user agent
93
+ context = browser.new_context(
94
+ user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
95
+ viewport={'width': 1280, 'height': 720}
96
+ )
97
+
98
+ # Create a new page
99
+ page = context.new_page()
100
+
101
+ # First test browser by visiting a simple site
102
+ status_updates.append("Testing browser connection...")
103
+ page.goto("https://www.google.com")
104
+ page.wait_for_load_state("networkidle")
105
+ status_updates.append(f"Browser working. Title: {page.title()}")
106
+
107
+ # Take test screenshot
108
+ try:
109
+ test_screenshot = f"screenshots/browser_test_{int(time.time())}.png"
110
+ page.screenshot(path=test_screenshot)
111
+ image_path = test_screenshot
112
+ status_updates.append(f"Browser test screenshot saved")
113
+ except Exception as e:
114
+ status_updates.append(f"Error taking screenshot: {str(e)}")
115
+
116
+ # Instagram login
117
+ status_updates.append("Navigating to Instagram...")
118
+ page.goto("https://www.instagram.com/")
119
+ page.wait_for_load_state("networkidle")
120
+
121
+ # Take screenshot of Instagram landing
122
+ try:
123
+ landing_screenshot = f"screenshots/instagram_landing_{int(time.time())}.png"
124
+ page.screenshot(path=landing_screenshot)
125
+ image_path = landing_screenshot
126
+ status_updates.append("Instagram home page loaded")
127
+ except Exception as e:
128
+ status_updates.append(f"Error taking landing screenshot: {str(e)}")
129
+
130
+ # Handle cookie consent if present
131
+ try:
132
+ if page.query_selector('text=Accept') or page.query_selector('text=Allow'):
133
+ status_updates.append("Handling cookie consent...")
134
+
135
+ # Try different button text variants
136
+ for button_text in ["Accept", "Allow", "Accept All", "Allow All Cookies"]:
137
+ try:
138
+ button = page.query_selector(f'text={button_text}')
139
+ if button:
140
+ button.click()
141
+ status_updates.append(f"Clicked '{button_text}' button")
142
+ page.wait_for_timeout(2000)
143
+ break
144
+ except Exception as btn_error:
145
+ logger.warning(f"Error clicking {button_text}: {str(btn_error)}")
146
+ continue
147
+ except Exception as e:
148
+ status_updates.append(f"No cookie dialog or error: {str(e)}")
149
+
150
+ # Wait for and fill login form
151
+ status_updates.append("Looking for login form...")
152
+ try:
153
+ page.wait_for_selector('input[name="username"]', state="visible", timeout=10000)
154
+
155
+ # Take pre-login screenshot
156
+ try:
157
+ pre_login_screenshot = f"screenshots/pre_login_{int(time.time())}.png"
158
+ page.screenshot(path=pre_login_screenshot)
159
+ image_path = pre_login_screenshot
160
+ except Exception as e:
161
+ status_updates.append(f"Error taking pre-login screenshot: {str(e)}")
162
+
163
+ # Enter credentials
164
+ status_updates.append(f"Entering username: {username}")
165
+ page.fill('input[name="username"]', username)
166
+ page.fill('input[name="password"]', password)
167
+ status_updates.append("Credentials entered")
168
+
169
+ # Click login button
170
+ status_updates.append("Clicking login button...")
171
+ page.click('button[type="submit"]')
172
+
173
+ # Wait for navigation
174
+ page.wait_for_load_state("networkidle")
175
+ page.wait_for_timeout(5000) # Additional wait for elements
176
+
177
+ # Take post-login screenshot
178
+ try:
179
+ post_login_screenshot = f"screenshots/post_login_{int(time.time())}.png"
180
+ page.screenshot(path=post_login_screenshot)
181
+ image_path = post_login_screenshot
182
+ except Exception as e:
183
+ status_updates.append(f"Error taking post-login screenshot: {str(e)}")
184
+
185
+ # Handle "Save Login Info" popup if it appears
186
+ try:
187
+ not_now_button = page.query_selector('text="Not Now"')
188
+ if not_now_button:
189
+ not_now_button.click()
190
+ status_updates.append("Dismissed 'Save Login Info' popup")
191
+ page.wait_for_timeout(2000)
192
+ except Exception as e:
193
+ status_updates.append(f"No 'Save Login Info' popup or error: {str(e)}")
194
+
195
+ # Handle notifications popup if it appears
196
+ try:
197
+ not_now_button = page.query_selector('text="Not Now"')
198
+ if not_now_button:
199
+ not_now_button.click()
200
+ status_updates.append("Dismissed notifications popup")
201
+ page.wait_for_timeout(2000)
202
+ except Exception as e:
203
+ status_updates.append(f"No notifications popup or error: {str(e)}")
204
+
205
+ # Verify we're on the feed
206
+ try:
207
+ feed_screenshot = f"screenshots/feed_{int(time.time())}.png"
208
+ page.screenshot(path=feed_screenshot)
209
+ image_path = feed_screenshot
210
+ status_updates.append("Successfully logged in! On Instagram feed now.")
211
+ except Exception as e:
212
+ status_updates.append(f"Error taking feed screenshot: {str(e)}")
213
+
214
+ # Start liking posts
215
+ status_updates.append(f"Starting to like posts (target: {max_likes})...")
216
+
217
+ # Like posts
218
+ likes_count = 0
219
+ scroll_count = 0
220
+ max_scrolls = 30
221
+
222
+ # Try to find posts
223
+ try:
224
+ page.wait_for_selector('article', timeout=10000)
225
+ status_updates.append("Found posts on feed")
226
+
227
+ while likes_count < max_likes and scroll_count < max_scrolls:
228
+ # Find like buttons
229
+ like_buttons = page.query_selector_all('article svg[aria-label="Like"]')
230
+
231
+ status_updates.append(f"Found {len(like_buttons)} like buttons on scroll {scroll_count}")
232
+
233
+ if len(like_buttons) == 0 and scroll_count > 5:
234
+ status_updates.append("No more like buttons found. Stopping.")
235
+ break
236
+
237
+ # Click like buttons
238
+ for i, button in enumerate(like_buttons):
239
+ if likes_count >= max_likes:
240
+ break
241
+
242
+ try:
243
+ # Scroll to button
244
+ button.scroll_into_view_if_needed()
245
+ page.wait_for_timeout(500)
246
+
247
+ # Click like
248
+ button.click()
249
+ likes_count += 1
250
+ status_updates.append(f"Liked post {likes_count}/{max_likes}")
251
+
252
+ # Wait between likes
253
+ page.wait_for_timeout(2000)
254
+ except Exception as e:
255
+ status_updates.append(f"Error liking post {i+1}: {str(e)}")
256
+ continue
257
+
258
+ # Scroll down to load more
259
+ page.evaluate("window.scrollBy(0, 1000)")
260
+ status_updates.append(f"Scrolled down to load more posts")
261
+ page.wait_for_timeout(3000)
262
+ scroll_count += 1
263
+
264
+ # Final status
265
+ final_message = f"Finished! Liked {likes_count} posts."
266
+ status_updates.append(final_message)
267
+
268
+ except Exception as e:
269
+ status_updates.append(f"Error finding or liking posts: {str(e)}")
270
+
271
+ except Exception as e:
272
+ status_updates.append(f"Error with login form: {str(e)}")
273
+
274
+ # Close the browser
275
+ browser.close()
276
+ status_updates.append("Browser closed")
277
+
278
+ return "\n".join(status_updates), image_path
279
+ except Exception as e:
280
+ error_message = f"Error: {str(e)}"
281
+ logger.error(error_message)
282
+ status_updates.append(error_message)
283
+ status_updates.append(traceback.format_exc())
284
+
285
+ return "\n".join(status_updates), image_path
286
+
287
+ # Simple interface for testing
288
+ def test_functionality():
289
+ """Simple function to test if the app is working"""
290
+ return "Instagram Auto-Liker is operational", save_screenshot("test")
291
+
292
+ # Gradio Interface
293
+ def create_interface():
294
+ with gr.Blocks(title="Instagram Auto-Liker") as app:
295
+ gr.Markdown("# Instagram Auto-Liker")
296
+ gr.Markdown("Enter your Instagram credentials and the number of posts to like.")
297
+
298
+ with gr.Row():
299
+ with gr.Column(scale=1):
300
+ username = gr.Textbox(label="Instagram Username")
301
+ password = gr.Textbox(label="Instagram Password", type="password")
302
+ max_likes = gr.Slider(minimum=1, maximum=100, value=10, step=1, label="Number of Posts to Like")
303
+ submit_btn = gr.Button("Start Liking Posts")
304
+ test_btn = gr.Button("Test App Function")
305
+
306
+ with gr.Column(scale=2):
307
+ status_output = gr.Textbox(label="Status Log", lines=15)
308
+ image_output = gr.Image(label="Latest Screenshot", type="filepath")
309
+
310
+ submit_btn.click(
311
+ fn=login_and_like_posts,
312
+ inputs=[username, password, max_likes],
313
+ outputs=[status_output, image_output]
314
+ )
315
+
316
+ test_btn.click(
317
+ fn=test_functionality,
318
+ inputs=[],
319
+ outputs=[status_output, image_output]
320
+ )
321
+
322
+ return app
323
+
324
+ # Make sure we install browsers first at module level
325
+ try:
326
+ download_playwright_browsers()
327
+ except Exception as e:
328
+ print(f"Warning: Failed to install browsers at startup: {e}")
329
 
330
+ # Launch the app
331
  if __name__ == "__main__":
332
+ print("Creating interface...")
333
+ app = create_interface()
334
+ print("Launching interface...")
335
+ app.launch(server_name="0.0.0.0", server_port=7860, share=True)
336
+ print("Interface launched.")