Added API for TTS Username Filters
This commit is contained in:
parent
d49779e76f
commit
c3e1c1cb60
82
app/api/settings/tts/filter/users/route.ts
Normal file
82
app/api/settings/tts/filter/users/route.ts
Normal file
@ -0,0 +1,82 @@
|
||||
import { db } from "@/lib/db"
|
||||
import { NextResponse } from "next/server";
|
||||
import fetchUserUsingAPI from "@/lib/validate-api";
|
||||
|
||||
export async function GET(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserUsingAPI(req)
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
||||
const filters = await db.ttsUsernameFilter.findMany({
|
||||
where: {
|
||||
userId: user.id
|
||||
}
|
||||
});
|
||||
|
||||
return NextResponse.json(filters);
|
||||
} catch (error) {
|
||||
console.log("[TTS/FILTER/USER]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserUsingAPI(req)
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
||||
const { username, tag } = await req.json();
|
||||
|
||||
const filter = await db.ttsUsernameFilter.upsert({
|
||||
where: {
|
||||
userId_username: {
|
||||
userId: user.id as string,
|
||||
username
|
||||
}
|
||||
},
|
||||
update: {
|
||||
tag
|
||||
},
|
||||
create: {
|
||||
userId: user.id as string,
|
||||
username,
|
||||
tag
|
||||
}
|
||||
});
|
||||
|
||||
return NextResponse.json(filter);
|
||||
} catch (error) {
|
||||
console.log("[TTS/FILTER/USER]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function DELETE(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserUsingAPI(req)
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
||||
const { searchParams } = new URL(req.url)
|
||||
const username = searchParams.get('username') as string
|
||||
|
||||
const filter = await db.ttsUsernameFilter.delete({
|
||||
where: {
|
||||
userId_username: {
|
||||
userId: user.id as string,
|
||||
username
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return NextResponse.json(filter)
|
||||
} catch (error) {
|
||||
console.log("[TTS/FILTER/USER]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
import axios from "axios";
|
||||
import * as React from 'react';
|
||||
import { Calendar, Check, ChevronsUpDown, MoreHorizontal, Plus, Tags, Trash, User } from "lucide-react"
|
||||
import { ApiKey, TwitchConnection } from "@prisma/client";
|
||||
import { ApiKey, TtsUsernameFilter, TwitchConnection } from "@prisma/client";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useSession } from "next-auth/react";
|
||||
import Link from "next/link";
|
||||
@ -23,6 +23,7 @@ import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { DropdownMenu, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger } from "@/components/ui/dropdown-menu";
|
||||
import { DropdownMenuContent, DropdownMenuTrigger } from "@radix-ui/react-dropdown-menu";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { db } from "@/lib/db";
|
||||
|
||||
const TTSFiltersPage = () => {
|
||||
const { data: session, status } = useSession();
|
||||
@ -30,33 +31,36 @@ const TTSFiltersPage = () => {
|
||||
const [moreOpen, setMoreOpen] = useState<number>(0)
|
||||
const [tag, setTag] = useState("blacklisted")
|
||||
const [open, setOpen] = useState<boolean>(false)
|
||||
const [userTags, setUserTag] = useState<{ username: string, tag: string }[]>([{ username: "test", tag:"blacklisted" }, { username: "hello world", tag:"moderator" }])
|
||||
const [userTags, setUserTag] = useState<{ username: string, tag: string }[]>([])
|
||||
const router = useRouter();
|
||||
|
||||
const labels = [
|
||||
const tags = [
|
||||
"blacklisted",
|
||||
"priority"
|
||||
]
|
||||
|
||||
// Username blacklist
|
||||
const usernameFilteredFormSchema = z.object({
|
||||
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.")
|
||||
//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()
|
||||
});
|
||||
|
||||
|
||||
const usernameFilteredForm = useForm({
|
||||
resolver: zodResolver(usernameFilteredFormSchema),
|
||||
defaultValues: {
|
||||
username: ""
|
||||
//userId: session?.user?.id ?? "",
|
||||
username: "",
|
||||
tag: ""
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
// const userFiltersData = (await axios.get("/api/settings/tts/filters/users")).data ?? {};
|
||||
// setApiKeys(userFiltersData)
|
||||
// console.log(userFiltersData);
|
||||
const userFiltersData = await axios.get("/api/settings/tts/filter/users");
|
||||
setUserTag(userFiltersData.data ?? [])
|
||||
} catch (error) {
|
||||
console.log("ERROR", error)
|
||||
}
|
||||
@ -65,47 +69,31 @@ const TTSFiltersPage = () => {
|
||||
fetchData().catch(console.error);
|
||||
}, []);
|
||||
|
||||
const onApiKeyAdd = async () => {
|
||||
///let usernames = blacklistedUsers.split("\n");
|
||||
//console.log(usernames)
|
||||
// try {
|
||||
// await axios.post("/api/settings/tts/filters/users", {
|
||||
// usernames: []
|
||||
// });
|
||||
// setUserFilters(userFilters.concat(usernames))
|
||||
// } catch (error) {
|
||||
// console.log("ERROR", error)
|
||||
// }
|
||||
}
|
||||
|
||||
const onApiKeyDelete = async (username: string) => {
|
||||
try {
|
||||
await axios.delete("/api/settings/tts/filters/users/" + username);
|
||||
//setUserFilters(userFilters.filter((u) => u != username))
|
||||
} catch (error) {
|
||||
console.log("ERROR", error)
|
||||
}
|
||||
const onDelete = () => {
|
||||
const username = userTags[Math.log2(moreOpen)].username
|
||||
axios.delete("/api/settings/tts/filter/users?username=" + username)
|
||||
.then(() => {
|
||||
setUserTag(userTags.filter((u) => u.username != username))
|
||||
}).catch((e) => console.error(e))
|
||||
}
|
||||
|
||||
const isLoading = usernameFilteredForm.formState.isSubmitting;
|
||||
|
||||
const addTwitchUser = (values: z.infer<typeof usernameFilteredFormSchema>) => {
|
||||
let response = null;
|
||||
console.log("TEST")
|
||||
console.log(values)
|
||||
const onAdd = (values: z.infer<typeof usernameFilteredFormSchema>) => {
|
||||
try {
|
||||
values.tag = tag
|
||||
axios.post("/api/settings/tts/filter/users", values)
|
||||
.then((d) => {
|
||||
userTags.push({ username: values.username, tag: tag })
|
||||
setUserTag(userTags)
|
||||
|
||||
// try {
|
||||
// response = await axios.post("/api/settings/tts/filter/badges", values);
|
||||
// } catch (error) {
|
||||
// console.log("[CONNECTIONS/TWITCH/POST]", error);
|
||||
// return;
|
||||
// }
|
||||
|
||||
userTags.push({ username: values.username, tag: tag })
|
||||
setUserTag(userTags)
|
||||
usernameFilteredForm.reset();
|
||||
router.refresh();
|
||||
//window.location.reload();
|
||||
usernameFilteredForm.reset();
|
||||
router.refresh();
|
||||
})
|
||||
} catch (error) {
|
||||
console.log("[TTS/FILTERS/USER]", error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
@ -114,12 +102,12 @@ const TTSFiltersPage = () => {
|
||||
<div className="px-10 py-10 w-full h-full flex-grow inset-y-1/2">
|
||||
<div>
|
||||
{userTags.map((user, index) => (
|
||||
<div className="flex w-full flex-col items-start justify-between rounded-md border px-4 py-3 sm:flex-row sm:items-center">
|
||||
<p className="text-sm font-medium leading-none">
|
||||
<div className="flex w-full items-start justify-between rounded-md border px-2 py-3">
|
||||
<p className="text-base font-medium">
|
||||
<span className="mr-2 rounded-lg bg-primary px-2 py-1 text-xs text-primary-foreground">
|
||||
{user.tag}
|
||||
</span>
|
||||
<span className="text-muted-foreground">{user.username}</span>
|
||||
<span className="text-white">{user.username}</span>
|
||||
</p>
|
||||
<DropdownMenu open={(moreOpen & (1 << index)) > 0} onOpenChange={() => setMoreOpen((v) => v ^ (1 << index))}>
|
||||
<DropdownMenuTrigger asChild>
|
||||
@ -144,17 +132,17 @@ const TTSFiltersPage = () => {
|
||||
<CommandList>
|
||||
<CommandEmpty>No label found.</CommandEmpty>
|
||||
<CommandGroup>
|
||||
{labels.map((label) => (
|
||||
{tags.map((tag) => (
|
||||
<CommandItem
|
||||
key={label}
|
||||
value={label}
|
||||
key={tag}
|
||||
value={tag}
|
||||
onSelect={(value) => {
|
||||
userTags[index].tag = value
|
||||
setUserTag(userTags)
|
||||
setMoreOpen(0)
|
||||
}}
|
||||
>
|
||||
{label}
|
||||
{tag}
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
@ -163,10 +151,7 @@ const TTSFiltersPage = () => {
|
||||
</DropdownMenuSubContent>
|
||||
</DropdownMenuSub>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem onClick={() => {
|
||||
userTags.splice(index, 1)
|
||||
setUserTag(userTags)
|
||||
}} className="text-red-600">
|
||||
<DropdownMenuItem onClick={onDelete} className="text-red-600">
|
||||
<Trash className="mr-2 h-4 w-4" />
|
||||
Delete
|
||||
</DropdownMenuItem>
|
||||
@ -176,9 +161,9 @@ const TTSFiltersPage = () => {
|
||||
</div>
|
||||
))}
|
||||
<Form {...usernameFilteredForm}>
|
||||
<form onSubmit={usernameFilteredForm.handleSubmit(addTwitchUser)}>
|
||||
<div className="flex w-full flex-col items-start justify-between rounded-md border px-4 py-3 sm:flex-row sm:items-center">
|
||||
<Label className=" mr-2 rounded-lg bg-primary px-2 py-1 text-xs text-primary-foreground">
|
||||
<form onSubmit={usernameFilteredForm.handleSubmit(onAdd)}>
|
||||
<div className="flex w-full items-start justify-between rounded-md border px-4 py-3">
|
||||
<Label className="mr-2 rounded-lg bg-primary px-2 py-1 text-xs text-primary-foreground">
|
||||
{tag}
|
||||
</Label>
|
||||
<FormField
|
||||
@ -219,15 +204,15 @@ const TTSFiltersPage = () => {
|
||||
<CommandList>
|
||||
<CommandEmpty>No label found.</CommandEmpty>
|
||||
<CommandGroup>
|
||||
{labels.map((label) => (
|
||||
{tags.map((tag) => (
|
||||
<CommandItem
|
||||
value={label}
|
||||
value={tag}
|
||||
onSelect={(value) => {
|
||||
setTag(value)
|
||||
setOpen(false)
|
||||
}}
|
||||
>
|
||||
{label}
|
||||
{tag}
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
|
@ -3,9 +3,8 @@ import { CardWrapper } from "./card-wrapper"
|
||||
export const LoginForm = () => {
|
||||
return (
|
||||
<CardWrapper
|
||||
headerLabel="Welcome back"
|
||||
>
|
||||
Login Form
|
||||
headerLabel="Welcome back">
|
||||
<div></div>
|
||||
</CardWrapper>
|
||||
)
|
||||
}
|
@ -12,7 +12,7 @@ const SettingsNavigation = async () => {
|
||||
</div>
|
||||
|
||||
<div className="flex h-full z-20 inset-y-1/3 w-full">
|
||||
<ul className="rounded-lg shadow-md pl-[25px] flex flex-col w-full justify-between rounded-md text-center align-center">
|
||||
<ul className="rounded-lg shadow-md pl-[25px] flex flex-col w-full justify-between text-center align-center">
|
||||
<li className="text-xs text-gray-400">
|
||||
Settings
|
||||
</li>
|
||||
|
@ -18,8 +18,8 @@ model User {
|
||||
apiKeys ApiKey[]
|
||||
accounts Account[]
|
||||
twitchConnections TwitchConnection[]
|
||||
createdProfiles TtsProfile[]
|
||||
profileStatus TtsProfileStatus[]
|
||||
ttsUsernameFilter TtsUsernameFilter[]
|
||||
ttsWordFilter TtsWordFilter[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
@ -65,69 +65,24 @@ model TwitchConnection {
|
||||
@@index([userId])
|
||||
}
|
||||
|
||||
model TtsProfile {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
statuses TtsProfileStatus[]
|
||||
badgeFilters TtsBadgeFilter[]
|
||||
usernameFilters TtsUsernameFilter[]
|
||||
wordFilters TtsWordReplacementFilter[]
|
||||
|
||||
creatorId String
|
||||
creator User @relation(fields: [creatorId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([creatorId])
|
||||
@@unique([creatorId, name])
|
||||
}
|
||||
|
||||
model TtsProfileStatus {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
enabled Boolean
|
||||
|
||||
userId String
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
profileId String
|
||||
profile TtsProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([userId])
|
||||
@@index([profileId])
|
||||
}
|
||||
|
||||
model TtsBadgeFilter {
|
||||
badgeId String
|
||||
|
||||
profileId String
|
||||
profile TtsProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([profileId])
|
||||
@@id([profileId, badgeId])
|
||||
}
|
||||
|
||||
model TtsUsernameFilter {
|
||||
username String
|
||||
tag String
|
||||
|
||||
profileId String
|
||||
profile TtsProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
|
||||
userId String
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([profileId])
|
||||
@@id([profileId, username])
|
||||
@@index([userId])
|
||||
@@id([userId, username])
|
||||
}
|
||||
|
||||
model TtsWordReplacementFilter {
|
||||
word String
|
||||
model TtsWordFilter {
|
||||
search String
|
||||
replace String
|
||||
|
||||
profileId String
|
||||
profile TtsProfile @relation(fields: [profileId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([profileId])
|
||||
@@id([profileId, word])
|
||||
}
|
||||
userId String
|
||||
profile User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([userId])
|
||||
@@id([userId, search])
|
||||
}
|
Loading…
Reference in New Issue
Block a user