/[sudobot]/branches/8.x/extensions/urlfish/src/services/URLFishService.ts
ViewVC logotype

Annotation of /branches/8.x/extensions/urlfish/src/services/URLFishService.ts

Parent Directory Parent Directory | Revision Log Revision Log


Revision 577 - (hide annotations)
Mon Jul 29 18:52:37 2024 UTC (8 months ago) by rakinar2
File MIME type: application/typescript
File size: 7398 byte(s)
chore: add old version archive branches (2.x to 9.x-dev)
1 rakinar2 577 import Service from "@sudobot/core/Service";
2     import FileSystem from "@sudobot/polyfills/FileSystem";
3     import { downloadFile } from "@sudobot/utils/download";
4     import { channelInfo, userInfo } from "@sudobot/utils/embed";
5     import { safeChannelFetch } from "@sudobot/utils/fetch";
6     import { sudoPrefix } from "@sudobot/utils/utils";
7     import { Colors, Message } from "discord.js";
8     import { ActionToTake, Config, GuildConfigWithExtension } from "src/types/config";
9    
10     export const name = "urlfish";
11    
12     export default class URLFishService extends Service {
13     private readonly domainListURL =
14     "https://raw.githubusercontent.com/mitchellkrogza/Phishing.Database/master/phishing-domains-ACTIVE.txt";
15     private _list: string[] = [];
16    
17     async boot() {
18     const urlfishDir = sudoPrefix("tmp/urlfish", true);
19     const dataFile = sudoPrefix("tmp/urlfish/LIST", false);
20    
21     if (await FileSystem.exists(dataFile)) {
22     this.client.logger.debug("URLFishService", "Phishing domain list already exists", dataFile);
23     } else {
24     this.client.logger.debug("URLFishService", "Phishing domain list not found", dataFile);
25     this.client.logger.debug("URLFishService", "Downloading list", dataFile);
26    
27     const url = this.domainListURL;
28     await downloadFile({
29     url,
30     name: "LIST",
31     path: urlfishDir
32     });
33     }
34    
35     const data = (await FileSystem.readFileContents<string>(dataFile)).split("\n");
36     this.client.logger.debug("URLFishService", `Loaded ${data.length} entries from file`);
37     this._list = data;
38     }
39    
40     get list() {
41     return this._list;
42     }
43    
44     scanMessage(message: Message) {
45     const urls = message.content.toLowerCase().split(" ");
46     const phishingURLs: string[] = [];
47    
48     for (const url of urls) {
49     const domain = url.startsWith("http") ? url.replace(/https?:\/?\/?/i, "") : url;
50    
51     if (this.list.includes(domain)) {
52     phishingURLs.push(url);
53     }
54     }
55    
56     return phishingURLs;
57     }
58    
59     async verifyMessage(message: Message) {
60     const config = this.client.configManager.get<GuildConfigWithExtension>(message.guildId!)?.urlfish;
61    
62     if (
63     !config?.enabled ||
64     (config.channels && "enabled_in" in config.channels && !config.channels.enabled_in.includes(message.channelId)) ||
65     (config.channels && "disabled_in" in config.channels && config.channels.disabled_in.includes(message.channelId)) ||
66     (await this.client.permissionManager.isImmuneToAutoMod(message.member!))
67     ) {
68     return;
69     }
70    
71     const links = this.scanMessage(message);
72    
73     if (links.length > 0) {
74     await this.takeAction(message, config);
75     await this.logMessage(message, config, links, config.action);
76     }
77     }
78    
79     async takeAction(message: Message<boolean>, config: NonNullable<Config>) {
80     switch (config.action) {
81     case "delete":
82     if (message.deletable) {
83     await message.delete();
84     }
85    
86     break;
87     case "warn":
88     await this.client.infractionManager.createMemberWarn(message.member!, {
89     guild: message.guild!,
90     reason:
91     config.infraction_reason ??
92     "We have detected phishing URLs in your message. Please refrain from posting these links.",
93     moderator: this.client.user!,
94     notifyUser: true,
95     sendLog: true
96     });
97    
98     break;
99     case "mute":
100     await this.client.infractionManager.createMemberMute(message.member!, {
101     guild: message.guild!,
102     reason:
103     config.infraction_reason ??
104     "We have detected phishing URLs in your message. Please refrain from posting these links.",
105     moderator: this.client.user!,
106     notifyUser: true,
107     sendLog: true,
108     duration: config.mute_duration ?? 3_600_000, // 1 hour,
109     autoRemoveQueue: true
110     });
111    
112     break;
113     case "kick":
114     await this.client.infractionManager.createMemberKick(message.member!, {
115     guild: message.guild!,
116     reason: config.infraction_reason ?? "We have detected phishing URLs in your message.",
117     moderator: this.client.user!,
118     notifyUser: true,
119     sendLog: true
120     });
121    
122     break;
123     case "ban":
124     await this.client.infractionManager.createUserBan(message.author, {
125     guild: message.guild!,
126     reason: config.infraction_reason ?? "We have detected phishing URLs in your message.",
127     moderator: this.client.user!,
128     notifyUser: true,
129     sendLog: true,
130     deleteMessageSeconds: 604_800, // 7 days,
131     autoRemoveQueue: true
132     });
133    
134     break;
135     }
136     }
137    
138     async logMessage(message: Message<boolean>, config: Config, links: string[], action: ActionToTake) {
139     if (!config?.log_channel || !message.guild) {
140     return;
141     }
142    
143     const logChannel = await safeChannelFetch(message.guild, config?.log_channel);
144    
145     if (!logChannel?.isTextBased()) {
146     return;
147     }
148    
149     const joinedLinks = links.join("\n");
150    
151     await logChannel.send({
152     embeds: [
153     {
154     title: `Phishing URLs detected in ${message.url}`,
155     fields: [
156     {
157     name: "URLs",
158     value: joinedLinks.substring(0, 1020) + (joinedLinks.length > 1020 ? "..." : "")
159     },
160     {
161     name: "Channel",
162     value: channelInfo(message.channel),
163     inline: true
164     },
165     {
166     name: "User",
167     value: userInfo(message.author),
168     inline: true
169     },
170     {
171     name: "Action",
172     value:
173     action === "ban"
174     ? "Banned"
175     : action[0].toUpperCase() + action.substring(1) + (action.endsWith("e") ? "d" : "ed"),
176     inline: true
177     }
178     ],
179     description: message.content || "*No content*",
180     color: Colors.Red,
181     timestamp: message.createdAt.toISOString(),
182     author: {
183     name: message.author.username,
184     icon_url: message.author.displayAvatarURL()
185     },
186     footer: {
187     text: `Detected by URLFish`
188     }
189     }
190     ]
191     });
192     }
193     }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26