Rishit commited on
Commit
b81669e
Β·
verified Β·
1 Parent(s): 7af81df

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +55 -40
src/streamlit_app.py CHANGED
@@ -161,7 +161,6 @@
161
 
162
 
163
 
164
-
165
  import streamlit as st
166
  import requests
167
  import csv
@@ -173,34 +172,34 @@ from concurrent.futures import ThreadPoolExecutor, as_completed
173
  import os
174
  import threading
175
  import schedule
176
- import os
177
 
178
  st.set_page_config(page_title="Temple Dekho WhatsApp Promo Scheduler", layout="wide")
179
  st.title("πŸ“… Temple Dekho WhatsApp Message Scheduler")
180
 
181
- # Create logs directory if not exists
182
  log_dir = "/tmp/logs"
183
  os.makedirs(log_dir, exist_ok=True)
184
 
185
  # --- Helper Functions ---
186
- def upload_media(file, access_token, phone_number_id):
187
- mime_type = mimetypes.guess_type(file.name)[0] or "application/octet-stream"
188
- files = {
189
- 'file': (file.name, file.getvalue(), mime_type),
190
- 'type': (None, mime_type),
191
- 'messaging_product': (None, 'whatsapp')
192
- }
193
- headers = {
194
- 'Authorization': f'Bearer {access_token}'
195
- }
196
- url = f"https://graph.facebook.com/v19.0/{phone_number_id}/media"
197
-
198
- try:
199
- res = requests.post(url, headers=headers, files=files)
200
- res.raise_for_status()
201
- return res.json().get("id"), res.status_code, res.text
202
- except Exception as e:
203
- return None, 500, str(e)
 
204
 
205
  def send_message(phone, payload, headers, retries=3, backoff_intervals=[5, 15, 30]):
206
  for attempt in range(retries):
@@ -251,7 +250,7 @@ def execute_campaign(params):
251
  logfile.write(result + "\n")
252
  logfile.flush()
253
 
254
- # --- UI Form to Schedule Campaign ---
255
  with st.form("schedule_form"):
256
  st.subheader("πŸ—“οΈ Schedule WhatsApp Campaign")
257
  col1, col2 = st.columns(2)
@@ -288,27 +287,45 @@ if submitted:
288
  if not csv_file:
289
  st.error("CSV file is required.")
290
  else:
 
 
 
 
 
291
  media_id = existing_media_id.strip() if existing_media_id.strip() else None
 
 
292
  if media_file and not media_id:
293
- media_id, status_code, response = upload_media(media_file, access_token, phone_number_id)
 
 
 
294
  if not media_id:
295
  st.error(f"Media upload failed. Status: {status_code}\nResponse: {response}")
 
296
 
297
- csv_file.seek(0)
298
- decoded = csv_file.read().decode('utf-8').strip()
299
- rows = csv.reader(io.StringIO(decoded))
300
- next(rows, None)
301
-
302
  phones = []
303
- for row in rows:
304
- if not row or not row[0].strip():
305
- continue
306
- num = row[0].strip()
307
- if num.isdigit():
308
- if len(num) == 10:
309
- phones.append("91" + num)
310
- elif len(num) == 12 and num.startswith("91"):
311
- phones.append(num)
 
 
 
 
 
 
 
 
 
 
 
312
 
313
  headers = {
314
  "Authorization": f"Bearer {access_token}",
@@ -340,7 +357,7 @@ if submitted:
340
  })
341
  components += buttons
342
  except:
343
- pass
344
 
345
  scheduled_datetime = datetime.combine(schedule_date, schedule_time)
346
 
@@ -367,5 +384,3 @@ if submitted:
367
  threading.Thread(target=run_scheduler, daemon=True).start()
368
 
369
  st.success(f"βœ… Campaign scheduled for {scheduled_datetime.strftime('%Y-%m-%d %H:%M:%S')}. UI can now be closed.")
370
-
371
-
 
161
 
162
 
163
 
 
164
  import streamlit as st
165
  import requests
166
  import csv
 
172
  import os
173
  import threading
174
  import schedule
 
175
 
176
  st.set_page_config(page_title="Temple Dekho WhatsApp Promo Scheduler", layout="wide")
177
  st.title("πŸ“… Temple Dekho WhatsApp Message Scheduler")
178
 
179
+ # Logs directory
180
  log_dir = "/tmp/logs"
181
  os.makedirs(log_dir, exist_ok=True)
182
 
183
  # --- Helper Functions ---
184
+ def upload_media(file_path, access_token, phone_number_id):
185
+ mime_type = mimetypes.guess_type(file_path)[0] or "application/octet-stream"
186
+ with open(file_path, "rb") as f:
187
+ files = {
188
+ 'file': (os.path.basename(file_path), f, mime_type),
189
+ 'type': (None, mime_type),
190
+ 'messaging_product': (None, 'whatsapp')
191
+ }
192
+ headers = {
193
+ 'Authorization': f'Bearer {access_token}'
194
+ }
195
+ url = f"https://graph.facebook.com/v19.0/{phone_number_id}/media"
196
+
197
+ try:
198
+ res = requests.post(url, headers=headers, files=files)
199
+ res.raise_for_status()
200
+ return res.json().get("id"), res.status_code, res.text
201
+ except Exception as e:
202
+ return None, 500, str(e)
203
 
204
  def send_message(phone, payload, headers, retries=3, backoff_intervals=[5, 15, 30]):
205
  for attempt in range(retries):
 
250
  logfile.write(result + "\n")
251
  logfile.flush()
252
 
253
+ # --- UI Form ---
254
  with st.form("schedule_form"):
255
  st.subheader("πŸ—“οΈ Schedule WhatsApp Campaign")
256
  col1, col2 = st.columns(2)
 
287
  if not csv_file:
288
  st.error("CSV file is required.")
289
  else:
290
+ # Save CSV to /tmp
291
+ csv_path = f"/tmp/{csv_file.name}"
292
+ with open(csv_path, "wb") as f:
293
+ f.write(csv_file.getbuffer())
294
+
295
  media_id = existing_media_id.strip() if existing_media_id.strip() else None
296
+
297
+ # Save media file to /tmp
298
  if media_file and not media_id:
299
+ media_path = f"/tmp/{media_file.name}"
300
+ with open(media_path, "wb") as f:
301
+ f.write(media_file.getbuffer())
302
+ media_id, status_code, response = upload_media(media_path, access_token, phone_number_id)
303
  if not media_id:
304
  st.error(f"Media upload failed. Status: {status_code}\nResponse: {response}")
305
+ st.stop()
306
 
307
+ # Process CSV
 
 
 
 
308
  phones = []
309
+ try:
310
+ with open(csv_path, "r", encoding="utf-8-sig") as f:
311
+ reader = csv.reader(f)
312
+ next(reader, None)
313
+ for row in reader:
314
+ if not row or not row[0].strip():
315
+ continue
316
+ num = row[0].strip()
317
+ if num.isdigit():
318
+ if len(num) == 10:
319
+ phones.append("91" + num)
320
+ elif len(num) == 12 and num.startswith("91"):
321
+ phones.append(num)
322
+ except Exception as e:
323
+ st.error(f"Error reading CSV: {e}")
324
+ st.stop()
325
+
326
+ if not phones:
327
+ st.error("No valid phone numbers found in CSV.")
328
+ st.stop()
329
 
330
  headers = {
331
  "Authorization": f"Bearer {access_token}",
 
357
  })
358
  components += buttons
359
  except:
360
+ pass # ignore if button input is malformed
361
 
362
  scheduled_datetime = datetime.combine(schedule_date, schedule_time)
363
 
 
384
  threading.Thread(target=run_scheduler, daemon=True).start()
385
 
386
  st.success(f"βœ… Campaign scheduled for {scheduled_datetime.strftime('%Y-%m-%d %H:%M:%S')}. UI can now be closed.")