Continue implementing WhatsApp
This commit is contained in:
@@ -3,6 +3,7 @@ import base64
|
||||
import io
|
||||
import secrets
|
||||
import time
|
||||
from urllib.parse import quote_plus
|
||||
from typing import Any
|
||||
|
||||
import aiohttp
|
||||
@@ -99,11 +100,94 @@ def list_accounts(service: str):
|
||||
|
||||
state = get_runtime_state(service_key)
|
||||
accounts = state.get("accounts") or []
|
||||
if service_key == "whatsapp" and not accounts:
|
||||
contacts = state.get("contacts") or []
|
||||
recovered = []
|
||||
seen = set()
|
||||
for row in contacts:
|
||||
if not isinstance(row, dict):
|
||||
continue
|
||||
candidate = str(row.get("identifier") or row.get("jid") or "").strip()
|
||||
if not candidate or candidate in seen:
|
||||
continue
|
||||
seen.add(candidate)
|
||||
recovered.append(candidate)
|
||||
if recovered:
|
||||
accounts = recovered
|
||||
update_runtime_state(service_key, accounts=recovered)
|
||||
if isinstance(accounts, list):
|
||||
return accounts
|
||||
return []
|
||||
|
||||
|
||||
def _account_key(value: str) -> str:
|
||||
raw = str(value or "").strip().lower()
|
||||
if "@" in raw:
|
||||
raw = raw.split("@", 1)[0]
|
||||
return raw
|
||||
|
||||
|
||||
def unlink_account(service: str, account: str) -> bool:
|
||||
service_key = _service_key(service)
|
||||
account_value = str(account or "").strip()
|
||||
if not account_value:
|
||||
return False
|
||||
|
||||
if service_key == "signal":
|
||||
import requests
|
||||
|
||||
base = str(getattr(settings, "SIGNAL_HTTP_URL", "http://signal:8080")).rstrip("/")
|
||||
target = quote_plus(account_value)
|
||||
for path in (f"/v1/accounts/{target}", f"/v1/account/{target}"):
|
||||
try:
|
||||
response = requests.delete(f"{base}{path}", timeout=20)
|
||||
if response.ok:
|
||||
return True
|
||||
except Exception:
|
||||
continue
|
||||
return False
|
||||
|
||||
if service_key in {"whatsapp", "instagram"}:
|
||||
state = get_runtime_state(service_key)
|
||||
key = _account_key(account_value)
|
||||
|
||||
raw_accounts = state.get("accounts") or []
|
||||
accounts = []
|
||||
for row in raw_accounts:
|
||||
value = str(row or "").strip()
|
||||
if not value:
|
||||
continue
|
||||
if _account_key(value) == key:
|
||||
continue
|
||||
accounts.append(value)
|
||||
|
||||
raw_contacts = state.get("contacts") or []
|
||||
contacts = []
|
||||
for row in raw_contacts:
|
||||
if not isinstance(row, dict):
|
||||
continue
|
||||
identifier = str(row.get("identifier") or "").strip()
|
||||
jid = str(row.get("jid") or "").strip()
|
||||
if _account_key(identifier) == key or _account_key(jid) == key:
|
||||
continue
|
||||
contacts.append(row)
|
||||
|
||||
update_runtime_state(
|
||||
service_key,
|
||||
accounts=accounts,
|
||||
contacts=contacts,
|
||||
connected=bool(accounts),
|
||||
pair_status=("connected" if accounts else ""),
|
||||
pair_qr="",
|
||||
warning=("" if accounts else "Account unlinked. Add account to link again."),
|
||||
last_event="account_unlinked",
|
||||
last_error="",
|
||||
)
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def get_service_warning(service: str) -> str:
|
||||
service_key = _service_key(service)
|
||||
if service_key == "signal":
|
||||
@@ -131,6 +215,18 @@ def request_pairing(service: str, device_name: str = ""):
|
||||
service_key = _service_key(service)
|
||||
if service_key not in {"whatsapp", "instagram"}:
|
||||
return
|
||||
state = get_runtime_state(service_key)
|
||||
existing_accounts = state.get("accounts") or []
|
||||
is_connected = bool(state.get("connected"))
|
||||
pair_status = str(state.get("pair_status") or "").strip().lower()
|
||||
if existing_accounts and (is_connected or pair_status == "connected"):
|
||||
update_runtime_state(
|
||||
service_key,
|
||||
warning="Account already linked.",
|
||||
pair_status="connected",
|
||||
pair_qr="",
|
||||
)
|
||||
return
|
||||
device = str(device_name or "GIA Device").strip() or "GIA Device"
|
||||
update_runtime_state(
|
||||
service_key,
|
||||
@@ -454,6 +550,17 @@ def get_link_qr(service: str, device_name: str):
|
||||
return cached
|
||||
|
||||
if service_key == "whatsapp":
|
||||
state = get_runtime_state(service_key)
|
||||
existing_accounts = state.get("accounts") or []
|
||||
pair_status = str(state.get("pair_status") or "").strip().lower()
|
||||
if existing_accounts and (
|
||||
bool(state.get("connected")) or pair_status == "connected"
|
||||
):
|
||||
raise RuntimeError(
|
||||
"WhatsApp account already linked in this runtime. "
|
||||
"Only one active linked device is supported. "
|
||||
"Unlink the current account first, then add a new one."
|
||||
)
|
||||
raise RuntimeError(
|
||||
"Neonize has not provided a pairing QR yet. "
|
||||
"Ensure UR is running with WHATSAPP_ENABLED=true and retry."
|
||||
|
||||
Reference in New Issue
Block a user