diff --git a/apps/website/astro.config.ts b/apps/website/astro.config.ts
index 709c4b4..80fe7d4 100644
--- a/apps/website/astro.config.ts
+++ b/apps/website/astro.config.ts
@@ -1,25 +1,27 @@
import path from "path";
import { fileURLToPath } from "url";
import { defineConfig } from "astro/config";
+import preact from "@astrojs/preact";
import sitemap from "@astrojs/sitemap";
import tailwind from "@astrojs/tailwind";
import cloudflare from "@astrojs/cloudflare";
import auth from "auth-astro";
+
import { CONFIG } from "./src/config";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
// https://astro.build/config
export default defineConfig({
- site: CONFIG.origin,
- integrations: [sitemap(), tailwind(), auth()],
- output: "server",
- adapter: cloudflare(),
- vite: {
- resolve: {
- alias: {
- "~": path.resolve(__dirname, "./src"),
- },
- },
- },
+ site: CONFIG.origin,
+ integrations: [sitemap(), tailwind(), auth(), preact()],
+ output: "server",
+ adapter: cloudflare(),
+ vite: {
+ resolve: {
+ alias: {
+ "~": path.resolve(__dirname, "./src"),
+ },
+ },
+ },
});
diff --git a/apps/website/auth.config.ts b/apps/website/auth.config.ts
index dab32e6..389e7b6 100644
--- a/apps/website/auth.config.ts
+++ b/apps/website/auth.config.ts
@@ -29,17 +29,8 @@ export default defineConfig({
(session.user as unknown as User).global_name =
token.global_name as string;
- const guilds = await fetch(
- "https://discord.com/api/v10/users/@me/guilds",
- {
- headers: {
- Authorization: `Bearer ${token.accessToken as string}`,
- "Cache-Control": "max-age=300",
- },
- }
- );
-
- (session.user as unknown as User).guilds = await guilds.json();
+ (session.user as unknown as User).discordAccessToken =
+ token.accessToken as string;
}
return session;
diff --git a/apps/website/bun.lockb b/apps/website/bun.lockb
index 6d5ea1d..26b57df 100755
Binary files a/apps/website/bun.lockb and b/apps/website/bun.lockb differ
diff --git a/apps/website/package.json b/apps/website/package.json
index 6bd6730..2d0f437 100644
--- a/apps/website/package.json
+++ b/apps/website/package.json
@@ -10,6 +10,7 @@
},
"dependencies": {
"@astrojs/cloudflare": "^11.0.1",
+ "@astrojs/preact": "^3.5.1",
"@astrojs/prefetch": "^0.2.1",
"@astrojs/sitemap": "^3.1.6",
"@astrojs/tailwind": "^5.1.0",
@@ -19,6 +20,7 @@
"astro-google-fonts-optimizer": "^0.2.2",
"astro-icon": "^0.8.0",
"auth-astro": "^4.1.2",
+ "preact": "^10.23.1",
"tailwindcss": "^3.3.1"
},
"devDependencies": {
diff --git a/apps/website/src/components/dashboard/UserInfo.astro b/apps/website/src/components/dashboard/UserInfo.astro
new file mode 100644
index 0000000..273a362
--- /dev/null
+++ b/apps/website/src/components/dashboard/UserInfo.astro
@@ -0,0 +1,23 @@
+---
+import { Image } from "astro:assets";
+import { getUser } from "~/lib/user";
+
+const user = await getUser(Astro.request);
+if (!user) {
+ return Astro.redirect("/auth/login");
+}
+---
+
+
+
+
+
+
diff --git a/apps/website/src/components/preact/Guild.tsx b/apps/website/src/components/preact/Guild.tsx
new file mode 100644
index 0000000..08ef8d6
--- /dev/null
+++ b/apps/website/src/components/preact/Guild.tsx
@@ -0,0 +1,28 @@
+import type { Guild } from "~/env";
+
+interface Props {
+ guild: Guild;
+ mutual: boolean;
+}
+
+export default function Guild({ guild, mutual }: Props) {
+ return (
+
+
+
+
+
{guild.name}
+
+
+ );
+}
diff --git a/apps/website/src/components/preact/GuildSelector.tsx b/apps/website/src/components/preact/GuildSelector.tsx
new file mode 100644
index 0000000..f9d89ee
--- /dev/null
+++ b/apps/website/src/components/preact/GuildSelector.tsx
@@ -0,0 +1,31 @@
+import { Component } from "preact";
+import Guild from "./Guild";
+import LoadingGuild from "./LoadingGuild";
+import type { MutualeGuild } from "~/env";
+
+interface State {
+ guilds: MutualeGuild[] | null;
+}
+
+export default class GuildSelector extends Component<{}, State> {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ guilds: null,
+ };
+ }
+
+ async componentDidMount() {
+ const response = await fetch("/api/user/guilds");
+ const data = await response.json();
+ this.setState({ guilds: data });
+ }
+
+ render() {
+ const { guilds } = this.state;
+ if (!guilds) return [...Array(15)].map(() => );
+
+ return guilds.map((g) => );
+ }
+}
diff --git a/apps/website/src/components/preact/LoadingGuild.tsx b/apps/website/src/components/preact/LoadingGuild.tsx
new file mode 100644
index 0000000..59e2a06
--- /dev/null
+++ b/apps/website/src/components/preact/LoadingGuild.tsx
@@ -0,0 +1,9 @@
+export default function LoadingGuild() {
+ return (
+
+ );
+}
diff --git a/apps/website/src/env.d.ts b/apps/website/src/env.d.ts
index 47ddad0..1bcd6b7 100644
--- a/apps/website/src/env.d.ts
+++ b/apps/website/src/env.d.ts
@@ -4,7 +4,7 @@ import type { User as AuthCoreUser } from "@auth/core/types";
export type User = AuthCoreUser & {
global_name: string;
- guilds: Guild[];
+ discordAccessToken: string;
};
export interface Guild {
@@ -14,3 +14,8 @@ export interface Guild {
permissions: string;
owner: boolean;
}
+
+export interface MutualeGuild {
+ mutual: boolean;
+ guild: Guild;
+}
diff --git a/apps/website/src/lib/guilds.ts b/apps/website/src/lib/guilds.ts
index 6f4220a..5776160 100644
--- a/apps/website/src/lib/guilds.ts
+++ b/apps/website/src/lib/guilds.ts
@@ -1,20 +1,28 @@
-import type { Guild } from "~/env";
+import type { Guild, MutualeGuild, User } from "~/env";
+
+export async function getUserGuilds(user: User): Promise {
+ const discordApiGuildsResponse = await fetch(
+ "https://discord.com/api/v10/users/@me/guilds",
+ {
+ headers: {
+ Authorization: `Bearer ${user.discordAccessToken as string}`,
+ "Cache-Control": "max-age=300",
+ },
+ }
+ );
+
+ return (await discordApiGuildsResponse.json()) as Guild[];
+}
// Checks if user has AMDINISTRATOR permissions in the guild
-export async function filterUserGuilds(guilds: Guild[]): Promise<
- {
- mutual: boolean;
- guild: Guild;
- }[]
-> {
+export async function filterUserGuilds(
+ guilds: Guild[]
+): Promise {
const filtered = guilds
.filter((g) => (BigInt(g.permissions) & 0x8n) == 0x8n)
.sort((a, b) => Number(b.owner) - Number(a.owner));
- const result: {
- mutual: boolean;
- guild: Guild;
- }[] = [];
+ const result: MutualeGuild[] = [];
for (const guild of filtered) {
const mutual = await isMutualGuild(guild);
diff --git a/apps/website/src/lib/user.ts b/apps/website/src/lib/user.ts
new file mode 100644
index 0000000..eae9165
--- /dev/null
+++ b/apps/website/src/lib/user.ts
@@ -0,0 +1,9 @@
+import { getSession } from "auth-astro/server";
+import type { User } from "~/env";
+
+export async function getUser(req: Request): Promise {
+ const session = await getSession(req);
+ if (!session || !session.user) return null;
+
+ return session.user as User;
+}
diff --git a/apps/website/src/pages/api/user/guilds.ts b/apps/website/src/pages/api/user/guilds.ts
index 9f28f00..13a3a47 100644
--- a/apps/website/src/pages/api/user/guilds.ts
+++ b/apps/website/src/pages/api/user/guilds.ts
@@ -1,23 +1,17 @@
import type { APIRoute } from "astro";
-import { getSession } from "auth-astro/server";
-import type { User } from "~/env";
+import { filterUserGuilds, getUserGuilds } from "~/lib/guilds";
+import { getUser } from "~/lib/user";
export const GET: APIRoute = async ({ request }) => {
- const session = await getSession(request);
- if (!session || !session.user) {
+ const user = await getUser(request);
+ if (!user) {
return new Response(null, {
status: 401,
});
}
- const user = session.user as User;
+ const guilds = await getUserGuilds(user);
+ const res = await filterUserGuilds(guilds);
- return Response.json(
- user.guilds.map((g) => ({
- id: g.id,
- name: g.name,
- owner: g.owner,
- permissions: g.permissions,
- }))
- );
+ return Response.json(res);
};
diff --git a/apps/website/src/pages/api/user/index.ts b/apps/website/src/pages/api/user/index.ts
deleted file mode 100644
index 6736781..0000000
--- a/apps/website/src/pages/api/user/index.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import type { APIRoute } from "astro";
-import { getSession } from "auth-astro/server";
-import type { User } from "~/env";
-
-export const GET: APIRoute = async ({ request }) => {
- const session = await getSession(request);
- if (!session || !session.user) {
- return new Response(null, {
- status: 401,
- });
- }
-
- const user = session.user as User;
-
- return Response.json({
- id: user.id,
- username: user.name,
- global_name: user.global_name,
- avatar_url: user.image,
- });
-};
diff --git a/apps/website/src/pages/dashboard/index.astro b/apps/website/src/pages/dashboard/index.astro
index 9a3baed..3165a2f 100644
--- a/apps/website/src/pages/dashboard/index.astro
+++ b/apps/website/src/pages/dashboard/index.astro
@@ -1,60 +1,18 @@
---
-import type { User } from "~/env";
-import { filterUserGuilds } from "~/lib/guilds";
-import { getSession } from "auth-astro/server";
import Layout from "~/layouts/Layout.astro";
import Container from "~/components/Container.astro";
-import { Image } from "astro:assets";
-
-const session = await getSession(Astro.request);
-if (!session || !session.user) {
- return Astro.redirect("/auth/login");
-}
-
-const user = session.user as User;
-const guilds = await filterUserGuilds(user.guilds);
+import GuildSelector from "~/components/preact/GuildSelector";
+import UserInfo from "~/components/dashboard/UserInfo.astro";
---
-
-
-
-
-
+
- {
- guilds.map(({ guild, mutual }) => (
-
- ))
- }
+