'use server' import { revalidatePath } from 'next/cache' import { auditSchreiben } from '@/server/audit' import { NichtErlaubt, pruefeRolle } from '@/server/berechtigung' import { db } from '@/server/db' import { KOPPLUNG_MINUTEN, kopplungscodeBauen, telegramAbholen, } from '@/server/integration/telegram' import { zammadAbgleichen } from '@/server/integration/zammad' import { spiegelSenden } from '@/server/integration/spiegel' import { umgebung } from '@/server/umgebung' import { jetzt } from '@/server/zeitgeber' export type Rueckmeldung = { ok: true; meldung: string } | { ok: false; fehler: string } async function akteurOderFehler() { try { return { akteur: await pruefeRolle('BENUTZER') } } catch (fehler) { if (fehler instanceof NichtErlaubt) { return { antwort: { ok: false as const, fehler: fehler.message } } } throw fehler } } /** * Erzeugt einen Kopplungscode für einen Telegram-Chat. * * Alte Codes desselben Benutzers fallen dabei weg: Zwei gültige Codes * gleichzeitig sind einer zu viel. */ export async function kopplungAnfordern(): Promise< { ok: true; code: string; minuten: number } | { ok: false; fehler: string } > { const geprueft = await akteurOderFehler() if ('antwort' in geprueft) return geprueft.antwort const { akteur } = geprueft if (!umgebung().telegramAktiv) { return { ok: false, fehler: 'Telegram ist auf diesem Server nicht eingerichtet.' } } await db.telegramKopplung.deleteMany({ where: { benutzerId: akteur.id } }) const code = kopplungscodeBauen() await db.telegramKopplung.create({ data: { code, benutzerId: akteur.id, gueltigBis: new Date(jetzt().getTime() + KOPPLUNG_MINUTEN * 60_000), }, }) await auditSchreiben({ akteur: { id: akteur.id, email: akteur.email }, aktion: 'telegram.kopplung-angefordert', objektTyp: 'TelegramKopplung', objektId: null, // Nie der Code selbst: Wer das Protokoll liest, könnte sonst koppeln. }) return { ok: true, code, minuten: KOPPLUNG_MINUTEN } } /** Trennt einen Chat wieder. */ export async function chatEntfernen(daten: FormData): Promise { const geprueft = await akteurOderFehler() if ('antwort' in geprueft) return geprueft.antwort const { akteur } = geprueft const id = daten.get('id') if (typeof id !== 'string' || id.length === 0) { return { ok: false, fehler: 'Ungültige Anfrage.' } } const chat = await db.telegramChat.findUnique({ where: { id }, select: { id: true, bezeichnung: true }, }) if (!chat) return { ok: false, fehler: 'Diesen Chat gibt es nicht.' } await db.telegramChat.delete({ where: { id: chat.id } }) await auditSchreiben({ akteur: { id: akteur.id, email: akteur.email }, aktion: 'telegram.getrennt', objektTyp: 'TelegramChat', objektId: chat.id, }) revalidatePath('/integrationen') return { ok: true, meldung: 'Chat getrennt.' } } /** Schaltet um, ob ein Chat Meldungen bekommt. */ export async function chatMeldungenUmschalten(daten: FormData): Promise { const geprueft = await akteurOderFehler() if ('antwort' in geprueft) return geprueft.antwort const { akteur } = geprueft const id = daten.get('id') if (typeof id !== 'string' || id.length === 0) { return { ok: false, fehler: 'Ungültige Anfrage.' } } const chat = await db.telegramChat.findUnique({ where: { id }, select: { id: true, meldungen: true }, }) if (!chat) return { ok: false, fehler: 'Diesen Chat gibt es nicht.' } const kuenftig = !chat.meldungen await db.telegramChat.update({ where: { id: chat.id }, data: { meldungen: kuenftig }, }) await auditSchreiben({ akteur: { id: akteur.id, email: akteur.email }, aktion: kuenftig ? 'telegram.meldungen-an' : 'telegram.meldungen-aus', objektTyp: 'TelegramChat', objektId: chat.id, }) revalidatePath('/integrationen') return { ok: true, meldung: kuenftig ? 'Dieser Chat bekommt Meldungen.' : 'Dieser Chat bekommt keine Meldungen mehr.', } } /** * Stößt einen Lauf von Hand an. * * Nützlich nach dem Einrichten: Sonst wüsste man erst beim nächsten Takt, ob * die Zugangsdaten stimmen. */ export async function laufAnstossen(daten: FormData): Promise { const geprueft = await akteurOderFehler() if ('antwort' in geprueft) return geprueft.antwort const { akteur } = geprueft const quelle = daten.get('quelle') const anstoss = { id: akteur.id, email: akteur.email } const einst = umgebung() try { if (quelle === 'ZAMMAD' && einst.zammadAktiv) { const bericht = await zammadAbgleichen(anstoss) revalidatePath('/integrationen') revalidatePath('/aufgaben') return { ok: true, meldung: `${bericht.angelegt} neu, ${bericht.aktualisiert} geändert, ${bericht.geschlossen} geschlossen.`, } } if (quelle === 'TELEGRAM' && einst.telegramAktiv) { const bericht = await telegramAbholen(anstoss) revalidatePath('/integrationen') revalidatePath('/aufgaben') return { ok: true, meldung: `${bericht.aufgaben} Aufgabe(n), ${bericht.gekoppelt} Kopplung(en), ${bericht.abgehakt} abgehakt.`, } } if (quelle === 'SPIEGEL' && einst.spiegelSendenAktiv) { const bericht = await spiegelSenden() revalidatePath('/integrationen') return { ok: true, meldung: `${bericht.belegungen} Belegung(en) und ${bericht.aufgaben} Aufgabe(n) geschickt.`, } } return { ok: false, fehler: 'Diese Integration ist hier nicht eingerichtet.' } } catch (fehler) { // Die Meldung des fremden Systems, nicht dessen Antwort im Ganzen. return { ok: false, fehler: fehler instanceof Error ? fehler.message : 'Der Lauf ist gescheitert.', } } }