3
0
Fork 0
mirror of https://github.com/ZeppelinBot/Zeppelin.git synced 2025-07-07 11:07:19 +00:00

feat: replace Phisherman with FishFish

This commit is contained in:
Dragory 2025-05-31 18:12:07 +00:00
parent bf08cade15
commit 8c2058821f
No known key found for this signature in database
13 changed files with 202 additions and 475 deletions

View file

@ -1,11 +1,10 @@
import { escapeInlineCode } from "discord.js";
import z from "zod/v4";
import { allowTimeout } from "../../../RegExpRunner.js";
import { phishermanDomainIsSafe } from "../../../data/Phisherman.js";
import { getFishFishDomain } from "../../../data/FishFish.js";
import { getUrlsInString, zRegex } from "../../../utils.js";
import { mergeRegexes } from "../../../utils/mergeRegexes.js";
import { mergeWordsIntoRegex } from "../../../utils/mergeWordsIntoRegex.js";
import { PhishermanPlugin } from "../../Phisherman/PhishermanPlugin.js";
import { getTextMatchPartialSummary } from "../functions/getTextMatchPartialSummary.js";
import { MatchableTextType, matchMultipleTextTypesOnMessage } from "../functions/matchMultipleTextTypesOnMessage.js";
import { automodTrigger } from "../helpers.js";
@ -40,6 +39,7 @@ const configSchema = z.strictObject({
include_verified: z.boolean().optional(),
})
.optional(),
include_malicious: z.boolean().default(false),
only_real_links: z.boolean().default(true),
match_messages: z.boolean().default(true),
match_embeds: z.boolean().default(true),
@ -155,22 +155,18 @@ export const MatchLinksTrigger = automodTrigger<MatchResultType>()({
}
}
if (trigger.phisherman) {
const phishermanResult = await pluginData.getPlugin(PhishermanPlugin).getDomainInfo(normalizedHostname);
if (phishermanResult != null && !phishermanDomainIsSafe(phishermanResult)) {
if (
(trigger.phisherman.include_suspected && !phishermanResult.verifiedPhish) ||
(trigger.phisherman.include_verified && phishermanResult.verifiedPhish)
) {
const suspectedVerified = phishermanResult.verifiedPhish ? "verified" : "suspected";
return {
extra: {
type,
link: link.input,
details: `using Phisherman (${suspectedVerified})`,
},
};
}
const includeMalicious =
trigger.include_malicious || trigger.phisherman?.include_suspected || trigger.phisherman?.include_verified;
if (includeMalicious) {
const domainInfo = getFishFishDomain(normalizedHostname);
if (domainInfo && domainInfo.category !== "safe") {
return {
extra: {
type,
link: link.input,
details: `(known ${domainInfo.category} domain)`,
},
};
}
}
}

View file

@ -1,41 +1,7 @@
import { PluginOptions, guildPlugin } from "knub";
import { hasPhishermanMasterAPIKey, phishermanApiKeyIsValid } from "../../data/Phisherman.js";
import { makePublicFn } from "../../pluginUtils.js";
import { getDomainInfo } from "./functions/getDomainInfo.js";
import { guildPlugin } from "knub";
import { PhishermanPluginType, zPhishermanConfig } from "./types.js";
export const PhishermanPlugin = guildPlugin<PhishermanPluginType>()({
name: "phisherman",
configSchema: zPhishermanConfig,
public(pluginData) {
return {
getDomainInfo: makePublicFn(pluginData, getDomainInfo),
};
},
async beforeLoad(pluginData) {
const { state } = pluginData;
pluginData.state.validApiKey = null;
if (!hasPhishermanMasterAPIKey()) {
// tslint:disable-next-line:no-console
console.warn("[PHISHERMAN] Could not load Phisherman plugin: master API key is missing");
return;
}
const apiKey = pluginData.config.get().api_key;
if (apiKey) {
const isValid = await phishermanApiKeyIsValid(apiKey).catch((err) => {
// tslint:disable-next-line:no-console
console.warn(`[PHISHERMAN] Error checking user API key validity:\n${err.toString()}`);
return false;
});
if (isValid) {
state.validApiKey = apiKey;
}
}
},
});

View file

@ -4,41 +4,12 @@ import { zPhishermanConfig } from "./types.js";
export const phishermanPluginDocs: ZeppelinPluginDocs = {
prettyName: "Phisherman",
type: "stable",
type: "legacy",
description: trimPluginDescription(`
Match scam/phishing links using the Phisherman API. See https://phisherman.gg/ for more details!
Match malicious links using Phisherman
`),
configurationGuide: trimPluginDescription(`
### Getting started
To get started, request an API key for Phisherman following the instructions at https://docs.phisherman.gg/guide/getting-started.html#requesting-api-access
Then, add the api key to the plugin's config:
~~~yml
phisherman:
config:
api_key: "your key here"
~~~
### Note
When using Phisherman features in Zeppelin, Zeppelin reports statistics about checked links back to Phisherman. This only includes the domain (e.g. zeppelin.gg), not the full link.
### Usage with Automod
Once you have configured the Phisherman plugin, you are ready to use it with automod. Currently, Phisherman is available as an option in the \`match_links\` plugin:
~~~yml
automod:
config:
rules:
# Clean any scam links detected by Phisherman
filter_scam_links:
triggers:
- match_links:
phisherman:
include_suspected: true # It's recommended to keep this enabled to catch new scam domains quickly
include_verified: true
actions:
clean: true
~~~
This plugin has been deprecated. Please use the \`include_malicious\` option for automod \`match_links\` trigger instead.
`),
configSchema: zPhishermanConfig,
};

View file

@ -1,31 +0,0 @@
import { GuildPluginData } from "knub";
import {
getPhishermanDomainInfo,
phishermanDomainIsSafe,
trackPhishermanCaughtDomain,
} from "../../../data/Phisherman.js";
import { PhishermanDomainInfo } from "../../../data/types/phisherman.js";
import { PhishermanPluginType } from "../types.js";
export async function getDomainInfo(
pluginData: GuildPluginData<PhishermanPluginType>,
domain: string,
): Promise<PhishermanDomainInfo | null> {
if (!pluginData.state.validApiKey) {
return null;
}
const info = await getPhishermanDomainInfo(domain).catch((err) => {
// tslint:disable-next-line:no-console
console.warn(`[PHISHERMAN] Error in getDomainInfo() for server ${pluginData.guild.id}: ${err.message}`);
if (err.message === "missing permissions") {
pluginData.state.validApiKey = null;
}
return null;
});
if (info != null && !phishermanDomainIsSafe(info)) {
trackPhishermanCaughtDomain(pluginData.state.validApiKey, domain);
}
return info;
}

View file

@ -7,7 +7,5 @@ export const zPhishermanConfig = z.strictObject({
export interface PhishermanPluginType extends BasePluginType {
configSchema: typeof zPhishermanConfig;
state: {
validApiKey: string | null;
};
state: {};
}