From 50ccf4d8d73da926d535745858ae90ea73b53900 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Wed, 20 Sep 2023 13:24:48 +0700 Subject: [PATCH] First releases --- src/index.ts | 83 ++++++++++++++++++++++++++++++++ src/providers/ConfigProvider.ts | 42 ++++++++++++++++ src/providers/DiscordProvider.ts | 50 +++++++++++++++++++ src/providers/SteamProvider.ts | 32 ++++++++++++ 4 files changed, 207 insertions(+) create mode 100644 src/index.ts create mode 100644 src/providers/ConfigProvider.ts create mode 100644 src/providers/DiscordProvider.ts create mode 100644 src/providers/SteamProvider.ts diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..edea690 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,83 @@ +import dotenv from 'dotenv'; +dotenv.config(); + +import ConfigProvider from './providers/ConfigProvider'; +import DiscordProvider from './providers/DiscordProvider'; +import SteamProvider from './providers/SteamProvider'; + +// 1 minute +const REFRESH_TIME = 60 * 1000; + +interface ReturnData { + [key: string]: { + discord?: { + user: any; + presences: any; + updatedAt: Date; + }; + steam?: { + user: any; + updatedAt: Date; + }; + }; +} + +let latestReturnData: ReturnData = {}; + +async function main() { + if (!ConfigProvider.isReady()) return; + + setInterval(async () => { + let newData: ReturnData = {}; + + for (let [key, value] of Object.entries(ConfigProvider.getConfig().users)) { + newData[key] = {}; + + // Discord + if (value.discord && DiscordProvider.isReady) { + // Discord data is already cached by the library, no need to limit it + let user = await DiscordProvider.getUser(value.discord); + let presences = await DiscordProvider.getPresence(value.discord); + newData[key].discord = { + user, + presences: presences, + updatedAt: new Date() + }; + } + + // Steam + if (value.steam && SteamProvider.isReady) { + if ( + latestReturnData[key] && + latestReturnData[key].steam && + latestReturnData[key].steam!.updatedAt.getTime() > Date.now() - REFRESH_TIME + ) { + newData[key].steam = latestReturnData[key].steam; + } else { + let user = await SteamProvider.getProfile(value.steam); + newData[key].steam = { + user, + updatedAt: new Date() + }; + } + } + } + + // Check for changes + for (let [key, value] of Object.entries(newData)) { + if (JSON.stringify(value) !== JSON.stringify(latestReturnData[key])) { + latestReturnData[key] = value; + } + } + }, 100); + + const server = Bun.serve({ + port: 3000, + async fetch(request: Request) { + return new Response(JSON.stringify(latestReturnData)); + } + }); + + console.log(`Listening on localhost:${server.port}`); +} +main(); diff --git a/src/providers/ConfigProvider.ts b/src/providers/ConfigProvider.ts new file mode 100644 index 0000000..cf4dd4c --- /dev/null +++ b/src/providers/ConfigProvider.ts @@ -0,0 +1,42 @@ +import fs from 'fs'; +import { Client, Events, GatewayIntentBits } from 'discord.js'; + +export interface Config { + global: { + discord_guild_id?: string; + discord_bot_token?: string; + steam_api_key?: string; + }; + users: { + [key: string]: any; + }; +} + +class ConfigProvider { + private config: Config = { + global: {}, + users: {} + }; + private ready = false; + + constructor() { + try { + let data = fs.readFileSync('./config.json', 'utf8'); + this.config = JSON.parse(data); + this.ready = true; + } catch (err) { + console.error('[ConfigProvider]', err); + return; + } + } + + public getConfig(): Config { + return this.config; + } + + public isReady(): boolean { + return this.ready; + } +} + +export default new ConfigProvider(); diff --git a/src/providers/DiscordProvider.ts b/src/providers/DiscordProvider.ts new file mode 100644 index 0000000..bc64764 --- /dev/null +++ b/src/providers/DiscordProvider.ts @@ -0,0 +1,50 @@ +import { Client, Events, GatewayIntentBits } from 'discord.js'; + +import ConfigProvider from './ConfigProvider'; + +class DiscordProvider { + private client: Client; + private guildId: string = ''; + private ready: boolean = false; + + constructor() { + this.client = new Client({ + intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildPresences] + }); + + this.client.once(Events.ClientReady, (client) => { + console.log('[DiscordProvider]', `Ready! Logged in as ${client.user.tag}`); + this.ready = true; + }); + + const token = ConfigProvider.getConfig().global.discord_bot_token; + const guild_id = ConfigProvider.getConfig().global.discord_guild_id; + + if (!token || !guild_id) { + console.error('[DiscordProvider]', 'Missing token or guild_id in config.json'); + return; + } + + this.guildId = guild_id; + + this.client.login(token); + } + + public async getUser(id: string) { + const user = this.client.users.cache.get(id) || (await this.client.users.fetch(id)); + return user; + } + + public async getPresence(id: string) { + const guild = this.client.guilds.cache.get(this.guildId) || (await this.client.guilds.fetch(this.guildId)); + const member = guild.members.cache.get(id) || (await guild.members.fetch(id)); + const presence = member.presence; + return presence; + } + + public get isReady(): boolean { + return this.ready; + } +} + +export default new DiscordProvider(); diff --git a/src/providers/SteamProvider.ts b/src/providers/SteamProvider.ts new file mode 100644 index 0000000..df6d226 --- /dev/null +++ b/src/providers/SteamProvider.ts @@ -0,0 +1,32 @@ +import SteamAPI from 'steamapi'; + +import ConfigProvider from './ConfigProvider'; + +class SteamProvider { + private client: SteamAPI; + private ready: boolean = false; + + constructor() { + this.client = new SteamAPI('dummy'); + const token = ConfigProvider.getConfig().global.steam_api_key; + + if (!token) { + console.error('[SteamProvider]', 'Missing steam_api_key in config'); + return; + } + + this.client = new SteamAPI(token); + this.ready = true; + } + + public async getProfile(id: string) { + let profile = await this.client.getUserSummary(id); + return profile; + } + + public get isReady(): boolean { + return this.ready; + } +} + +export default new SteamProvider();