From 96aae48b48b77ab114d882b01a3314305e528e25 Mon Sep 17 00:00:00 2001 From: gc <30398469+gc@users.noreply.github.com> Date: Tue, 16 Jul 2024 01:21:42 +1000 Subject: [PATCH] Various improvements/fixes --- docker-compose.yml | 4 +- src/index.ts | 14 ++++-- src/lib/grandExchange.ts | 13 ++--- src/lib/roboChimp.ts | 33 +++++++++++-- src/lib/util/linkedAccountsUtil.ts | 47 ------------------- src/lib/util/syncDisabledCommands.ts | 20 ++++++++ src/mahoji/commands/minion.ts | 21 ++------- src/mahoji/commands/rp.ts | 15 ------ .../lib/abstracted_commands/ironmanCommand.ts | 8 ---- src/mahoji/lib/events.ts | 37 +-------------- tests/unit/getUsersPerkTier.test.ts | 13 ----- tests/unit/utils.ts | 4 -- 12 files changed, 73 insertions(+), 156 deletions(-) delete mode 100644 src/lib/util/linkedAccountsUtil.ts create mode 100644 src/lib/util/syncDisabledCommands.ts delete mode 100644 tests/unit/getUsersPerkTier.test.ts diff --git a/docker-compose.yml b/docker-compose.yml index 36de7bd1b2..26ea7e6f3c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -19,8 +19,8 @@ services: depends_on: - db environment: - ROBOCHIMP_DATABASE_URL: postgresql://postgres:postgres@db:5435/robochimp_integration_test?connection_limit=500&pool_timeout=0&schema=public - DATABASE_URL: postgresql://postgres:postgres@db:5435/osb_integration_test?connection_limit=500&pool_timeout=0&schema=public + ROBOCHIMP_DATABASE_URL: postgresql://postgres:postgres@db:5435/robochimp_integration_test?connection_limit=10&pool_timeout=0&schema=public + DATABASE_URL: postgresql://postgres:postgres@db:5435/osb_integration_test?connection_limit=10&pool_timeout=0&schema=public WAIT_HOSTS: db:5435 volumes: diff --git a/src/index.ts b/src/index.ts index 0dad9104d1..e5a34d6ae5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,10 +12,12 @@ import { isObject } from 'e'; import { SENTRY_DSN, SupportServer } from './config'; import { syncActivityCache } from './lib/Task'; -import { BLACKLISTED_GUILDS, BLACKLISTED_USERS } from './lib/blacklists'; +import { cacheBadges } from './lib/badges'; +import { BLACKLISTED_GUILDS, BLACKLISTED_USERS, syncBlacklists } from './lib/blacklists'; import { Channel, Events, META_CONSTANTS, gitHash, globalConfig } from './lib/constants'; import { economyLog } from './lib/economyLogs'; import { onMessage } from './lib/events'; +import { GrandExchange } from './lib/grandExchange'; import { modalInteractionHook } from './lib/modals'; import { runStartupScripts } from './lib/startupScripts'; import { OldSchoolBotClient } from './lib/structures/OldSchoolBotClient'; @@ -24,8 +26,9 @@ import { CACHED_ACTIVE_USER_IDS, syncActiveUserIDs } from './lib/util/cachedUser import { interactionHook } from './lib/util/globalInteractions'; import { handleInteractionError } from './lib/util/interactionReply'; import { logError } from './lib/util/logError'; +import { syncDisabledCommands } from './lib/util/syncDisabledCommands'; import { allCommands } from './mahoji/commands/allCommands'; -import { onStartup } from './mahoji/lib/events'; +import { onStartup, syncCustomPrices } from './mahoji/lib/events'; import { postCommand } from './mahoji/lib/postCommand'; import { preCommand } from './mahoji/lib/preCommand'; import { convertMahojiCommandToAbstractCommand } from './mahoji/lib/util'; @@ -193,7 +196,12 @@ async function main() { await Promise.all([ runTimedLoggedFn('Sync Active User IDs', syncActiveUserIDs), runTimedLoggedFn('Sync Activity Cache', syncActivityCache), - runTimedLoggedFn('Startup Scripts', runStartupScripts) + runTimedLoggedFn('Startup Scripts', runStartupScripts), + runTimedLoggedFn('Sync Disabled Commands', syncDisabledCommands), + runTimedLoggedFn('Sync Blacklist', syncBlacklists), + runTimedLoggedFn('Syncing prices', syncCustomPrices), + runTimedLoggedFn('Caching badges', cacheBadges), + runTimedLoggedFn('Init Grand Exchange', () => GrandExchange.init()) ]); await runTimedLoggedFn('Log In', () => client.login(globalConfig.botToken)); console.log(`Logged in as ${globalClient.user.username}`); diff --git a/src/lib/grandExchange.ts b/src/lib/grandExchange.ts index dcb431a612..e2078d8bd5 100644 --- a/src/lib/grandExchange.ts +++ b/src/lib/grandExchange.ts @@ -260,8 +260,6 @@ class GrandExchangeSingleton { } }); - for (const tx of allActiveListingsInTimePeriod) sanityCheckTransaction(tx); - const item = getOSItem(geListing.item_id); const buyLimit = this.getItemBuyLimit(item); const totalSold = sumArr(allActiveListingsInTimePeriod.map(listing => listing.quantity_bought)); @@ -414,6 +412,7 @@ ${type} ${toKMB(quantity)} ${item.name} for ${toKMB(price)} each, for a total of ...makeTransactFromTableBankQueries({ bankToAdd: result.cost }) ]); + sanityCheckListing(listing); debugLog(`${user.id} created ${type} listing, removing ${result.cost}, adding it to the g.e bank.`); return { @@ -567,7 +566,7 @@ ${type} ${toKMB(quantity)} ${item.name} for ${toKMB(price)} each, for a total of } ); - await prisma.$transaction([ + const [newTx] = await prisma.$transaction([ prisma.gETransaction.create({ data: { buy_listing_id: buyerListing.id, @@ -617,6 +616,8 @@ ${type} ${toKMB(quantity)} ${item.name} for ${toKMB(price)} each, for a total of ...makeTransactFromTableBankQueries({ bankToRemove: bankToRemoveFromGeBank }) ]); + sanityCheckTransaction(newTx); + debugLog(`Transaction completed, the new G.E bank is ${JSON.stringify((await this.fetchOwnedBank()).bank)}.`); const buyerUser = await mUserFetch(buyerListing.user_id); @@ -767,11 +768,7 @@ ${type} ${toKMB(quantity)} ${item.name} for ${toKMB(price)} each, for a total of } async extensiveVerification() { - await Promise.all([ - prisma.gETransaction.findMany().then(txs => txs.map(tx => sanityCheckTransaction(tx))), - prisma.gEListing.findMany().then(listings => listings.map(listing => sanityCheckListing(listing))), - this.checkGECanFullFilAllListings() - ]); + await this.checkGECanFullFilAllListings(); return true; } diff --git a/src/lib/roboChimp.ts b/src/lib/roboChimp.ts index 0cb689f0bc..348686b0e7 100644 --- a/src/lib/roboChimp.ts +++ b/src/lib/roboChimp.ts @@ -1,11 +1,12 @@ -import { formatOrdinal } from '@oldschoolgg/toolkit'; +import { PerkTier, formatOrdinal } from '@oldschoolgg/toolkit'; import type { TriviaQuestion, User } from '@prisma/robochimp'; import { calcWhatPercent, round, sumArr } from 'e'; import deepEqual from 'fast-deep-equal'; import { pick } from 'lodash'; import type { Bank } from 'oldschooljs'; -import { BOT_TYPE, globalConfig, masteryKey } from './constants'; +import { SupportServer } from '../config'; +import { BOT_TYPE, BitField, Roles, globalConfig, masteryKey } from './constants'; import { getTotalCl } from './data/Collections'; import { calculateMastery } from './mastery'; import { MUserStats } from './structures/MUserStats'; @@ -163,5 +164,31 @@ function cacheRoboChimpUser(user: RobochimpUser) { } export function getPerkTierSync(user: string | MUser) { - return roboChimpCache.get(typeof user === 'string' ? user : user.id)?.perk_tier ?? 0; + const elligibleTiers = []; + if (typeof user !== 'string') { + if ( + [BitField.isContributor, BitField.isModerator, BitField.IsWikiContributor].some(bit => + user.bitfield.includes(bit) + ) + ) { + return PerkTier.Four; + } + + if ( + user.bitfield.includes(BitField.IsPatronTier1) || + user.bitfield.includes(BitField.HasPermanentTierOne) || + user.bitfield.includes(BitField.BothBotsMaxedFreeTierOnePerks) + ) { + elligibleTiers.push(PerkTier.Two); + } else { + const guild = globalClient.guilds.cache.get(SupportServer); + const member = guild?.members.cache.get(user.id); + if (member && [Roles.Booster].some(roleID => member.roles.cache.has(roleID))) { + elligibleTiers.push(PerkTier.One); + } + } + } + + elligibleTiers.push(roboChimpCache.get(typeof user === 'string' ? user : user.id)?.perk_tier ?? 0); + return Math.max(...elligibleTiers); } diff --git a/src/lib/util/linkedAccountsUtil.ts b/src/lib/util/linkedAccountsUtil.ts deleted file mode 100644 index 7542c65a36..0000000000 --- a/src/lib/util/linkedAccountsUtil.ts +++ /dev/null @@ -1,47 +0,0 @@ -import type { User } from '@prisma/client'; - -import { mahojiUsersSettingsFetch } from '../../mahoji/mahojiSettings'; -import { MUserClass } from '../MUser'; - -async function syncLinkedAccountPerks(user: MUser) { - const main = user.user.main_account; - const allAccounts: string[] = [...user.user.ironman_alts]; - if (main) { - allAccounts.push(main); - } - const allUsers = await Promise.all( - allAccounts.map(a => - mahojiUsersSettingsFetch(a, { - id: true, - premium_balance_tier: true, - premium_balance_expiry_date: true, - bitfield: true, - ironman_alts: true, - main_account: true, - minion_ironman: true - }) - ) - ); - allUsers.map(u => new MUserClass(u as User)); -} - -export async function syncLinkedAccounts() { - const users = await prisma.user.findMany({ - where: { - ironman_alts: { - isEmpty: false - } - }, - select: { - id: true, - ironman_alts: true, - premium_balance_tier: true, - premium_balance_expiry_date: true, - bitfield: true - } - }); - for (const u of users) { - const mUser = new MUserClass(u as User); - await syncLinkedAccountPerks(mUser); - } -} diff --git a/src/lib/util/syncDisabledCommands.ts b/src/lib/util/syncDisabledCommands.ts new file mode 100644 index 0000000000..bb92a347b1 --- /dev/null +++ b/src/lib/util/syncDisabledCommands.ts @@ -0,0 +1,20 @@ +import { DISABLED_COMMANDS, globalConfig } from '../constants'; + +export async function syncDisabledCommands() { + const disabledCommands = await prisma.clientStorage.upsert({ + where: { + id: globalConfig.clientID + }, + select: { disabled_commands: true }, + create: { + id: globalConfig.clientID + }, + update: {} + }); + + if (disabledCommands.disabled_commands) { + for (const command of disabledCommands.disabled_commands) { + DISABLED_COMMANDS.add(command); + } + } +} diff --git a/src/mahoji/commands/minion.ts b/src/mahoji/commands/minion.ts index ef993a5d43..10df58df98 100644 --- a/src/mahoji/commands/minion.ts +++ b/src/mahoji/commands/minion.ts @@ -22,12 +22,12 @@ import type { AttackStyles } from '../../lib/minions/functions'; import { blowpipeCommand, blowpipeDarts } from '../../lib/minions/functions/blowpipeCommand'; import { degradeableItemsCommand } from '../../lib/minions/functions/degradeableItemsCommand'; import { allPossibleStyles, trainCommand } from '../../lib/minions/functions/trainCommand'; -import { roboChimpUserFetch } from '../../lib/roboChimp'; +import { roboChimpCache, roboChimpUserFetch } from '../../lib/roboChimp'; import { Minigames } from '../../lib/settings/minigames'; import Skills from '../../lib/skilling/skills'; import creatures from '../../lib/skilling/skills/hunter/creatures'; import { MUserStats } from '../../lib/structures/MUserStats'; -import { convertLVLtoXP, getUsername, isValidNickname } from '../../lib/util'; +import { convertLVLtoXP, isValidNickname } from '../../lib/util'; import { getKCByName } from '../../lib/util/getKCByName'; import getOSItem, { getItem } from '../../lib/util/getOSItem'; import { handleMahojiConfirmation } from '../../lib/util/handleMahojiConfirmation'; @@ -81,21 +81,10 @@ export async function getUserInfo(user: MUser) { const task = minionActivityCache.get(user.id); const taskText = task ? `${task.type}` : 'None'; - const premiumDate = Number(user.user.premium_balance_expiry_date); - const premiumTier = user.user.premium_balance_tier; - const result = { perkTier: user.perkTier(), isBlacklisted: BLACKLISTED_USERS.has(user.id), badges: user.badgesString, - mainAccount: - user.user.main_account !== null - ? `${user.user.username ?? 'Unknown Username'}[${user.user.main_account}]` - : 'None', - ironmanAlts: user.user.ironman_alts.map(async id => `${await getUsername(id)}[${id}]`), - premiumBalance: `${premiumDate ? new Date(premiumDate).toLocaleString() : ''} ${ - premiumTier ? `Tier ${premiumTier}` : '' - }`, isIronman: user.isIronman, bitfields, currentTask: taskText, @@ -107,16 +96,14 @@ export async function getUserInfo(user: MUser) { 2 ); + const roboCache = await roboChimpCache.get(user.id); return { ...result, everythingString: `${user.badgedUsername}[${user.id}] **Current Trip:** ${taskText} -**Perk Tier:** ${result.perkTier} +**Perk Tier:** ${roboCache?.perk_tier ?? 'None'} **Blacklisted:** ${result.isBlacklisted} **Badges:** ${result.badges} -**Main Account:** ${result.mainAccount} -**Ironman Alts:** ${result.ironmanAlts} -**Patron Balance:** ${result.premiumBalance} **Ironman:** ${result.isIronman} **Bitfields:** ${result.bitfields} **Patreon Connected:** ${result.patreon} diff --git a/src/mahoji/commands/rp.ts b/src/mahoji/commands/rp.ts index fb76eef208..cc6aa846b2 100644 --- a/src/mahoji/commands/rp.ts +++ b/src/mahoji/commands/rp.ts @@ -30,7 +30,6 @@ import getOSItem from '../../lib/util/getOSItem'; import { handleMahojiConfirmation } from '../../lib/util/handleMahojiConfirmation'; import { deferInteraction } from '../../lib/util/interactionReply'; import itemIsTradeable from '../../lib/util/itemIsTradeable'; -import { syncLinkedAccounts } from '../../lib/util/linkedAccountsUtil'; import { makeBankImage } from '../../lib/util/makeBankImage'; import { migrateUser } from '../../lib/util/migrateUser'; import { parseBank } from '../../lib/util/parseStringBank'; @@ -694,20 +693,6 @@ ORDER BY item_id ASC;`); return returnStringOrFile(`[${result.map(i => i.item_id).join(',')}]`); } - if (options.action?.patreon_reset) { - const bitfieldsToRemove = [ - BitField.IsPatronTier1, - BitField.IsPatronTier2, - BitField.IsPatronTier3, - BitField.IsPatronTier4, - BitField.IsPatronTier5, - BitField.IsPatronTier6 - ]; - await prisma.$queryRaw`UPDATE users SET bitfield = bitfield - '{${bitfieldsToRemove.join(',')}'::int[];`; - await syncLinkedAccounts(); - return 'Finished.'; - } - if (options.player?.set_buy_date) { const userToCheck = await mUserFetch(options.player.set_buy_date.user.user.id); const res = SnowflakeUtil.deconstruct(options.player.set_buy_date.message_id); diff --git a/src/mahoji/lib/abstracted_commands/ironmanCommand.ts b/src/mahoji/lib/abstracted_commands/ironmanCommand.ts index 49d92228b2..2855556e3b 100644 --- a/src/mahoji/lib/abstracted_commands/ironmanCommand.ts +++ b/src/mahoji/lib/abstracted_commands/ironmanCommand.ts @@ -95,13 +95,9 @@ After becoming an ironman: const mUser = (await mUserFetch(user.id)).user; type KeysThatArentReset = - | 'ironman_alts' - | 'main_account' | 'bank_bg_hex' | 'bank_sort_weightings' | 'bank_sort_method' - | 'premium_balance_expiry_date' - | 'premium_balance_tier' | 'minion_bought_date' | 'id' | 'pets' @@ -127,15 +123,11 @@ After becoming an ironman: const createOptions: Required> = { id: user.id, - main_account: mUser.main_account, - ironman_alts: mUser.ironman_alts, bank_bg_hex: mUser.bank_bg_hex, bank_sort_method: mUser.bank_sort_method, bank_sort_weightings: mUser.bank_sort_weightings as ItemBank, minion_bought_date: mUser.minion_bought_date, RSN: mUser.RSN, - premium_balance_expiry_date: mUser.premium_balance_expiry_date, - premium_balance_tier: mUser.premium_balance_tier, pets: mUser.pets as ItemBank, bitfield: bitFieldsToKeep.filter(i => user.bitfield.includes(i)) }; diff --git a/src/mahoji/lib/events.ts b/src/mahoji/lib/events.ts index 478d38c865..5673359333 100644 --- a/src/mahoji/lib/events.ts +++ b/src/mahoji/lib/events.ts @@ -2,17 +2,12 @@ import type { ItemBank } from 'oldschooljs/dist/meta/types'; import { bulkUpdateCommands } from '@oldschoolgg/toolkit'; import { production } from '../../config'; -import { cacheBadges } from '../../lib/badges'; -import { syncBlacklists } from '../../lib/blacklists'; -import { Channel, DISABLED_COMMANDS, META_CONSTANTS, globalConfig } from '../../lib/constants'; +import { Channel, META_CONSTANTS, globalConfig } from '../../lib/constants'; import { initCrons } from '../../lib/crons'; -import { GrandExchange } from '../../lib/grandExchange'; import { initTickers } from '../../lib/tickers'; -import { runTimedLoggedFn } from '../../lib/util'; import { cacheCleanup } from '../../lib/util/cachedUserIDs'; import { mahojiClientSettingsFetch } from '../../lib/util/clientSettings'; -import { syncLinkedAccounts } from '../../lib/util/linkedAccountsUtil'; import { sendToChannelID } from '../../lib/util/webhook'; import { CUSTOM_PRICE_CACHE } from '../commands/sell'; @@ -23,28 +18,8 @@ export async function syncCustomPrices() { } } -async function syncDisabledCommands() { - const disabledCommands = await prisma.clientStorage.upsert({ - where: { - id: globalConfig.clientID - }, - select: { disabled_commands: true }, - create: { - id: globalConfig.clientID - }, - update: {} - }); - - if (disabledCommands.disabled_commands) { - for (const command of disabledCommands.disabled_commands) { - DISABLED_COMMANDS.add(command); - } - } -} - export async function onStartup() { globalClient.application.commands.fetch({ guildId: production ? undefined : globalConfig.testingServerID }); - if (!production) { console.log('Syncing commands locally...'); await bulkUpdateCommands({ @@ -54,18 +29,8 @@ export async function onStartup() { }); } - runTimedLoggedFn('Sync Disabled Commands', syncDisabledCommands); - - runTimedLoggedFn('Sync Blacklist', syncBlacklists); - - runTimedLoggedFn('Syncing prices', syncCustomPrices); - - runTimedLoggedFn('Caching badges', cacheBadges); cacheCleanup(); - runTimedLoggedFn('Sync Linked Accounts', syncLinkedAccounts); - runTimedLoggedFn('Init Grand Exchange', GrandExchange.init.bind(GrandExchange)); - initCrons(); initTickers(); diff --git a/tests/unit/getUsersPerkTier.test.ts b/tests/unit/getUsersPerkTier.test.ts deleted file mode 100644 index 72d5a537f6..0000000000 --- a/tests/unit/getUsersPerkTier.test.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { describe, expect, test } from 'vitest'; - -import { BitField, PerkTier } from '../../src/lib/constants'; -import { getUsersPerkTier } from '../../src/lib/perkTiers'; -import { mockMUser } from './utils'; - -describe('getUsersPerkTier', () => { - test('general', () => { - expect(getUsersPerkTier(mockMUser())).toEqual(0); - expect(getUsersPerkTier(mockMUser({ bitfield: [BitField.IsPatronTier3] }))).toEqual(PerkTier.Four); - expect(getUsersPerkTier(mockMUser({ bitfield: [BitField.isModerator] }))).toEqual(PerkTier.Four); - }); -}); diff --git a/tests/unit/utils.ts b/tests/unit/utils.ts index b2a77220eb..c32e36475b 100644 --- a/tests/unit/utils.ts +++ b/tests/unit/utils.ts @@ -36,8 +36,6 @@ interface MockUserArgs { skills_prayer?: number; skills_fishing?: number; GP?: number; - premium_balance_tier?: number; - premium_balance_expiry_date?: number; bitfield?: BitField[]; id?: string; } @@ -81,8 +79,6 @@ const mockUser = (overrides?: MockUserArgs): User => { skills_slayer: 0, skills_hitpoints: overrides?.skills_hitpoints ?? convertLVLtoXP(10), GP: overrides?.GP ?? 0, - premium_balance_tier: overrides?.premium_balance_tier, - premium_balance_expiry_date: overrides?.premium_balance_expiry_date, ironman_alts: [], bitfield: overrides?.bitfield ?? [], username: 'Magnaboy',