false,'error'=>'forbidden'], 403); $j = json_in(); $action = (string)($j['action'] ?? 'list'); $r = redis(); if ($action === 'list') { $cs = $r->sMembers(global_bans_key()); if (!is_array($cs)) $cs = []; sort($cs); json_out(['ok'=>true, 'callsigns'=>$cs, 'can_write'=>$acting_level >= 3]); } csrf_check(); if ($acting_level < 3) json_out(['ok'=>false,'error'=>'lvl3_required'], 403); if ($action === 'add') { $cs = base_call((string)($j['value'] ?? '')); if ($cs === '' || !preg_match('/^[A-Z0-9]+$/', $cs)) json_out(['ok'=>false,'error'=>'invalid_callsign'], 400); $r->sAdd(global_bans_key(), $cs); json_out(['ok'=>true]); } if ($action === 'remove') { $cs = base_call((string)($j['value'] ?? '')); if ($cs === '') json_out(['ok'=>false,'error'=>'invalid_callsign'], 400); $r->sRem(global_bans_key(), $cs); json_out(['ok'=>true]); } json_out(['ok'=>false,'error'=>'unknown_action'], 400);