@amatiscorp/disguard 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1028 -0
  3. package/dist/AntiSpam.d.ts +36 -0
  4. package/dist/AntiSpam.d.ts.map +1 -0
  5. package/dist/AntiSpam.js +196 -0
  6. package/dist/AntiSpam.js.map +1 -0
  7. package/dist/defaults.d.ts +5 -0
  8. package/dist/defaults.d.ts.map +1 -0
  9. package/dist/defaults.js +184 -0
  10. package/dist/defaults.js.map +1 -0
  11. package/dist/detectors/caps.d.ts +3 -0
  12. package/dist/detectors/caps.d.ts.map +1 -0
  13. package/dist/detectors/caps.js +29 -0
  14. package/dist/detectors/caps.js.map +1 -0
  15. package/dist/detectors/duplicates.d.ts +3 -0
  16. package/dist/detectors/duplicates.d.ts.map +1 -0
  17. package/dist/detectors/duplicates.js +40 -0
  18. package/dist/detectors/duplicates.js.map +1 -0
  19. package/dist/detectors/emojis.d.ts +3 -0
  20. package/dist/detectors/emojis.d.ts.map +1 -0
  21. package/dist/detectors/emojis.js +35 -0
  22. package/dist/detectors/emojis.js.map +1 -0
  23. package/dist/detectors/flood.d.ts +3 -0
  24. package/dist/detectors/flood.d.ts.map +1 -0
  25. package/dist/detectors/flood.js +24 -0
  26. package/dist/detectors/flood.js.map +1 -0
  27. package/dist/detectors/images.d.ts +9 -0
  28. package/dist/detectors/images.d.ts.map +1 -0
  29. package/dist/detectors/images.js +105 -0
  30. package/dist/detectors/images.js.map +1 -0
  31. package/dist/detectors/incident.d.ts +10 -0
  32. package/dist/detectors/incident.d.ts.map +1 -0
  33. package/dist/detectors/incident.js +18 -0
  34. package/dist/detectors/incident.js.map +1 -0
  35. package/dist/detectors/links.d.ts +3 -0
  36. package/dist/detectors/links.d.ts.map +1 -0
  37. package/dist/detectors/links.js +85 -0
  38. package/dist/detectors/links.js.map +1 -0
  39. package/dist/detectors/mentions.d.ts +3 -0
  40. package/dist/detectors/mentions.d.ts.map +1 -0
  41. package/dist/detectors/mentions.js +47 -0
  42. package/dist/detectors/mentions.js.map +1 -0
  43. package/dist/enforcement.d.ts +4 -0
  44. package/dist/enforcement.d.ts.map +1 -0
  45. package/dist/enforcement.js +153 -0
  46. package/dist/enforcement.js.map +1 -0
  47. package/dist/index.d.ts +8 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +22 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/store/MemoryStore.d.ts +18 -0
  52. package/dist/store/MemoryStore.d.ts.map +1 -0
  53. package/dist/store/MemoryStore.js +96 -0
  54. package/dist/store/MemoryStore.js.map +1 -0
  55. package/dist/types.d.ts +208 -0
  56. package/dist/types.d.ts.map +1 -0
  57. package/dist/types.js +3 -0
  58. package/dist/types.js.map +1 -0
  59. package/dist/utils/hash.d.ts +9 -0
  60. package/dist/utils/hash.d.ts.map +1 -0
  61. package/dist/utils/hash.js +42 -0
  62. package/dist/utils/hash.js.map +1 -0
  63. package/dist/utils/normalize.d.ts +5 -0
  64. package/dist/utils/normalize.d.ts.map +1 -0
  65. package/dist/utils/normalize.js +35 -0
  66. package/dist/utils/normalize.js.map +1 -0
  67. package/dist/utils/similarity.d.ts +5 -0
  68. package/dist/utils/similarity.d.ts.map +1 -0
  69. package/dist/utils/similarity.js +45 -0
  70. package/dist/utils/similarity.js.map +1 -0
  71. package/dist/utils/urls.d.ts +18 -0
  72. package/dist/utils/urls.d.ts.map +1 -0
  73. package/dist/utils/urls.js +148 -0
  74. package/dist/utils/urls.js.map +1 -0
  75. package/package.json +62 -0
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_PHISHING_KEYWORDS = exports.OFFICIAL_BRANDS = exports.DEFAULT_SHORTENERS = void 0;
4
+ exports.extractUrls = extractUrls;
5
+ exports.isDiscordInvite = isDiscordInvite;
6
+ exports.hostMatchesList = hostMatchesList;
7
+ exports.isShortener = isShortener;
8
+ exports.brandLookalike = brandLookalike;
9
+ exports.messageHasPhishingKeywords = messageHasPhishingKeywords;
10
+ const similarity_1 = require("./similarity");
11
+ const URL_RE = /(?:https?:\/\/|www\.)[^\s<>()]+|(?:discord\.gg|discord\.com\/invite|discordapp\.com\/invite)\/[^\s<>()]+/gi;
12
+ const MARKDOWN_LINK_RE = /\[[^\]]*]\(\s*<?(https?:\/\/[^)\s>]+)>?\s*\)/gi;
13
+ const IPV4_RE = /^(?:\d{1,3}\.){3}\d{1,3}$/;
14
+ exports.DEFAULT_SHORTENERS = [
15
+ "bit.ly",
16
+ "bitly.com",
17
+ "tinyurl.com",
18
+ "t.co",
19
+ "goo.gl",
20
+ "ow.ly",
21
+ "is.gd",
22
+ "cutt.ly",
23
+ "rebrand.ly",
24
+ "rb.gy",
25
+ "shorturl.at",
26
+ "s.id",
27
+ "tiny.cc",
28
+ "clck.ru",
29
+ "adf.ly",
30
+ ];
31
+ exports.OFFICIAL_BRANDS = {
32
+ discord: ["discord.com", "discord.gg", "discordapp.com", "discordapp.net", "discord.media"],
33
+ steam: ["steampowered.com", "steamcommunity.com", "steamgames.com"],
34
+ github: ["github.com", "githubusercontent.com"],
35
+ google: ["google.com", "youtube.com", "youtu.be"],
36
+ twitter: ["twitter.com", "x.com"],
37
+ facebook: ["facebook.com", "fb.com"],
38
+ instagram: ["instagram.com"],
39
+ paypal: ["paypal.com", "paypal.me"],
40
+ roblox: ["roblox.com"],
41
+ };
42
+ exports.DEFAULT_PHISHING_KEYWORDS = [
43
+ "free nitro",
44
+ "nitro free",
45
+ "nitro gratis",
46
+ "steam gift",
47
+ "steamcommunity",
48
+ "airdrop",
49
+ "wallet connect",
50
+ "claim reward",
51
+ "claim nitro",
52
+ "reclama nitro",
53
+ "regalo nitro",
54
+ "discord gift",
55
+ "login to claim",
56
+ "verify your account",
57
+ "verifica tu cuenta",
58
+ "authorize app",
59
+ "oauth",
60
+ ];
61
+ function sanitizeRaw(raw) {
62
+ return raw.replace(/[.,)!?;:'"]+$/g, "");
63
+ }
64
+ function toHref(raw) {
65
+ const clean = sanitizeRaw(raw);
66
+ if (/^https?:\/\//i.test(clean))
67
+ return clean;
68
+ if (/^discord\.(gg|com|app)/i.test(clean))
69
+ return `https://${clean}`;
70
+ return `https://${clean}`;
71
+ }
72
+ function extractUrls(text) {
73
+ const found = new Map();
74
+ const add = (raw) => {
75
+ const href = toHref(raw);
76
+ try {
77
+ const url = new URL(href);
78
+ const hostname = url.hostname.toLowerCase().replace(/^www\./, "");
79
+ const key = href.toLowerCase();
80
+ if (found.has(key))
81
+ return;
82
+ found.set(key, {
83
+ raw: sanitizeRaw(raw),
84
+ href,
85
+ hostname,
86
+ isInvite: isDiscordInvite(hostname, url.pathname),
87
+ isIp: IPV4_RE.test(hostname),
88
+ isPunycode: hostname.includes("xn--"),
89
+ });
90
+ }
91
+ catch {
92
+ // URL malformada: se ignora.
93
+ }
94
+ };
95
+ for (const match of text.matchAll(MARKDOWN_LINK_RE)) {
96
+ add(match[1]);
97
+ }
98
+ for (const match of text.matchAll(URL_RE)) {
99
+ add(match[0]);
100
+ }
101
+ return [...found.values()];
102
+ }
103
+ function isDiscordInvite(hostname, pathname) {
104
+ if (hostname === "discord.gg")
105
+ return true;
106
+ return ((hostname === "discord.com" || hostname === "discordapp.com") &&
107
+ pathname.toLowerCase().startsWith("/invite/"));
108
+ }
109
+ function hostMatchesList(hostname, list) {
110
+ const normalized = hostname.toLowerCase();
111
+ return list.some((entry) => {
112
+ const item = entry.toLowerCase().replace(/^https?:\/\//, "").replace(/^www\./, "").split("/")[0];
113
+ return normalized === item || normalized.endsWith(`.${item}`);
114
+ });
115
+ }
116
+ function isShortener(hostname, extra = []) {
117
+ return hostMatchesList(hostname, [...exports.DEFAULT_SHORTENERS, ...extra]);
118
+ }
119
+ function brandLookalike(hostname) {
120
+ const labels = hostname.split(".");
121
+ const sld = labels.length >= 2 ? labels[labels.length - 2] : labels[0];
122
+ const compact = sld.replace(/[^a-z0-9]/g, "");
123
+ for (const [brand, official] of Object.entries(exports.OFFICIAL_BRANDS)) {
124
+ if (hostMatchesList(hostname, official))
125
+ continue;
126
+ const brandDistance = brand.length <= 5 ? 1 : 2;
127
+ if ((0, similarity_1.looksLike)(compact, brand, brandDistance)) {
128
+ return brand;
129
+ }
130
+ for (const domain of official) {
131
+ const officialSld = domain.split(".")[0].replace(/[^a-z0-9]/g, "");
132
+ const maxDistance = officialSld.length >= 10 ? 3 : officialSld.length >= 7 ? 2 : 1;
133
+ if ((0, similarity_1.looksLike)(compact, officialSld, maxDistance)) {
134
+ return brand;
135
+ }
136
+ }
137
+ }
138
+ return null;
139
+ }
140
+ function messageHasPhishingKeywords(text, extra = []) {
141
+ const haystack = text.toLowerCase().normalize("NFKD");
142
+ for (const keyword of [...exports.DEFAULT_PHISHING_KEYWORDS, ...extra]) {
143
+ if (haystack.includes(keyword.toLowerCase()))
144
+ return keyword;
145
+ }
146
+ return null;
147
+ }
148
+ //# sourceMappingURL=urls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"urls.js","sourceRoot":"","sources":["../../src/utils/urls.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@amatiscorp/disguard",
3
+ "version": "1.0.0",
4
+ "description": "Configurable antispam for discord.js bots: flood, repeated messages, phishing, duplicate images, and more.",
5
+ "keywords": [
6
+ "disguard",
7
+ "discord",
8
+ "discord.js",
9
+ "antispam",
10
+ "anti-spam",
11
+ "moderation",
12
+ "phishing",
13
+ "security",
14
+ "automod"
15
+ ],
16
+ "license": "MIT",
17
+ "author": "Jackson",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/Amatis-Corp/NPM-Security-Discord.git"
21
+ },
22
+ "bugs": {
23
+ "url": "https://github.com/Amatis-Corp/NPM-Security-Discord/issues"
24
+ },
25
+ "homepage": "https://github.com/Amatis-Corp/NPM-Security-Discord#readme",
26
+ "main": "dist/index.js",
27
+ "types": "dist/index.d.ts",
28
+ "exports": {
29
+ ".": {
30
+ "types": "./dist/index.d.ts",
31
+ "default": "./dist/index.js"
32
+ }
33
+ },
34
+ "files": [
35
+ "dist",
36
+ "README.md",
37
+ "LICENSE"
38
+ ],
39
+ "publishConfig": {
40
+ "access": "public"
41
+ },
42
+ "engines": {
43
+ "node": ">=18"
44
+ },
45
+ "scripts": {
46
+ "build": "tsc",
47
+ "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
48
+ "prepublishOnly": "npm run clean && npm run build",
49
+ "test": "vitest run",
50
+ "test:watch": "vitest",
51
+ "dev": "node examples/basic.js"
52
+ },
53
+ "peerDependencies": {
54
+ "discord.js": "^14.0.0"
55
+ },
56
+ "devDependencies": {
57
+ "@types/node": "^22.13.10",
58
+ "discord.js": "^14.18.0",
59
+ "typescript": "^5.8.2",
60
+ "vitest": "^3.0.8"
61
+ }
62
+ }