# /home/Autopartes/pos/blueprints/whatsapp_bp.py """WhatsApp via Baileys Bridge. Endpoints: GET /pos/api/whatsapp/status -- Connection status GET /pos/api/whatsapp/qr -- Get QR code POST /pos/api/whatsapp/connect -- Start connection POST /pos/api/whatsapp/logout -- Disconnect POST /pos/api/whatsapp/webhook -- Receive messages (public) POST /pos/api/whatsapp/send -- Send message GET /pos/api/whatsapp/conversations -- List conversations """ from flask import Blueprint, request, jsonify, g from middleware import require_auth from tenant_db import get_tenant_conn from services import whatsapp_service whatsapp_bp = Blueprint('whatsapp', __name__, url_prefix='/pos/api/whatsapp') @whatsapp_bp.route('/status', methods=['GET']) @require_auth() def status(): return jsonify(whatsapp_service.get_status()) @whatsapp_bp.route('/qr', methods=['GET']) @require_auth() def qr(): return jsonify(whatsapp_service.get_qr()) @whatsapp_bp.route('/connect', methods=['POST']) @require_auth() def connect(): return jsonify(whatsapp_service.connect()) @whatsapp_bp.route('/logout', methods=['POST']) @require_auth() def logout(): return jsonify(whatsapp_service.logout()) @whatsapp_bp.route('/webhook', methods=['POST']) def webhook(): """Receive messages from Baileys bridge (public, no auth).""" data = request.get_json(force=True, silent=True) or {} if data.get('event') != 'messages.upsert': return jsonify({'ok': True}) msg = whatsapp_service.process_incoming(data) if not msg.get('phone') or msg.get('from_me'): return jsonify({'ok': True}) # Save to DB if tenant connection available try: # Try to get a tenant connection (use default tenant for webhook) conn = get_tenant_conn(11) # TODO: resolve tenant from phone number cur = conn.cursor() cur.execute(""" INSERT INTO whatsapp_messages (phone, direction, message_text, wa_message_id) VALUES (%s, 'incoming', %s, %s) ON CONFLICT DO NOTHING """, (msg['phone'], msg['text'], msg['message_id'])) conn.commit() cur.close() conn.close() except Exception: pass # Auto-reply with AI chatbot if msg.get('text'): try: from services.ai_chat import chat ai_resp = chat(msg['text']) reply = ai_resp.get('message', '') if reply: whatsapp_service.send_message(msg['phone'], reply) except Exception: pass return jsonify({'ok': True}) @whatsapp_bp.route('/send', methods=['POST']) @require_auth() def send(): data = request.get_json() or {} phone = data.get('phone', '') message = data.get('message', '') if not phone or not message: return jsonify({'error': 'phone and message required'}), 400 result = whatsapp_service.send_message(phone, message) # Save outgoing message try: conn = get_tenant_conn(g.tenant_id) cur = conn.cursor() cur.execute(""" INSERT INTO whatsapp_messages (phone, direction, message_text) VALUES (%s, 'outgoing', %s) """, (phone, message)) conn.commit() cur.close() conn.close() except Exception: pass return jsonify(result) @whatsapp_bp.route('/conversations', methods=['GET']) @require_auth() def conversations(): try: conn = get_tenant_conn(g.tenant_id) cur = conn.cursor() cur.execute(""" SELECT phone, MAX(message_text) as last_message, MAX(created_at) as last_at, COUNT(*) as msg_count FROM whatsapp_messages GROUP BY phone ORDER BY MAX(created_at) DESC LIMIT 50 """) convos = [{'phone': r[0], 'last_message': r[1], 'last_at': str(r[2]), 'count': r[3]} for r in cur.fetchall()] cur.close() conn.close() return jsonify({'conversations': convos}) except Exception as e: return jsonify({'conversations': [], 'error': str(e)}) @whatsapp_bp.route('/conversations/', methods=['GET']) @require_auth() def conversation_messages(phone): try: conn = get_tenant_conn(g.tenant_id) cur = conn.cursor() cur.execute(""" SELECT id, direction, message_text, created_at FROM whatsapp_messages WHERE phone = %s ORDER BY created_at LIMIT 100 """, (phone,)) msgs = [{'id': r[0], 'direction': r[1], 'text': r[2], 'date': str(r[3])} for r in cur.fetchall()] cur.close() conn.close() return jsonify({'messages': msgs}) except Exception as e: return jsonify({'messages': [], 'error': str(e)})