Skip to content

Commit

Permalink
sync online database of users (#171)
Browse files Browse the repository at this point in the history
* add dep and update env vars

* create turso db updating

* sync db every 3 seconds

* polish link commands

* bump refresh interval to 6 seconds
  • Loading branch information
Yoru authored Apr 13, 2024
1 parent 4f78f37 commit f7c60ed
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 6 deletions.
2 changes: 2 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ ACCESS_TOKEN=
CLIENT_ID=
CLIENT_SECRET=
CALLBACK_URL=
TURSO_URL=
TURSO_TOKEN=
KEY=
IV=
3 changes: 2 additions & 1 deletion globals.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ declare module "bun" {
CLIENT_SECRET: string;
CLIENT_ID: string;
CALLBACK_URL: string;
OSU_CAPITAL_ACCESS_TOKEN: string;
TURSO_URL: string;
TURSO_TOKEN: string;
KEY?: string;
IV?: string;
}
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@
"build": "sh ./cli/build.sh"
},
"dependencies": {
"@libsql/client": "^0.6.0",
"@lilybird/handlers": "beta",
"@lilybird/transformers": "alpha",
"lilybird": "beta",
"osu-web.js": "^2.4.0",
"rosu-pp-js": "^1.0.1",
"tasai": "^1.0.0"
},
"devDependencies": {
},
"devDependencies": {
"@types/bun": "latest",
"eslint": "^8.55.0",
"@typescript-eslint/parser": "^6.13.2",
Expand Down
11 changes: 10 additions & 1 deletion src/commands/osu/link.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { encrypt } from "../..";
import { buildAuthUrl } from "@utils/osu";
import { getUser } from "@utils/database";
import { slashCommandsIds } from "@utils/cache";
import type { AuthScope } from "@type/osu";
import type { SlashCommand } from "@lilybird/handlers";
import type { ApplicationCommandData, Interaction } from "@lilybird/transformers";
Expand All @@ -14,8 +16,15 @@ async function run(interaction: Interaction<ApplicationCommandData>): Promise<vo
if (!interaction.inGuild()) return;
await interaction.deferReply(true);

const encryptedDiscordId = `${encrypt(interaction.member.user.id)}`;
const userId = interaction.member.user.id;
const user = getUser(userId);
if (user?.banchoId) {
const unlinkCommand = slashCommandsIds.get("unlink");
await interaction.editReply(`You're already linked to the bot. You ${unlinkCommand} to unlink yourself!`);
return;
}

const encryptedDiscordId = `${encrypt(userId)}`;
const authUrl = buildRedirectPage(encryptedDiscordId);
await interaction.editReply(`You can [click here](<${authUrl}>) to link your osu! account to the bot!`);
}
Expand Down
2 changes: 2 additions & 0 deletions src/commands/osu/unlink.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { getUser, removeUser } from "@utils/database";
import { slashCommandsIds } from "@utils/cache";
import { removeUserOnline } from "@utils/turso";
import type { SlashCommand } from "@lilybird/handlers";
import type { ApplicationCommandData, Interaction } from "@lilybird/transformers";

Expand All @@ -21,6 +22,7 @@ async function run(interaction: Interaction<ApplicationCommandData>): Promise<vo
return;
}

await removeUserOnline(userId);
removeUser(userId);
await interaction.editReply(`Sad to see you go :(\nYou can always re-link yourself using ${linkCommand}!`);
}
6 changes: 6 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import { initializeDatabase, loadLogs, client } from "./utils/initalize";
import { getAccessToken } from "./utils/osu";
import { syncUsersWithLocal } from "@utils/turso";
import { createHandler } from "@lilybird/handlers/simple";
import { createClient, Intents } from "lilybird";
import { c } from "tasai";
Expand All @@ -23,6 +24,11 @@ setInterval(async () => {
client.setAccessToken(accessToken);
}, 1000 * 60 * 60);

// refresh database every 6 seconds
setInterval(async () => {
await syncUsersWithLocal();
}, 6);

const keyString = process.env.KEY ?? randomBytes(32);
const ivString = process.env.IV ?? randomBytes(16);

Expand Down
7 changes: 5 additions & 2 deletions src/utils/database.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import db from "../data.db" with { type: "sqlite" };
import type { DatabaseMap, DatabaseGuild, DatabaseUser, DatabaseCommands } from "@type/database";

export function getUsers(): Array<DatabaseUser | null> {
return db.prepare("SELECT * FROM users").all() as Array<DatabaseUser | null>;
}

export function getUser(id: string | number): DatabaseUser | null {
const data: DatabaseUser | null = db.prepare("SELECT * FROM users WHERE id = ?").get(id) as DatabaseUser | null;
if (typeof data?.score_embeds === "string") data.score_embeds = Number(data.score_embeds);
const data = db.prepare("SELECT * FROM users WHERE id = ?").get(id) as DatabaseUser | null;

return data;
}
Expand Down
2 changes: 2 additions & 0 deletions src/utils/initalize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import db from "../data.db" with { type: "sqlite" };
import { getAccessToken } from "./osu";
import { slashCommandsIds } from "./cache";
import { Client as OsuClient } from "osu-web.js";
import { createClient } from "@libsql/client";
import { mkdir, access, readFile, writeFile, readdir } from "node:fs/promises";
import type { Client as LilybirdClient, POSTApplicationCommandStructure } from "lilybird";
import type { DefaultMessageCommand, DefaultSlashCommand } from "@type/commands";

const { accessToken } = await getAccessToken(+process.env.CLIENT_ID, process.env.CLIENT_SECRET, ["public"]);
export const client = new OsuClient(accessToken);
export const tursoClient = createClient({ url: process.env.TURSO_URL, authToken: process.env.TURSO_TOKEN });

export const messageCommands = new Map<string, DefaultMessageCommand>();
export const commandAliases = new Map<string, string>();
Expand Down
42 changes: 42 additions & 0 deletions src/utils/turso.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { getUsers, insertData } from "./database";
import { tursoClient as client } from "./initalize";

export async function syncUsersWithLocal(): Promise<void> {
const usersOnline = (await getUsersOnline()).sort((a, b) => Number(a?.id) - Number(b?.id));
const usersLocalMap = new Map(getUsers().map((user) => [user?.id, user]));

const max = Math.max(usersOnline.length, usersLocalMap.size);
const maxWhich = usersOnline.length > usersLocalMap.size ? "online" : "local";

for (let i = 0; i < max; i++) {
if (maxWhich === "local" && i >= usersLocalMap.size) continue;

const online = usersOnline[i];
if (!online) continue;

const localUser = usersLocalMap.get(online.id);
if (!localUser) {
insertData({ table: "users", id: online.id, data: [ { name: "banchoId", value: online.banchoId } ] });
console.log("Synced:", online);
}
}
}

export async function getUsersOnline(): Promise<Array<{ id: string, banchoId: number } | null>> {
const { rows } = await client.execute("SELECT * FROM users;");

const response: Array<{ id: string, banchoId: number }> = [];
for (let i = 0; i < rows.length; i++) {
const row = rows[i];
response.push({
id: typeof row.id === "string" ? row.id.split(".")[0] : "",
banchoId: typeof row.banchoId === "number" ? row.banchoId : -1
});
}

return response;
}

export async function removeUserOnline(id: string | number): Promise<void> {
await client.execute({ sql: "DELETE FROM users WHERE id = ?;", args: [id] });
}

0 comments on commit f7c60ed

Please sign in to comment.