From 61311f8edc1c07662b1fa262ad5fc8a688a330ce Mon Sep 17 00:00:00 2001 From: diomonogatari <17832206+diomonogatari@users.noreply.github.com> Date: Sun, 23 Aug 2026 17:08:01 +0100 Subject: [PATCH 1/3] fix: missing nodemon on devDependencies --- package-lock.json | 239 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 2 files changed, 240 insertions(+) diff --git a/package-lock.json b/package-lock.json index d7c0347..f37e48f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,6 +35,7 @@ "husky": "8.0.1", "jest": "28.1.3", "jest-cli": "28.1.3", + "nodemon": "^3.1.14", "prettier": "^3.3.3", "ts-node": "^10.9.2", "typescript": "^5.9.3", @@ -4143,6 +4144,19 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", @@ -4320,6 +4334,44 @@ "node": ">=10" } }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/ci-info": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", @@ -6246,6 +6298,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/has-property-descriptors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", @@ -6379,6 +6441,13 @@ "node": ">= 4" } }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true, + "license": "ISC" + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -6527,6 +6596,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-boolean-object": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", @@ -9151,6 +9233,87 @@ "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", "dev": true }, + "node_modules/nodemon": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.14.tgz", + "integrity": "sha512-jakjZi93UtB3jHMWsXL68FXSAosbLfY0In5gtKq3niLSkrWznrVBzXFNOEMJUfc9+Ke7SHWoAZsiMkNP3vq6Jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^10.2.1", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/nodemon/node_modules/brace-expansion": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/nodemon/node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/nodemon/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/normalize-package-data": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", @@ -9702,6 +9865,13 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true, + "license": "MIT" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -9900,6 +10070,19 @@ "node": ">= 6" } }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/redent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", @@ -10268,6 +10451,32 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -10589,6 +10798,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/supports-hyperlinks": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", @@ -10800,6 +11022,16 @@ "node": ">=8.0" } }, + "node_modules/touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true, + "license": "ISC", + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -11073,6 +11305,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true, + "license": "MIT" + }, "node_modules/undici": { "version": "6.21.3", "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz", diff --git a/package.json b/package.json index b85d255..5c816da 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "husky": "8.0.1", "jest": "28.1.3", "jest-cli": "28.1.3", + "nodemon": "^3.1.14", "prettier": "^3.3.3", "ts-node": "^10.9.2", "typescript": "^5.9.3", From 4623923d689e13e6937b47e0636e1047926b5269 Mon Sep 17 00:00:00 2001 From: diomonogatari <17832206+diomonogatari@users.noreply.github.com> Date: Sun, 23 Aug 2026 18:49:40 +0100 Subject: [PATCH 2/3] feat: add embedder service to fix links in user messages --- domain/service/embedFriendlyLinkService.ts | 3 + index.ts | 13 ++ .../service/embedFriendlyLinkService.ts | 39 ++++++ .../service/embedFriendlyLinkService.spec.ts | 113 ++++++++++++++++++ 4 files changed, 168 insertions(+) create mode 100644 domain/service/embedFriendlyLinkService.ts create mode 100644 infrastructure/service/embedFriendlyLinkService.ts create mode 100644 vitest/service/embedFriendlyLinkService.spec.ts diff --git a/domain/service/embedFriendlyLinkService.ts b/domain/service/embedFriendlyLinkService.ts new file mode 100644 index 0000000..80e425e --- /dev/null +++ b/domain/service/embedFriendlyLinkService.ts @@ -0,0 +1,3 @@ +export default interface EmbedFriendlyLinkService { + replaceLinkWithEmbedFriendly(message: string): Promise; +} diff --git a/index.ts b/index.ts index 747a146..3b6cf82 100644 --- a/index.ts +++ b/index.ts @@ -4,6 +4,7 @@ import { CronJob } from "cron"; import SendWelcomeMessageUseCase from "./application/usecases/sendWelcomeMessageUseCase"; import FileMessageRepository from "./infrastructure/repository/fileMessageRepository"; import ChatService from "./domain/service/chatService"; +import EmbedFriendlyLinkService from "./domain/service/embedFriendlyLinkService"; import DiscordChatService from "./infrastructure/service/discordChatService"; import ConsoleLoggerService from "./infrastructure/service/consoleLoggerService"; import MessageRepository from "./domain/repository/messageRepository"; @@ -21,6 +22,7 @@ import DontAskToAskCommand from "./application/command/dontAskToAskCommand"; import OnlyCodeQuestionsCommand from "./application/command/onlyCodeQuestionsCommand"; import AnonymousQuestionCommand from "./application/command/anonymousQuestionCommand"; import { Command } from "./types"; +import DiscordEmbedFriendlyLinkService from "./infrastructure/service/embedFriendlyLinkService"; dotenv.config(); @@ -39,6 +41,7 @@ const client = new Client({ const messageRepository: MessageRepository = new FileMessageRepository(); const chatService: ChatService = new DiscordChatService(client); +const embedFriendlyService: EmbedFriendlyLinkService = new DiscordEmbedFriendlyLinkService(); const loggerService: LoggerService = new ConsoleLoggerService(); const channelResolver: ChannelResolver = new ChannelResolver(); const questionTrackingService: QuestionTrackingService = new QuestionTrackingService(); @@ -141,6 +144,16 @@ client.on(Events.MessageCreate, async (message: Message) => { } }); +client.on(Events.MessageCreate, async (message: Message) => { + if (message.author.bot) return; + + const embedFriendlyLink = await embedFriendlyService.replaceLinkWithEmbedFriendly(message.content); + + if (!embedFriendlyLink) return; + + await chatService.sendMessageToChannel(embedFriendlyLink, message.channelId); +}); + client.on(Events.InteractionCreate, async (interaction) => { if (interaction.isButton()) { await interactionResolver.resolveButtonInteraction(interaction); diff --git a/infrastructure/service/embedFriendlyLinkService.ts b/infrastructure/service/embedFriendlyLinkService.ts new file mode 100644 index 0000000..06682a5 --- /dev/null +++ b/infrastructure/service/embedFriendlyLinkService.ts @@ -0,0 +1,39 @@ +import EmbedFriendlyLinkService from "../../domain/service/embedFriendlyLinkService"; + +export default class DiscordEmbedFriendlyLinkService implements EmbedFriendlyLinkService { + private readonly providers = new Map([ + ["instagram.com", "kkinstagram.com"], + ["x.com", "fxtwitter.com"], + ["twitter.com", "fxtwitter.com"], + ["tiktok.com", "tnktok.com"], + ["bsky.app", "fxbsky.app"], + ["reddit.com", "vxreddit.com"], + ["redd.it", "vxreddit.com"], + ]); + + async replaceLinkWithEmbedFriendly(message: string): Promise { + const matches = message.match(/https?:\/\/[^\s]+/g) ?? []; + + const match = matches + .map((value) => { + try { + const url = new URL(value); + const hostname = url.hostname.replace(/^www\./, ""); + const replacement = this.providers.get(hostname); + + return replacement ? { url, replacement } : null; + } catch { + return null; + } + }) + .find((value) => value !== null); + + if (!match) { + return null; + } + + match.url.hostname = match.replacement; + + return match.url.toString(); + } +} diff --git a/vitest/service/embedFriendlyLinkService.spec.ts b/vitest/service/embedFriendlyLinkService.spec.ts new file mode 100644 index 0000000..a444629 --- /dev/null +++ b/vitest/service/embedFriendlyLinkService.spec.ts @@ -0,0 +1,113 @@ +import { describe, it, expect } from "vitest"; +import EmbedFriendlyLinkService from "../../domain/service/embedFriendlyLinkService"; +import DiscordEmbedFriendlyLinkService from "../../infrastructure/service/embedFriendlyLinkService"; + +describe("EmbedFriendlyLinkService", () => { + const embedFriendlyLinkService: EmbedFriendlyLinkService = new DiscordEmbedFriendlyLinkService(); + + describe("replaceLinkWithEmbedFriendly", () => { + it("should replace an X link", async () => { + const result = await embedFriendlyLinkService.replaceLinkWithEmbedFriendly( + "Check this out https://x.com/user/status/123456" + ); + + expect(result).toBe("https://fxtwitter.com/user/status/123456"); + }); + + it("should replace a Twitter link", async () => { + const result = await embedFriendlyLinkService.replaceLinkWithEmbedFriendly( + "https://twitter.com/user/status/123456" + ); + + expect(result).toBe("https://fxtwitter.com/user/status/123456"); + }); + + it("should replace an Instagram link", async () => { + const result = await embedFriendlyLinkService.replaceLinkWithEmbedFriendly( + "Check this out https://instagram.com/p/ABC123" + ); + + expect(result).toBe("https://kkinstagram.com/p/ABC123"); + }); + + it("should replace a TikTok link", async () => { + const result = await embedFriendlyLinkService.replaceLinkWithEmbedFriendly( + "https://tiktok.com/@user/video/123456" + ); + + expect(result).toBe("https://tnktok.com/@user/video/123456"); + }); + + it("should replace a Bluesky link", async () => { + const result = await embedFriendlyLinkService.replaceLinkWithEmbedFriendly( + "https://bsky.app/profile/user.bsky.social/post/123456" + ); + + expect(result).toBe("https://fxbsky.app/profile/user.bsky.social/post/123456"); + }); + + it("should replace a Reddit link", async () => { + const result = await embedFriendlyLinkService.replaceLinkWithEmbedFriendly( + "https://reddit.com/r/programming/comments/abc123/example" + ); + + expect(result).toBe("https://vxreddit.com/r/programming/comments/abc123/example"); + }); + + it("should replace a redd.it link", async () => { + const result = await embedFriendlyLinkService.replaceLinkWithEmbedFriendly("https://redd.it/abc123"); + + expect(result).toBe("https://vxreddit.com/abc123"); + }); + + it("should return null when the message contains no URL", async () => { + const result = await embedFriendlyLinkService.replaceLinkWithEmbedFriendly("This message contains no links"); + + expect(result).toBeNull(); + }); + + it("should return null when the URL is not supported", async () => { + const result = await embedFriendlyLinkService.replaceLinkWithEmbedFriendly("https://google.com/something"); + + expect(result).toBeNull(); + }); + + it("should preserve the URL path and query parameters", async () => { + const result = await embedFriendlyLinkService.replaceLinkWithEmbedFriendly( + "https://x.com/foo/status/123456789?foo=bar" + ); + + expect(result).toBe("https://fxtwitter.com/foo/status/123456789?foo=bar"); + }); + + it("should support www domains", async () => { + const result = await embedFriendlyLinkService.replaceLinkWithEmbedFriendly( + "https://www.x.com/user/status/123456" + ); + + expect(result).toBe("https://fxtwitter.com/user/status/123456"); + }); + + it("should support HTTP URLs", async () => { + const result = await embedFriendlyLinkService.replaceLinkWithEmbedFriendly("http://x.com/user/status/123456"); + + expect(result).toBe("http://fxtwitter.com/user/status/123456"); + }); + + it("should replace the first supported link", async () => { + const result = await embedFriendlyLinkService.replaceLinkWithEmbedFriendly( + "https://google.com https://x.com/user/status/123" + ); + + expect(result).toBe("https://fxtwitter.com/user/status/123"); + }); + + it("should return null when all URLs are unsupported", async () => { + const result = await embedFriendlyLinkService.replaceLinkWithEmbedFriendly( + "https://google.com https://example.com/foo" + ); + + expect(result).toBeNull(); + }); + }); +}); From 5a315787c002a9fe22745cc3e92607eb6267e388 Mon Sep 17 00:00:00 2001 From: diomonogatari <17832206+diomonogatari@users.noreply.github.com> Date: Tue, 25 Aug 2026 13:59:14 +0100 Subject: [PATCH 3/3] feat: supress original message embeds to stop over polluting chat --- index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/index.ts b/index.ts index 3b6cf82..4da454c 100644 --- a/index.ts +++ b/index.ts @@ -151,6 +151,7 @@ client.on(Events.MessageCreate, async (message: Message) => { if (!embedFriendlyLink) return; + await message.suppressEmbeds(true); await chatService.sendMessageToChannel(embedFriendlyLink, message.channelId); });