Send a bug report to one place, on purpose, after reading it

The page built its own markdown and nothing could send it; local and upstream
are different people, so neither falls back to the other.
This commit is contained in:
Gmer4Lfe
2026-08-13 16:32:36 -04:00
parent 2c1fd4c8bf
commit 2ccc93bb14
6 changed files with 261 additions and 39 deletions
+67
View File
@@ -1372,6 +1372,73 @@ function vv_ai_bug_report(array $b): string {
return $out;
}
// Where a report can go from this install, resolved once so the page and the sender agree.
//
// Local is opt-in and off by default, because a default that files into the operator's own
// tracker means every report from every other install lands somewhere the maintainer never
// looks — a fallback chain is right for fetching code and wrong for sending a report.
function vv_ai_bug_targets(): array {
$v = vv_conf_vars();
$slot = strtoupper(vv_detect_host());
$on = strtolower(trim($v['BUG_REPORT_LOCAL_ENABLED'] ?? 'false')) === 'true';
$url = trim((string) ($v[$slot . '_BUG_REPORT_URL'] ?? ''));
$repo = trim((string) ($v[$slot . '_BUG_REPORT_REPO'] ?? ''));
$token = trim((string) ($v[$slot . '_BUG_REPORT_TOKEN'] ?? ''));
return [
// Configured is not the same as enabled: the switch is off but the details are filled in
// is a state worth showing, because it is what "why did this go to GitHub" looks like.
'local_enabled' => $on,
'local_configured' => $url !== '' && $repo !== '' && $token !== '',
'local_url' => $url,
'local_repo' => $repo,
'github_repo' => trim((string) ($v['BUG_REPORT_GITHUB_REPO'] ?? 'FailedProxy/Varaverk')),
];
}
// Files the report as an issue on the operator's own Gitea. Only ever reached when the switch is
// on and the details are present — never as a fallback from a failed GitHub send, because the two
// go to different people and quietly substituting one for the other is the whole failure mode
// this design exists to avoid.
function vv_ai_bug_send_local(string $title, string $body): array {
$t = vv_ai_bug_targets();
if (!$t['local_enabled']) return ['ok' => false, 'error' => 'local reporting is switched off'];
if (!$t['local_configured']) return ['ok' => false, 'error' => 'local reporting is on but URL, repo or token is blank'];
if (!function_exists('curl_init')) return ['ok' => false, 'error' => 'curl is unavailable'];
$v = vv_conf_vars();
$slot = strtoupper(vv_detect_host());
$token = trim((string) ($v[$slot . '_BUG_REPORT_TOKEN'] ?? ''));
$api = rtrim($t['local_url'], '/') . '/api/v1/repos/' . trim($t['local_repo'], '/') . '/issues';
$ch = curl_init($api);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json',
'Authorization: token ' . $token],
CURLOPT_POSTFIELDS => json_encode(['title' => $title, 'body' => $body]),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_FOLLOWLOCATION => false,
]);
$resp = curl_exec($ch);
$code = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
$err = curl_error($ch);
curl_close($ch);
if ($resp === false) return ['ok' => false, 'error' => 'could not reach Gitea: ' . $err];
if ($code === 401 || $code === 403) return ['ok' => false, 'error' => 'Gitea refused the token (HTTP ' . $code . ')'];
if ($code === 404) return ['ok' => false, 'error' => 'Gitea has no such repo (HTTP 404) — check the owner/repo'];
if ($code < 200 || $code >= 300) return ['ok' => false, 'error' => 'Gitea returned HTTP ' . $code];
$d = json_decode((string) $resp, true);
// The URL back is the whole point of sending server-side rather than opening a form: it is
// proof the issue exists, and somewhere to go and look at it.
return ['ok' => true, 'url' => $d['html_url'] ?? '', 'number' => $d['number'] ?? null];
}
// Best effort, and blank rather than wrong. /etc/unraid-version is a shell assignment; on
// anything that is not Unraid there is simply no file and the report says "?".
function vv_ai_bug_unraid_version(): string {