mirror of
https://git.haroon.hackclub.app/haroon/osu-leaderboard.git
synced 2024-11-09 23:39:40 +00:00
linking works now (hooray)
This commit is contained in:
parent
d1e0ca8d46
commit
610522b16d
3 changed files with 135 additions and 32 deletions
BIN
bun.lockb
BIN
bun.lockb
Binary file not shown.
150
index.ts
150
index.ts
|
@ -1,36 +1,132 @@
|
|||
Bun.serve({
|
||||
port: 41691,
|
||||
async fetch(req: Request) {
|
||||
if (req.method == "OPTIONS") {
|
||||
return new Response(null)
|
||||
}
|
||||
const url = new URL(req.url, "https://loc.al/");
|
||||
const { App, ExpressReceiver } = (await import("@slack/bolt"));
|
||||
import postgres from "postgres";
|
||||
import "dotenv/config";
|
||||
import bcrypt from "bcrypt";
|
||||
|
||||
if (url.pathname == "/callback") {
|
||||
const code = url.searchParams.get("code");
|
||||
const sql = postgres({
|
||||
host: '/var/run/postgresql',
|
||||
database: 'haroon_osu',
|
||||
username: 'haroon'
|
||||
})
|
||||
|
||||
const data = await fetch("https://osu.ppy.sh/oauth/token", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
},
|
||||
body: `client_id=33126&client_secret=${encodeURIComponent(Bun.env.CLIENT_SECRET!)}&code=${code}&grant_type=authorization_code&redirect_uri=${encodeURIComponent("https://osu.haroon.hackclub.app/callback")}`
|
||||
}).then(res => res.json());
|
||||
const receiver = new ExpressReceiver({ signingSecret: process.env.SLACK_SIGNING_SECRET! })
|
||||
|
||||
if (data.error) {
|
||||
console.log(data)
|
||||
return new Response(`Something went wrong: \n\n${data.message} (${data.error})\n\nThis has been reported.`)
|
||||
} else {
|
||||
const user = await fetch("https://osu.ppy.sh/api/v2/me", {
|
||||
headers: {
|
||||
"Authorization": `Bearer ${data.access_token}`
|
||||
const app = new App({
|
||||
token: process.env.SLACK_BOT_TOKEN,
|
||||
signingSecret: process.env.SLACK_SIGNING_SECRET,
|
||||
receiver,
|
||||
installerOptions: {
|
||||
port: 41691
|
||||
}
|
||||
});
|
||||
|
||||
const states = new Map();
|
||||
|
||||
app.command("/osu-link", async (ctx) => {
|
||||
await ctx.ack();
|
||||
|
||||
const [ exists = null ] = await sql`SELECT osu_id FROM links WHERE slack_id = ${ctx.context.userId}`;
|
||||
|
||||
if (exists) {
|
||||
return ctx.respond({
|
||||
text: "This slack account is already linked to an osu! account.",
|
||||
unfurl_links: true,
|
||||
blocks: [
|
||||
{
|
||||
type: 'section',
|
||||
text: {
|
||||
type: "mrkdwn",
|
||||
text: `This slack account is already linked to an <https://osu.ppy.sh/users/${exists.osu_id}/|osu! account>.`
|
||||
}
|
||||
}).then(res => res.json());
|
||||
}
|
||||
]
|
||||
|
||||
return new Response(`Hello, ${user.username}!`)
|
||||
})
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const verifCode = `OSULEADERBOARD-${ctx.context.userId}-${Date.now()}`;
|
||||
|
||||
states.set(ctx.context.userId, verifCode);
|
||||
|
||||
const encodedCode = await bcrypt.hash(verifCode, 10);
|
||||
|
||||
ctx.respond({
|
||||
replace_original: true,
|
||||
text: "View this message in your client to verify!",
|
||||
blocks: [
|
||||
{
|
||||
type: 'section',
|
||||
text: {
|
||||
type: "mrkdwn",
|
||||
text: `Hey <@${ctx.context.userId}>! To link your osu! account to your Slack account, click this button:`
|
||||
},
|
||||
"accessory": {
|
||||
"type": "button",
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "Link account",
|
||||
"emoji": true
|
||||
},
|
||||
"value": "link",
|
||||
"url": `https://osu.ppy.sh/oauth/authorize?client_id=33126&redirect_uri=https://osu.haroon.hackclub.app/osu/callback&response_type=code&state=${encodeURIComponent(ctx.context.userId + ":" + encodedCode)}`,
|
||||
"action_id": "link"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
})
|
||||
|
||||
return new Response(null, { status: 404 });
|
||||
receiver.router.get("/osu/callback", async (req, res) => {
|
||||
res.contentType("text/html")
|
||||
|
||||
const code = req.query.code as string;
|
||||
const state = req.query.state as string;
|
||||
|
||||
const [userId, hash] = state.split(':');
|
||||
|
||||
try {
|
||||
const isValid = await bcrypt.compare(states.get(userId), hash);
|
||||
|
||||
if (!isValid) {
|
||||
throw new Error();
|
||||
}
|
||||
} catch (err) {
|
||||
return res.send(`Something went wrong: <br><br>Your state was invalid. Please re-authenticate. (invalid_state)<br><br>This has been reported.`)
|
||||
}
|
||||
|
||||
states.delete(userId);
|
||||
|
||||
const data = await fetch("https://osu.ppy.sh/oauth/token", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
},
|
||||
body: `client_id=33126&client_secret=${encodeURIComponent(process.env.CLIENT_SECRET!)}&code=${code}&grant_type=authorization_code&redirect_uri=${encodeURIComponent("https://osu.haroon.hackclub.app/osu/callback")}`
|
||||
}).then(res => res.json());
|
||||
|
||||
if (data.error) {
|
||||
console.log(data)
|
||||
return res.send(`Something went wrong: <br><br>${data.message} (${data.error})<br><br>This has been reported.`)
|
||||
} else {
|
||||
const user = await fetch("https://osu.ppy.sh/api/v2/me", {
|
||||
headers: {
|
||||
"Authorization": `Bearer ${data.access_token}`
|
||||
}
|
||||
}).then(res => res.json());
|
||||
|
||||
// {user.id} - osu! user ID
|
||||
// userId - slack user ID
|
||||
|
||||
sql`INSERT INTO links VALUES (${user.id}, ${userId})`
|
||||
|
||||
return res.send(`Your osu! account (${user.id}) has been successfully linked to your Slack account (${userId})!`)
|
||||
}
|
||||
})
|
||||
|
||||
;(async () => {
|
||||
await app.start(41691);
|
||||
|
||||
console.log('⚡️ Bolt app is running!');
|
||||
})();
|
|
@ -7,5 +7,12 @@
|
|||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@slack/bolt": "^3.19.0",
|
||||
"@types/bcrypt": "^5.0.2",
|
||||
"bcrypt": "^5.1.1",
|
||||
"dotenv": "^16.4.5",
|
||||
"postgres": "^3.4.4"
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue