diff --git a/.env.example b/.env.example index 37cda13863..6cded0509d 100644 --- a/.env.example +++ b/.env.example @@ -7,7 +7,6 @@ ROBOCHIMP_DATABASE_URL=postgresql://postgres:postgres@localhost:5436/robochimp_t DATABASE_URL=postgresql://postgres:postgres@localhost:5435/osb_test # Optional -#REDIS_PORT=6379 #TESTING_SERVER_ID=123456789012345678 # Dont change these: diff --git a/docker-compose.yml b/docker-compose.yml index 0310384b6c..f3a87b3193 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,14 +11,6 @@ services: POSTGRES_PASSWORD: postgres PGPORT: 5435 - redis: - image: redis:latest - restart: always - environment: - - REDIS_PORT=6379 - ports: - - "6379:6379" - app: build: context: . @@ -26,8 +18,7 @@ services: target: build-run depends_on: - db - - redis environment: 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, redis:6379 + WAIT_HOSTS: db:5435 diff --git a/package.json b/package.json index 57ad79bca4..ece159dd7b 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "test:types": "concurrently \"tsc --noEmit -p tests/unit\" \"tsc --noEmit -p tests/integration\" \"tsc --noEmit -p src\"", "test:lint": "biome check --diagnostic-level=error", "test:unit": "vitest run --config vitest.unit.config.mts", - "test:docker": "docker compose up --no-attach db --no-attach redis --build --abort-on-container-exit && docker compose down -v", + "test:docker": "docker compose up --no-attach db --build --abort-on-container-exit && docker compose down -v", "test:watch": "vitest --config vitest.unit.config.mts --coverage", "test:ci:unit": "pnpm concurrent \"pnpm test:unit\" \"pnpm test:lint\" \"tsc -p tests/integration\" \"tsc -p tests/unit\"", "============MISC": "============", diff --git a/packages/toolkit/esbuild.cjs b/packages/toolkit/esbuild.cjs index b3a0ff5b99..08286104d2 100644 --- a/packages/toolkit/esbuild.cjs +++ b/packages/toolkit/esbuild.cjs @@ -10,7 +10,7 @@ const baseConfig = { entryPoints, platform: 'node', sourcemap: false, - external: ['discord.js', 'ioredis'], + external: ['discord.js'], loader: { '.json': 'copy' } diff --git a/packages/toolkit/package.json b/packages/toolkit/package.json index 01355b8695..72304055e6 100644 --- a/packages/toolkit/package.json +++ b/packages/toolkit/package.json @@ -31,7 +31,6 @@ "deepmerge": "4.3.1", "emoji-regex": "^10.2.1", "fast-deep-equal": "^3.1.3", - "ioredis": "^5.4.1", "math-expression-evaluator": "^1.3.14", "pure-rand": "^6.1.0", "zod": "^3.23.8" diff --git a/packages/toolkit/src/TSRedis.ts b/packages/toolkit/src/TSRedis.ts deleted file mode 100644 index d02e10e8aa..0000000000 --- a/packages/toolkit/src/TSRedis.ts +++ /dev/null @@ -1,61 +0,0 @@ -import Redis, { type RedisOptions } from 'ioredis'; -import { z } from 'zod'; - -const patronTierChangeMessageSchema = z.object({ - type: z.literal('patron_tier_change'), - new_tier: z.number().int(), - old_tier: z.number().int(), - discord_ids: z.array(z.string()), - first_time_patron: z.boolean() -}); - -const pingMessageSchema = z.object({ - type: z.literal('ping') -}); - -const messageSchema = z.union([pingMessageSchema, patronTierChangeMessageSchema]); - -type Message = z.infer; - -const CHANNEL_ID = 'main'; -export class TSRedis { - private redis: Redis; - public isMocked: boolean; - - constructor(options: RedisOptions & { mocked: boolean } = { mocked: false }) { - this.redis = options.mocked ? (null as any) : new Redis(options); - this.isMocked = options.mocked; - } - - disconnect() { - if (this.isMocked) return Promise.resolve(); - return this.redis.disconnect(false); - } - - subscribe(callback: (message: Message) => void) { - if (this.isMocked) return Promise.resolve(); - this.redis.subscribe(CHANNEL_ID, err => { - if (err) { - console.error('Failed to subscribe: ', err); - } - }); - - this.redis.on('message', (receivedChannel, message) => { - if (receivedChannel === CHANNEL_ID) { - try { - const parsedMessage = JSON.parse(message); - const validatedMessage = messageSchema.parse(parsedMessage); - callback(validatedMessage); - } catch (error) { - console.error('Failed to parse message: ', error); - } - } - }); - } - - publish(message: Message) { - if (this.isMocked) return Promise.resolve(); - const parsedMessage = messageSchema.parse(message); - return this.redis.publish(CHANNEL_ID, JSON.stringify(parsedMessage)); - } -} diff --git a/packages/toolkit/src/structures.ts b/packages/toolkit/src/structures.ts index 350bc9b871..9d3b5cbc8e 100644 --- a/packages/toolkit/src/structures.ts +++ b/packages/toolkit/src/structures.ts @@ -2,4 +2,3 @@ export * from './lib/GeneralBank'; export * from './lib/SimpleTable'; export * from './lib/UserError'; export * from './lib/Stopwatch'; -export * from './TSRedis'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 23c9e5622f..f12dd992ce 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -184,9 +184,6 @@ importers: fast-deep-equal: specifier: ^3.1.3 version: 3.1.3 - ioredis: - specifier: ^5.4.1 - version: 5.4.1 math-expression-evaluator: specifier: ^1.3.14 version: 1.4.0 @@ -466,9 +463,6 @@ packages: cpu: [x64] os: [win32] - '@ioredis/commands@1.2.0': - resolution: {integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==} - '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -1296,10 +1290,6 @@ packages: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} - cluster-key-slot@1.1.2: - resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} - engines: {node: '>=0.10.0'} - color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -1404,10 +1394,6 @@ packages: delegates@1.0.0: resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} - denque@2.1.0: - resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} - engines: {node: '>=0.10'} - detect-libc@2.0.3: resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} engines: {node: '>=8'} @@ -1669,10 +1655,6 @@ packages: inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - ioredis@5.4.1: - resolution: {integrity: sha512-2YZsvl7jopIa1gaePkeMtd9rAcSjOOjPtpcLlOeusyO+XH2SK5ZcT+UCrElPP+WVIInh2TzeI4XW9ENaSLVVHA==} - engines: {node: '>=12.22.0'} - iota-array@1.0.0: resolution: {integrity: sha512-pZ2xT+LOHckCatGQ3DcG/a+QuEqvoxqkiL7tvE8nn3uuu+f6i1TtpB5/FtWFbxUuVr5PZCx8KskuGatbJDXOWA==} @@ -1804,12 +1786,6 @@ packages: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} - lodash.defaults@4.2.0: - resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} - - lodash.isarguments@3.1.0: - resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} - lodash.snakecase@4.1.1: resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} @@ -2250,14 +2226,6 @@ packages: resolution: {integrity: sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==} engines: {node: '>=12'} - redis-errors@1.2.0: - resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==} - engines: {node: '>=4'} - - redis-parser@3.0.0: - resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==} - engines: {node: '>=4'} - regenerator-runtime@0.14.1: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} @@ -2424,9 +2392,6 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - standard-as-callback@2.1.0: - resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} - std-env@3.8.0: resolution: {integrity: sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==} @@ -2959,8 +2924,6 @@ snapshots: '@esbuild/win32-x64@0.24.0': optional: true - '@ioredis/commands@1.2.0': {} - '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -3857,8 +3820,6 @@ snapshots: clone@1.0.4: {} - cluster-key-slot@1.1.2: {} - color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -3952,8 +3913,6 @@ snapshots: delegates@1.0.0: {} - denque@2.1.0: {} - detect-libc@2.0.3: {} discord-api-types@0.37.100: {} @@ -4259,20 +4218,6 @@ snapshots: inherits@2.0.4: {} - ioredis@5.4.1: - dependencies: - '@ioredis/commands': 1.2.0 - cluster-key-slot: 1.1.2 - debug: 4.3.7(supports-color@5.5.0) - denque: 2.1.0 - lodash.defaults: 4.2.0 - lodash.isarguments: 3.1.0 - redis-errors: 1.2.0 - redis-parser: 3.0.0 - standard-as-callback: 2.1.0 - transitivePeerDependencies: - - supports-color - iota-array@1.0.0: {} ip-address@9.0.5: @@ -4389,10 +4334,6 @@ snapshots: dependencies: p-locate: 5.0.0 - lodash.defaults@4.2.0: {} - - lodash.isarguments@3.1.0: {} - lodash.snakecase@4.1.1: {} lodash@4.17.21: {} @@ -4851,12 +4792,6 @@ snapshots: indent-string: 5.0.0 strip-indent: 4.0.0 - redis-errors@1.2.0: {} - - redis-parser@3.0.0: - dependencies: - redis-errors: 1.2.0 - regenerator-runtime@0.14.1: {} remeda@2.17.3: @@ -5071,8 +5006,6 @@ snapshots: stackback@0.0.2: {} - standard-as-callback@2.1.0: {} - std-env@3.8.0: {} string-split-by@1.0.0: diff --git a/src/lib/constants.ts b/src/lib/constants.ts index fd74dd6400..06693cb05d 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -481,7 +481,6 @@ export const ParsedCustomEmojiWithGroups = /(?a?):(?[^:]+):(? { - debugLog(`Received message from Redis: ${JSON.stringify(message)}`); - if (message.type === 'patron_tier_change') { - if (message.new_tier === 0) { - return handleDeletedPatron(message.discord_ids); - } else { - return handleEditPatron(message.discord_ids); - } - } -}); diff --git a/src/lib/patreonUtils.ts b/src/lib/patreonUtils.ts deleted file mode 100644 index 6deee41b44..0000000000 --- a/src/lib/patreonUtils.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { BadgesEnum } from './constants'; -import { populateRoboChimpCache } from './perkTier'; - -export async function handleDeletedPatron(userID: string[]) { - const users = await prisma.user.findMany({ - where: { - id: { - in: userID - } - } - }); - - for (const user of users) { - if (user.badges.includes(BadgesEnum.Patron) || user.badges.includes(BadgesEnum.LimitedPatron)) { - await prisma.user.updateMany({ - where: { - id: user.id - }, - data: { - badges: user.badges.filter(b => b !== BadgesEnum.Patron && b !== BadgesEnum.LimitedPatron) - } - }); - } - } - - await populateRoboChimpCache(); -} - -export async function handleEditPatron(userID: string[]) { - const users = await prisma.user.findMany({ - where: { - id: { - in: userID - } - } - }); - - const usersToGiveBadge = users.filter( - u => !u.badges.includes(BadgesEnum.Patron) && !u.badges.includes(BadgesEnum.LimitedPatron) - ); - await prisma.user.updateMany({ - where: { - id: { - in: usersToGiveBadge.map(u => u.id) - } - }, - data: { - badges: { - push: BadgesEnum.Patron - } - } - }); - - await populateRoboChimpCache(); -} diff --git a/src/lib/workers/casket.worker.ts b/src/lib/workers/casket.worker.ts index 433a36ff90..c697c7b7bb 100644 --- a/src/lib/workers/casket.worker.ts +++ b/src/lib/workers/casket.worker.ts @@ -6,8 +6,8 @@ import { EliteMimicTable, type ItemBank, MasterMimicTable } from 'oldschooljs'; import type { CasketWorkerArgs } from '.'; import { ClueTiers } from '../clues/clueTiers'; -if (global.prisma || global.redis) { - throw new Error('Prisma/Redis is loaded in the casket worker!'); +if (global.prisma) { + throw new Error('Prisma is loaded in the casket worker!'); } export default async ({ clueTierID, quantity }: CasketWorkerArgs): Promise<[ItemBank, string]> => { diff --git a/src/lib/workers/finish.worker.ts b/src/lib/workers/finish.worker.ts index e886ea2ec9..945aa1ddba 100644 --- a/src/lib/workers/finish.worker.ts +++ b/src/lib/workers/finish.worker.ts @@ -6,8 +6,8 @@ import { Bank } from 'oldschooljs'; import type { FinishWorkerArgs, FinishWorkerReturn } from '.'; import getOSItem from '../util/getOSItem'; -if (global.prisma || global.redis) { - throw new Error('Prisma/Redis is loaded in the finish worker!'); +if (global.prisma) { + throw new Error('Prisma is loaded in the finish worker!'); } export default async ({ name, tertiaries }: FinishWorkerArgs): FinishWorkerReturn => { diff --git a/src/lib/workers/kill.worker.ts b/src/lib/workers/kill.worker.ts index f6e9f66747..9425923a72 100644 --- a/src/lib/workers/kill.worker.ts +++ b/src/lib/workers/kill.worker.ts @@ -9,8 +9,8 @@ import killableMonsters from '../minions/data/killableMonsters'; import { handleNexKills } from '../simulation/nex'; import { simulatedKillables } from '../simulation/simulatedKillables'; -if (global.prisma || global.redis) { - throw new Error('Prisma/Redis is loaded in the kill worker!'); +if (global.prisma) { + throw new Error('Prisma is loaded in the kill worker!'); } export default async ({ diff --git a/src/mahoji/lib/exitHandler.ts b/src/mahoji/lib/exitHandler.ts index 14324c629b..e1469c00ad 100644 --- a/src/mahoji/lib/exitHandler.ts +++ b/src/mahoji/lib/exitHandler.ts @@ -8,12 +8,7 @@ export async function exitCleanup() { console.log('Cleaning up and exiting...'); TimerManager.destroy(); await updateTestBotStatus(false); - await Promise.all([ - globalClient.destroy(), - prisma.$disconnect(), - redis.disconnect(), - roboChimpClient.$disconnect() - ]); + await Promise.all([globalClient.destroy(), prisma.$disconnect(), roboChimpClient.$disconnect()]); console.log('\nCleaned up and exited.'); } catch (err) { console.error(err); diff --git a/tests/integration/redis.test.ts b/tests/integration/redis.test.ts deleted file mode 100644 index 0c8e9b9d4e..0000000000 --- a/tests/integration/redis.test.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { expect, test } from 'vitest'; - -import { TSRedis } from '@oldschoolgg/toolkit/structures'; -import { sleep } from 'e'; -import { BadgesEnum, BitField, globalConfig } from '../../src/lib/constants'; -import { roboChimpCache } from '../../src/lib/perkTier'; -import { getUsersPerkTier } from '../../src/lib/perkTiers'; -import { createTestUser } from './util'; - -function makeSender() { - return new TSRedis({ mocked: !globalConfig.redisPort, port: globalConfig.redisPort }); -} - -test.skip('Should add patron badge', async () => { - const user = await createTestUser(); - expect(user.user.badges).not.includes(BadgesEnum.Patron); - const _redis = makeSender(); - await _redis.publish({ - type: 'patron_tier_change', - discord_ids: [user.id], - new_tier: 1, - old_tier: 0, - first_time_patron: false - }); - await sleep(250); - await user.sync(); - expect(user.user.badges).includes(BadgesEnum.Patron); -}); - -test.skip('Should remove patron badge', async () => { - const user = await createTestUser(undefined, { badges: [BadgesEnum.Patron] }); - expect(user.user.badges).includes(BadgesEnum.Patron); - const _redis = makeSender(); - await _redis.publish({ - type: 'patron_tier_change', - discord_ids: [user.id], - new_tier: 0, - old_tier: 1, - first_time_patron: false - }); - await sleep(550); - await user.sync(); - expect(user.user.badges).not.includes(BadgesEnum.Patron); -}); - -test.skip('Should add to cache', async () => { - const users = [await createTestUser(), await createTestUser(), await createTestUser()]; - await roboChimpClient.user.createMany({ - data: users.map(u => ({ - id: BigInt(u.id), - perk_tier: 5 - })) - }); - const _redis = makeSender(); - await _redis.publish({ - type: 'patron_tier_change', - discord_ids: users.map(u => u.id), - new_tier: 5, - old_tier: 2, - first_time_patron: false - }); - await sleep(250); - for (const user of users) { - const cached = roboChimpCache.get(user.id); - expect(getUsersPerkTier(user)).toEqual(5); - expect(cached!.perk_tier).toEqual(5); - } -}); - -test.skip( - 'Should remove from cache', - async () => { - const users = [await createTestUser(), await createTestUser(), await createTestUser()]; - await roboChimpClient.user.createMany({ - data: users.map(u => ({ - id: BigInt(u.id), - perk_tier: 0 - })) - }); - const _redis = makeSender(); - await _redis.publish({ - type: 'patron_tier_change', - discord_ids: users.map(u => u.id), - new_tier: 0, - old_tier: 5, - first_time_patron: false - }); - await sleep(250); - for (const user of users) { - expect(getUsersPerkTier(user)).toEqual(0); - const cached = roboChimpCache.get(user.id); - expect(cached).toEqual(undefined); - } - }, - { - retry: 1 - } -); - -test.skip('Should recognize special bitfields', async () => { - const users = [ - await createTestUser(undefined, { bitfield: [BitField.HasPermanentTierOne] }), - await createTestUser(undefined, { bitfield: [BitField.BothBotsMaxedFreeTierOnePerks] }) - ]; - for (const user of users) { - expect(getUsersPerkTier(user)).toEqual(2); - } -}); - -test.skip('Should sdffsddfss', async () => { - const user = await createTestUser(); - roboChimpCache.set(user.id, { perk_tier: 5 } as any); - expect(getUsersPerkTier(user)).toEqual(5); -});