Compare commits

..

2 commits

5 changed files with 47 additions and 27 deletions

View file

@ -49,12 +49,19 @@ To get started with li'l Judd, follow the instructions below.
VITE_DISCORD_CLIENT=your_discord_client_id VITE_DISCORD_CLIENT=your_discord_client_id
VITE_DISCORD_CLIENT_SECRET=your_discord_client_secret VITE_DISCORD_CLIENT_SECRET=your_discord_client_secret
VITE_DISCORD_BOT_TOKEN=your_discord_bot_token VITE_DISCORD_BOT_TOKEN=your_discord_bot_token
VITE_DISCORD_BOT_PERMISSIONS=18977581952080
VITE_AUTH_SECRET=your_auth_secret VITE_AUTH_SECRET=your_auth_secret
VITE_DATABASE_URL=your_database_url VITE_DATABASE_URL=your_database_url
``` ```
Recieve your discord applications client id & secret, as well as the bot token from the [Applications dashboard](https://discord.com/developers/applications/).
How to generate your `VITE_AUTH_SECRET` with [`openssl rand -base64 32`](https://authjs.dev/reference/core#secret).
Composite your `VITE_DATABASE_URL` like [`postgres://postgres:adminadmin@0.0.0.0:5432/db`](https://orm.drizzle.team/docs/get-started-postgresql#postgresjs).
#### Development #### Development
Specify `VITE_AUTH_REDIRECT_PROXY_URL` only if necessary, particularly when setting up a reverse proxy to test authentication with callbacks to your development box. [Auth.js Docs Reference](https://authjs.dev/reference/nextjs/#redirectproxyurl) Specify `VITE_AUTH_REDIRECT_PROXY_URL` only if necessary, particularly when setting up a reverse proxy to test authentication with callbacks to your development box. [Auth.js Docs Reference](https://authjs.dev/reference/nextjs/#redirectproxyurl)
@ -120,6 +127,6 @@ If you'd like to contribute to li'l Judd, feel free to open an issue or submit a
## License ## License
This project is licensed under the [MIT License](LICENSE). This project is licensed under the [GPL v3 License](LICENSE).
Happy splatting! 🦑🎮 Happy splatting! 🦑🎮

View file

@ -40,7 +40,7 @@ function NavBar() {
</ul> </ul>
<ul class="flex-row responsive thick"> <ul class="flex-row responsive thick">
<Li <Li
href="https://discord.com/api/oauth2/authorize?client_id=1024410658973941862&permissions=18977581952080&scope=bot" href={`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`}
name="Invite to your server" name="Invite to your server"
> >
<FontAwesomeIcon class="lower" icon={faCirclePlus} size="xl" /> <FontAwesomeIcon class="lower" icon={faCirclePlus} size="xl" />

View file

@ -1,6 +1,7 @@
import type { AdapterAccount } from "@auth/core/adapters"; import type { AdapterAccount } from "@auth/core/adapters";
import { relations } from "drizzle-orm"; import { relations } from "drizzle-orm";
import { import {
boolean,
integer, integer,
pgTable, pgTable,
primaryKey, primaryKey,
@ -71,7 +72,7 @@ export const matchPlannings = pgTable("match_planning", {
roleId: varchar("role_id", { length: 20 }).notNull(), roleId: varchar("role_id", { length: 20 }).notNull(),
opponentName: varchar("opponent_name", { length: 100 }).notNull(), opponentName: varchar("opponent_name", { length: 100 }).notNull(),
messageId: varchar("message_id", { length: 20 }).notNull(), messageId: varchar("message_id", { length: 20 }).notNull(),
ts: timestamp("ts").notNull(), utc_ts: timestamp("utc_ts").notNull(),
guildId: varchar("guild_id", { length: 20 }) guildId: varchar("guild_id", { length: 20 })
.notNull() .notNull()
.references(() => guilds.id, { onDelete: "cascade" }), .references(() => guilds.id, { onDelete: "cascade" }),
@ -107,6 +108,7 @@ export const timePlannings = pgTable("time_planning", {
}), }),
channelId: varchar("channel_id", { length: 20 }).notNull(), channelId: varchar("channel_id", { length: 20 }).notNull(),
target_interval: smallint("target_interval").notNull(), target_interval: smallint("target_interval").notNull(),
roles: boolean("roles").notNull(),
isAvailableRoleId: varchar("is_available_role_id", { length: 20 }), isAvailableRoleId: varchar("is_available_role_id", { length: 20 }),
wantsToBeNotifieRoledId: varchar("wants_to_be_notified_role_id", { wantsToBeNotifieRoledId: varchar("wants_to_be_notified_role_id", {
length: 20, length: 20,

View file

@ -98,9 +98,10 @@ const getPayload = async (
function config() { function config() {
const params = useParams(); const params = useParams();
const navigator = useNavigate(); const navigator = useNavigate();
let timezoneRef: HTMLInputElement; let [timezoneRef, setTimezoneRef] = createSignal<HTMLInputElement>();
let timePlanningRef: HTMLInputElement; let [timePlanningRef, setTimePlanningRef] = createSignal<HTMLInputElement>();
let pingableRolesRef: HTMLInputElement; let [pingableRolesRef, setPingableRolesRef] =
createSignal<HTMLInputElement>();
const [timezone, setTimezone] = createSignal(guessTZ()); const [timezone, setTimezone] = createSignal(guessTZ());
const [payload] = createResource(params.guildId, async (id) => { const [payload] = createResource(params.guildId, async (id) => {
@ -136,14 +137,21 @@ function config() {
), ),
); );
createEffect(() => (timezoneRef.value = timezone())); createEffect(() => {
createEffect( const ref = timezoneRef();
() => (timePlanningRef.checked = config.features.timePlanning.enabled), if (!ref) return;
); ref.value = timezone();
createEffect( });
() => createEffect(() => {
(pingableRolesRef.checked = config.features.timePlanning.pingableRoles), 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;
});
return ( return (
<Layout site="config"> <Layout site="config">
@ -155,8 +163,9 @@ function config() {
class="guildpfp" class="guildpfp"
src={ src={
guild()?.icon guild()?.icon
? `https://cdn.discordapp.com/icons/${guild()?.id}/${guild() ? `https://cdn.discordapp.com/icons/${guild()?.id}/${
?.icon}.webp?size=240` guild()?.icon
}.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"
@ -174,7 +183,7 @@ function config() {
type="text" type="text"
list="timezones" list="timezones"
id="timezone" id="timezone"
ref={timezoneRef!} ref={(e) => setTimezoneRef(e)}
// disabled={!tzNames().find((e) => e === timezone())} // disabled={!tzNames().find((e) => e === timezone())}
onInput={(e) => setTimezone(e.target.value)} onInput={(e) => setTimezone(e.target.value)}
/> />
@ -211,7 +220,7 @@ function config() {
hidden hidden
type="checkbox" type="checkbox"
id="timePlanning" id="timePlanning"
ref={timePlanningRef!} ref={(e) => setTimePlanningRef(e)}
onInput={(e) => onInput={(e) =>
setConfig("features", "timePlanning", "enabled", e.target.checked) setConfig("features", "timePlanning", "enabled", e.target.checked)
} }
@ -246,7 +255,7 @@ function config() {
hidden hidden
type="checkbox" type="checkbox"
id="pingableRoles" id="pingableRoles"
ref={pingableRolesRef!} ref={(e) => setPingableRolesRef(e)}
onInput={(e) => onInput={(e) =>
setConfig( setConfig(
"features", "features",

4
src/types/env.d.ts vendored
View file

@ -1,9 +1,10 @@
/// <reference types="vinxi/client" /> /// <reference types="vinxi/client" />
interface ImportMetaEnv { interface ImportMetaEnv {
readonly VITE_DISCORD_CLIENT: string; readonly VITE_DISCORD_CLIENT_ID: string;
readonly VITE_DISCORD_CLIENT_SECRET: string; readonly VITE_DISCORD_CLIENT_SECRET: string;
readonly VITE_DISCORD_BOT_TOKEN: string; readonly VITE_DISCORD_BOT_TOKEN: string;
readonly VITE_DISCORD_BOT_PERMISSIONS: string;
readonly VITE_AUTH_SECRET: string; readonly VITE_AUTH_SECRET: string;
readonly VITE_AUTH_REDIRECT_PROXY_URL: string | undefined; readonly VITE_AUTH_REDIRECT_PROXY_URL: string | undefined;
@ -11,6 +12,7 @@ interface ImportMetaEnv {
readonly VITE_DATABASE_URL: string; readonly VITE_DATABASE_URL: string;
} }
// eslint-disable-next-line no-unused-vars
interface ImportMeta { interface ImportMeta {
readonly env: ImportMetaEnv; readonly env: ImportMetaEnv;
} }