amarorn / scripts /capture_superbet.py
beAnalytic's picture
feat: sync main with feature/superbet-live-inplay
16c19b8 verified
Raw
History Blame Contribute Delete
7.79 kB
#!/usr/bin/env python3
"""Script para capturar apostas abertas da Superbet via clipboard.
Uso:
1. Abra a página "Minhas Apostas" da Superbet no navegador
2. Copie o texto do card da aposta (Ctrl+C ou Cmd+C)
3. Rode: ./scripts/capture_superbet.py
4. O script lê a área de transferência, parseia e envia para a API
5. A aposta aparece no painel ao vivo automaticamente
Dependências:
pip install pyperclip requests
"""
from __future__ import annotations
import argparse
import json
import sys
try:
import pyperclip
import requests
except ImportError:
print("Instale as dependências: pip install pyperclip requests")
sys.exit(1)
API_BASE = "http://127.0.0.1:8000"
def parse_clipboard(text: str) -> dict | None:
"""Extrai dados da aposta a partir do texto copiado da Superbet."""
lines = [line.strip() for line in text.strip().splitlines() if line.strip()]
if not lines:
return None
# Primeira linha com nomes do evento
event_line = lines[0]
# Tentar separar por ·, —, -, vs, x
teams = None
for sep in ("·", "—", " - ", " vs ", " x "):
if sep in event_line:
parts = event_line.split(sep)
if len(parts) >= 2:
teams = (parts[0].strip(), parts[1].strip())
break
if not teams:
return None
# Linhas com "CRIAR APOSTA" → combo
# Linhas com "Total de Gols" → over/under
# Linhas com "Ambas as Equipes Marcam" → btts
# Linhas com "Resultado Final" → h2h
picks = []
import re
for ln in lines:
ln_lower = ln.lower()
if "resultado final" in ln_lower:
m = re.search(r"resultado final.*[-—]\s*([1X2])", ln, re.I)
outcome = m.group(1) if m else None
picks.append({"market": "h2h", "outcome": outcome or "1"})
elif "total de gols" in ln_lower:
m = re.search(r"(?:mais|menos) de ([\d.]+)", ln_lower)
val = m.group(1) if m else "2.5"
over = "mais" in ln_lower
picks.append({"market": f"over_{val}", "outcome": "yes" if over else "no", "target_value": val})
elif "ambas as equipes marcam" in ln_lower:
yes = "sim" in ln_lower
picks.append({"market": "btts_any_half" if "algum dos tempos" in ln_lower else "btts", "outcome": "yes" if yes else "no"})
elif re.search(r"\w+\s*-\s*vence|vencer", ln_lower):
picks.append({"market": "h2h", "outcome": "home" if teams[0].lower() in ln_lower else "away"})
elif "próximo gol" in ln_lower or "proximo gol" in ln_lower or "2º gol" in ln_lower:
m = re.search(r"-\s*(\w+)", ln)
outcome = None
if m:
name = m.group(1).strip().lower()
if name in ("1", teams[0].lower().split()[0]):
outcome = "home"
elif name in ("2", teams[1].lower().split()[0]):
outcome = "away"
picks.append({"market": "next_goal", "outcome": outcome or "home"})
elif "criar aposta" in ln_lower:
picks.append({"market": "combo", "outcome": "combo"})
# Extrair valor apostado
stake = 0.0
for ln in lines:
m = re.search(r"APOSTA\s*([\d.,]+)", ln)
if m:
stake = float(m.group(1).replace(".", "").replace(",", "."))
break
# Extrair odd total
total_odd = 0.0
for ln in lines:
m = re.search(r"ODDS\s*TOTAIS\s*([\d.,]+)", ln)
if m:
total_odd = float(m.group(1).replace(",", "."))
break
m = re.search(r"@\s*([\d.,]+)", ln)
if m:
total_odd = float(m.group(1).replace(",", "."))
# Extrair ticket code (ex: 892P-1YINSZ)
ticket_code = None
for ln in lines:
m = re.search(r"\b([A-Z0-9]{3,}-?[A-Z0-9]{5,})\b", ln)
if m and not re.search(r"ODDS|APOSTA|Ganho|R\\$", ln):
ticket_code = m.group(1)
break
# Extrair ganho potencial
potential_return = 0.0
for ln in lines:
m = re.search(r"GANHO\s+POTENCIAL\s*R?\$?\s*([\d.,]+)", ln, re.I)
if m:
potential_return = float(m.group(1).replace(".", "").replace(",", "."))
break
m = re.search(r"Retorno\s*R?\$?\s*([\d.,]+)", ln, re.I)
if m:
potential_return = float(m.group(1).replace(".", "").replace(",", "."))
break
if not picks or stake <= 0 or total_odd <= 1:
return None
return {
"event_name": event_line,
"home_team": teams[0],
"away_team": teams[1],
"picks": picks,
"stake": stake,
"odds_placed": total_odd,
"potential_return": potential_return if potential_return > 0 else round(stake * total_odd, 2),
"ticket_code": ticket_code,
"source": "clipboard_capture",
}
def send_to_api(payload: dict, api_key: str | None = None) -> dict:
headers = {"Content-Type": "application/json"}
if api_key:
headers["X-API-Key"] = api_key
resp = requests.post(
f"{API_BASE}/user/open-bets",
json=payload,
headers=headers,
timeout=15,
)
resp.raise_for_status()
return resp.json()
def main() -> None:
parser = argparse.ArgumentParser(description="Captura aposta da Superbet via clipboard")
parser.add_argument("--api-key", default=None, help="API key para autenticação")
parser.add_argument("--text", default=None, help="Texto da aposta (em vez de clipboard)")
parser.add_argument("--paste", action="store_true", help="Lê JSON do clipboard e envia direto (modo DevTools)")
args = parser.parse_args()
if args.paste:
raw = pyperclip.paste()
try:
payload_list = json.loads(raw)
if not isinstance(payload_list, list):
payload_list = [payload_list]
except json.JSONDecodeError:
print("❌ JSON inválido no clipboard.")
sys.exit(1)
for payload in payload_list:
payload.setdefault("source", "clipboard_paste")
try:
result = send_to_api(payload, api_key=args.api_key)
print(f"🎉 Enviado: {payload.get('event_name')} — ID {result.get('id')}")
except requests.HTTPError as e:
print(f"❌ Erro: {e}")
return
text = args.text or pyperclip.paste()
if not text or len(text) < 20:
print("❌ Área de transferência vazia ou texto muito curto.")
print(" Copie o card da aposta da Superbet e tente novamente.")
sys.exit(1)
print("🔍 Analisando texto copiado...")
payload = parse_clipboard(text)
if not payload:
print("❌ Não consegui extrair dados válidos.")
print(" Certifique-se de copiar o card completo: evento, mercado, valor e odd.")
sys.exit(1)
print(f"✅ Aposta identificada: {payload['home_team']} × {payload['away_team']}")
print(f" Mercados: {', '.join(p['market'] for p in payload['picks'])}")
print(f" Stake: R$ {payload['stake']:.2f} · Odd: {payload['odds_placed']:.2f}")
print(f" Ganho potencial: R$ {payload['potential_return']:.2f}")
print(f" Ticket: {payload.get('ticket_code') or 'não identificado'}")
print("📡 Enviando para a API...")
try:
result = send_to_api(payload, api_key=args.api_key)
print(f"🎉 Aposta cadastrada! ID: {result.get('id')}")
print(" Aposta aparece no painel: /ao-vivo")
except requests.HTTPError as e:
print(f"❌ Erro da API: {e}")
try:
print(e.response.json().get("detail", ""))
except Exception:
pass
sys.exit(1)
if __name__ == "__main__":
main()