Spaces:
Sleeping
Sleeping
| import os | |
| import logging | |
| from datetime import datetime | |
| from groq import Groq | |
| from twilio.rest import Client | |
| from dotenv import load_dotenv | |
| load_dotenv() | |
| logging.basicConfig(format="%(asctime)s | %(levelname)s | %(message)s", level=logging.INFO) | |
| logger = logging.getLogger(__name__) | |
| BOT_TOKEN = os.environ["TELEGRAM_BOT_TOKEN"] | |
| MY_USER_ID = int(os.environ["TELEGRAM_USER_ID"]) | |
| WIFE_NUMBER = os.environ["WIFE_WHATSAPP_NUMBER"] | |
| TWILIO_FROM = os.environ["TWILIO_WHATSAPP_FROM"] | |
| TWILIO_SID = os.environ["TWILIO_ACCOUNT_SID"] | |
| TWILIO_TOKEN = os.environ["TWILIO_AUTH_TOKEN"] | |
| GROQ_KEY = os.environ["GROQ_API_KEY"] | |
| groq_client = Groq(api_key=GROQ_KEY) | |
| twilio_client = Client(TWILIO_SID, TWILIO_TOKEN) | |
| SYSTEM_PROMPT = "You are a helpful assistant that converts short personal status updates from a husband into warm WhatsApp messages to his wife. Return ONLY the final message text. No quotes, no explanations. Keep it friendly, casual, and under 2 sentences. Add a relevant emoji at the end." | |
| FALLBACK_TEMPLATES = { | |
| "office": "Hey! Reached office safely", | |
| "lunch": "Just had lunch, all good!", | |
| "late": "Running late today, will update soon", | |
| "home": "Reached home safely!", | |
| "meeting": "In a meeting, will reply later", | |
| "leaving": "Leaving office now, on my way!", | |
| } | |
| message_log = [] | |
| TELEGRAM_API = "https://api.telegram.org/bot" + BOT_TOKEN | |
| def generate_whatsapp_message(user_input): | |
| try: | |
| response = groq_client.chat.completions.create( | |
| model="llama3-8b-8192", | |
| messages=[ | |
| {"role": "system", "content": SYSTEM_PROMPT}, | |
| {"role": "user", "content": user_input}, | |
| ], | |
| temperature=0.7, | |
| max_tokens=100, | |
| ) | |
| return response.choices[0].message.content.strip() | |
| except Exception as e: | |
| logger.error("Groq error: %s", e) | |
| lower = user_input.lower() | |
| for keyword, template in FALLBACK_TEMPLATES.items(): | |
| if keyword in lower: | |
| return template | |
| return "Quick update: " + user_input | |
| def send_whatsapp(message): | |
| try: | |
| result = twilio_client.messages.create( | |
| body=message, | |
| from_="whatsapp:" + TWILIO_FROM, | |
| to="whatsapp:" + WIFE_NUMBER, | |
| ) | |
| logger.info("WhatsApp sent: SID=%s", result.sid) | |
| return True | |
| except Exception as e: | |
| logger.error("Twilio error: %s", e) | |
| return False | |
| def log_message(user_input, sent_message, success): | |
| message_log.append({ | |
| "time": datetime.now().strftime("%d %b %H:%M"), | |
| "input": user_input, | |
| "sent": sent_message, | |
| "success": success, | |
| }) | |
| if len(message_log) > 20: | |
| message_log.pop(0) | |
| async def send_telegram_reply(chat_id, text): | |
| """Send reply back to Telegram using httpx directly.""" | |
| import httpx | |
| url = TELEGRAM_API + "/sendMessage" | |
| payload = {"chat_id": chat_id, "text": text} | |
| try: | |
| async with httpx.AsyncClient() as client: | |
| await client.post(url, json=payload, timeout=10) | |
| except Exception as e: | |
| logger.error("Telegram reply error: %s", e) | |
| async def handle_update(data: dict): | |
| """Process incoming Telegram webhook update.""" | |
| message = data.get("message") or data.get("edited_message") | |
| if not message: | |
| return | |
| chat_id = message["chat"]["id"] | |
| user_id = message["from"]["id"] | |
| text = message.get("text", "").strip() | |
| if not text: | |
| return | |
| # Security check | |
| if user_id != MY_USER_ID: | |
| await send_telegram_reply(chat_id, "Sorry, this bot is private.") | |
| return | |
| # Handle commands | |
| if text == "/start": | |
| await send_telegram_reply(chat_id, | |
| "Status Bot is ready!\n\n" | |
| "Just type any update and I will send a WhatsApp to your wife.\n\n" | |
| "Examples:\n" | |
| "- reached office\n" | |
| "- had lunch\n" | |
| "- coming late, around 9pm\n" | |
| "- leaving office now\n\n" | |
| "Type /test to send a test message\n" | |
| "Type /history to see last 5 sent messages" | |
| ) | |
| return | |
| if text == "/test": | |
| await send_telegram_reply(chat_id, "Sending test message to your wife...") | |
| success = send_whatsapp("Test message from Status Bot - everything is working!") | |
| if success: | |
| await send_telegram_reply(chat_id, "Test sent successfully!") | |
| else: | |
| await send_telegram_reply(chat_id, "Failed. Check Twilio credentials in HF Secrets.") | |
| return | |
| if text == "/history": | |
| if not message_log: | |
| await send_telegram_reply(chat_id, "No messages sent yet.") | |
| return | |
| lines = ["Last messages:\n"] | |
| for entry in reversed(message_log[-5:]): | |
| status = "OK" if entry["success"] else "FAILED" | |
| lines.append("[" + status + "] " + entry["time"] + "\nYou: " + entry["input"] + "\nSent: " + entry["sent"] + "\n") | |
| await send_telegram_reply(chat_id, "\n".join(lines)) | |
| return | |
| # Normal message - generate and send WhatsApp | |
| await send_telegram_reply(chat_id, "Generating message...") | |
| whatsapp_msg = generate_whatsapp_message(text) | |
| success = send_whatsapp(whatsapp_msg) | |
| log_message(text, whatsapp_msg, success) | |
| if success: | |
| await send_telegram_reply(chat_id, "Sent to wife:\n" + whatsapp_msg) | |
| else: | |
| await send_telegram_reply(chat_id, "Failed to send.\nMessage was: " + whatsapp_msg) | |