liljudd-website/src/routes/config/index.tsx
2024-03-01 20:50:11 +01:00

143 lines
4.3 KiB
TypeScript

import {
faBadgeCheck,
faCircleExclamation,
faPlus,
} from "@fortawesome/pro-regular-svg-icons";
import { useLocation, useNavigate } from "@solidjs/router";
import { eq } from "drizzle-orm";
import createClient from "openapi-fetch";
import { For, createResource } from "solid-js";
import { getRequestEvent } from "solid-js/web";
import { FontAwesomeIcon } from "~/components/FontAwesomeIcon";
import Layout from "~/components/Layout";
import db from "~/drizzle";
import { discordTokens } from "~/drizzle/schema";
import { paths } from "~/types/discord";
import "../../styles/pages/config.scss";
if (typeof import.meta.env.VITE_DISCORD_CLIENT_ID === "undefined")
throw new Error("No env VITE_DISCORD_CLIENT_ID found!");
if (typeof import.meta.env.VITE_DISCORD_OAUTH2_PERMISSIONS === "undefined")
throw new Error("No env VITE_DISCORD_OAUTH2_PERMISSIONS found!");
const initialValue = () => ({
success: null as boolean | null,
guilds: [] as {
id: string;
name: string;
icon: string | null | undefined;
}[],
});
const getPayload = async (): Promise<
| { success: false; message: string }
| (ReturnType<typeof initialValue> & { success: true })
> => {
"use server";
const event = getRequestEvent();
if (!event) return { success: false, message: "No request event!" };
const pathname = new URL(event.request.url).pathname;
const { user } = event.nativeEvent.context;
if (!user) return { success: false, message: "User not logged in!" };
const tokens = await db.query.discordTokens
.findFirst({
where: eq(discordTokens.userId, user.id),
})
.execute();
if (!tokens) return { success: false, message: "No discord access token!" };
const { GET } = createClient<paths>({
baseUrl: "https://discord.com/api/v10",
});
const { data: guilds, error } = await GET("/users/@me/guilds", {
headers: { Authorization: `Bearer ${tokens.accessToken}` },
});
if (error) {
console.log(error);
return { success: false, message: "Error on discord api request!" };
}
console.log(pathname, "success");
return {
success: true,
guilds:
guilds
?.filter((e) => parseInt(e.permissions) & (1 << 5))
.map(({ id, name, icon }) => ({ id, name, icon })) ?? [],
};
};
function index() {
const navigator = useNavigate();
const location = useLocation();
const [payload] = createResource(
// eslint-disable-next-line solid/reactivity
async () => {
const payload = await getPayload().catch((e) => console.warn(e));
if (!payload) {
console.error(location.pathname, payload);
return initialValue();
}
if (!payload.success) {
console.log(location.pathname, payload.message, "No success");
navigator("/", { replace: false });
return initialValue();
}
return payload;
},
{ deferStream: true },
);
const icons = [faPlus, faCircleExclamation, faBadgeCheck];
const colors = [undefined, "orange", "green"];
return (
<Layout site="config">
<h3 class="text-center">Configure li&apos;l Judd in</h3>
<div>
<For each={payload()?.guilds}>
{(guild, i) => {
return (
<a
href={
i() % 3 === 0
? `/config/${guild.id}`
: `https://discord.com/api/oauth2/authorize?client_id=${import.meta.env.VITE_DISCORD_CLIENT_ID}&permissions=${import.meta.env.VITE_DISCORD_OAUTH2_PERMISSIONS}&scope=bot&guild_id=${guild.id}`
}
class="flex-row centered"
>
<img
class="guildpfp"
src={
guild.icon
? `https://cdn.discordapp.com/icons/${guild.id}/${guild.icon}.webp?size=240`
: "https://cdn.discordapp.com/icons/1040502664506646548/bb5a51c4659cf47bdd942bb11e974da7.webp?size=240"
}
alt="Server pfp"
/>
<h1>{guild.name}</h1>
<FontAwesomeIcon
// beat={i() % 3 === 1}
color={colors[i() % 3]}
icon={icons[i() % 3]}
size="xl"
/>
</a>
);
}}
</For>
</div>
</Layout>
);
}
export default index;