From d225a5e9e9c591476b9c4fa71165242b26ba6e72 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Wed, 11 Oct 2023 20:25:42 +0200 Subject: [PATCH 1/5] chore: add redis Signed-off-by: Sefa Eyeoglu --- package.json | 1 + pnpm-lock.yaml | 74 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 1fd726d7..5ec4f53e 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "discord.js": "14.14.1", "just-random": "3.2.0", "kleur": "4.1.5", + "redis": "4.6.10", "tsx": "4.1.1" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e48f8baf..dd97a445 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,6 +17,9 @@ dependencies: kleur: specifier: 4.1.5 version: 4.1.5 + redis: + specifier: 4.6.10 + version: 4.6.10 tsx: specifier: 4.1.1 version: 4.1.1 @@ -403,6 +406,55 @@ packages: fastq: 1.15.0 dev: true + /@redis/bloom@1.2.0(@redis/client@1.5.11): + resolution: {integrity: sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==} + peerDependencies: + '@redis/client': ^1.0.0 + dependencies: + '@redis/client': 1.5.11 + dev: false + + /@redis/client@1.5.11: + resolution: {integrity: sha512-cV7yHcOAtNQ5x/yQl7Yw1xf53kO0FNDTdDU6bFIMbW6ljB7U7ns0YRM+QIkpoqTAt6zK5k9Fq0QWlUbLcq9AvA==} + engines: {node: '>=14'} + dependencies: + cluster-key-slot: 1.1.2 + generic-pool: 3.9.0 + yallist: 4.0.0 + dev: false + + /@redis/graph@1.1.0(@redis/client@1.5.11): + resolution: {integrity: sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg==} + peerDependencies: + '@redis/client': ^1.0.0 + dependencies: + '@redis/client': 1.5.11 + dev: false + + /@redis/json@1.0.6(@redis/client@1.5.11): + resolution: {integrity: sha512-rcZO3bfQbm2zPRpqo82XbW8zg4G/w4W3tI7X8Mqleq9goQjAGLL7q/1n1ZX4dXEAmORVZ4s1+uKLaUOg7LrUhw==} + peerDependencies: + '@redis/client': ^1.0.0 + dependencies: + '@redis/client': 1.5.11 + dev: false + + /@redis/search@1.1.5(@redis/client@1.5.11): + resolution: {integrity: sha512-hPP8w7GfGsbtYEJdn4n7nXa6xt6hVZnnDktKW4ArMaFQ/m/aR7eFvsLQmG/mn1Upq99btPJk+F27IQ2dYpCoUg==} + peerDependencies: + '@redis/client': ^1.0.0 + dependencies: + '@redis/client': 1.5.11 + dev: false + + /@redis/time-series@1.0.5(@redis/client@1.5.11): + resolution: {integrity: sha512-IFjIgTusQym2B5IZJG3XKr5llka7ey84fw/NOYqESP5WUfQs9zz1ww/9+qoz4ka/S6KcGBodzlCeZ5UImKbscg==} + peerDependencies: + '@redis/client': ^1.0.0 + dependencies: + '@redis/client': 1.5.11 + dev: false + /@sapphire/async-queue@1.5.0: resolution: {integrity: sha512-JkLdIsP8fPAdh9ZZjrbHWR/+mZj0wvKS5ICibcLrRI1j84UmLMshx5n9QmL8b95d4onJ2xxiyugTgSAX7AalmA==} engines: {node: '>=v14.0.0', npm: '>=7.0.0'} @@ -665,6 +717,11 @@ packages: supports-color: 7.2.0 dev: true + /cluster-key-slot@1.1.2: + resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} + engines: {node: '>=0.10.0'} + dev: false + /color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -966,6 +1023,11 @@ packages: dev: false optional: true + /generic-pool@3.9.0: + resolution: {integrity: sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==} + engines: {node: '>= 4'} + dev: false + /get-tsconfig@4.7.2: resolution: {integrity: sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==} dependencies: @@ -1281,6 +1343,17 @@ packages: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} dev: true + /redis@4.6.10: + resolution: {integrity: sha512-mmbyhuKgDiJ5TWUhiKhBssz+mjsuSI/lSZNPI9QvZOYzWvYGejtb+W3RlDDf8LD6Bdl5/mZeG8O1feUGhXTxEg==} + dependencies: + '@redis/bloom': 1.2.0(@redis/client@1.5.11) + '@redis/client': 1.5.11 + '@redis/graph': 1.1.0(@redis/client@1.5.11) + '@redis/json': 1.0.6(@redis/client@1.5.11) + '@redis/search': 1.1.5(@redis/client@1.5.11) + '@redis/time-series': 1.0.5(@redis/client@1.5.11) + dev: false + /resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -1482,7 +1555,6 @@ packages: /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: true /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} From c29d5dfb8db6dc084b64d47f78973d9f8c9b0a35 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Thu, 16 Nov 2023 22:53:09 +0100 Subject: [PATCH 2/5] chore: add redis to devShell Signed-off-by: Sefa Eyeoglu --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index df941f9d..9b8d6554 100644 --- a/flake.nix +++ b/flake.nix @@ -37,7 +37,7 @@ shellHook = '' ${config.pre-commit.installationScript} ''; - packages = with pkgs; [nodePackages.pnpm]; + packages = with pkgs; [nodePackages.pnpm redis]; }; formatter = pkgs.alejandra; }; From e6337cf6bd9894358fb433f9ddbd36afea5ecd6b Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Thu, 16 Nov 2023 23:06:32 +0100 Subject: [PATCH 3/5] feat: store pluralkit users in redis Signed-off-by: Sefa Eyeoglu --- src/index.ts | 28 ++++++++++++++++++++++++++-- src/storage.ts | 22 ++++++++++++++++++++++ src/utils/pluralKit.ts | 26 +++++++++++++++++++------- 3 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 src/storage.ts diff --git a/src/index.ts b/src/index.ts index e33afd30..54590c4b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,8 +7,14 @@ import { PermissionFlagsBits, ChannelType, Events, + Message, } from 'discord.js'; import { reuploadCommands } from './_reupload'; +import { + connect as connectStorage, + isUserPlural, + storeUserPlurality, +} from './storage'; import * as BuildConfig from './constants'; import { parseLog } from './logs'; @@ -26,7 +32,11 @@ import { sayCommand } from './commands/say'; import random from 'just-random'; import { green, bold, yellow, cyan } from 'kleur/colors'; import 'dotenv/config'; -import { proxied } from './utils/pluralKit'; +import { + fetchPluralKitMessage, + isMessageProxied, + pkDelay, +} from './utils/pluralKit'; const client = new Client({ intents: [ @@ -42,6 +52,11 @@ const client = new Client({ partials: [Partials.Channel], }); +const handleWebhookMessage = async (e: Message) => { + const pkMessage = await fetchPluralKitMessage(e); + if (pkMessage !== null) storeUserPlurality(pkMessage.sender); +}; + client.once('ready', async () => { console.log(green('Discord bot ready!')); @@ -89,7 +104,15 @@ client.once('ready', async () => { if (e.author === client.user) return; - if (await proxied(e)) return; + if (e.webhookId !== null) { + // defer PK detection + setTimeout(async () => { + await handleWebhookMessage(e); + }, pkDelay); + } + + if ((await isUserPlural(e.author.id)) && (await isMessageProxied(e))) + return; if (e.cleanContent.match(BuildConfig.ETA_REGEX)) { await e.reply( @@ -196,6 +219,7 @@ client.on(Events.ThreadCreate, async (channel) => { reuploadCommands() .then(() => { + connectStorage(); client.login(process.env.DISCORD_TOKEN); }) .catch((e) => { diff --git a/src/storage.ts b/src/storage.ts new file mode 100644 index 00000000..c3b40c94 --- /dev/null +++ b/src/storage.ts @@ -0,0 +1,22 @@ +import { createClient } from 'redis'; + +export const client = createClient({ + url: process.env.REDIS_URL || 'redis://localhost:6379', +}); + +export const storeUserPlurality = async (userId: string) => { + // Just store some value. We only care about the presence of this key + await client + .multi() + .set(`user:${userId}:pk`, '0') + .expire(`user:${userId}:pk`, 7 * 24 * 60 * 60) + .exec(); +}; + +export const isUserPlural = async (userId: string) => { + return (await client.exists(`user:${userId}:pk`)) > 0; +}; + +export const connect = () => { + client.connect(); +}; diff --git a/src/utils/pluralKit.ts b/src/utils/pluralKit.ts index 7753a955..cb2f28c9 100644 --- a/src/utils/pluralKit.ts +++ b/src/utils/pluralKit.ts @@ -1,10 +1,22 @@ -import { Message } from "discord.js"; +import { Message } from 'discord.js'; -export async function proxied(message: Message): Promise { - if (message.webhookId !== null) - return false; +interface PkMessage { + sender: string; +} + +export const pkDelay = 500; + +export async function fetchPluralKitMessage(message: Message) { + const response = await fetch( + `https://api.pluralkit.me/v2/messages/${message.id}` + ); + + if (!response.ok) return null; + + return (await response.json()) as PkMessage; +} - await new Promise(resolve => setTimeout(resolve, 300)); - const response = await fetch(`https://api.pluralkit.me/v2/messages/${message.id}`); - return response.ok; +export async function isMessageProxied(message: Message) { + await new Promise((resolve) => setTimeout(resolve, pkDelay)); + return (await fetchPluralKitMessage(message)) !== null; } From 889ef8820a9490599ae0ba3f5af9ba6ee5bcbc40 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Fri, 17 Nov 2023 17:27:49 +0100 Subject: [PATCH 4/5] refactor: move handleWebhookMessage into callback Signed-off-by: Sefa Eyeoglu --- src/index.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/index.ts b/src/index.ts index 54590c4b..f3f344b1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,7 +7,6 @@ import { PermissionFlagsBits, ChannelType, Events, - Message, } from 'discord.js'; import { reuploadCommands } from './_reupload'; import { @@ -52,11 +51,6 @@ const client = new Client({ partials: [Partials.Channel], }); -const handleWebhookMessage = async (e: Message) => { - const pkMessage = await fetchPluralKitMessage(e); - if (pkMessage !== null) storeUserPlurality(pkMessage.sender); -}; - client.once('ready', async () => { console.log(green('Discord bot ready!')); @@ -107,7 +101,8 @@ client.once('ready', async () => { if (e.webhookId !== null) { // defer PK detection setTimeout(async () => { - await handleWebhookMessage(e); + const pkMessage = await fetchPluralKitMessage(e); + if (pkMessage !== null) storeUserPlurality(pkMessage.sender); }, pkDelay); } From 1c7e263f4ff81da1305163cc3d7300630e8f3ff7 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Fri, 17 Nov 2023 18:58:39 +0100 Subject: [PATCH 5/5] fix: increase PK delay Signed-off-by: Sefa Eyeoglu --- src/utils/pluralKit.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/pluralKit.ts b/src/utils/pluralKit.ts index cb2f28c9..3f5aae31 100644 --- a/src/utils/pluralKit.ts +++ b/src/utils/pluralKit.ts @@ -4,7 +4,7 @@ interface PkMessage { sender: string; } -export const pkDelay = 500; +export const pkDelay = 1000; export async function fetchPluralKitMessage(message: Message) { const response = await fetch(