fix(maria): „am trimis la suport" doar cand puntea chiar a trimis, si un log care nu minte
Gasite citind logul rularii de test de azi.
1. `requests` NU ridica exceptie la 4xx/5xx, iar puntea raspunde 503 cand nu e
conectata la WhatsApp si 500 cand `sendMessage` cade. send_reply/send_image
ignorau codul, deci escaladarea se inregistra `notified: true` si omul primea
„te contacteaza cineva" pentru un mesaj care nu plecase nicaieri — exact
promisiunea pentru care exista ESCALATED_RECORDED. Acum trimiterea intoarce
motivul esecului ("" la reusita), iar `notified` si `notify_error` vin de acolo.
2. Puntea nu loga nimic la trimitere: o escaladare nu lasa nicio urma pe partea de
WhatsApp, deci nu se poate verifica daca captura chiar a ajuns la suport.
/send si /send-image logheaza acum destinatarul si inceputul mesajului.
3. Mesajele primite se logau taiate la 80 de caractere, fara semn ca sunt taiate.
Un mesaj de exact 80 arata ca unul intreg — asa am ajuns azi la concluzia
gresita ca gardul de „mesaj prea vag" nu functioneaza, cand de fapt mesajul era
mai lung decat parea. 200 de caractere si „… (+N)".
4. La o captura pe un fir deschis se logau doua linii „caut dupa" diferite, iar
prima nu era interogarea folosita. Prima zice acum „din captura, retin".
Teste: 103 pass (una noua: puntea respinge cu 503 -> notified false).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4uzvgm7AyJch5WH8QHRhY
This commit is contained in:
@@ -187,16 +187,34 @@ def ask_llm(chunks: list[str], question: str, istoric: list[dict] | None = None)
|
||||
return resp.json()["choices"][0]["message"]["content"]
|
||||
|
||||
|
||||
def send_reply(to: str, text: str) -> None:
|
||||
requests.post(f"{bridge_url()}/send", json={"to": to, "text": REPLY_PREFIX + text}, timeout=15)
|
||||
def _trimite(url: str, corp: dict, catre: str, timeout: int) -> str:
|
||||
"""Trimite prin punte. Intoarce "" daca a plecat, altfel motivul esecului.
|
||||
|
||||
`requests` NU ridica exceptie la 4xx/5xx, iar puntea raspunde 503 cand nu e
|
||||
conectata la WhatsApp si 500 cand `sendMessage` cade. Fara verificarea
|
||||
codului, escaladarea se inregistra ca „notificata" si Maria promitea „te
|
||||
contacteaza cineva" pentru un mesaj care nu plecase nicaieri — exact
|
||||
promisiunea pe care ESCALATED_RECORDED exista ca sa n-o facem.
|
||||
"""
|
||||
try:
|
||||
resp = requests.post(url, json=corp, timeout=timeout)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
print(f"[consumer] trimitere esuata catre {catre}: {exc}", file=sys.stderr)
|
||||
return str(exc)
|
||||
if resp.status_code >= 400:
|
||||
motiv = f"HTTP {resp.status_code}: {resp.text[:150]}"
|
||||
print(f"[consumer] trimitere esuata catre {catre}: {motiv}", file=sys.stderr)
|
||||
return motiv
|
||||
return ""
|
||||
|
||||
|
||||
def send_image(to: str, path: str, caption: str) -> None:
|
||||
requests.post(
|
||||
f"{bridge_url()}/send-image",
|
||||
json={"to": to, "path": path, "caption": caption},
|
||||
timeout=60,
|
||||
)
|
||||
def send_reply(to: str, text: str) -> str:
|
||||
return _trimite(f"{bridge_url()}/send", {"to": to, "text": REPLY_PREFIX + text}, to, 15)
|
||||
|
||||
|
||||
def send_image(to: str, path: str, caption: str) -> str:
|
||||
return _trimite(f"{bridge_url()}/send-image",
|
||||
{"to": to, "path": path, "caption": caption}, to, 60)
|
||||
|
||||
|
||||
def react_seen(to: str, message_id: str, from_me: bool) -> None:
|
||||
@@ -269,7 +287,9 @@ def prepare_query(msg: dict) -> tuple[str | None, str | None, str | None]:
|
||||
file=sys.stderr,
|
||||
)
|
||||
cautare = ocr.retrieval_query(text, ocr_text)
|
||||
print(f"[consumer] caut dupa: {cautare!r}", file=sys.stderr)
|
||||
# „din captura", nu „caut dupa": pe un fir, interogarea finala e alta (ancora
|
||||
# plus asta) si se logheaza separat — doua linii „caut dupa" induceau in eroare.
|
||||
print(f"[consumer] din captura, retin: {cautare!r}", file=sys.stderr)
|
||||
return build_image_question(text, ocr_text), cautare, None
|
||||
|
||||
|
||||
@@ -323,15 +343,14 @@ def escalate(msg: dict, question: str, search_result: dict, fir: dict | None = N
|
||||
f"{(msg.get('ocr_text') or msg.get('text') or '').strip()[:1200]}"
|
||||
+ (f"\n\n--- discutia de pana acum ---\n{discutie}" if discutie else "")
|
||||
)
|
||||
try:
|
||||
if media.get("path") and os.path.exists(media["path"]):
|
||||
send_image(jid, media["path"], rezumat[:1000])
|
||||
else:
|
||||
requests.post(f"{bridge_url()}/send", json={"to": jid, "text": rezumat}, timeout=20)
|
||||
record["notified"] = True
|
||||
except Exception as exc: # noqa: BLE001
|
||||
record["notify_error"] = str(exc)
|
||||
print(f"[consumer] escaladare: notificarea a esuat: {exc}", file=sys.stderr)
|
||||
if media.get("path") and os.path.exists(media["path"]):
|
||||
eroare = send_image(jid, media["path"], rezumat[:1000])
|
||||
else:
|
||||
eroare = _trimite(f"{bridge_url()}/send", {"to": jid, "text": rezumat}, jid, 20)
|
||||
record["notified"] = not eroare
|
||||
if eroare:
|
||||
record["notify_error"] = eroare
|
||||
print(f"[consumer] escaladare: notificarea a esuat: {eroare}", file=sys.stderr)
|
||||
else:
|
||||
print("[consumer] escaladare: SUPPORT_JID nesetat — doar in jurnal", file=sys.stderr)
|
||||
|
||||
@@ -362,15 +381,9 @@ def _notifica_suport(text: str, imagine: str | None = None) -> bool:
|
||||
jid = config.get("SUPPORT_JID") or ""
|
||||
if not jid:
|
||||
return False
|
||||
try:
|
||||
if imagine and os.path.exists(imagine):
|
||||
send_image(jid, imagine, text[:1000])
|
||||
else:
|
||||
requests.post(f"{bridge_url()}/send", json={"to": jid, "text": text}, timeout=20)
|
||||
return True
|
||||
except Exception as exc: # noqa: BLE001
|
||||
print(f"[consumer] mesaj catre suport netrimis: {exc}", file=sys.stderr)
|
||||
return False
|
||||
if imagine and os.path.exists(imagine):
|
||||
return not send_image(jid, imagine, text[:1000])
|
||||
return not _trimite(f"{bridge_url()}/send", {"to": jid, "text": text}, jid, 20)
|
||||
|
||||
|
||||
def completeaza(ref: str, msg: dict, text: str) -> str | None:
|
||||
|
||||
@@ -124,3 +124,23 @@ def test_notificarea_esuata_nu_pierde_jurnalul(rezultat_fara_acoperire, monkeypa
|
||||
inregistrare = json.loads(next((config.STATE_DIR / "escalations").glob("*.json")).read_text())
|
||||
assert inregistrare["notified"] is False
|
||||
assert "puntea nu raspunde" in inregistrare["notify_error"]
|
||||
|
||||
|
||||
def test_puntea_respinge_mesajul_nu_promitem_ca_a_plecat(rezultat_fara_acoperire, monkeypatch):
|
||||
"""503 „not connected to WhatsApp" nu ridica exceptie in requests — dar nu e trimitere.
|
||||
|
||||
Fara verificarea codului, escaladarea se scria „notificata" si omul primea
|
||||
„te contacteaza cineva" pentru un mesaj care nu plecase nicaieri.
|
||||
"""
|
||||
monkeypatch.setitem(config._env, "SUPPORT_JID", "40799999999@s.whatsapp.net")
|
||||
|
||||
class Respins:
|
||||
status_code = 503
|
||||
text = '{"ok":false,"error":"not connected to WhatsApp"}'
|
||||
|
||||
monkeypatch.setattr(consumer.requests, "post", lambda *a, **kw: Respins())
|
||||
consumer.escalate(_mesaj(), "intrebare", rezultat_fara_acoperire)
|
||||
|
||||
inregistrare = json.loads(next((config.STATE_DIR / "escalations").glob("*.json")).read_text())
|
||||
assert inregistrare["notified"] is False
|
||||
assert "503" in inregistrare["notify_error"]
|
||||
|
||||
@@ -285,7 +285,12 @@ async function startConnection() {
|
||||
fromMe: msg.key.fromMe || false,
|
||||
});
|
||||
|
||||
console.log(`[whatsapp] Message from ${msg.pushName || 'unknown'} in ${msg.key.remoteJid}: ${media ? '[imagine] ' : ''}${text.substring(0, 80)}`);
|
||||
// Taiat, dar marcat: 80 de caractere fix aratau ca un mesaj intreg, iar
|
||||
// logul e primul loc in care te uiti cand un raspuns iese prost. Pe
|
||||
// 2026-09-01 asta a dus la concluzia gresita ca gardul de „mesaj prea vag"
|
||||
// nu functioneaza, cand de fapt mesajul era mai lung decat parea in log.
|
||||
const scurt = text.length > 200 ? `${text.substring(0, 200)}… (+${text.length - 200})` : text;
|
||||
console.log(`[whatsapp] Message from ${msg.pushName || 'unknown'} in ${msg.key.remoteJid}: ${media ? '[imagine] ' : ''}${scurt}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -372,6 +377,7 @@ app.post('/send', async (req, res) => {
|
||||
|
||||
try {
|
||||
const result = await sock.sendMessage(to, { text });
|
||||
console.log(`[whatsapp] -> ${to}: ${text.substring(0, 120)}${text.length > 120 ? '…' : ''}`);
|
||||
res.json({ ok: true, id: result.key.id });
|
||||
} catch (err) {
|
||||
console.error('[whatsapp] Send failed:', err.message);
|
||||
@@ -398,6 +404,7 @@ app.post('/send-image', async (req, res) => {
|
||||
try {
|
||||
const buffer = fs.readFileSync(resolved);
|
||||
const result = await sock.sendMessage(to, { image: buffer, caption: caption || undefined });
|
||||
console.log(`[whatsapp] -> ${to}: [imagine ${buffer.length} octeti] ${(caption || '').substring(0, 100)}`);
|
||||
res.json({ ok: true, id: result.key.id });
|
||||
} catch (err) {
|
||||
console.error('[whatsapp] Send image failed:', err.message);
|
||||
|
||||
Reference in New Issue
Block a user