curl, PowerShell e Python
Os três exemplos mandam o mesmo cartão no formato GGspeak, com key: rodar de novo com state em ok atualiza o cartão. O link vem de uma variável de ambiente, GGSPEAK_WEBHOOK.
curl -fsS -X POST "$GGSPEAK_WEBHOOK" \ -H "Content-Type: application/json" \ -d '{ "key": "backup-noturno", "card": { "title": "Backup noturno", "state": "alert", "body": "pg_dump falhou: sem espaço em disco", "fields": [{ "name": "Servidor", "value": "sp-1" }] } }'-f faz o curl sair com erro em respostas 4xx e 5xx, e -S mostra a mensagem mesmo com -s. Para ver o corpo do erro, tire o -f.
# O Windows PowerShell 5.1 pode usar TLS antigo por padrão.[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$body = @{ key = 'backup-noturno' card = @{ title = 'Backup noturno' state = 'alert' body = 'pg_dump falhou: sem espaço em disco' fields = @(@{ name = 'Servidor'; value = 'sp-1' }) }} | ConvertTo-Json -Depth 5
try { # Os bytes em UTF-8: sem isso, o 5.1 estraga acentos. Invoke-RestMethod -Method Post -Uri $env:GGSPEAK_WEBHOOK ` -ContentType 'application/json; charset=utf-8' ` -Body ([System.Text.Encoding]::UTF8.GetBytes($body))} catch { # No 5.1, o corpo do erro fica em ErrorDetails. Write-Error $_.ErrorDetails.Message}Com sucesso, a resposta é 204 e Invoke-RestMethod não devolve nada. Com ?wait=true na URL, devolve a mensagem como objeto.
import osimport requests
payload = { "key": "backup-noturno", "card": { "title": "Backup noturno", "state": "alert", "body": "pg_dump falhou: sem espaço em disco", "fields": [{"name": "Servidor", "value": "sp-1"}], },}
r = requests.post(os.environ["GGSPEAK_WEBHOOK"], json=payload, timeout=10)
if r.status_code == 429: try: wait = r.json()["retry_after"] # segundos, com decimais except (ValueError, KeyError, TypeError): # 429 de um proxy, sem o corpo do GGspeak wait = r.headers.get("Retry-After", "1") print(f"Muitos envios. Tente de novo em {wait} s.")elif not r.ok: try: err = r.json() print(f"{err['code']}: {err['message']} ({err['docs']})") except (ValueError, KeyError, TypeError): # erro de gateway, sem JSON print(f"HTTP {r.status_code}: {r.text[:200]}")O requests já manda Content-Type: application/json e codifica em UTF-8 com json=. r.ok é verdadeiro no 204.
Para ficar em ok quando o script termina bem, mande outro POST com a mesma key e "state": "ok" (o cartão vira “Resolvido”). Os códigos de erro estão em Erros.