Files
MikrotikManager/hooks/use-alerts-telegram-preview.ts
T

35 lines
2.4 KiB
TypeScript

"use client"
import {useEffect,useRef,useState,useSyncExternalStore} from "react"
import {testTelegramSchema,type TestTelegramBody} from "@mmapp/contracts/alerts"
import {can} from "@/lib/auth"
import {telegramPending,subscribeTelegramPending,setTelegramPending} from "@/lib/alerts-telegram-checkpoint"
import {ApiClientError} from "@/shared/api/http-client"
import {testAlertsTelegram} from "@/shared/api/alerts"
export function useAlertsTelegramPreview(base:string,live:boolean,available:boolean,onBegin:()=>boolean,onEnd:()=>void){
const source=JSON.stringify([live,base])
const unknown=useSyncExternalStore(subscribeTelegramPending,()=>telegramPending(source),()=>false)
const [busy,setBusy]=useState(false),[error,setError]=useState<string|null>(null),[outcome,setOutcome]=useState<string|null>(null)
const active=useRef(true),lock=useRef(false),controller=useRef<AbortController|null>(null)
useEffect(()=>{active.current=true;return()=>{active.current=false;controller.current?.abort()}},[source])
const enabled=live&&available&&can("mm:alerts:write")
async function test(payload:TestTelegramBody){
if(!enabled||lock.current||telegramPending(source)||!active.current||!can("mm:alerts:write"))return false
const parsed=testTelegramSchema.strict().safeParse(payload)
if(!parsed.success){setError("Проверьте параметры тестового сообщения");return false}
if(!onBegin())return false
lock.current=true;controller.current=new AbortController();setBusy(true);setError(null);setOutcome(null);setTelegramPending(source,true)
const current=()=>active.current&&can("mm:alerts:write")
try{
await testAlertsTelegram(base,parsed.data,{signal:controller.current.signal});if(!current())return false
setTelegramPending(source,false);setOutcome("Telegram API подтвердил приём тестового правила. Проверьте его в чате.");return true
}catch(e){
if(e instanceof ApiClientError&&[400,401,403,409,422].includes(e.status)&&current())setTelegramPending(source,false)
if(current())setError(e instanceof Error?e.message:"Результат отправки не получен");return false
}finally{lock.current=false;controller.current=null;if(active.current){setBusy(false);onEnd()}}
}
function review(){if(!enabled||busy)return;setTelegramPending(source,false)}
function clear(){setError(null);setOutcome(null)}
return {test,busy,error,outcome,unknown,enabled,review,clear}
}