Compare commits
No commits in common. "b28ceb86591ea06138f6749545ad2839ac143169" and "4e6bd72a213345a3a9b283dc4bf46a1865f93a5b" have entirely different histories.
b28ceb8659
...
4e6bd72a21
5 changed files with 198 additions and 369 deletions
|
@ -22,7 +22,7 @@
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/components/schemas/bootConfig"
|
"$ref": "#/components/schemas/guildConfig"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -382,20 +382,6 @@
|
||||||
},
|
},
|
||||||
"components": {
|
"components": {
|
||||||
"schemas": {
|
"schemas": {
|
||||||
"bootConfig": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"guilds": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/components/schemas/guildConfig"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"accessToken": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"guildConfig": {
|
"guildConfig": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -520,17 +506,17 @@
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "varchar(20)"
|
"format": "varchar(20)",
|
||||||
},
|
"example": [
|
||||||
"example": [
|
"1234567890123456789",
|
||||||
"1234567890123456789",
|
"1234567890123456789",
|
||||||
"1234567890123456789",
|
"1234567890123456789",
|
||||||
"1234567890123456789",
|
"1234567890123456789",
|
||||||
"1234567890123456789",
|
"1234567890123456789",
|
||||||
"1234567890123456789",
|
"1234567890123456789",
|
||||||
"1234567890123456789",
|
"1234567890123456789"
|
||||||
"1234567890123456789"
|
]
|
||||||
]
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,111 +0,0 @@
|
||||||
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<paths>({
|
|
||||||
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(),
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -1,62 +0,0 @@
|
||||||
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<paths>({
|
|
||||||
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 })) ?? [],
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -1,15 +1,18 @@
|
||||||
|
import { getSession } from "@auth/solid-start";
|
||||||
import { faToggleOff, faToggleOn } from "@fortawesome/pro-regular-svg-icons";
|
import { faToggleOff, faToggleOn } from "@fortawesome/pro-regular-svg-icons";
|
||||||
import { useLocation, useNavigate, useParams } from "@solidjs/router";
|
import { useNavigate, useParams } from "@solidjs/router";
|
||||||
import {
|
import { eq } from "drizzle-orm";
|
||||||
For,
|
import moment from "moment-timezone";
|
||||||
Index,
|
import createClient from "openapi-fetch";
|
||||||
createEffect,
|
import { Index, createEffect, createResource, createSignal } from "solid-js";
|
||||||
createResource,
|
|
||||||
createSignal,
|
|
||||||
} from "solid-js";
|
|
||||||
import { createStore } from "solid-js/store";
|
import { createStore } from "solid-js/store";
|
||||||
|
import { getRequestEvent } from "solid-js/web";
|
||||||
import { FontAwesomeIcon } from "~/components/FontAwesomeIcon";
|
import { FontAwesomeIcon } from "~/components/FontAwesomeIcon";
|
||||||
import Layout from "~/components/Layout";
|
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";
|
import "../../styles/pages/config.scss";
|
||||||
|
|
||||||
const guessTZ = () => Intl.DateTimeFormat().resolvedOptions().timeZone;
|
const guessTZ = () => Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||||
|
@ -20,75 +23,113 @@ const initialValue = (params: ReturnType<typeof useParams>) => ({
|
||||||
id: params.guildId,
|
id: params.guildId,
|
||||||
name: undefined as string | undefined,
|
name: undefined as string | undefined,
|
||||||
icon: undefined as string | null | undefined,
|
icon: undefined as string | null | undefined,
|
||||||
channel: "",
|
|
||||||
channels: [] as { id: string; name: string }[],
|
|
||||||
},
|
},
|
||||||
tzNames: [guessTZ()],
|
tzNames: [guessTZ()],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const getPayload = async (
|
||||||
|
id: string,
|
||||||
|
): 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 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<paths>({
|
||||||
|
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() {
|
function config() {
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const navigator = useNavigate();
|
const navigator = useNavigate();
|
||||||
const location = useLocation();
|
let [timezoneRef, setTimezoneRef] = createSignal<HTMLInputElement>();
|
||||||
const [timezoneRef, setTimezoneRef] = createSignal<HTMLInputElement>();
|
let [timePlanningRef, setTimePlanningRef] = createSignal<HTMLInputElement>();
|
||||||
const [timePlanningRef, setTimePlanningRef] =
|
let [pingableRolesRef, setPingableRolesRef] =
|
||||||
createSignal<HTMLInputElement>();
|
|
||||||
const [channelRef, setChannelRef] = createSignal<HTMLSelectElement>();
|
|
||||||
const [pingableRolesRef, setPingableRolesRef] =
|
|
||||||
createSignal<HTMLInputElement>();
|
createSignal<HTMLInputElement>();
|
||||||
|
|
||||||
const [timezone, setTimezone] = createSignal(guessTZ());
|
const [timezone, setTimezone] = createSignal(guessTZ());
|
||||||
const [payload] = createResource(
|
const [payload] = createResource(params.guildId, async (id) => {
|
||||||
params.guildId,
|
const payload = await getPayload(id);
|
||||||
async (id) => {
|
|
||||||
const payload = await fetch(`http://localhost:3000/api/config/${id}`)
|
|
||||||
.then(
|
|
||||||
(res) =>
|
|
||||||
res.json() as Promise<
|
|
||||||
| {
|
|
||||||
success: false;
|
|
||||||
message: string;
|
|
||||||
}
|
|
||||||
| (ReturnType<typeof initialValue> & {
|
|
||||||
success: true;
|
|
||||||
})
|
|
||||||
>,
|
|
||||||
)
|
|
||||||
.catch((e) => console.warn(e, id));
|
|
||||||
|
|
||||||
if (!payload) return initialValue(params);
|
if (!payload.success) {
|
||||||
|
console.log(payload.message, "No success");
|
||||||
if (!payload.success) {
|
navigator("/config", { replace: false });
|
||||||
console.log(payload);
|
return initialValue(params);
|
||||||
console.log(location.pathname, payload.message, "No success");
|
}
|
||||||
// navigator("/config", { replace: false });
|
return payload;
|
||||||
return initialValue(params);
|
});
|
||||||
}
|
const guild = () => payload()?.guild ?? initialValue(params).guild;
|
||||||
return payload;
|
const tzNames = () => payload()?.tzNames ?? [];
|
||||||
},
|
|
||||||
{ initialValue: initialValue(params) },
|
|
||||||
);
|
|
||||||
const [config, setConfig] = createStore({
|
const [config, setConfig] = createStore({
|
||||||
features: {
|
features: {
|
||||||
timePlanning: {
|
timePlanning: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
channelId: "833442323160891452",
|
|
||||||
pingableRoles: false,
|
pingableRoles: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
createEffect(() => console.log(payload.loading, payload()));
|
createEffect(() => console.log(payload()));
|
||||||
createEffect(() => console.log("timezone", timezone()));
|
createEffect(() => console.log("timezone", timezone()));
|
||||||
createEffect(() =>
|
createEffect(() =>
|
||||||
console.log("timePlanning.enabled", config.features.timePlanning.enabled),
|
console.log("timePlanning.enabled", config.features.timePlanning.enabled),
|
||||||
);
|
);
|
||||||
createEffect(() =>
|
|
||||||
console.log(
|
|
||||||
"timePlanning.channelId",
|
|
||||||
config.features.timePlanning.channelId,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
createEffect(() =>
|
createEffect(() =>
|
||||||
console.log(
|
console.log(
|
||||||
"timePlanning.pingableRoles",
|
"timePlanning.pingableRoles",
|
||||||
|
@ -106,42 +147,11 @@ function config() {
|
||||||
if (!ref) return;
|
if (!ref) return;
|
||||||
ref.checked = config.features.timePlanning.enabled;
|
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(() => {
|
createEffect(() => {
|
||||||
const ref = pingableRolesRef();
|
const ref = pingableRolesRef();
|
||||||
if (!ref) return;
|
if (!ref) return;
|
||||||
ref.checked = config.features.timePlanning.pingableRoles;
|
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 (
|
return (
|
||||||
<Layout site="config">
|
<Layout site="config">
|
||||||
|
@ -152,15 +162,15 @@ function config() {
|
||||||
<img
|
<img
|
||||||
class="guildpfp"
|
class="guildpfp"
|
||||||
src={
|
src={
|
||||||
payload().guild.icon
|
guild()?.icon
|
||||||
? `https://cdn.discordapp.com/icons/${payload().guild.id}/${
|
? `https://cdn.discordapp.com/icons/${guild()?.id}/${
|
||||||
payload().guild.icon
|
guild()?.icon
|
||||||
}.webp?size=240`
|
}.webp?size=240`
|
||||||
: "https://cdn.discordapp.com/icons/1040502664506646548/bb5a51c4659cf47bdd942bb11e974da7.webp?size=240"
|
: "https://cdn.discordapp.com/icons/1040502664506646548/bb5a51c4659cf47bdd942bb11e974da7.webp?size=240"
|
||||||
}
|
}
|
||||||
alt="Server pfp"
|
alt="Server pfp"
|
||||||
/>
|
/>
|
||||||
<h1>{payload().guild.name}</h1>
|
<h1>{guild()?.name ?? "li'l Judds home base"}</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -179,7 +189,7 @@ function config() {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<datalist id="timezones">
|
<datalist id="timezones">
|
||||||
<Index each={payload().tzNames}>
|
<Index each={tzNames()}>
|
||||||
{(zone) => <option value={zone()} />}
|
{(zone) => <option value={zone()} />}
|
||||||
</Index>
|
</Index>
|
||||||
</datalist>
|
</datalist>
|
||||||
|
@ -221,28 +231,12 @@ function config() {
|
||||||
>
|
>
|
||||||
<div class="flex-row">
|
<div class="flex-row">
|
||||||
<label>Target channel:</label>
|
<label>Target channel:</label>
|
||||||
<select
|
<select value={timezone()}>
|
||||||
ref={(e) => setChannelRef(e)}
|
<optgroup label="--Select a Channel--">
|
||||||
onInput={(e) =>
|
<Index each={tzNames()}>
|
||||||
setConfig(
|
{(channel) => <option>{channel()}</option>}
|
||||||
"features",
|
</Index>
|
||||||
"timePlanning",
|
</optgroup>
|
||||||
"channelId",
|
|
||||||
e.target.value,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<option
|
|
||||||
disabled={!!config.features.timePlanning.channelId}
|
|
||||||
value=""
|
|
||||||
>
|
|
||||||
--Select a Channel--
|
|
||||||
</option>
|
|
||||||
<For each={payload().guild.channels}>
|
|
||||||
{(channel) => (
|
|
||||||
<option value={channel.id}>{channel.name}</option>
|
|
||||||
)}
|
|
||||||
</For>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-row">
|
<div class="flex-row">
|
||||||
|
@ -277,7 +271,6 @@ function config() {
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<button>Apply</button>
|
<button>Apply</button>
|
||||||
<button onClick={() => navigator("/config")}>Back</button>
|
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
|
@ -1,12 +1,20 @@
|
||||||
|
import { getSession } from "@auth/solid-start";
|
||||||
import {
|
import {
|
||||||
faBadgeCheck,
|
faBadgeCheck,
|
||||||
faCircleExclamation,
|
faCircleExclamation,
|
||||||
faPlus,
|
faPlus,
|
||||||
} from "@fortawesome/pro-regular-svg-icons";
|
} from "@fortawesome/pro-regular-svg-icons";
|
||||||
import { useLocation, useNavigate } from "@solidjs/router";
|
import { useNavigate } from "@solidjs/router";
|
||||||
import { For, Suspense, createEffect, createResource } from "solid-js";
|
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 { FontAwesomeIcon } from "~/components/FontAwesomeIcon";
|
||||||
import Layout from "~/components/Layout";
|
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";
|
import "../../styles/pages/config.scss";
|
||||||
|
|
||||||
const initialValue = () => ({
|
const initialValue = () => ({
|
||||||
|
@ -18,40 +26,66 @@ const initialValue = () => ({
|
||||||
}[],
|
}[],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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 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<paths>({
|
||||||
|
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() {
|
function index() {
|
||||||
const navigator = useNavigate();
|
const navigator = useNavigate();
|
||||||
const location = useLocation();
|
|
||||||
|
|
||||||
const [payload] = createResource(async () => {
|
const [payload] = createResource(async () => {
|
||||||
const payload = await fetch("http://localhost:3000/api/config")
|
const payload = await getPayload();
|
||||||
.then(
|
|
||||||
(res) =>
|
|
||||||
res.json() as Promise<
|
|
||||||
| {
|
|
||||||
success: false;
|
|
||||||
message: string;
|
|
||||||
}
|
|
||||||
| (ReturnType<typeof initialValue> & {
|
|
||||||
success: true;
|
|
||||||
})
|
|
||||||
>,
|
|
||||||
)
|
|
||||||
.catch((e) => console.warn(e));
|
|
||||||
|
|
||||||
if (!payload) return;
|
|
||||||
|
|
||||||
if (!payload.success) {
|
if (!payload.success) {
|
||||||
console.log(location.pathname, payload.message, "No success");
|
console.log(payload.message, "No success");
|
||||||
navigator("/", { replace: false });
|
navigator("/", { replace: false });
|
||||||
return initialValue();
|
return initialValue();
|
||||||
}
|
}
|
||||||
console.log(location.pathname, "success");
|
console.log("success");
|
||||||
return payload;
|
return payload;
|
||||||
});
|
});
|
||||||
createEffect(() => console.log(payload()?.guilds, payload()?.guilds.length));
|
|
||||||
// createRenderEffect(() =>
|
|
||||||
// console.log(payload()?.guilds, payload()?.guilds.length),
|
|
||||||
// );
|
|
||||||
|
|
||||||
const icons = [faPlus, faCircleExclamation, faBadgeCheck];
|
const icons = [faPlus, faCircleExclamation, faBadgeCheck];
|
||||||
const colors = [undefined, "orange", "green"];
|
const colors = [undefined, "orange", "green"];
|
||||||
|
@ -60,39 +94,28 @@ function index() {
|
||||||
<Layout site="config">
|
<Layout site="config">
|
||||||
<h3 class="text-center">Configure li'l Judd in</h3>
|
<h3 class="text-center">Configure li'l Judd in</h3>
|
||||||
<div>
|
<div>
|
||||||
<Suspense>
|
<For each={payload()?.guilds ?? []}>
|
||||||
<For each={payload()?.guilds}>
|
{(guild, i) => (
|
||||||
{(guild, i) => {
|
<a href={`/config/${guild.id}`} class="flex-row centered">
|
||||||
return (
|
<img
|
||||||
<a
|
class="guildpfp"
|
||||||
href={
|
src={
|
||||||
i() % 3 === 0
|
guild.icon
|
||||||
? `/config/${guild.id}`
|
? `https://cdn.discordapp.com/icons/${guild.id}/${guild.icon}.webp?size=240`
|
||||||
: `https://discord.com/api/oauth2/authorize?client_id=${import.meta.env.VITE_DISCORD_CLIENT_ID}&permissions=${import.meta.env.VITE_DISCORD_BOT_PERMISSIONS}&scope=bot&guild_id=${guild.id}`
|
: "https://cdn.discordapp.com/icons/1040502664506646548/bb5a51c4659cf47bdd942bb11e974da7.webp?size=240"
|
||||||
}
|
}
|
||||||
class="flex-row centered"
|
alt="Server pfp"
|
||||||
>
|
/>
|
||||||
<img
|
<h1>{guild.name}</h1>
|
||||||
class="guildpfp"
|
<FontAwesomeIcon
|
||||||
src={
|
// beat={i() % 3 === 1}
|
||||||
guild.icon
|
color={colors[i() % 3]}
|
||||||
? `https://cdn.discordapp.com/icons/${guild.id}/${guild.icon}.webp?size=240`
|
icon={icons[i() % 3]}
|
||||||
: "https://cdn.discordapp.com/icons/1040502664506646548/bb5a51c4659cf47bdd942bb11e974da7.webp?size=240"
|
size="xl"
|
||||||
}
|
/>
|
||||||
alt="Server pfp"
|
</a>
|
||||||
/>
|
)}
|
||||||
<h1>{guild.name}</h1>
|
</For>
|
||||||
<FontAwesomeIcon
|
|
||||||
// beat={i() % 3 === 1}
|
|
||||||
color={colors[i() % 3]}
|
|
||||||
icon={icons[i() % 3]}
|
|
||||||
size="xl"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</For>
|
|
||||||
</Suspense>
|
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in a new issue