Compare commits
3 commits
renovate/s
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
365b6bd381 | ||
|
c765dfded7 | ||
|
7b0d45d17e |
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -173,3 +173,5 @@ dist
|
||||||
|
|
||||||
# Finder (MacOS) folder config
|
# Finder (MacOS) folder config
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
replay-*.osr
|
392
index.ts
392
index.ts
|
@ -6,6 +6,14 @@ import "dotenv/config";
|
||||||
import bcrypt from "bcrypt";
|
import bcrypt from "bcrypt";
|
||||||
import type { StaticSelectAction } from "@slack/bolt";
|
import type { StaticSelectAction } from "@slack/bolt";
|
||||||
import { inspect } from "node:util";
|
import { inspect } from "node:util";
|
||||||
|
import { scheduleJob } from "node-schedule";
|
||||||
|
|
||||||
|
// @ts-expect-error No typings :)))))))))))
|
||||||
|
import osr from "node-osr";
|
||||||
|
import { Client, Events } from "ordr.js";
|
||||||
|
|
||||||
|
import io from "socket.io-client";
|
||||||
|
import fs from "fs";
|
||||||
|
|
||||||
const sql = postgres({
|
const sql = postgres({
|
||||||
host: '/var/run/postgresql',
|
host: '/var/run/postgresql',
|
||||||
|
@ -24,6 +32,8 @@ const app = new App({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const ordr = new Client(process.env.ORDR_TOKEN!);
|
||||||
|
|
||||||
const states = new Map();
|
const states = new Map();
|
||||||
|
|
||||||
app.command("/osu-link", async (ctx) => {
|
app.command("/osu-link", async (ctx) => {
|
||||||
|
@ -162,11 +172,12 @@ async function getTemporaryToken(): Promise<string> {
|
||||||
return data.access_token;
|
return data.access_token;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getAccessToken(slack_id: string): Promise<string|null> {
|
async function getAccessToken(slack_id: string): Promise<string | null> {
|
||||||
const user = await sql`SELECT * FROM links WHERE slack_id = ${slack_id}`;
|
const user = await sql`SELECT * FROM links WHERE slack_id = ${slack_id}`;
|
||||||
|
|
||||||
if (!user.length) return null
|
if (!user.length) return null
|
||||||
|
|
||||||
|
try {
|
||||||
const data = await fetch("https://osu.ppy.sh/oauth/token", {
|
const data = await fetch("https://osu.ppy.sh/oauth/token", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
|
@ -178,6 +189,10 @@ async function getAccessToken(slack_id: string): Promise<string|null> {
|
||||||
await sql`UPDATE links SET refresh_token = ${data.refresh_token} WHERE slack_id = ${slack_id}`;
|
await sql`UPDATE links SET refresh_token = ${data.refresh_token} WHERE slack_id = ${slack_id}`;
|
||||||
|
|
||||||
return data.access_token;
|
return data.access_token;
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function sendGET<T>(path: string, token?: string): Promise<T> {
|
async function sendGET<T>(path: string, token?: string): Promise<T> {
|
||||||
|
@ -202,20 +217,26 @@ function splitArray<T>(arr: T[], maxElements: number): T[][] {
|
||||||
}
|
}
|
||||||
/// GENERATED ///
|
/// GENERATED ///
|
||||||
|
|
||||||
const cache: {
|
type CacheUser = {
|
||||||
username: string,
|
username: string;
|
||||||
id: number,
|
id: number;
|
||||||
slackId: string,
|
slackId: string;
|
||||||
score: {
|
score: {
|
||||||
osu: number,
|
osu: number;
|
||||||
taiko: number
|
taiko: number;
|
||||||
fruits: number,
|
fruits: number;
|
||||||
mania: number
|
mania: number;
|
||||||
}
|
};
|
||||||
}[] = []
|
}
|
||||||
|
|
||||||
|
const cache: CacheUser[] = []
|
||||||
|
|
||||||
const multiplayerRoundCache: any[] = [];
|
const multiplayerRoundCache: any[] = [];
|
||||||
|
|
||||||
|
const sentWarningDM = {
|
||||||
|
ref: false
|
||||||
|
}
|
||||||
|
|
||||||
async function cacheStuff(): Promise<void> {
|
async function cacheStuff(): Promise<void> {
|
||||||
const token = await getTemporaryToken();
|
const token = await getTemporaryToken();
|
||||||
|
|
||||||
|
@ -264,7 +285,49 @@ async function cacheStuff(): Promise<void> {
|
||||||
|
|
||||||
const tohken = await getAccessToken("U06TBP41C3E") as string;
|
const tohken = await getAccessToken("U06TBP41C3E") as string;
|
||||||
|
|
||||||
if (!tohken) return;
|
if (!tohken) {
|
||||||
|
const verifCode = `OSULEADERBOARD-U06TBP41C3E-${Date.now()}`;
|
||||||
|
|
||||||
|
states.set('U06TBP41C3E', verifCode);
|
||||||
|
|
||||||
|
const encodedCode = await bcrypt.hash(verifCode, 10);
|
||||||
|
|
||||||
|
await app.client.chat.postMessage({
|
||||||
|
channel: "U06TBP41C3E",
|
||||||
|
text: "uh oh, your token seems to have expired!! multiplayer round fetching + daily challenges are disabled.",
|
||||||
|
blocks: [
|
||||||
|
{
|
||||||
|
type: 'section',
|
||||||
|
text: {
|
||||||
|
type: "mrkdwn",
|
||||||
|
text: `uh oh, your token seems to have expired!! multiplayer round fetching + daily challenges are disabled.`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'section',
|
||||||
|
text: {
|
||||||
|
type: "mrkdwn",
|
||||||
|
text: `Please re-authenticate to generate it by clicking the Reauthenticate button.`
|
||||||
|
},
|
||||||
|
"accessory": {
|
||||||
|
"type": "button",
|
||||||
|
"text": {
|
||||||
|
"type": "plain_text",
|
||||||
|
"text": "Reauthenticate",
|
||||||
|
"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("U06TBP41C3E:" + encodedCode)}&scope=public`,
|
||||||
|
"action_id": "link"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
sentWarningDM.ref = true;
|
||||||
|
|
||||||
|
return
|
||||||
|
};
|
||||||
|
|
||||||
const rooms = await fetch(`https://osu.ppy.sh/api/v2/rooms?category=realtime`, {
|
const rooms = await fetch(`https://osu.ppy.sh/api/v2/rooms?category=realtime`, {
|
||||||
headers: {
|
headers: {
|
||||||
|
@ -480,17 +543,23 @@ app.command('/osu-profile', async (ctx) => {
|
||||||
app.command('/osu-leaderboard', async (ctx) => {
|
app.command('/osu-leaderboard', async (ctx) => {
|
||||||
await ctx.ack();
|
await ctx.ack();
|
||||||
|
|
||||||
const cached = splitArray<any>(cache, 10)[0].sort((a, b) => {
|
const cached = splitArray<CacheUser>(cache.sort((a, b) => {
|
||||||
return b.score.osu - a.score.osu
|
return b.score.osu - a.score.osu
|
||||||
});
|
}), 10);
|
||||||
|
|
||||||
const users = [];
|
const users = [];
|
||||||
|
|
||||||
for (let i in cached) {
|
for (let i in cached[0]) {
|
||||||
const cachedU = cached[i];
|
try {
|
||||||
const slackProfile = (await ctx.client.users.info({ user: cachedU.slackId })).user!;
|
const cachedU = cached[0][i];
|
||||||
|
const slackInfo = await ctx.client.users.info({ user: cachedU.slackId })
|
||||||
|
const slackProfile = slackInfo.user!;
|
||||||
|
|
||||||
users.push(`${parseInt(i) + 1}. <https://hackclub.slack.com/team/${slackProfile.id}|${slackProfile.profile!.display_name_normalized}> / <https://osu.ppy.sh/users/${cachedU.id}|${cachedU.username}> - ${cachedU.score.osu.toLocaleString()}`)
|
users.push(`${users.length + 1}. <https://hackclub.slack.com/team/${slackProfile.id}|${slackProfile.profile!.display_name_normalized}> / <https://osu.ppy.sh/users/${cachedU.id}|${cachedU.username}> - ${cachedU.score.osu.toLocaleString()}`)
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.respond({
|
ctx.respond({
|
||||||
|
@ -588,19 +657,24 @@ app.action(/change-leaderboard\|.+/, async (ctx) => {
|
||||||
return ctx.respond({ replace_original: false, response_type: "ephemeral", text: `This leaderboard was initialised by <@${userId}>. Only they can manage it.` })
|
return ctx.respond({ replace_original: false, response_type: "ephemeral", text: `This leaderboard was initialised by <@${userId}>. Only they can manage it.` })
|
||||||
}
|
}
|
||||||
|
|
||||||
const selected = action.selected_option.value;
|
const selected = action.selected_option.value as "osu" | "taiko" | "fruits" | "mania";
|
||||||
|
|
||||||
const cached = splitArray<any>(cache, 10)[0].sort((a, b) => {
|
const cached = splitArray<any>(cache.sort((a, b) => {
|
||||||
return b.score[selected] - a.score[selected]
|
return b.score[selected] - a.score[selected]
|
||||||
});
|
}), 10)[0];
|
||||||
|
|
||||||
const users = [];
|
const users = [];
|
||||||
|
|
||||||
for (let i in cached) {
|
for (let i in cached) {
|
||||||
|
try {
|
||||||
const cachedU = cached[i];
|
const cachedU = cached[i];
|
||||||
const slackProfile = (await ctx.client.users.info({ user: cachedU.slackId })).user!;
|
const slackProfile = (await ctx.client.users.info({ user: cachedU.slackId })).user!;
|
||||||
|
|
||||||
users.push(`${parseInt(i) + 1}. <https://hackclub.slack.com/team/${slackProfile.id}|${slackProfile.profile!.display_name_normalized}> / <https://osu.ppy.sh/users/${cachedU.id}|${cachedU.username}> - ${cachedU.score[selected].toLocaleString()}`)
|
users.push(`${users.length + 1}. <https://hackclub.slack.com/team/${slackProfile.id}|${slackProfile.profile!.display_name_normalized}> / <https://osu.ppy.sh/users/${cachedU.id}|${cachedU.username}> - ${cachedU.score[selected].toLocaleString()}`)
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.respond({
|
ctx.respond({
|
||||||
|
@ -859,6 +933,41 @@ app.command('/osu-search', async (ctx) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const accessToken = await getAccessToken(ctx.context.userId!);
|
||||||
|
|
||||||
|
if (!accessToken) {
|
||||||
|
const verifCode = `OSULEADERBOARD-${ctx.context.userId}-${Date.now()}`;
|
||||||
|
|
||||||
|
states.set(ctx.context.userId, verifCode);
|
||||||
|
|
||||||
|
const encodedCode = await bcrypt.hash(verifCode, 10);
|
||||||
|
|
||||||
|
return ctx.respond({
|
||||||
|
response_type: 'ephemeral',
|
||||||
|
text: `Hey <@${ctx.context.userId}>, your token has expired. Please re-authenticate to generate it by clicking the Reauthenticate button.`,
|
||||||
|
blocks: [
|
||||||
|
{
|
||||||
|
type: 'section',
|
||||||
|
text: {
|
||||||
|
type: 'mrkdwn',
|
||||||
|
text: `Hey <@${ctx.context.userId}>, your token has expired. Please re-authenticate to generate it by clicking the \`Reauthenticate\` button.`
|
||||||
|
},
|
||||||
|
"accessory": {
|
||||||
|
"type": "button",
|
||||||
|
"text": {
|
||||||
|
"type": "plain_text",
|
||||||
|
"text": "Reauthenticate",
|
||||||
|
"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)}&scope=public`,
|
||||||
|
"action_id": "link"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
ctx.client.views.open({
|
ctx.client.views.open({
|
||||||
trigger_id: ctx.payload.trigger_id,
|
trigger_id: ctx.payload.trigger_id,
|
||||||
view: {
|
view: {
|
||||||
|
@ -1057,7 +1166,7 @@ app.view("search", async (ctx) => {
|
||||||
|
|
||||||
const set = data.beatmapsets[0];
|
const set = data.beatmapsets[0];
|
||||||
|
|
||||||
return ctx.client.chat.postMessage({
|
ctx.client.chat.postMessage({
|
||||||
channel: ctx.view.private_metadata,
|
channel: ctx.view.private_metadata,
|
||||||
"blocks": [
|
"blocks": [
|
||||||
{
|
{
|
||||||
|
@ -1090,12 +1199,249 @@ receiver.router.get('*', (req, res) => {
|
||||||
res.redirect(`https://osu.ppy.sh${req.path}`)
|
res.redirect(`https://osu.ppy.sh${req.path}`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
enum Mods {
|
||||||
|
EZ = "Easy",
|
||||||
|
NF = "No Fail",
|
||||||
|
HT = "Half Time",
|
||||||
|
HR = "Hard Rock",
|
||||||
|
SD = "Sudden Death",
|
||||||
|
PF = "Perfect",
|
||||||
|
DT = "Double Time",
|
||||||
|
NC = "Nightcore",
|
||||||
|
HD = "Hidden",
|
||||||
|
FI = "Fade In",
|
||||||
|
FL = "Flashlight",
|
||||||
|
RL = "Relax",
|
||||||
|
AP = "Autopilot",
|
||||||
|
SO = "Spun Out",
|
||||||
|
"1K" = "One Key",
|
||||||
|
"2K" = "Two Keys",
|
||||||
|
"3K" = "Three Keys",
|
||||||
|
"4K" = "Four Keys",
|
||||||
|
"5K" = "Five Keys",
|
||||||
|
"6K" = "Six Keys",
|
||||||
|
"7K" = "Seven Keys",
|
||||||
|
"8K" = "Eight Keys",
|
||||||
|
"9K" = "Nine Keys",
|
||||||
|
"10K" = "Ten Keys"
|
||||||
|
}
|
||||||
|
|
||||||
|
async function debugDailyChallenge() {
|
||||||
|
// Daily Challenge!!
|
||||||
|
|
||||||
|
const tohken = await getAccessToken("U06TBP41C3E");
|
||||||
|
|
||||||
|
const rooms: any[] = await fetch(`https://osu.ppy.sh/api/v2/rooms`, {
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Bearer ${tohken}`,
|
||||||
|
'X-Api-Version': '20240529'
|
||||||
|
}
|
||||||
|
}).then(res => res.json());
|
||||||
|
|
||||||
|
const dailyChallenge = rooms.find(room => room.host.id == 3 && room.active && room.category == "daily_challenge");
|
||||||
|
|
||||||
|
const currentSong = dailyChallenge.current_playlist_item
|
||||||
|
|
||||||
|
const ruleset = [":osu-standard: osu!standard", ":osu-taiko: osu!taiko", ":osu-catch: osu!catch", ":osu-mania: osu!mania"][currentSong.ruleset_id]
|
||||||
|
|
||||||
|
return app.client.chat.postMessage({
|
||||||
|
channel: "C165V7XT9",
|
||||||
|
text: "A new daily challenge has started!",
|
||||||
|
"blocks": [
|
||||||
|
{
|
||||||
|
"type": "header",
|
||||||
|
text: {
|
||||||
|
text: ruleset.split(' ').shift() + " A new daily challenge has started!",
|
||||||
|
emoji: true,
|
||||||
|
type: "plain_text"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "section",
|
||||||
|
"text": {
|
||||||
|
"type": "mrkdwn",
|
||||||
|
"text": `<https://osu.ppy.sh/beatmapsets/${currentSong.beatmap.beatmapset_id
|
||||||
|
}#osu/${currentSong.beatmap.id
|
||||||
|
}|${currentSong.beatmap.beatmapset.title
|
||||||
|
} - ${currentSong.beatmap.beatmapset.artist
|
||||||
|
} (${currentSong.beatmap.difficulty_rating
|
||||||
|
})>
|
||||||
|
|
||||||
|
*Ruleset:* ${ruleset}
|
||||||
|
*Required mods:* ${currentSong.required_mods.length === 0 ? "None" : currentSong.required_mods.map((mod: any) =>
|
||||||
|
// @ts-ignore I HATE THIS
|
||||||
|
Mods[mod.acronym] || mod.acronym
|
||||||
|
).join(', ')}`
|
||||||
|
},
|
||||||
|
"accessory": {
|
||||||
|
"type": "image",
|
||||||
|
"image_url": dailyChallenge.host.avatar_url,
|
||||||
|
"alt_text": `${dailyChallenge.host.username}'s osu profile picture`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
unfurl_links: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type QueueJob = {
|
||||||
|
md5: string,
|
||||||
|
playerName: string,
|
||||||
|
ts: string,
|
||||||
|
userId: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const queue: QueueJob[] = []
|
||||||
|
// key is renderID
|
||||||
|
const waiting = new Map<number, QueueJob>()
|
||||||
|
|
||||||
|
const processQueue = async () => {
|
||||||
|
if (queue.length > 0) {
|
||||||
|
const job = queue.shift()!;
|
||||||
|
|
||||||
|
setTimeout(processQueue, 5000)
|
||||||
|
|
||||||
|
app.client.reactions.add({
|
||||||
|
channel: "C165V7XT9",
|
||||||
|
name: "thinkspin",
|
||||||
|
timestamp: job.ts
|
||||||
|
})
|
||||||
|
|
||||||
|
const render = await ordr.sendRender({
|
||||||
|
replay: `replay-${job.md5}.osr`,
|
||||||
|
skin: 'default',
|
||||||
|
username: job.playerName,
|
||||||
|
showDanserLogo: false,
|
||||||
|
resolution: '1280x720'
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log(render)
|
||||||
|
|
||||||
|
// @ts-ignore Error code 0 DOES exist: https://ordr.issou.best/docs/#section/Error-codes
|
||||||
|
if (render.errorCode !== 0) {
|
||||||
|
app.client.chat.postEphemeral({
|
||||||
|
channel: "C165V7XT9",
|
||||||
|
user: job.userId,
|
||||||
|
text: `Hey: it looks like you posted a replay! Unfortunately, I couldn't generate a video of it: "${render.message}"`
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
waiting.set(render.renderID!, job);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const socket = io('https://apis.issou.best', {
|
||||||
|
path: '/ordr/ws',
|
||||||
|
autoConnect: false
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on('connect', () => {
|
||||||
|
console.log('Connected to ordr websocket!')
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on('disconnect', reason => {
|
||||||
|
if (reason == "io server disconnect") {
|
||||||
|
socket.connect()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on('render_done_json', async (render) => {
|
||||||
|
const job = waiting.get(render.renderID!);
|
||||||
|
|
||||||
|
if (!job) return;
|
||||||
|
|
||||||
|
app.client.chat.postMessage({
|
||||||
|
channel: 'C165V7XT9',
|
||||||
|
thread_ts: job.ts,
|
||||||
|
reply_broadcast: true,
|
||||||
|
text: `<${render.videoUrl}|replay-${job.md5}.mp4>`,
|
||||||
|
unfurl_media: true
|
||||||
|
})
|
||||||
|
|
||||||
|
app.client.reactions.remove({
|
||||||
|
channel: "C165V7XT9",
|
||||||
|
name: "thinkspin",
|
||||||
|
timestamp: job.ts
|
||||||
|
})
|
||||||
|
|
||||||
|
waiting.delete(render.renderID!);
|
||||||
|
})
|
||||||
|
|
||||||
|
const addToQueue = (job: QueueJob) => {
|
||||||
|
queue.push(job);
|
||||||
|
if (queue.length === 1) {
|
||||||
|
processQueue();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
app.event("message", async (ctx) => {
|
||||||
|
if (ctx.event.channel != "C165V7XT9") return;
|
||||||
|
if (ctx.event.subtype != "file_share") return;
|
||||||
|
const ts = ctx.event.ts;
|
||||||
|
|
||||||
|
const history = await ctx.client.conversations.history({
|
||||||
|
channel: "C165V7XT9",
|
||||||
|
latest: ts,
|
||||||
|
limit: 1,
|
||||||
|
inclusive: true
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!(history.messages && history.messages.length > 0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const message = history.messages[0];
|
||||||
|
|
||||||
|
if (!message.files) return;
|
||||||
|
if (message.files.length === 0) return;
|
||||||
|
|
||||||
|
const replay = message.files.find(file => file.name?.endsWith(".osr"));
|
||||||
|
|
||||||
|
if (!replay) return;
|
||||||
|
|
||||||
|
const replayData = await fetch(replay.url_private_download!, {
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Bearer ${process.env.SLACK_BOT_TOKEN}`
|
||||||
|
}
|
||||||
|
}).then(res => res.arrayBuffer());
|
||||||
|
|
||||||
|
const replayBuffer = Buffer.from(replayData);
|
||||||
|
|
||||||
|
const _replay = await osr.read(replayBuffer);
|
||||||
|
|
||||||
|
if (_replay.gameMode !== 0) {
|
||||||
|
ctx.client.chat.postEphemeral({
|
||||||
|
channel: "C165V7XT9",
|
||||||
|
user: ctx.context.userId!,
|
||||||
|
text: "Hey: it looks like you posted a replay! Unfortunately, it's not an :osu-standard: osu!standard replay, and so I can't generate a video of it. Sorry!"
|
||||||
|
})
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const replayFile = fs.createWriteStream(`replay-${_replay.replayMD5}.osr`);
|
||||||
|
|
||||||
|
replayFile.write(replayBuffer);
|
||||||
|
replayFile.end();
|
||||||
|
|
||||||
|
addToQueue({
|
||||||
|
md5: _replay.replayMD5,
|
||||||
|
playerName: _replay.playerName,
|
||||||
|
ts: ts,
|
||||||
|
userId: ctx.context.userId!
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
; (async () => {
|
; (async () => {
|
||||||
await app.start(41691);
|
await app.start(41691);
|
||||||
|
|
||||||
console.log('⚡️ Bolt app is running!');
|
console.log('⚡️ Bolt app is running!');
|
||||||
|
|
||||||
|
socket.connect();
|
||||||
|
|
||||||
cacheStuff();
|
cacheStuff();
|
||||||
|
|
||||||
setInterval(cacheStuff, 60 * 1000) // Cache every minute. Ratelimit is 1200 req/m anyways.
|
setInterval(cacheStuff, 60 * 1000) // Cache every minute. Ratelimit is 1200 req/m anyways.
|
||||||
|
|
||||||
|
scheduleJob('30 5 0 * * *', debugDailyChallenge)
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -9,10 +9,15 @@
|
||||||
"typescript": "^5.0.0"
|
"typescript": "^5.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@slack/bolt": "^4.0.0",
|
"@slack/bolt": "^3.19.0",
|
||||||
"@types/bcrypt": "^5.0.2",
|
"@types/bcrypt": "^5.0.2",
|
||||||
|
"@types/node-schedule": "^2.1.7",
|
||||||
"bcrypt": "^5.1.1",
|
"bcrypt": "^5.1.1",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"postgres": "^3.4.4"
|
"node-osr": "^1.2.1",
|
||||||
|
"node-schedule": "^2.1.1",
|
||||||
|
"ordr.js": "^4.0.0",
|
||||||
|
"postgres": "^3.4.4",
|
||||||
|
"socket.io-client": "^4.8.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue