diff --git a/app/api/settings/tts/default/route.ts b/app/api/settings/tts/default/route.ts index 0d5d498..eab0a6f 100644 --- a/app/api/settings/tts/default/route.ts +++ b/app/api/settings/tts/default/route.ts @@ -19,7 +19,7 @@ export async function GET(req: Request) { const voice = voices.find(v => v.value == new String(u?.ttsDefaultVoice)) return NextResponse.json(voice); } catch (error) { - console.log("[TTS/FILTER/USER]", error); + console.log("[TTS/FILTER/DEFAULT]", error); return new NextResponse("Internal Error", { status: 500 }); } } @@ -32,11 +32,9 @@ export async function POST(req: Request) { } const { voice } = await req.json(); - console.log(voice) + if (!voice || !voices.map(v => v.label.toLowerCase()).includes(voice.toLowerCase())) return new NextResponse("Bad Request", { status: 400 }); const v = voices.find(v => v.label.toLowerCase() == voice.toLowerCase()) - if (v == null) - return new NextResponse("Bad Request", { status: 400 }); await db.user.update({ where: { @@ -49,7 +47,7 @@ export async function POST(req: Request) { return new NextResponse("", { status: 200 }); } catch (error) { - console.log("[TTS/FILTER/USER]", error); + console.log("[TTS/FILTER/DEFAULT]", error); return new NextResponse("Internal Error", { status: 500 }); } } \ No newline at end of file diff --git a/app/api/settings/tts/filter/users/route.ts b/app/api/settings/tts/filter/users/route.ts index 551a6cd..fd87aef 100644 --- a/app/api/settings/tts/filter/users/route.ts +++ b/app/api/settings/tts/filter/users/route.ts @@ -30,6 +30,8 @@ export async function POST(req: Request) { } const { username, tag } = await req.json(); + if (!username || username.length < 4 || username.length > 25) return new NextResponse("Bad Request", { status: 400 }); + if (!tag || !["blacklisted", "priority"].includes(tag)) return new NextResponse("Bad Request", { status: 400 }); const filter = await db.ttsUsernameFilter.upsert({ where: { @@ -64,6 +66,7 @@ export async function DELETE(req: Request) { const { searchParams } = new URL(req.url) const username = searchParams.get('username') as string + if (!username || username.length < 4 || username.length > 25) return new NextResponse("Bad Request", { status: 400 }); const filter = await db.ttsUsernameFilter.delete({ where: { diff --git a/app/api/settings/tts/filter/words/route.ts b/app/api/settings/tts/filter/words/route.ts index 080d271..bae2306 100644 --- a/app/api/settings/tts/filter/words/route.ts +++ b/app/api/settings/tts/filter/words/route.ts @@ -30,6 +30,8 @@ export async function POST(req: Request) { } const { search, replace } = await req.json(); + if (!search || search.length < 4 || search.length > 200) return new NextResponse("Bad Request", { status: 400 }); + if (!replace) return new NextResponse("Bad Request", { status: 400 }); const filter = await db.ttsWordFilter.create({ data: { @@ -54,6 +56,9 @@ export async function PUT(req: Request) { } const { id, search, replace } = await req.json(); + if (!id || id.length < 1) return new NextResponse("Bad Request", { status: 400 }); + if (!search || search.length < 4 || search.length > 200) return new NextResponse("Bad Request", { status: 400 }); + if (!replace) return new NextResponse("Bad Request", { status: 400 }); const filter = await db.ttsWordFilter.update({ where: { @@ -83,8 +88,11 @@ export async function DELETE(req: Request) { const { searchParams } = new URL(req.url) const id = searchParams.get('id') as string const search = searchParams.get('search') as string + if (!id && !search) return new NextResponse("Bad Request", { status: 400 }); if (search) { + if (search.length < 4 || search.length > 200) return new NextResponse("Bad Request", { status: 400 }); + const filter = await db.ttsWordFilter.delete({ where: { userId_search: { @@ -96,6 +104,8 @@ export async function DELETE(req: Request) { return NextResponse.json(filter) } else if (id) { + if (id.length < 1) return new NextResponse("Bad Request", { status: 400 }); + const filter = await db.ttsWordFilter.delete({ where: { id: id diff --git a/app/api/settings/tts/route.ts b/app/api/settings/tts/route.ts index e9c0cd2..e3e04a8 100644 --- a/app/api/settings/tts/route.ts +++ b/app/api/settings/tts/route.ts @@ -10,21 +10,14 @@ export async function GET(req: Request) { return new NextResponse("Unauthorized", { status: 401 }); } - const u = await db.user.findFirst({ - where: { - id: user.id - } - }); - let list : { value: string; label: string; gender: string; language: string; }[] = [] - const enabled = u?.ttsEnabledVoice ?? 0 - for (let i = 0; i < voices.length; i++) { - var v = voices[i] + const enabled = user.ttsEnabledVoice + for (let v of voices) { var n = Number.parseInt(v.value) - 1 if ((enabled & (1 << n)) > 0) { list.push(v) @@ -46,7 +39,6 @@ export async function POST(req: Request) { } let { voice } = await req.json(); - console.log(voice) voice = voice & ((1 << voices.length) - 1) await db.user.update({ diff --git a/app/settings/tts/filters/page.tsx b/app/settings/tts/filters/page.tsx index 3ecf7fc..ced59a5 100644 --- a/app/settings/tts/filters/page.tsx +++ b/app/settings/tts/filters/page.tsx @@ -10,11 +10,16 @@ import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, Command import { Input } from "@/components/ui/input"; import { useRouter } from "next/navigation"; import { useForm } from "react-hook-form"; -import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; +import { Form, FormControl, FormField, FormItem, FormMessage } from "@/components/ui/form"; import * as z from "zod"; import { zodResolver } from "@hookform/resolvers/zod"; import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"; import { Label } from "@/components/ui/label"; +import { ToastAction } from "@/components/ui/toast" +import { useToast } from "@/components/ui/use-toast" +import InfoNotice from "@/components/elements/info-notice"; +import { Toaster } from "@/components/ui/toaster"; +import { stringifyError } from "next/dist/shared/lib/utils"; const TTSFiltersPage = () => { @@ -23,6 +28,8 @@ const TTSFiltersPage = () => { const [tag, setTag] = useState("blacklisted") const [open, setOpen] = useState(false) const [userTags, setUserTag] = useState<{ username: string, tag: string }[]>([]) + const { toast } = useToast() + const [error, setError] = useState("") const router = useRouter(); const tags = [ @@ -30,9 +37,24 @@ const TTSFiltersPage = () => { "priority" ] + const toasting = (title: string, error: Error) => { + toast({ + title: title, + description: error.message, + variant: "error" + }) + } + + const success = (title: string, description: string) => { + toast({ + title: title, + description: description, + variant: "success" + }) + } + // Username blacklist const usernameFilteredFormSchema = z.object({ - //userId: z.string().trim().min(1), username: z.string().trim().min(4).max(25).regex(new RegExp("[a-zA-Z0-9][a-zA-Z0-9\_]{3,24}"), "Must be a valid twitch username."), tag: z.string().trim() }); @@ -40,7 +62,6 @@ const TTSFiltersPage = () => { const usernameFilteredForm = useForm({ resolver: zodResolver(usernameFilteredFormSchema), defaultValues: { - //userId: session?.user?.id ?? "", username: "", tag: "" } @@ -52,18 +73,18 @@ const TTSFiltersPage = () => { const userFiltersData = await axios.get("/api/settings/tts/filter/users") setUserTag(userFiltersData.data ?? []) } catch (error) { - console.log("ERROR", error) + toasting("Failed to fetch all the username filters.", error as Error) } try { const replacementData = await axios.get("/api/settings/tts/filter/words") setReplacements(replacementData.data ?? []) - } catch (e) { - console.log("ERROR", e) + } catch (error) { + toasting("Failed to fetch all the word filters.", error as Error) } }; - fetchData().catch(console.error); + fetchData().catch((error) => toasting("Failed to fetch all the username filters.", error as Error)); }, []); const onDelete = () => { @@ -71,33 +92,34 @@ const TTSFiltersPage = () => { axios.delete("/api/settings/tts/filter/users?username=" + username) .then(() => { setUserTag(userTags.filter((u) => u.username != username)) - }).catch((e) => console.error(e)) + success("Username filter deleted", `"${username.toLowerCase()}" is now back to normal.`) + }).catch((error) => toasting("Failed to delete the username filter.", error as Error)) } const isSubmitting = usernameFilteredForm.formState.isSubmitting; const onAddExtended = (values: z.infer, test: boolean = true) => { - try { - const original = userTags.find(u => u.username.toLowerCase() == values.username.toLowerCase()) + const original = userTags.find(u => u.username.toLowerCase() == values.username.toLowerCase()) - if (test) - values.tag = tag - - axios.post("/api/settings/tts/filter/users", values) - .then((d) => { - if (original == null) { - userTags.push({ username: values.username.toLowerCase(), tag: values.tag }) - } else { - original.tag = values.tag - } - setUserTag(userTags) + if (test) + values.tag = tag + + axios.post("/api/settings/tts/filter/users", values) + .then((d) => { + if (original == null) { + userTags.push({ username: values.username.toLowerCase(), tag: values.tag }) + } else { + original.tag = values.tag + } + setUserTag(userTags) - usernameFilteredForm.reset(); - router.refresh(); - }) - } catch (error) { - console.log("[TTS/FILTERS/USER]", error); - } + usernameFilteredForm.reset(); + router.refresh(); + if (values.tag == "blacklisted") + success("Username filter added", `"${values.username.toLowerCase()}" will be blocked.`) + else if (values.tag == "priority") + success("Username filter added", `"${values.username.toLowerCase()}" will be taking priority.`) + }).catch(error => toasting("Failed to add the username filter.", error as Error)) } const onAdd = (values: z.infer) => { @@ -108,27 +130,24 @@ const TTSFiltersPage = () => { const [replacements, setReplacements] = useState<{ id: string, search: string, replace: string, userId: string }[]>([]) const onReplaceAdd = async () => { + if (search.length <= 0) { + toasting("Unable to add the word filter.", new Error("Search must not be empty.")) + return + } + await axios.post("/api/settings/tts/filter/words", { search, replace }) .then(d => { replacements.push({ id: d.data.id, search: d.data.search, replace: d.data.replace, userId: d.data.userId }) setReplacements(replacements) setSearch("") - }).catch(e => { - // TODO: handle already exist. - console.log("LOGGED:", e) - return null - }) + success("Word filter added", `"${d.data.search}" will be replaced.`) + }).catch(error => toasting("Failed to add the word filter.", error as Error)) } const onReplaceUpdate = async (data: { id: string, search: string, replace: string, userId: string }) => { await axios.put("/api/settings/tts/filter/words", data) - .then(d => { - //setReplacements(replacements.filter(r => r.id != id)) - }).catch(e => { - // TODO: handle does not exist. - console.log("LOGGED:", e) - return null - }) + .then(() => success("Word filter updated", "")) + .catch(error => toasting("Failed to update the word filter.", error as Error)) } const onReplaceDelete = async (id: string) => { @@ -136,29 +155,10 @@ const TTSFiltersPage = () => { .then(d => { const r = replacements.filter(r => r.id != d.data.id) setReplacements(r) - console.log(r) - }).catch(e => { - // TODO: handle does not exist. - console.log("LOGGED:", e) - return null - }) + success("Word filter deleted", `No more filter for "${d.data.search}"`) + }).catch(error => toasting("Failed to delete the word filter.", error as Error)) } - // const replaceFormSchema = z.object({ - // //userId: z.string().trim().min(1), - // search: z.string().trim().min(1), - // replace: z.string().trim().min(0), - // }); - - // const replaceForm = useForm({ - // resolver: zodResolver(replaceFormSchema), - // defaultValues: { - // //userId: session?.user?.id ?? "", - // search: "", - // replace: "" - // } - // }); - let [search, setSearch] = useState("") let [replace, setReplace] = useState("") let [searchInfo, setSearchInfo] = useState("") @@ -166,10 +166,11 @@ const TTSFiltersPage = () => { return (
TTS Filters
-
+
+