Skip to content

Commit

Permalink
feat: add whishper integration
Browse files Browse the repository at this point in the history
  • Loading branch information
aamirazad committed Jul 6, 2024
1 parent 2a9cea3 commit 451c532
Show file tree
Hide file tree
Showing 4 changed files with 231 additions and 1 deletion.
47 changes: 47 additions & 0 deletions src/app/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ import { users } from "@/server/db/schema";
import type { PaperlessDocumentsType } from "@/types";
import { auth } from "@clerk/nextjs/server";

/*
Clerk helpers
___| | ___ _ __| | __
/ __| |/ _ | '__| |/ /
| (__| | __| | | <
\___|_|\___|_| |_|\_\
*/

export async function setUserProperty<K extends keyof UsersTableType>(
propertyName: K,
value: UsersTableType[K],
Expand Down Expand Up @@ -43,6 +51,15 @@ export async function getUserData() {
return userData;
}

/*
Paperless
| _ \ __ _ _ __ ___ _ __| | ___ ___ ___
| |_) / _` | '_ \ / _ | '__| |/ _ / __/ __|
| __| (_| | |_) | __| | | | __\__ \__ \
|_| \__,_| .__/ \___|_| |_|\___|___|___/
|_|
*/

export async function getPaperlessDocuments(query: string) {
const userData = await getUserData();

Expand All @@ -63,3 +80,33 @@ export async function getPaperlessDocuments(query: string) {

return data;
}

/*
Whishper
\ \ / (_)___| |__ _ __ ___ _ __
\ \ /\ / /| / __| '_ \| '_ \ / _ | '__|
\ V V / | \__ | | | | |_) | __| |
\_/\_/ |_|___|_| |_| .__/ \___|_|
|_|
*/

export async function getWhishperRecordings(query: string) {
const userData = await getUserData();

if (!query || query == "null" || query.length < 3 || !userData) return null;

const response = await fetch(
`${userData.whishperURL}/api/documents/?query=${query}&page=1&page_size=10&truncate_content=true`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Token ${userData.paperlessToken}`,
},
},
);

const data = (await response.json()) as PaperlessDocumentsType;

return data;
}
165 changes: 165 additions & 0 deletions src/app/whishper/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
"use client";

import { SignedIn, SignedOut } from "@clerk/nextjs";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { Button } from "@/components/ui/button";
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import Link from "next/link";
import { zodResolver } from "@hookform/resolvers/zod";
import { useCallback } from "react";
import { useQuery } from "@tanstack/react-query";
import { getUserData, getWhishperRecordings } from "../actions";
import LoadingSpinner from "@/components/loading-spinner";

function SearchForm() {
const formSchema = z.object({
query: z.string().min(3).max(256),
});
const router = useRouter();
const pathname = usePathname();
const searchParams = useSearchParams();
const givenQuery = searchParams.get("query") ?? "";
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
query: givenQuery,
},
});

const createQueryString = useCallback(
(name: string, value: string) => {
const params = new URLSearchParams(searchParams.toString());
params.set(name, value);

return params.toString();
},
[searchParams],
);

function onSubmit(values: z.infer<typeof formSchema>) {
if (values.query)
router.replace(pathname + "?" + createQueryString("query", values.query));
}

return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="w-64 space-y-4">
<FormField
control={form.control}
name="query"
render={({ field }) => (
<FormItem>
<FormLabel>Search for your voice recordings</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit" className="dark:bg-slate-200">
Submit
</Button>
</form>
</Form>
);
}

function RecordingsList() {
const searchParams = useSearchParams();
const query = searchParams.get("query");

const WhishperRecordings = useQuery({
queryKey: ["key", query],
queryFn: async () => {
if (!query) {
return Promise.resolve(null);
}
const response = await getWhishperRecordings(query);
return response;
},
// This ensures the query does not run if there's no query string
enabled: !!query,
});

const userData = useQuery({
queryKey: ["userData"],
queryFn: async () => {
const data = await getUserData();
return data;
},
});

if (!query) {
return <h1 className="text-2xl font-bold">Start Searching!</h1>;
}

if (WhishperRecordings.isLoading || userData.isLoading) {
return <LoadingSpinner>Loading...</LoadingSpinner>;
} else if (!userData.data?.whishperURL) {
return (
<h1 className="text-2xl font-bold">
You need to set your paperless url in{" "}
<Link href="/settings">settings</Link>
</h1>
);
} else if (!WhishperRecordings.data || WhishperRecordings.error) {
return (
<h1 className="text-2xl font-bold">
Connection failed! Check that the whishper url is set correctly in{" "}
<Link href="/settings">settings</Link>
</h1>
);
}

const WhishperRecordingsMap = WhishperRecordings.data.results;

if (WhishperRecordingsMap.length === 0) {
return <h1 className="text-2xl font-bold">No results!</h1>;
}

return (
<>
<h1 className="text-2xl font-bold">Search Results</h1>
<ul className="list-disc">
{WhishperRecordingsMap.map((recording, index) => (
<li className="underline" key={index}>
<Link
className="underline hover:text-slate-300"
href={`/paperless/document/${recording.id}?query=${query}`}
>
{recording.title}
</Link>
</li>
))}
</ul>
</>
);
}

export default function WhishperPage() {
return (
<main className="">
<div className="flex flex-col items-center justify-center">
<SignedOut>
<div className="flex flex-col text-center text-2xl">
Please <Link href="/sign-in">sign in</Link>
</div>
</SignedOut>
<SignedIn>
<SearchForm />
</SignedIn>
</div>
</main>
);
}
17 changes: 17 additions & 0 deletions src/components/topnav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,13 @@ export function TopNav() {
Paperless-ngx
</Link>
<Separator orientation="vertical" />
<Link
href="/whishper"
className={buttonVariants({ variant: "link" })}
>
Whishper
</Link>
<Separator orientation="vertical" />
<ImmichTooltip />
<Separator orientation="vertical" />
<div className={buttonVariants({ variant: "link" })}>
Expand Down Expand Up @@ -160,6 +167,16 @@ export function TopNav() {
Paperless-ngx
</Link>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem asChild>
<Link
href="/whishper"
className={buttonVariants({ variant: "link" })}
>
Whishper
</Link>
</DropdownMenuItem>
<Separator orientation="horizontal" />
<ImmichTooltip />
<DropdownMenuSeparator />
</DropdownMenuContent>
Expand Down
3 changes: 2 additions & 1 deletion src/server/db/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const users = createTable("users", {
userId: varchar("userId", { length: 256 }).notNull().unique(),
paperlessURL: varchar("paperlessURL", { length: 256 }),
paperlessToken: varchar("paperlessToken", { length: 256 }),
whishperURL: varchar("whishperURL", { length: 256 }),
});

export type UsersTableType = typeof users.$inferSelect;
export type UsersTableType = typeof users.$inferSelect;

0 comments on commit 451c532

Please sign in to comment.