CoolFace
Apppublic

Bishall10/ipo

sourceHugging Faceupdated 3mo agoView on Hugging Face
0likes
notifications.py182 linesDownload Raw Back to root
1"""2notifications.py3----------------4Email notification utilities for the IPO automation.5"""6 7import os8import smtplib9from email.mime.text import MIMEText10from email.mime.multipart import MIMEMultipart11from dotenv import load_dotenv12 13load_dotenv()14 15 16def send_email_notification(to_email, subject, message):17    """18    Sends an email notification via Gmail SMTP.19    Reads SENDER_EMAIL, SENDER_PASSWORD, SMTP_SERVER, SMTP_PORT from .env.20    Silently skips if credentials are missing or no recipient is given.21    """22    if not to_email:23        return24 25    # 1. Try Google Apps Script (Web API) first - Works on Hugging Face26    gmail_api_url = os.getenv("GMAIL_API_URL")27    if gmail_api_url:28        try:29            import requests30            response = requests.post(31                gmail_api_url,32                json={"to": to_email, "subject": subject, "body": message},33                timeout=1034            )35            if response.status_code == 200:36                print(f"✅ Email sent via Google Apps Script to {to_email}")37                return True38            else:39                print(f"❌ Google Apps Script Error: {response.text}")40        except Exception as e:41            print(f"❌ Google Apps Script Exception: {str(e)}")42 43    # 2. Fallback to SMTP44    sender_email = os.getenv("SENDER_EMAIL")45    sender_password = os.getenv("SENDER_PASSWORD")46    smtp_server = os.getenv("SMTP_SERVER") or "smtp.gmail.com"47    smtp_port = int(os.getenv("SMTP_PORT") or 465)48 49    if not (sender_email and sender_password or gmail_api_url):50        print("Warning: Skipping email notification (No SENDER_EMAIL or GMAIL_API_URL found)")51        return False52 53    try:54        msg = MIMEMultipart()55        msg["From"] = f"IPO Automation <{sender_email}>"56        msg["To"] = to_email57        msg["Subject"] = subject58        msg.attach(MIMEText(message, "plain"))59 60        if sender_email and sender_password:61            server = smtplib.SMTP_SSL(smtp_server, smtp_port, timeout=10)62            server.login(sender_email, sender_password)63            server.send_message(msg)64            server.quit()65            print(f"✅ Email sent via SMTP to {to_email}")66            return True67        return False68    except Exception as e:69        print(f"❌ SMTP Error: {str(e)}")70        return False71 72 73def send_push_notification(tokens, title, body):74    """75    Sends FCM Push Notification to list of tokens.76    """77    if not tokens:78        return79 80    try:81        import firebase_admin82        from firebase_admin import credentials, messaging83 84        if not firebase_admin._apps:85            # Look for config in default location86            cred_path = os.path.join(os.path.dirname(__file__), "config", "firebase_vcc.json")87            if os.path.exists(cred_path):88                cred = credentials.Certificate(cred_path)89            else:90                # Fallback: load from base64-encoded env variable (GitHub Actions)91                import base64, json92                b64 = os.environ.get("FIREBASE_CREDENTIALS_B64", "")93                if not b64:94                    print(f"Warning: Firebase credentials not found. Set FIREBASE_CREDENTIALS_B64 env var. Skipping push notification.")95                    return96                cred_json = json.loads(base64.b64decode(b64).decode())97                cred = credentials.Certificate(cred_json)98            firebase_admin.initialize_app(cred)99 100        android_config = messaging.AndroidConfig(101            priority='high',102            notification=messaging.AndroidNotification(103                channel_id='high_importance_channel',104                sticky=True,105                default_vibrate_timings=True,106                default_sound=True,107            )108        )109        110        message = messaging.MulticastMessage(111            notification=messaging.Notification(title=title, body=body),112            tokens=tokens,113            android=android_config,114        )115        response = messaging.send_each_for_multicast(message)116        print(f"Push Notification Sent: {response.success_count} success, {response.failure_count} failure")117        return response118    except Exception as e:119        print(f"Warning: Failed to send push notification: {e}")120 121 122def broadcast_push_notification(title, body):123    """124    Fetches all unique FCM tokens from the database and sends a broadcast message.125    """126    db_url = os.getenv("DATABASE_URL")127    if not db_url:128        print("Error: DATABASE_URL not found. Cannot broadcast.")129        return130 131    try:132        import psycopg2133        conn = psycopg2.connect(db_url)134        cur = conn.cursor()135        cur.execute("SELECT DISTINCT token FROM automation_fcmtoken")136        tokens = [t[0] for t in cur.fetchall()]137        cur.close()138        conn.close()139 140        if tokens:141            print(f"Broadcasting to {len(tokens)} tokens...")142            return send_push_notification(tokens, title, body)143        else:144            print("No tokens found to broadcast.")145    except Exception as e:146        print(f"Error in broadcast: {e}")147 148 149def get_fcm_tokens_for_user(username, owner_id=None):150    """151    Fetches all FCM tokens for a user, using owner_id if provided, 152    or falling back to lookup by meroshare username.153    """154    db_url = os.getenv("DATABASE_URL")155    if not db_url:156        return []157    try:158        import psycopg2159        conn = psycopg2.connect(db_url)160        cur = conn.cursor()161        162        # If owner_id is not provided, look it up from the account table163        if not owner_id and username:164            cur.execute("SELECT owner_id FROM automation_account WHERE meroshare_user = %s", (username,))165            row = cur.fetchone()166            if row:167                owner_id = row[0]168        169        if owner_id:170            cur.execute("SELECT token FROM automation_fcmtoken WHERE user_id = %s", (owner_id,))171            tokens = [r[0] for r in cur.fetchall()]172            cur.close()173            conn.close()174            return tokens175            176        cur.close()177        conn.close()178    except Exception as e:179        print(f"Error fetching FCM tokens for user {username}: {e}")180    return []181 182