mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-08-22 11:05:09 -05:00
Access command initial
This commit is contained in:
@@ -5,4 +5,6 @@ DB_PATH=db.sqlite3
|
||||
// auth
|
||||
SESSION_SECRET=secret
|
||||
DISCORD_CLIENT_ID=
|
||||
DISCORD_CLIENT_SECRET=
|
||||
DISCORD_CLIENT_SECRET=
|
||||
|
||||
LOHI_TOKEN=salmon
|
||||
@@ -11,3 +11,5 @@ export const PLUS_UPVOTE = 1;
|
||||
export const PLUS_DOWNVOTE = -1;
|
||||
|
||||
export const ADMIN_DISCORD_ID = "79237403620945920";
|
||||
|
||||
export const LOHI_TOKEN_HEADER_NAME = "Lohi-Token";
|
||||
|
||||
@@ -83,3 +83,19 @@ export function findAll() {
|
||||
"id" | "discordId" | "discordName" | "discordDiscriminator" | "plusTier"
|
||||
>[];
|
||||
}
|
||||
|
||||
const findAllPlusMembersStm = sql.prepare(`
|
||||
SELECT "User"."discordId", "PlusTier"."tier" as "plusTier"
|
||||
FROM "User"
|
||||
LEFT JOIN "PlusTier" ON "PlusTier"."userId" = "User".id
|
||||
WHERE "PlusTier"."tier" IS NOT NULL
|
||||
`);
|
||||
|
||||
export type FindAllPlusMembers = Pick<
|
||||
UserWithPlusTier,
|
||||
"discordId" | "plusTier"
|
||||
>[];
|
||||
|
||||
export function findAllPlusMembers() {
|
||||
return findAllPlusMembersStm.all() as FindAllPlusMembers;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@ import type * as plusSuggestions from "~/db/models/plusSuggestions.server";
|
||||
import { monthsVotingRange } from "./modules/plus-server";
|
||||
import type { PlusSuggestion, User, UserWithPlusTier } from "./db/types";
|
||||
import { allTruthy } from "./utils/arrays";
|
||||
import { ADMIN_DISCORD_ID } from "./constants";
|
||||
import { ADMIN_DISCORD_ID, LOHI_TOKEN_HEADER_NAME } from "./constants";
|
||||
import invariant from "tiny-invariant";
|
||||
|
||||
// TODO: 1) move "root checkers" to one file and utils to one file 2) make utils const for more terseness
|
||||
|
||||
@@ -206,3 +207,10 @@ export function canPerformAdminActions(user?: Pick<User, "discordId">) {
|
||||
if (!user) return false;
|
||||
return user.discordId === ADMIN_DISCORD_ID;
|
||||
}
|
||||
|
||||
invariant(process.env["LOHI_TOKEN"], "LOHI_TOKEN is required");
|
||||
export function canAccessLohiEndpoint(request: Request) {
|
||||
return (
|
||||
request.headers.get(LOHI_TOKEN_HEADER_NAME) === process.env["LOHI_TOKEN"]
|
||||
);
|
||||
}
|
||||
|
||||
17
app/routes/plus/list.ts
Normal file
17
app/routes/plus/list.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { json } from "@remix-run/node";
|
||||
import type { LoaderFunction } from "@remix-run/node";
|
||||
import { db } from "~/db";
|
||||
import { canAccessLohiEndpoint } from "~/permissions";
|
||||
import type { FindAllPlusMembers } from "~/db/models/users.server";
|
||||
|
||||
export interface PlusListLoaderData {
|
||||
users: FindAllPlusMembers;
|
||||
}
|
||||
|
||||
export const loader: LoaderFunction = ({ request }) => {
|
||||
if (!canAccessLohiEndpoint(request)) {
|
||||
throw new Response(null, { status: 403 });
|
||||
}
|
||||
|
||||
return json<PlusListLoaderData>({ users: db.users.findAllPlusMembers() });
|
||||
};
|
||||
@@ -1,3 +1,5 @@
|
||||
BOT_TOKEN=
|
||||
TEST_GUILD_ID=
|
||||
BOT_ID=
|
||||
BOT_ID=
|
||||
SENDOU_INK_URL=http://localhost:5800
|
||||
LOHI_TOKEN=salmon
|
||||
45
discord-bot/commands/access.ts
Normal file
45
discord-bot/commands/access.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { SlashCommandBuilder } from "@discordjs/builders";
|
||||
import invariant from "tiny-invariant";
|
||||
import { LOHI_TOKEN_HEADER_NAME } from "~/constants";
|
||||
import type { PlusListLoaderData } from "~/routes/plus/list";
|
||||
import ids from "../ids";
|
||||
import type { BotCommand } from "../types";
|
||||
|
||||
const COMMAND_NAME = "access";
|
||||
|
||||
export const accessCommand: BotCommand = {
|
||||
guilds: [ids.guilds.plusServer],
|
||||
name: COMMAND_NAME,
|
||||
builder: new SlashCommandBuilder()
|
||||
.setName(COMMAND_NAME)
|
||||
.setDescription(
|
||||
"Get the corresponding Plus Server membership role if you have access"
|
||||
),
|
||||
execute: async ({ interaction }) => {
|
||||
const { users } = await usersWithAccess();
|
||||
|
||||
if (!users.some((u) => u.discordId === interaction.user.id)) {
|
||||
return interaction.reply("You currently don't have access");
|
||||
}
|
||||
|
||||
// TODO: logic to change roles here
|
||||
return interaction.reply("ok");
|
||||
},
|
||||
};
|
||||
|
||||
async function usersWithAccess(): Promise<PlusListLoaderData> {
|
||||
invariant(process.env["SENDOU_INK_URL"], "SENDOU_INK_URL is not set");
|
||||
invariant(process.env["LOHI_TOKEN"], "LOHI_TOKEN is not set");
|
||||
|
||||
const response = await fetch(`${process.env["SENDOU_INK_URL"]}/plus/list`, {
|
||||
headers: [[LOHI_TOKEN_HEADER_NAME, process.env["LOHI_TOKEN"]]],
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`Failed to fetch users. Response status was ${response.status}`
|
||||
);
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
import { questionCommand } from "./q";
|
||||
import { lfgRoleCommand } from "./lfg";
|
||||
import { accessCommand } from "./access";
|
||||
import type { BotCommand } from "discord-bot/types";
|
||||
|
||||
export const commands = [questionCommand, lfgRoleCommand];
|
||||
export const commands = [questionCommand, lfgRoleCommand, accessCommand];
|
||||
|
||||
export const commandsMap = Object.fromEntries(commands.map((c) => [c.name, c]));
|
||||
|
||||
|
||||
66
discord-bot/package-lock.json
generated
66
discord-bot/package-lock.json
generated
@@ -1,13 +1,11 @@
|
||||
{
|
||||
"name": "discord-bot",
|
||||
"name": "lohi",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "discord-bot",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"name": "lohi",
|
||||
"dependencies": {
|
||||
"@discordjs/builders": "^0.15.0",
|
||||
"@discordjs/rest": "^0.5.0",
|
||||
@@ -16,6 +14,7 @@
|
||||
"dotenv": "^16.0.1",
|
||||
"tiny-invariant": "^1.2.0",
|
||||
"ts-node": "^10.8.1",
|
||||
"tsconfig-paths": "^4.0.0",
|
||||
"typescript": "^4.7.3"
|
||||
}
|
||||
},
|
||||
@@ -328,6 +327,17 @@
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/json5": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
|
||||
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
|
||||
"bin": {
|
||||
"json5": "lib/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/make-error": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
|
||||
@@ -352,6 +362,11 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/minimist": {
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
|
||||
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
@@ -371,6 +386,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/strip-bom": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
|
||||
"integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/tiny-invariant": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz",
|
||||
@@ -428,6 +451,16 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/tsconfig-paths": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.0.0.tgz",
|
||||
"integrity": "sha512-SLBg2GBKlR6bVtMgJJlud/o3waplKtL7skmLkExomIiaAtLGtVsoXIqP3SYdjbcH9lq/KVv7pMZeCBpLYOit6Q==",
|
||||
"dependencies": {
|
||||
"json5": "^2.2.1",
|
||||
"minimist": "^1.2.6",
|
||||
"strip-bom": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
|
||||
@@ -752,6 +785,11 @@
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
"json5": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
|
||||
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA=="
|
||||
},
|
||||
"make-error": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
|
||||
@@ -770,6 +808,11 @@
|
||||
"mime-db": "1.52.0"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
|
||||
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
@@ -778,6 +821,11 @@
|
||||
"whatwg-url": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"strip-bom": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
|
||||
"integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="
|
||||
},
|
||||
"tiny-invariant": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz",
|
||||
@@ -813,6 +861,16 @@
|
||||
"yn": "3.1.1"
|
||||
}
|
||||
},
|
||||
"tsconfig-paths": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.0.0.tgz",
|
||||
"integrity": "sha512-SLBg2GBKlR6bVtMgJJlud/o3waplKtL7skmLkExomIiaAtLGtVsoXIqP3SYdjbcH9lq/KVv7pMZeCBpLYOit6Q==",
|
||||
"requires": {
|
||||
"json5": "^2.2.1",
|
||||
"minimist": "^1.2.6",
|
||||
"strip-bom": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"tslib": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "lohi",
|
||||
"scripts": {
|
||||
"dev": "ts-node index.ts",
|
||||
"dev": "node --experimental-fetch --require ts-node/register --require tsconfig-paths/register index.ts",
|
||||
"commands": "ts-node deploy-commands.ts",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
@@ -13,6 +13,7 @@
|
||||
"dotenv": "^16.0.1",
|
||||
"tiny-invariant": "^1.2.0",
|
||||
"ts-node": "^10.8.1",
|
||||
"tsconfig-paths": "^4.0.0",
|
||||
"typescript": "^4.7.3"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user