From bbc8f088e7a8a096180b66927c7a8780356d03a8 Mon Sep 17 00:00:00 2001 From: gc <30398469+gc@users.noreply.github.com> Date: Tue, 24 Dec 2024 11:16:16 +1100 Subject: [PATCH] various changes/fixes --- package.json | 2 +- packages/toolkit/package.json | 12 ++-- prisma/schema.prisma | 8 +++ src/index.ts | 4 +- src/lib/rawSql.ts | 8 +++ src/lib/util/clLeaderboard.ts | 12 ++-- src/mahoji/commands/admin.ts | 9 +++ src/mahoji/commands/leaderboard.ts | 67 +++++++++++++------ src/mahoji/lib/events.ts | 103 +++++++---------------------- src/mahoji/lib/exitHandler.ts | 3 - 10 files changed, 113 insertions(+), 115 deletions(-) diff --git a/package.json b/package.json index 4b727c95b6..89a6aa02ce 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "private": true, "scripts": { "============DEVELOPMENT": "============", - "watch": "nodemon --delay 1ms -e ts -w src --exec \"pnpm build && node --enable-source-maps dist\"", + "watch": "nodemon --delay 1ms -e ts -w src --exec \"pnpm build:esbuild && node --enable-source-maps dist\"", "dev:stage1": "pnpm concurrent \"pnpm install\" \"prisma db push\" \"pnpm generate:robochimp\"", "dev:stage2": "pnpm concurrent \"pnpm commands\" \"pnpm creatables\" \"pnpm wiki\" \"pnpm build\"", "dev:stage3": "pnpm lint && pnpm test", diff --git a/packages/toolkit/package.json b/packages/toolkit/package.json index 72304055e6..183835f6b9 100644 --- a/packages/toolkit/package.json +++ b/packages/toolkit/package.json @@ -5,19 +5,19 @@ "description": "Oldschoolgg Toolkit", "exports": { ".": { + "types": "./dist/util.d.ts", "require": "./dist/cjs/util.cjs", - "import": "./dist/esm/util.mjs", - "types": "./dist/util.d.ts" + "import": "./dist/esm/util.mjs" }, "./util": { + "types": "./dist/util.d.ts", "require": "./dist/cjs/util.cjs", - "import": "./dist/esm/util.mjs", - "types": "./dist/util.d.ts" + "import": "./dist/esm/util.mjs" }, "./structures": { + "types": "./dist/structures.d.ts", "require": "./dist/cjs/structures.cjs", - "import": "./dist/esm/structures.mjs", - "types": "./dist/structures.d.ts" + "import": "./dist/esm/structures.mjs" } }, "scripts": { diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 632696f771..1882c9b31f 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1137,6 +1137,14 @@ model UserEvent { @@map("user_event") } +model Badges { + id Int @id @default(autoincrement()) + + text String + + @@map("badges") +} + enum command_name_enum { testpotato achievementdiary diff --git a/src/index.ts b/src/index.ts index ad6ecf92b6..f44cca579a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -209,10 +209,10 @@ async function main() { asyncExitHook(exitCleanup, { wait: 2000 }) - ) + ), + client.login(globalConfig.botToken) ]); if (process.env.TEST) return; - await client.login(globalConfig.botToken); console.log(`Logged in as ${globalClient.user.username}`); } diff --git a/src/lib/rawSql.ts b/src/lib/rawSql.ts index 45def967e9..b42d0023a9 100644 --- a/src/lib/rawSql.ts +++ b/src/lib/rawSql.ts @@ -26,3 +26,11 @@ export async function loggedRawPrismaQuery(query: string): Promise return null; } + +export const SQL = { + SELECT_FULL_NAME: + "TRIM(COALESCE(string_agg(b.text, ' '), '') || ' ' || COALESCE(username, 'Unknown')) AS full_name", + LEFT_JOIN_BADGES: 'LEFT JOIN badges b ON b.id = ANY(u.badges)', + GROUP_BY_U_ID: 'GROUP BY u.id', + WHERE_IRON: (ironOnly: boolean) => (ironOnly ? '"minion.ironman" = true' : '') +} as const; diff --git a/src/lib/util/clLeaderboard.ts b/src/lib/util/clLeaderboard.ts index 9df88176dc..3fa0e134b5 100644 --- a/src/lib/util/clLeaderboard.ts +++ b/src/lib/util/clLeaderboard.ts @@ -1,4 +1,6 @@ import { stringMatches } from '@oldschoolgg/toolkit/util'; + +import { SQL } from '../rawSql.js'; import { userEventsToMap } from './userEvents'; export async function fetchMultipleCLLeaderboards( @@ -34,12 +36,14 @@ export async function fetchMultipleCLLeaderboards( const userIdsList = userIds.length > 0 ? userIds.map(i => `'${i}'`).join(', ') : 'NULL'; const query = ` -SELECT id, qty +SELECT id, qty, full_name FROM ( - SELECT id, CARDINALITY(cl_array & ${SQL_ITEMS}) AS qty - FROM users + SELECT u.id, CARDINALITY(cl_array & ${SQL_ITEMS}) AS qty, ${SQL.SELECT_FULL_NAME} + FROM users u + ${SQL.LEFT_JOIN_BADGES} WHERE (cl_array && ${SQL_ITEMS} - ${ironmenOnly ? 'AND "users"."minion.ironman" = true' : ''}) ${userIds.length > 0 ? `OR id IN (${userIdsList})` : ''} + ${ironmenOnly ? 'AND "u"."minion.ironman" = true' : ''}) ${userIds.length > 0 ? `OR u.id IN (${userIdsList})` : ''} + ${SQL.GROUP_BY_U_ID} ) AS subquery ORDER BY qty DESC LIMIT ${resultLimit}; diff --git a/src/mahoji/commands/admin.ts b/src/mahoji/commands/admin.ts index baf816db32..fd8b80b435 100644 --- a/src/mahoji/commands/admin.ts +++ b/src/mahoji/commands/admin.ts @@ -899,6 +899,15 @@ Guilds Blacklisted: ${BLACKLISTED_GUILDS.size}`; } if (options.sync_commands) { + if (!globalConfig.isProduction) { + await bulkUpdateCommands({ + client: globalClient.mahojiClient, + commands: Array.from(globalClient.mahojiClient.commands.values()), + guildID: globalConfig.supportServerID + }); + return 'Done.'; + } + const global = Boolean(globalConfig.isProduction); const totalCommands = Array.from(globalClient.mahojiClient.commands.values()); const globalCommands = totalCommands.filter(i => !i.guildID); diff --git a/src/mahoji/commands/leaderboard.ts b/src/mahoji/commands/leaderboard.ts index 5e53e6a195..fda5f479e9 100644 --- a/src/mahoji/commands/leaderboard.ts +++ b/src/mahoji/commands/leaderboard.ts @@ -11,8 +11,8 @@ import { masteryKey } from '../../lib/constants'; import { allClNames, getCollectionItems } from '../../lib/data/Collections'; import { effectiveMonsters } from '../../lib/minions/data/killableMonsters'; import { allOpenables } from '../../lib/openables'; +import { SQL } from '../../lib/rawSql.js'; import { Minigames } from '../../lib/settings/minigames'; - import Skills from '../../lib/skilling/skills'; import Agility from '../../lib/skilling/skills/agility'; import Hunter from '../../lib/skilling/skills/hunter/hunter'; @@ -83,7 +83,7 @@ function doMenuWrapper({ formatter }: { ironmanOnly: boolean; - users: { id: string; score: number }[]; + users: { id: string; score: number; full_name?: string }[]; title: string; interaction: ChatInputCommandInteraction; user: MUser; @@ -97,7 +97,7 @@ function doMenuWrapper({ const chnk = chunked[c]; const unwaited = chnk.map( async (user, i) => - `${getPos(c, i)}**${await getUsername(user.id)}:** ${formatter ? formatter(user.score) : user.score.toLocaleString()}` + `${getPos(c, i)}**${user.full_name ?? (await getUsername(user.id))}:** ${formatter ? formatter(user.score) : user.score.toLocaleString()}` ); const pageText = (await Promise.all(unwaited)).join('\n'); return { embeds: [new EmbedBuilder().setTitle(title).setDescription(pageText)] }; @@ -212,13 +212,20 @@ async function sacrificeLb( ) { if (type === 'value') { const list = ( - await prisma.$queryRawUnsafe<{ id: string; amount: number }[]>( - `SELECT "id", "sacrificedValue" - FROM users - WHERE "sacrificedValue" > 0 - ${ironmanOnly ? 'AND "minion.ironman" = true' : ''} - ORDER BY "sacrificedValue" - DESC LIMIT 2000;` + await prisma.$queryRawUnsafe<{ id: string; full_name: string; amount: number }[]>( + `SELECT + u.id, + ${SQL.SELECT_FULL_NAME}, + "sacrificedValue" +FROM + users u +${SQL.LEFT_JOIN_BADGES} +WHERE + "sacrificedValue" > 10000 +${ironmanOnly ? 'AND "minion.ironman" = true' : ''} +${SQL.GROUP_BY_U_ID} +ORDER BY "sacrificedValue" DESC +LIMIT 400;` ) ).map((res: any) => ({ ...res, amount: Number.parseInt(res.sacrificedValue) })); @@ -229,8 +236,7 @@ async function sacrificeLb( chunk(list, LB_PAGE_SIZE).map((subList, i) => subList .map( - ({ id, amount }, j) => - `${getPos(i, j)}**${getUsernameSync(id)}:** ${amount.toLocaleString()} GP ` + ({ full_name, amount }, j) => `${getPos(i, j)}**${full_name}:** ${amount.toLocaleString()} GP ` ) .join('\n') ), @@ -240,13 +246,32 @@ async function sacrificeLb( return lbMsg('Most Value Sacrificed'); } - const mostUniques: { id: string; sacbanklength: number }[] = await prisma.$queryRawUnsafe( - `SELECT u.user_id::text AS id, u.sacbanklength - FROM ( - SELECT (SELECT COUNT(*)::int FROM JSONB_OBJECT_KEYS(sacrificed_bank)) sacbanklength, user_id FROM user_stats - ${ironmanOnly ? 'INNER JOIN users ON users.id::bigint = user_stats.user_id WHERE "minion.ironman" = true' : ''} - ) u - ORDER BY u.sacbanklength DESC LIMIT 10; + const mostUniques: { full_name: string; sacbanklength: number }[] = await prisma.$queryRawUnsafe( + ` +SELECT + ${SQL.SELECT_FULL_NAME}, + u.sacbanklength +FROM ( + SELECT + (SELECT COUNT(*)::int FROM JSONB_OBJECT_KEYS(sacrificed_bank)) AS sacbanklength, + u.id AS user_id, + u.username, + u.badges + FROM + user_stats + INNER JOIN + users u ON u.id::bigint = user_stats.user_id + WHERE + sacrificed_bank::text != '{}' + ${ironmanOnly ? 'AND "minion.ironman" = true' : ''} +) u +LEFT JOIN + badges b ON b.id = ANY(u.badges) +GROUP BY + u.username, u.sacbanklength +ORDER BY + u.sacbanklength DESC +LIMIT 10; ` ); doMenu( @@ -256,8 +281,8 @@ async function sacrificeLb( chunk(mostUniques, LB_PAGE_SIZE).map((subList, i) => subList .map( - ({ id, sacbanklength }, j) => - `${getPos(i, j)}**${getUsernameSync(id)}:** ${sacbanklength.toLocaleString()} Unique Sac's` + ({ full_name, sacbanklength }, j) => + `${getPos(i, j)}**${full_name}:** ${sacbanklength.toLocaleString()} Unique Sac's` ) .join('\n') ), diff --git a/src/mahoji/lib/events.ts b/src/mahoji/lib/events.ts index 2f2de401b2..dc85bea0b3 100644 --- a/src/mahoji/lib/events.ts +++ b/src/mahoji/lib/events.ts @@ -1,9 +1,7 @@ import type { ItemBank } from 'oldschooljs/dist/meta/types'; -import { bulkUpdateCommands } from '@oldschoolgg/toolkit/util'; -import { ActivityType, bold, time } from 'discord.js'; import { startBlacklistSyncing } from '../../lib/blacklists'; -import { Channel, META_CONSTANTS, globalConfig } from '../../lib/constants'; +import { Channel, META_CONSTANTS, badges, globalConfig } from '../../lib/constants'; import { initCrons } from '../../lib/crons'; import { initTickers } from '../../lib/tickers'; import { logWrapFn } from '../../lib/util'; @@ -11,60 +9,6 @@ import { mahojiClientSettingsFetch } from '../../lib/util/clientSettings'; import { sendToChannelID } from '../../lib/util/webhook'; import { CUSTOM_PRICE_CACHE } from '../commands/sell'; -export async function updateTestBotStatus(online = true) { - try { - if (globalConfig.isProduction) return; - const idMap: Record = { - '829398443821891634': '1265571664142270464', - '577488230539067403': '1265582554644217977', - '353484579840983042': '1265582554644217977', - '897549995446779964': '1265582743970910259', - '1158785741028081696': '1265583194108067925' - }; - const catChannelID = idMap[globalConfig.clientID]; - if (!catChannelID) return; - const cat = await globalClient.channels.fetch(catChannelID); - if (!cat || !cat.isTextBased() || cat.isDMBased()) { - console.log('Could not find status channel'); - return; - } - - const emoji = online ? '🟢' : '🔴'; - let text = ''; - if (online) { - text = `${emoji} ${globalClient.user.username} is ONLINE ${emoji} - -Turned on ${time(new Date(), 'R')}`; - text = bold(text); - } else { - text = `${emoji} ${globalClient.user.username} is offline ${emoji} - -Turned off ${time(new Date(), 'R')}`; - } - const message = await cat.messages - .fetch({ limit: 5 }) - .then(messages => messages.filter(m => m.author.id === globalClient.user!.id)) - .then(msg => msg.first()); - if (!message) { - await cat.send(text); - } else { - await message.edit(text); - } - if (online) { - await globalClient.user.setPresence({ - status: 'online', - activities: [ - { - name: `${emoji} ONLINE`, - type: ActivityType.Custom - } - ] - }); - } - } catch (err) { - console.error(err); - } -} export async function syncCustomPrices() { const clientData = await mahojiClientSettingsFetch({ custom_prices: true }); for (const [key, value] of Object.entries(clientData.custom_prices as ItemBank)) { @@ -72,31 +16,34 @@ export async function syncCustomPrices() { } } -export const onStartup = logWrapFn('onStartup', async () => { - const syncTestBotCommands = globalConfig.isProduction - ? null - : bulkUpdateCommands({ - client: globalClient.mahojiClient, - commands: Array.from(globalClient.mahojiClient.commands.values()), - guildID: globalConfig.supportServerID +async function updateBadgeTable() { + const badgesInDb = await prisma.badges.findMany(); + for (const [_id, emojiString] of Object.entries(badges)) { + const id = Number(_id); + if (!badgesInDb.find(b => b.id === id)) { + await prisma.badges.create({ + data: { + id, + text: emojiString + } }); + } + } +} +export const onStartup = logWrapFn('onStartup', async () => { initCrons(); initTickers(); - const sendStartupMessage = globalConfig.isProduction - ? sendToChannelID(Channel.GeneralChannel, { - content: `I have just turned on!\n\n${META_CONSTANTS.RENDERED_STR}` - }).catch(console.error) - : null; + if (globalConfig.isProduction) { + sendToChannelID(Channel.GeneralChannel, { + content: `I have just turned on!\n\n${META_CONSTANTS.RENDERED_STR}` + }).catch(console.error); + } - await Promise.all([ - globalClient.application.commands.fetch({ - guildId: globalConfig.isProduction ? undefined : globalConfig.supportServerID - }), - updateTestBotStatus(), - sendStartupMessage, - syncTestBotCommands, - startBlacklistSyncing() - ]); + globalClient.application.commands.fetch({ + guildId: globalConfig.isProduction ? undefined : globalConfig.supportServerID + }); + updateBadgeTable(); + startBlacklistSyncing(); }); diff --git a/src/mahoji/lib/exitHandler.ts b/src/mahoji/lib/exitHandler.ts index e1469c00ad..28f0087aa5 100644 --- a/src/mahoji/lib/exitHandler.ts +++ b/src/mahoji/lib/exitHandler.ts @@ -1,13 +1,10 @@ import { TimerManager } from '@sapphire/timer-manager'; -import { updateTestBotStatus } from './events'; - export async function exitCleanup() { try { globalClient.isShuttingDown = true; console.log('Cleaning up and exiting...'); TimerManager.destroy(); - await updateTestBotStatus(false); await Promise.all([globalClient.destroy(), prisma.$disconnect(), roboChimpClient.$disconnect()]); console.log('\nCleaned up and exited.'); } catch (err) {