|
import streamlit as st |
|
import pandas as pd |
|
import smtplib |
|
from email.mime.text import MIMEText |
|
from email.mime.multipart import MIMEMultipart |
|
import gspread |
|
from oauth2client.service_account import ServiceAccountCredentials |
|
from streamlit_option_menu import option_menu |
|
from io import BytesIO |
|
import requests |
|
from email.mime.application import MIMEApplication |
|
import os |
|
|
|
|
|
def read_file(path): |
|
try: |
|
with open(path, 'rb') as file: |
|
return file.read() |
|
except Exception as e: |
|
st.error(f"Failed to read file from {path}: {str(e)}") |
|
return None |
|
|
|
|
|
def get_content_type(file_path): |
|
if file_path.lower().endswith('.pdf'): |
|
return 'application/pdf' |
|
elif file_path.lower().endswith('.csv'): |
|
return 'text/csv' |
|
elif file_path.lower().endswith('.xlsx'): |
|
return 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' |
|
else: |
|
return 'application/octet-stream' |
|
|
|
|
|
EMAIL_HOST = 'smtp.gmail.com' |
|
EMAIL_PORT = 587 |
|
EMAIL_HOST_USER = 'ninadmandavkar@gofynd.com' |
|
EMAIL_HOST_PASSWORD = 'vxay jiss cctw lsdo' |
|
|
|
|
|
st.set_page_config(page_title="Alerter",page_icon="",layout="centered") |
|
|
|
|
|
html_title = """ |
|
<style> |
|
.fixed-title { |
|
font-size: 60px; |
|
color: #ffffff; |
|
background-image: linear-gradient(to right, #ff0000, #ffdab9); |
|
background-clip: text; |
|
-webkit-background-clip: text; |
|
text-fill-color: transparent; |
|
-webkit-text-fill-color: transparent; |
|
text-shadow: 2px 2px 4px rgba(0,0,0,0.4); |
|
} |
|
</style> |
|
<h1 class="fixed-title">Alerter</h1> |
|
""" |
|
st.markdown(html_title, unsafe_allow_html=True) |
|
|
|
menu_options = [ |
|
{"label": "Internal users", "icon": "π", "description": "Upload a document and schedule it for email"}, |
|
{"label": "External users", "icon": "π", "description": "Schedule an email with BigQuery data"}, |
|
{"label": "Recon checking", "icon": "π", "description": "Schedule an email with BigQuery data"}, |
|
{"label": "Manual BQ upload", "icon": "π", "description": "Schedule an email with BigQuery data"}, |
|
{"label": "Invoice splitter", "icon": "π", "description": "Schedule an email with BigQuery data"}, |
|
{"label": "Seller sale validation", "icon": "π", "description": "Schedule an email with BigQuery data"}, |
|
|
|
{"label": "Payment working", "icon": "π", "description": "Schedule an email with BigQuery data"} |
|
] |
|
|
|
|
|
selected_option = option_menu( |
|
menu_title="Select Integration", |
|
options=[option["label"] for option in menu_options], |
|
icons=[option["icon"] for option in menu_options], |
|
menu_icon="cast", |
|
default_index=0, |
|
orientation="horizontal" |
|
) |
|
|
|
if selected_option == "External users": |
|
|
|
html_subject = """ |
|
<html> |
|
<head> |
|
<style> |
|
.button { |
|
display: inline-block; |
|
padding: 10px 20px; |
|
border-radius: 12px; |
|
background: linear-gradient(to bottom, #f8f9fa, #e0e0e0); |
|
box-shadow: |
|
0 6px 12px rgba(0, 0, 0, 0.3), |
|
0 8px 16px rgba(0, 0, 0, 0.2), |
|
inset 0 -2px 4px rgba(255, 255, 255, 0.6); |
|
text-align: center; |
|
position: relative; |
|
transform: translateY(4px); |
|
transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out; |
|
cursor: pointer; |
|
user-select: none; |
|
} |
|
.button:hover { |
|
box-shadow: |
|
0 8px 16px rgba(0, 0, 0, 0.3), |
|
0 12px 24px rgba(0, 0, 0, 0.2); |
|
transform: translateY(2px); |
|
} |
|
.button:active { |
|
box-shadow: |
|
0 4px 8px rgba(0, 0, 0, 0.3), |
|
0 6px 12px rgba(0, 0, 0, 0.2); |
|
transform: translateY(0); |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<div class="button"> |
|
<h3 style=" |
|
font-size: 20px; |
|
color: #ffffff; |
|
background-image: linear-gradient(to right, #800000, #ff0000, #ffdab9); |
|
background-clip: text; |
|
-webkit-background-clip: text; |
|
text-fill-color: transparent; |
|
-webkit-text-fill-color: transparent; |
|
margin: 0; |
|
text-shadow: 0 2px 5px rgba(0, 0, 0, 0.4); |
|
">Select an option</h3> |
|
</div> |
|
</body> |
|
</html> |
|
""" |
|
|
|
st.markdown(html_subject, unsafe_allow_html=True) |
|
|
|
|
|
upload_option = st.radio("", ["Upload Spreadsheet (CSV or Excel)", "Google Sheets URL"]) |
|
|
|
|
|
|
|
if upload_option == "Upload Spreadsheet (CSV or Excel)": |
|
html_subject = """ |
|
<html> |
|
<head> |
|
<style> |
|
.button { |
|
display: inline-block; |
|
padding: 10px 20px; |
|
border-radius: 12px; |
|
background: linear-gradient(to bottom, #f8f9fa, #e0e0e0); |
|
box-shadow: |
|
0 6px 12px rgba(0, 0, 0, 0.3), |
|
0 8px 16px rgba(0, 0, 0, 0.2), |
|
inset 0 -2px 4px rgba(255, 255, 255, 0.6); |
|
text-align: center; |
|
position: relative; |
|
transform: translateY(4px); |
|
transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out; |
|
cursor: pointer; |
|
user-select: none; |
|
} |
|
.button:hover { |
|
box-shadow: |
|
0 8px 16px rgba(0, 0, 0, 0.3), |
|
0 12px 24px rgba(0, 0, 0, 0.2); |
|
transform: translateY(2px); |
|
} |
|
.button:active { |
|
box-shadow: |
|
0 4px 8px rgba(0, 0, 0, 0.3), |
|
0 6px 12px rgba(0, 0, 0, 0.2); |
|
transform: translateY(0); |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<div class="button"> |
|
<h3 style=" |
|
font-size: 20px; |
|
color: #ffffff; |
|
background-image: linear-gradient(to right, #800000, #ff0000, #ffdab9); |
|
background-clip: text; |
|
-webkit-background-clip: text; |
|
text-fill-color: transparent; |
|
-webkit-text-fill-color: transparent; |
|
margin: 0; |
|
text-shadow: 0 2px 5px rgba(0, 0, 0, 0.4); |
|
">Upload documents</h3> |
|
</div> |
|
</body> |
|
</html> |
|
""" |
|
|
|
st.markdown(html_subject, unsafe_allow_html=True) |
|
uploaded_file = st.file_uploader("", type=["csv", "xlsx"]) |
|
if uploaded_file: |
|
|
|
if uploaded_file.name.endswith(".csv"): |
|
df = pd.read_csv(uploaded_file) |
|
else: |
|
df = pd.read_excel(uploaded_file) |
|
|
|
st.write("") |
|
st.write("") |
|
|
|
elif upload_option == "Google Sheets URL": |
|
html_subject = """ |
|
<html> |
|
<head> |
|
<style> |
|
.button { |
|
display: inline-block; |
|
padding: 10px 20px; |
|
border-radius: 12px; |
|
background: linear-gradient(to bottom, #f8f9fa, #e0e0e0); |
|
box-shadow: |
|
0 6px 12px rgba(0, 0, 0, 0.3), |
|
0 8px 16px rgba(0, 0, 0, 0.2), |
|
inset 0 -2px 4px rgba(255, 255, 255, 0.6); |
|
text-align: center; |
|
position: relative; |
|
transform: translateY(4px); |
|
transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out; |
|
cursor: pointer; |
|
user-select: none; |
|
} |
|
.button:hover { |
|
box-shadow: |
|
0 8px 16px rgba(0, 0, 0, 0.3), |
|
0 12px 24px rgba(0, 0, 0, 0.2); |
|
transform: translateY(2px); |
|
} |
|
.button:active { |
|
box-shadow: |
|
0 4px 8px rgba(0, 0, 0, 0.3), |
|
0 6px 12px rgba(0, 0, 0, 0.2); |
|
transform: translateY(0); |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<div class="button"> |
|
<h3 style=" |
|
font-size: 20px; |
|
color: #ffffff; |
|
background-image: linear-gradient(to right, #800000, #ff0000, #ffdab9); |
|
background-clip: text; |
|
-webkit-background-clip: text; |
|
text-fill-color: transparent; |
|
-webkit-text-fill-color: transparent; |
|
margin: 0; |
|
text-shadow: 0 2px 5px rgba(0, 0, 0, 0.4); |
|
">Enter Google sheets url</h3> |
|
</div> |
|
</body> |
|
</html> |
|
""" |
|
|
|
st.markdown(html_subject, unsafe_allow_html=True) |
|
sheet_url = st.text_input("") |
|
if sheet_url: |
|
try: |
|
|
|
scope = ["https://spreadsheets.google.com/feeds", 'https://www.googleapis.com/auth/drive'] |
|
|
|
|
|
creds = ServiceAccountCredentials.from_json_keyfile_name('fynd-db-48954327ef17.json', scope) |
|
client = gspread.authorize(creds) |
|
|
|
|
|
sheet = client.open_by_url(sheet_url).sheet1 |
|
data = sheet.get_all_records() |
|
df = pd.DataFrame(data) |
|
|
|
except Exception as e: |
|
st.error(f"Failed to load Google Sheets: {str(e)}") |
|
|
|
if 'df' in locals(): |
|
|
|
df = df.drop(columns=['status'], errors='ignore') |
|
st.dataframe(df) |
|
|
|
button_styles = """ |
|
<style> |
|
div.stButton > button { |
|
color: #ffffff; /* Text color */ |
|
font-size: 30px; |
|
background-image: linear-gradient(to right, #800000, #ff0000); /* Maroon to light red gradient */ |
|
border: none; |
|
padding: 10px 20px; |
|
cursor: pointer; |
|
border-radius: 15px; |
|
display: inline-block; |
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1), 0 8px 15px rgba(0, 0, 0, 0.1); /* Box shadow */ |
|
transition: all 0.3s ease; /* Smooth transition on hover */ |
|
} |
|
div.stButton > button:hover { |
|
background-color: #00ff00; /* Hover background color */ |
|
color: #ff0000; /* Hover text color */ |
|
box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2), 0 12px 20px rgba(0, 0, 0, 0.2); /* Box shadow on hover */ |
|
} |
|
</style> |
|
""" |
|
st.markdown(button_styles, unsafe_allow_html=True) |
|
|
|
if st.button("Send Emails"): |
|
|
|
for index, row in df.iterrows(): |
|
email = row['Email Addresses'] |
|
subject = row['Subject'] |
|
message = row['Message'] |
|
cc_addresses = row['CC Addresses'].split(',') if 'CC Addresses' in row else [] |
|
Folder_IDs = row['Folder IDs'].split(',') |
|
|
|
|
|
|
|
|
|
msg = MIMEMultipart() |
|
msg['From'] = EMAIL_HOST_USER |
|
msg['To'] = email |
|
msg['Subject'] = subject |
|
|
|
if cc_addresses: |
|
msg['Cc'] = ','.join(cc_addresses) |
|
|
|
body = f"""{message}""" |
|
msg.attach(MIMEText(body, 'plain')) |
|
|
|
|
|
|
|
for folder_id in Folder_IDs: |
|
pdf_path = folder_id.strip() |
|
if pdf_path.endswith('.pdf'): |
|
pdf_content = read_file(pdf_path) |
|
if pdf_content: |
|
part = MIMEApplication(pdf_content, Name=os.path.basename(pdf_path)) |
|
part['Content-Disposition'] = f'attachment; filename="{os.path.basename(pdf_path)}"' |
|
msg.attach(part) |
|
|
|
|
|
|
|
for folder_id in Folder_IDs: |
|
csv_path = folder_id.strip() |
|
if csv_path.endswith('.csv'): |
|
csv_content = read_file(csv_path) |
|
if csv_content: |
|
part = MIMEApplication(csv_content, Name=os.path.basename(csv_path)) |
|
part['Content-Disposition'] = f'attachment; filename="{os.path.basename(csv_path)}"' |
|
msg.attach(part) |
|
|
|
|
|
for folder_id in Folder_IDs: |
|
xlsx_path = folder_id.strip() |
|
if xlsx_path.endswith('.xlsx'): |
|
xlsx_content = read_file(xlsx_path) |
|
if xlsx_content: |
|
part = MIMEApplication(xlsx_content, Name=os.path.basename(xlsx_path)) |
|
part['Content-Disposition'] = f'attachment; filename="{os.path.basename(xlsx_path)}"' |
|
msg.attach(part) |
|
|
|
|
|
|
|
|
|
for folder_id in Folder_IDs: |
|
zip_path = folder_id.strip() |
|
if zip_path.endswith('.zip'): |
|
zip_content = read_file(zip_path) |
|
if zip_content: |
|
part = MIMEApplication(zip_content, Name=os.path.basename(zip_path)) |
|
part['Content-Disposition'] = f'attachment; filename="{os.path.basename(zip_path)}"' |
|
msg.attach(part) |
|
|
|
|
|
|
|
try: |
|
with smtplib.SMTP(EMAIL_HOST, EMAIL_PORT) as server: |
|
server.starttls() |
|
server.login(EMAIL_HOST_USER, EMAIL_HOST_PASSWORD) |
|
server.sendmail(msg['From'], [email] + cc_addresses, msg.as_string()) |
|
st.success(f"Email sent to {email}") |
|
except Exception as e: |
|
st.error(f"Failed to send email to {email}: {str(e)}") |
|
|
|
|
|
|
|
elif selected_option == "Internal users": |
|
with open('ap.py') as file: |
|
exec(file.read()) |
|
|
|
elif selected_option == "Recon checking": |
|
with open('recon.py') as file: |
|
exec(file.read()) |
|
|
|
elif selected_option == "Manual BQ upload": |
|
with open('bq.py') as file: |
|
exec(file.read()) |
|
|
|
elif selected_option == "Invoice splitter": |
|
with open('splitter.py') as file: |
|
exec(file.read()) |
|
|
|
elif selected_option == "Seller sale validation": |
|
with open('seller.py') as file: |
|
exec(file.read()) |
|
|
|
elif selected_option == "Payment working": |
|
with open('payments.py') as file: |
|
exec(file.read()) |
|
|
|
|
|
|