Bug-Reports, Devlog-Threads und Watchdog

- /bug (alle Member): erstellt Gitea-Issue inkl. Screenshot-Upload als Asset;
  bug_reports-Tabelle für den Rückkanal — Issue geschlossen (issues-Webhook)
  → DM an den Reporter
- Auto-Thread '💬 Devlog <Datum>' unter jedem Devlog-Post (Setting, Default an)
- Watchdog: prüft Setting watchdog_urls alle 2 min, DM an Admin nach 2 Fails
  in Folge + Entwarnung mit Downtime-Dauer
- Setup-Seite: Bug-Repo, Threads-Toggle, Watchdog-URLs; Env GITEA_API_TOKEN/GITEA_URL

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-23 11:29:01 +02:00
co-authored by Claude Opus 4.8
parent 4fb3a6d02c
commit 07c3bf47d0
15 changed files with 359 additions and 4 deletions
+38
View File
@@ -0,0 +1,38 @@
// Minimaler Gitea-API-Client (Token-Auth) — für /bug → Issues
import { config } from './config.js';
function headers(extra = {}) {
return {
Authorization: `token ${config.giteaApiToken}`,
Accept: 'application/json',
...extra,
};
}
/** Issue anlegen; gibt { number, html_url } zurück */
export async function createIssue(repo, title, body) {
const res = await fetch(`${config.giteaUrl}/api/v1/repos/${repo}/issues`, {
method: 'POST',
headers: headers({ 'Content-Type': 'application/json' }),
body: JSON.stringify({ title, body }),
});
if (!res.ok) {
throw new Error(`Gitea createIssue ${res.status}: ${(await res.text()).slice(0, 200)}`);
}
const issue = await res.json();
return { number: issue.number, html_url: issue.html_url };
}
/** Datei (z. B. Screenshot) als Issue-Attachment hochladen */
export async function uploadIssueAsset(repo, issueNumber, filename, buffer) {
const form = new FormData();
form.append('attachment', new Blob([buffer]), filename);
const res = await fetch(
`${config.giteaUrl}/api/v1/repos/${repo}/issues/${issueNumber}/assets?name=${encodeURIComponent(filename)}`,
{ method: 'POST', headers: headers(), body: form }
);
if (!res.ok) {
throw new Error(`Gitea uploadIssueAsset ${res.status}`);
}
return res.json();
}