diff --git a/src/routes/api/config/[guildId].tsx b/src/routes/api/config/[guildId].tsx new file mode 100644 index 0000000..53189ed --- /dev/null +++ b/src/routes/api/config/[guildId].tsx @@ -0,0 +1,111 @@ +import { getSession } from "@auth/solid-start"; +import { APIEvent } from "@solidjs/start/server/types"; +import { eq } from "drizzle-orm"; +import moment from "moment-timezone"; +import createClient from "openapi-fetch"; +import db from "~/drizzle"; +import { accounts } from "~/drizzle/schema"; +import { authOptions } from "~/server/auth"; +import { paths } from "~/types/discord"; + +type data = { + success: boolean | null; + guild: { + id: string; + name: string | undefined; + icon: string | null | undefined; + channel: string; + channels: { + id: string; + name: string; + }[]; + }; + tzNames: string[]; +}; + +export const GET = async ( + event: APIEvent, +): Promise< + { success: false; message: string } | (data & { success: true }) +> => { + const id = event.params.guildId; + // const id = "598539452343648256"; + // const location = useLocation(); + if (!event) return { success: false, message: "No request event!" }; + + const session = await getSession(event.request, authOptions); + if (!session?.user?.id) + return { success: false, message: "No user with id!" }; + + const { DISCORD_ACCESS_TOKEN } = ( + await db + .selectDistinct({ DISCORD_ACCESS_TOKEN: accounts.access_token }) + .from(accounts) + .where(eq(accounts.userId, session.user?.id)) + .limit(1) + .execute() + )[0]; + if (!DISCORD_ACCESS_TOKEN) + return { success: false, message: "No discord access token!" }; + + const { GET } = createClient({ + baseUrl: "https://discord.com/api/v10", + }); + const guildsRequest = await GET("/users/@me/guilds", { + headers: { Authorization: `Bearer ${DISCORD_ACCESS_TOKEN}` }, + }); + const channelsRequest = await GET("/guilds/{guild_id}/channels", { + params: { + path: { + guild_id: id, + }, + }, + headers: { Authorization: `Bot ${import.meta.env.VITE_DISCORD_BOT_TOKEN}` }, + }); + + if (guildsRequest.error || channelsRequest.error) { + console.log(guildsRequest.error, channelsRequest.error, location.pathname); + return { + success: false, + message: "Error on one of the discord api requests!", + }; + } + + const guild = guildsRequest.data?.find((e) => e.id === id); + + if (!guild) + return { + success: false, + message: "User is in no such guild with requested id!", + }; + if (!(parseInt(guild.permissions) & (1 << 5))) + return { + success: false, + message: + "User is no MANAGE_GUILD permissions on this guild with requested id!", + }; + + let channels: data["guild"]["channels"] = []; + channelsRequest.data?.forEach((channel) => { + if (channel.type !== 0) return; + channels.push({ + id: channel.id, + name: channel.name, + }); + }); + + console.log("done"); + + return { + success: true, + guild: { + id: guild.id, + name: guild.name, + icon: guild.icon, + // channel: "1162917335275950180", + channel: "", + channels, + }, + tzNames: moment.tz.names(), + }; +}; diff --git a/src/routes/api/config/index.tsx b/src/routes/api/config/index.tsx new file mode 100644 index 0000000..1eec136 --- /dev/null +++ b/src/routes/api/config/index.tsx @@ -0,0 +1,62 @@ +import { getSession } from "@auth/solid-start"; +import { APIEvent } from "@solidjs/start/server/types"; +import { eq } from "drizzle-orm"; +import createClient from "openapi-fetch"; +import db from "~/drizzle"; +import { accounts } from "~/drizzle/schema"; +import { authOptions } from "~/server/auth"; +import { paths } from "~/types/discord"; + +type data = { + success: boolean | null; + guilds: { + id: string; + name: string; + icon: string | null | undefined; + }[]; +}; + +export const GET = async ( + event: APIEvent, +): Promise< + { success: false; message: string } | (data & { success: true }) +> => { + if (!event) return { success: false, message: "No request event!" }; + + const session = await getSession(event.request, authOptions); + if (!session?.user?.id) + return { success: false, message: "No user with id!" }; + + const { DISCORD_ACCESS_TOKEN } = ( + await db + .selectDistinct({ DISCORD_ACCESS_TOKEN: accounts.access_token }) + .from(accounts) + .where(eq(accounts.userId, session.user?.id)) + .limit(1) + .execute() + )[0]; + if (!DISCORD_ACCESS_TOKEN) + return { success: false, message: "No discord access token!" }; + + const { GET } = createClient({ + baseUrl: "https://discord.com/api/v10", + }); + const { data: guilds, error } = await GET("/users/@me/guilds", { + headers: { Authorization: `Bearer ${DISCORD_ACCESS_TOKEN}` }, + }); + + console.log("guilds", guilds); + + if (error) { + console.log(error); + return { success: false, message: "Error on discord api request!" }; + } + + return { + success: true, + guilds: + guilds + ?.filter((e) => parseInt(e.permissions) & (1 << 5)) + .map(({ id, name, icon }) => ({ id, name, icon })) ?? [], + }; +}; diff --git a/src/routes/config/[guildId].tsx b/src/routes/config/[guildId].tsx index 04501dc..9e372c9 100644 --- a/src/routes/config/[guildId].tsx +++ b/src/routes/config/[guildId].tsx @@ -1,18 +1,15 @@ -import { getSession } from "@auth/solid-start"; import { faToggleOff, faToggleOn } from "@fortawesome/pro-regular-svg-icons"; -import { useNavigate, useParams } from "@solidjs/router"; -import { eq } from "drizzle-orm"; -import moment from "moment-timezone"; -import createClient from "openapi-fetch"; -import { Index, createEffect, createResource, createSignal } from "solid-js"; +import { useLocation, useNavigate, useParams } from "@solidjs/router"; +import { + For, + Index, + createEffect, + createResource, + createSignal, +} from "solid-js"; import { createStore } from "solid-js/store"; -import { getRequestEvent } from "solid-js/web"; import { FontAwesomeIcon } from "~/components/FontAwesomeIcon"; import Layout from "~/components/Layout"; -import db from "~/drizzle"; -import { accounts } from "~/drizzle/schema"; -import { authOptions } from "~/server/auth"; -import { paths } from "~/types/discord"; import "../../styles/pages/config.scss"; const guessTZ = () => Intl.DateTimeFormat().resolvedOptions().timeZone; @@ -23,113 +20,75 @@ const initialValue = (params: ReturnType) => ({ id: params.guildId, name: undefined as string | undefined, icon: undefined as string | null | undefined, + channel: "", + channels: [] as { id: string; name: string }[], }, tzNames: [guessTZ()], }); -const getPayload = async ( - id: string, -): Promise< - | { success: false; message: string } - | (ReturnType & { success: true }) -> => { - "use server"; - const event = getRequestEvent(); - if (!event) return { success: false, message: "No request event!" }; - - const session = await getSession(event.request, authOptions); - if (!session?.user?.id) - return { success: false, message: "No user with id!" }; - - const { DISCORD_ACCESS_TOKEN } = ( - await db - .selectDistinct({ DISCORD_ACCESS_TOKEN: accounts.access_token }) - .from(accounts) - .where(eq(accounts.userId, session.user?.id)) - .limit(1) - .execute() - )[0]; - if (!DISCORD_ACCESS_TOKEN) - return { success: false, message: "No discord access token!" }; - - // const guilds = await fetch("https://discord.com/api/users/@me/guilds", { - // headers: { Authorization: `Bearer ${DISCORD_ACCESS_TOKEN}` }, - // }).then((res) => res.json()); - const { GET } = createClient({ - baseUrl: "https://discord.com/api/v10", - }); - const { data: guilds, error } = await GET("/users/@me/guilds", { - headers: { Authorization: `Bearer ${DISCORD_ACCESS_TOKEN}` }, - }); - - if (error) { - console.log(error); - return { success: false, message: "Error on discord api request!" }; - } - - const guild = guilds?.find((e) => e.id === id); - - if (!guild) - return { - success: false, - message: "User is in no such guild with requested id!", - }; - if (!(parseInt(guild.permissions) & (1 << 5))) - return { - success: false, - message: - "User is no MANAGE_GUILD permissions on this guild with requested id!", - }; - - return { - success: true, - guild: { - id: guild.id, - name: guild.name, - icon: guild.icon, - }, - // guild: guilds - // .filter((e: any) => e.permissions & (1 << 5)) - // .map((e: any) => e.name), - tzNames: moment.tz.names(), - }; -}; - function config() { const params = useParams(); const navigator = useNavigate(); - let [timezoneRef, setTimezoneRef] = createSignal(); - let [timePlanningRef, setTimePlanningRef] = createSignal(); - let [pingableRolesRef, setPingableRolesRef] = + const location = useLocation(); + const [timezoneRef, setTimezoneRef] = createSignal(); + const [timePlanningRef, setTimePlanningRef] = + createSignal(); + const [channelRef, setChannelRef] = createSignal(); + const [pingableRolesRef, setPingableRolesRef] = createSignal(); const [timezone, setTimezone] = createSignal(guessTZ()); - const [payload] = createResource(params.guildId, async (id) => { - const payload = await getPayload(id); + const [payload] = createResource( + params.guildId, + async (id) => { + const payload = await fetch(`http://localhost:3000/api/config/${id}`) + .then( + (res) => + res.json() as Promise< + | { + success: false; + message: string; + } + | (ReturnType & { + success: true; + }) + >, + ) + .catch((e) => console.warn(e, id)); - if (!payload.success) { - console.log(payload.message, "No success"); - navigator("/config", { replace: false }); - return initialValue(params); - } - return payload; - }); - const guild = () => payload()?.guild ?? initialValue(params).guild; - const tzNames = () => payload()?.tzNames ?? []; + if (!payload) return initialValue(params); + + if (!payload.success) { + console.log(payload); + console.log(location.pathname, payload.message, "No success"); + // navigator("/config", { replace: false }); + return initialValue(params); + } + return payload; + }, + { initialValue: initialValue(params) }, + ); const [config, setConfig] = createStore({ features: { timePlanning: { enabled: false, + channelId: "833442323160891452", pingableRoles: false, }, }, }); - createEffect(() => console.log(payload())); + createEffect(() => console.log(payload.loading, payload())); createEffect(() => console.log("timezone", timezone())); createEffect(() => console.log("timePlanning.enabled", config.features.timePlanning.enabled), ); + createEffect(() => + console.log( + "timePlanning.channelId", + config.features.timePlanning.channelId, + ), + ); createEffect(() => console.log( "timePlanning.pingableRoles", @@ -147,11 +106,42 @@ function config() { if (!ref) return; ref.checked = config.features.timePlanning.enabled; }); + createEffect(() => { + const channelId = payload().guild.channel; + setConfig("features", "timePlanning", "channelId", channelId); + console.log(channelId, payload()); + const ref = channelRef(); + if (!ref) return; + if ( + !ref || + !channelId || + !payload().guild.channels.find((e) => e.id === channelId) + ) + return; + ref.value = channelId; + }); createEffect(() => { const ref = pingableRolesRef(); if (!ref) return; ref.checked = config.features.timePlanning.pingableRoles; }); + createEffect(() => { + const ref = timezoneRef(); + if (!ref) return; + ref.value = timezone(); + }); + createEffect(() => { + const ref = timePlanningRef(); + if (!ref) return; + ref.checked = config.features.timePlanning.enabled; + }); + createEffect(() => { + const ref = pingableRolesRef(); + if (!ref) return; + ref.checked = config.features.timePlanning.pingableRoles; + }); + + // console.log(payload()); return ( @@ -162,15 +152,15 @@ function config() { Server pfp -

{guild()?.name ?? "li'l Judds home base"}

+

{payload().guild.name}

@@ -189,7 +179,7 @@ function config() { /> - + {(zone) => @@ -231,12 +221,28 @@ function config() { >
- setChannelRef(e)} + onInput={(e) => + setConfig( + "features", + "timePlanning", + "channelId", + e.target.value, + ) + } + > + + + {(channel) => ( + + )} +
@@ -271,6 +277,7 @@ function config() {
+
diff --git a/src/routes/config/index.tsx b/src/routes/config/index.tsx index e2de17c..207831a 100644 --- a/src/routes/config/index.tsx +++ b/src/routes/config/index.tsx @@ -1,20 +1,12 @@ -import { getSession } from "@auth/solid-start"; import { faBadgeCheck, faCircleExclamation, faPlus, } from "@fortawesome/pro-regular-svg-icons"; -import { 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 { useLocation, useNavigate } from "@solidjs/router"; +import { For, Suspense, createEffect, createResource } from "solid-js"; import { FontAwesomeIcon } from "~/components/FontAwesomeIcon"; import Layout from "~/components/Layout"; -import db from "~/drizzle"; -import { accounts } from "~/drizzle/schema"; -import { authOptions } from "~/server/auth"; -import { paths } from "~/types/discord"; import "../../styles/pages/config.scss"; const initialValue = () => ({ @@ -26,66 +18,40 @@ const initialValue = () => ({ }[], }); -const getPayload = async (): Promise< - | { success: false; message: string } - | (ReturnType & { success: true }) -> => { - ("use server"); - const event = getRequestEvent(); - if (!event) return { success: false, message: "No request event!" }; - - const session = await getSession(event.request, authOptions); - if (!session?.user?.id) - return { success: false, message: "No user with id!" }; - - const { DISCORD_ACCESS_TOKEN } = ( - await db - .selectDistinct({ DISCORD_ACCESS_TOKEN: accounts.access_token }) - .from(accounts) - .where(eq(accounts.userId, session.user?.id)) - .limit(1) - .execute() - )[0]; - if (!DISCORD_ACCESS_TOKEN) - return { success: false, message: "No discord access token!" }; - - const { GET } = createClient({ - baseUrl: "https://discord.com/api/v10", - }); - const { data: guilds, error } = await GET("/users/@me/guilds", { - headers: { Authorization: `Bearer ${DISCORD_ACCESS_TOKEN}` }, - }); - - console.log("guilds", guilds); - - if (error) { - console.log(error); - return { success: false, message: "Error on discord api request!" }; - } - - 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(async () => { - const payload = await getPayload(); + const payload = await fetch("http://localhost:3000/api/config") + .then( + (res) => + res.json() as Promise< + | { + success: false; + message: string; + } + | (ReturnType & { + success: true; + }) + >, + ) + .catch((e) => console.warn(e)); + + if (!payload) return; if (!payload.success) { - console.log(payload.message, "No success"); + console.log(location.pathname, payload.message, "No success"); navigator("/", { replace: false }); return initialValue(); } - console.log("success"); + console.log(location.pathname, "success"); return payload; }); + createEffect(() => console.log(payload()?.guilds, payload()?.guilds.length)); + // createRenderEffect(() => + // console.log(payload()?.guilds, payload()?.guilds.length), + // ); const icons = [faPlus, faCircleExclamation, faBadgeCheck]; const colors = [undefined, "orange", "green"]; @@ -94,28 +60,39 @@ function index() {

Configure li'l Judd in

- - {(guild, i) => ( - - Server pfp -

{guild.name}

- -
- )} -
+ + + {(guild, i) => { + return ( + + Server pfp +

{guild.name}

+ +
+ ); + }} +
+
);