FIXED MASSIVE SECURITY ISSUE! oh and eslint
This commit is contained in:
parent
07a05621e7
commit
7ec9cead2a
1
.eslintignore
Normal file
1
.eslintignore
Normal file
@ -0,0 +1 @@
|
|||||||
|
*.js
|
47
.eslintrc.js
Normal file
47
.eslintrc.js
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
module.exports = {
|
||||||
|
'env': {
|
||||||
|
'es2021': true,
|
||||||
|
'node': true
|
||||||
|
},
|
||||||
|
'extends': [
|
||||||
|
'eslint:recommended',
|
||||||
|
'plugin:@typescript-eslint/recommended'
|
||||||
|
],
|
||||||
|
'parser': '@typescript-eslint/parser',
|
||||||
|
'parserOptions': {
|
||||||
|
'ecmaVersion': 13,
|
||||||
|
'sourceType': 'module',
|
||||||
|
'project': 'tsconfig.json',
|
||||||
|
'tsconfigRootDir': __dirname,
|
||||||
|
},
|
||||||
|
'plugins': [
|
||||||
|
'@typescript-eslint'
|
||||||
|
],
|
||||||
|
'rules': {
|
||||||
|
'no-empty': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
'allowEmptyCatch': true,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'@typescript-eslint/no-explicit-any': 'off',
|
||||||
|
'@typescript-eslint/no-unused-vars': 'off',
|
||||||
|
'indent': [
|
||||||
|
'error',
|
||||||
|
2
|
||||||
|
],
|
||||||
|
'linebreak-style': [
|
||||||
|
'error',
|
||||||
|
'unix'
|
||||||
|
],
|
||||||
|
'quotes': [
|
||||||
|
'error',
|
||||||
|
'single'
|
||||||
|
],
|
||||||
|
'semi': [
|
||||||
|
'error',
|
||||||
|
'always'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -2,5 +2,6 @@
|
|||||||
/.out/
|
/.out/
|
||||||
deployment.json
|
deployment.json
|
||||||
*.js
|
*.js
|
||||||
|
!.eslintrc.js
|
||||||
*.d.ts
|
*.d.ts
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
|
@ -50,6 +50,7 @@ export class IRCFormatter extends Formatter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public strip(msg: string): string {
|
public strip(msg: string): string {
|
||||||
|
// eslint-disable-next-line no-control-regex
|
||||||
return msg.replace(/(\x03\d{0,2}(,\d{0,2})?)/g, '').replace(/[\x0F\x02\x16\x1F]/g, '');
|
return msg.replace(/(\x03\d{0,2}(,\d{0,2})?)/g, '').replace(/[\x0F\x02\x16\x1F]/g, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,22 +73,22 @@ export class IRCFormatter extends Formatter {
|
|||||||
// Special types
|
// Special types
|
||||||
if (elemParams && elemParams.type) {
|
if (elemParams && elemParams.type) {
|
||||||
switch (elemParams.type) {
|
switch (elemParams.type) {
|
||||||
case 'time':
|
case 'time':
|
||||||
elemValue = new Date(elemValue).toString();
|
elemValue = new Date(elemValue).toString();
|
||||||
break;
|
break;
|
||||||
case 'metric':
|
case 'metric':
|
||||||
elemValue = thousandsSeparator(elemValue);
|
elemValue = thousandsSeparator(elemValue);
|
||||||
break;
|
break;
|
||||||
case 'timesince':
|
case 'timesince':
|
||||||
elemValue = timeSince(elemValue);
|
elemValue = timeSince(elemValue);
|
||||||
break;
|
break;
|
||||||
case 'duration':
|
case 'duration':
|
||||||
elemValue = toHHMMSS(elemValue);
|
elemValue = toHHMMSS(elemValue);
|
||||||
break;
|
break;
|
||||||
case 'description':
|
case 'description':
|
||||||
valueColor = 'blue';
|
valueColor = 'blue';
|
||||||
elemValue = `"${elemValue}"`;
|
elemValue = `"${elemValue}"`;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
325
irc/irc.ts
325
irc/irc.ts
@ -25,20 +25,31 @@ export interface IIRCMessage {
|
|||||||
raw: IIRCLine;
|
raw: IIRCLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IQueue {
|
||||||
|
await: string;
|
||||||
|
from: string;
|
||||||
|
do: (line: IIRCLine) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface INickStore {
|
||||||
|
checked: number;
|
||||||
|
result: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
declare type ConnectSocket = TLSSocket | Socket;
|
declare type ConnectSocket = TLSSocket | Socket;
|
||||||
|
|
||||||
export class IRC extends EventEmitter {
|
export class IRC extends EventEmitter {
|
||||||
public alive = false;
|
public alive = false;
|
||||||
private authenticated = false;
|
public authenticated = false;
|
||||||
private serverData: {[key: string]: any} = {
|
public serverData: { [key: string]: any } = {
|
||||||
name: '',
|
name: '',
|
||||||
supportedModes: {},
|
supportedModes: {},
|
||||||
serverSupports: {},
|
serverSupports: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
private queue: any[] = [];
|
public queue: IQueue[] = [];
|
||||||
private channels: string[] = [];
|
public channels: string[] = [];
|
||||||
private nickservStore: {[key: string]: any} = {};
|
public nickservStore: { [key: string]: INickStore } = {};
|
||||||
|
|
||||||
private socket: ConnectSocket | null = null;
|
private socket: ConnectSocket | null = null;
|
||||||
|
|
||||||
@ -83,7 +94,7 @@ export class IRC extends EventEmitter {
|
|||||||
this.joinMissingChannels(this.options.channels);
|
this.joinMissingChannels(this.options.channels);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.on('testnick', (data) => {
|
this.on('testnick', (data: { nickname: string; func: (result: boolean) => void }) => {
|
||||||
if (this.nickservStore[data.nickname] != null) {
|
if (this.nickservStore[data.nickname] != null) {
|
||||||
if (this.nickservStore[data.nickname].result === true) {
|
if (this.nickservStore[data.nickname].result === true) {
|
||||||
data.func(true);
|
data.func(true);
|
||||||
@ -95,25 +106,28 @@ export class IRC extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.options.nickserv && this.options.nickserv.enabled && this.options.nickserv.command) {
|
if (this.options.nickserv
|
||||||
|
&& this.options.nickserv.enabled
|
||||||
|
&& this.options.nickserv.command
|
||||||
|
) {
|
||||||
this.queue.push({
|
this.queue.push({
|
||||||
await: 'NOTICE',
|
await: 'NOTICE',
|
||||||
from: 'NickServ',
|
from: 'NickServ',
|
||||||
do: (line: IIRCLine) => {
|
do: (line: IIRCLine) => {
|
||||||
const splitline = line.trailing!.split(' ');
|
if (!line.trailing) {
|
||||||
if (splitline![1] !== '0') {
|
return data.func(false);
|
||||||
this.nickservStore[data.nickname] = {
|
|
||||||
result: true,
|
|
||||||
checked: Date.now(),
|
|
||||||
};
|
|
||||||
data.func(true);
|
|
||||||
} else {
|
|
||||||
this.nickservStore[data.nickname] = {
|
|
||||||
result: false,
|
|
||||||
checked: Date.now(),
|
|
||||||
};
|
|
||||||
data.func(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const splitline = line.trailing.trim().split(' ');
|
||||||
|
let result = false;
|
||||||
|
if (splitline[2] !== '0') {
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.nickservStore[data.nickname] = {
|
||||||
|
result, checked: Date.now(),
|
||||||
|
};
|
||||||
|
data.func(result);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.write('PRIVMSG nickserv :%s %s', this.options.nickserv.command, data.nickname);
|
this.write('PRIVMSG nickserv :%s %s', this.options.nickserv.command, data.nickname);
|
||||||
@ -134,7 +148,7 @@ export class IRC extends EventEmitter {
|
|||||||
if (!this.alive) {
|
if (!this.alive) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.socket!.write(data + '\r\n');
|
this.socket?.write(data + '\r\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
private joinMissingChannels(arr: string[]): void {
|
private joinMissingChannels(arr: string[]): void {
|
||||||
@ -155,158 +169,169 @@ export class IRC extends EventEmitter {
|
|||||||
private handleServerLine(line: IIRCLine): void {
|
private handleServerLine(line: IIRCLine): void {
|
||||||
if (this.queue.length) {
|
if (this.queue.length) {
|
||||||
let skipHandling = false;
|
let skipHandling = false;
|
||||||
for (const i in this.queue) {
|
const afterModifyQueue: IQueue[] = [];
|
||||||
const entry = this.queue[i];
|
this.queue.forEach((entry) => {
|
||||||
if (entry.await && line.command === entry.await) {
|
if (entry.await && line.command === entry.await) {
|
||||||
if (entry.from && line.user.nickname.toLowerCase() === entry.from.toLowerCase()) {
|
if (entry.from && line.user.nickname.toLowerCase() === entry.from.toLowerCase()) {
|
||||||
if (entry.do) {
|
if (entry.do) {
|
||||||
skipHandling = true;
|
skipHandling = true;
|
||||||
this.queue.splice(parseInt(i, 10), 1);
|
|
||||||
entry.do(line);
|
entry.do(line);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
afterModifyQueue.push(entry);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.queue = afterModifyQueue;
|
||||||
|
|
||||||
if (skipHandling) {
|
if (skipHandling) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (line.command.toLowerCase()) {
|
switch (line.command.toLowerCase()) {
|
||||||
case 'cap':
|
case 'cap':
|
||||||
if (line.trailing === 'sasl' && line.arguments![1] === 'ACK' && !this.authenticated) {
|
if (line.trailing === 'sasl' && line.arguments?.[1] === 'ACK' && !this.authenticated) {
|
||||||
this.write('AUTHENTICATE PLAIN');
|
this.write('AUTHENTICATE PLAIN');
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '+':
|
case '+':
|
||||||
case ':+':
|
case ':+': {
|
||||||
if (this.authenticated) {
|
if (this.authenticated) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const authline = Buffer.from(this.options.nick + '\x00' + this.options.username + '\x00' + this.options.password)
|
const authline = Buffer.from(this.options.nick + '\x00' + this.options.username + '\x00' + this.options.password)
|
||||||
.toString('base64');
|
.toString('base64');
|
||||||
this.write('AUTHENTICATE %s', authline);
|
this.write('AUTHENTICATE %s', authline);
|
||||||
break;
|
break;
|
||||||
case '904':
|
}
|
||||||
this.emit('error', {
|
case '904':
|
||||||
error: new Error(line.trailing),
|
this.emit('error', {
|
||||||
fatal: true
|
error: new Error(line.trailing),
|
||||||
});
|
fatal: true
|
||||||
break;
|
});
|
||||||
case '903':
|
break;
|
||||||
this.write('CAP END');
|
case '903':
|
||||||
break;
|
this.write('CAP END');
|
||||||
case 'notice':
|
break;
|
||||||
case 'privmsg':
|
case 'notice':
|
||||||
if (!line.user.nickname || line.user.nickname === '') {
|
case 'privmsg':
|
||||||
return;
|
if (!line.user.nickname || line.user.nickname === '') {
|
||||||
}
|
return;
|
||||||
this.emit('message', {
|
}
|
||||||
message: line.trailing,
|
this.emit('message', {
|
||||||
to: line.arguments![0],
|
message: line.trailing,
|
||||||
nickname: line.user.nickname,
|
to: line.arguments?.[0],
|
||||||
raw: line
|
nickname: line.user.nickname,
|
||||||
});
|
raw: line
|
||||||
break;
|
});
|
||||||
case '001':
|
break;
|
||||||
this.serverData.name = line.user.hostname;
|
case '001':
|
||||||
this.authenticated = true;
|
this.serverData.name = line.user.hostname;
|
||||||
|
this.authenticated = true;
|
||||||
|
|
||||||
// Set nick to what the server actually thinks is our nick
|
// Set nick to what the server actually thinks is our nick
|
||||||
this.options.nick = line.arguments![0];
|
this.options.nick = line.arguments?.[0] || 'Squeebot';
|
||||||
this.emit('authenticated', true);
|
this.emit('authenticated', true);
|
||||||
|
|
||||||
// Send a whois request for self in order to reliably fetch hostname of self
|
// Send a whois request for self in order to reliably fetch hostname of self
|
||||||
this.write('WHOIS %s', this.options.nick);
|
this.write('WHOIS %s', this.options.nick);
|
||||||
|
break;
|
||||||
|
case '005': {
|
||||||
|
if (!line.arguments) {
|
||||||
break;
|
break;
|
||||||
case '005':
|
}
|
||||||
const argv = line.arguments!.slice(1);
|
const argv = line.arguments?.slice(1);
|
||||||
for (const a in argv) {
|
for (const entry of argv) {
|
||||||
let t: any = argv[a];
|
if (entry.indexOf('=') !== -1) {
|
||||||
if (t.indexOf('=') !== -1) {
|
const t = entry.split('=') as string[];
|
||||||
t = t.split('=');
|
if (t[0] === 'PREFIX') {
|
||||||
if (t[0] === 'PREFIX') {
|
const d = t[1].match(/\((\w+)\)(.*)/);
|
||||||
const d = t[1].match(/\((\w+)\)(.*)/);
|
if (d) {
|
||||||
const r = d![1].split('');
|
const r = d[1].split('');
|
||||||
const aa = d![2].split('');
|
const aa = d[2].split('');
|
||||||
for (const b in r) {
|
r.forEach((value, index) => {
|
||||||
this.serverData.supportedModes[r[b]] = aa[b];
|
this.serverData.supportedModes[value] = aa[index];
|
||||||
}
|
});
|
||||||
} else if (t[0] === 'NETWORK') {
|
|
||||||
this.serverData.network = t[1];
|
|
||||||
} else if (t[0] === 'CHANNELLEN') {
|
|
||||||
this.serverData.maxChannelLength = parseInt(t[1], 10);
|
|
||||||
}
|
}
|
||||||
|
} else if (t[0] === 'NETWORK') {
|
||||||
if (!isNaN(parseInt(t[1], 10))) {
|
this.serverData.network = t[1];
|
||||||
t[1] = parseInt(t[1], 10);
|
} else if (t[0] === 'CHANNELLEN') {
|
||||||
}
|
this.serverData.maxChannelLength = parseInt(t[1], 10);
|
||||||
this.serverData.serverSupports[t[0]] = t[1];
|
|
||||||
} else {
|
|
||||||
this.serverData.serverSupports[t] = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let numeral: string | number = t[1];
|
||||||
|
if (!isNaN(parseInt(numeral, 10))) {
|
||||||
|
numeral = parseInt(numeral, 10);
|
||||||
|
}
|
||||||
|
this.serverData.serverSupports[t[0]] = numeral;
|
||||||
|
} else {
|
||||||
|
this.serverData.serverSupports[entry] = true;
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
// Set hostname from 396 (non-standard)
|
break;
|
||||||
case '396':
|
}
|
||||||
this.options.hostname = line.arguments![1];
|
// Set hostname from 396 (non-standard)
|
||||||
break;
|
case '396':
|
||||||
|
this.options.hostname = line.arguments?.[1];
|
||||||
|
break;
|
||||||
// Set hostname from self-whois
|
// Set hostname from self-whois
|
||||||
case '311':
|
case '311':
|
||||||
if (line.arguments![1] !== this.options.nick) {
|
if (line.arguments?.[1] !== this.options.nick) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.options.hostname = line.arguments![3];
|
this.options.hostname = line.arguments?.[3];
|
||||||
break;
|
break;
|
||||||
case 'quit':
|
case 'quit':
|
||||||
if (line.user.nickname !== this.options.nick) {
|
if (line.user.nickname !== this.options.nick) {
|
||||||
if (this.nickservStore[line.user.nickname]) {
|
if (this.nickservStore[line.user.nickname]) {
|
||||||
delete this.nickservStore[line.user.nickname];
|
|
||||||
}
|
|
||||||
|
|
||||||
this.emit('leave', {
|
|
||||||
nickname: line.user.nickname
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'nick':
|
|
||||||
if (line.user.nickname === this.options.nick) {
|
|
||||||
this.options.nick = line.arguments![0];
|
|
||||||
} else if (this.nickservStore[line.user.nickname]) {
|
|
||||||
delete this.nickservStore[line.user.nickname];
|
delete this.nickservStore[line.user.nickname];
|
||||||
}
|
}
|
||||||
this.emit('nick', {
|
|
||||||
oldNick: line.user.nickname,
|
|
||||||
newNick: line.arguments![0]
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'join':
|
|
||||||
if (line.user.nickname === this.options.nick && line.trailing) {
|
|
||||||
this.channels.push(line.trailing);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.emit('join', {
|
|
||||||
nickname: line.user.nickname,
|
|
||||||
channel: line.trailing
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'part':
|
|
||||||
case 'kick':
|
|
||||||
if (line.user.nickname === this.options.nick) {
|
|
||||||
const indexAt = this.channels.indexOf(line.arguments![0]);
|
|
||||||
if (indexAt !== -1) {
|
|
||||||
this.channels.splice(indexAt, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.emit('leave', {
|
this.emit('leave', {
|
||||||
nickname: line.user.nickname,
|
nickname: line.user.nickname
|
||||||
channel: line.arguments![0]
|
|
||||||
});
|
});
|
||||||
break;
|
}
|
||||||
case 'error':
|
break;
|
||||||
this.emit('error', { fatal: true, error: new Error(line.raw) });
|
case 'nick':
|
||||||
break;
|
if (line.user.nickname === this.options.nick) {
|
||||||
|
this.options.nick = line.arguments?.[0] || 'unknown';
|
||||||
|
} else if (this.nickservStore[line.user.nickname]) {
|
||||||
|
delete this.nickservStore[line.user.nickname];
|
||||||
|
}
|
||||||
|
this.emit('nick', {
|
||||||
|
oldNick: line.user.nickname,
|
||||||
|
newNick: line.arguments?.[0]
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'join':
|
||||||
|
if (line.user.nickname === this.options.nick && line.trailing) {
|
||||||
|
this.channels.push(line.trailing);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.emit('join', {
|
||||||
|
nickname: line.user.nickname,
|
||||||
|
channel: line.trailing
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'part':
|
||||||
|
case 'kick':
|
||||||
|
if (line.user.nickname === this.options.nick && line.arguments) {
|
||||||
|
const indexAt = this.channels.indexOf(line.arguments[0]);
|
||||||
|
if (indexAt !== -1) {
|
||||||
|
this.channels.splice(indexAt, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.emit('leave', {
|
||||||
|
nickname: line.user.nickname,
|
||||||
|
channel: line.arguments?.[0]
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'error':
|
||||||
|
this.emit('error', { fatal: true, error: new Error(line.raw) });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,8 +346,8 @@ export class IRC extends EventEmitter {
|
|||||||
// Predict the length the server is going to split at
|
// Predict the length the server is going to split at
|
||||||
// :nickname!username@hostname command args :trailing\r\n
|
// :nickname!username@hostname command args :trailing\r\n
|
||||||
const header = this.options.nick.length +
|
const header = this.options.nick.length +
|
||||||
this.options.hostname!.length +
|
(this.options.hostname || '').length +
|
||||||
this.options.username!.length + 4 + 2;
|
(this.options.username || '').length + 4 + 2;
|
||||||
const offset = command.length + args.length + 3 + header;
|
const offset = command.length + args.length + 3 + header;
|
||||||
|
|
||||||
// Split the message up into chunks
|
// Split the message up into chunks
|
||||||
@ -383,14 +408,14 @@ export class IRC extends EventEmitter {
|
|||||||
this.socket = connection;
|
this.socket = connection;
|
||||||
|
|
||||||
let buffer: any = '';
|
let buffer: any = '';
|
||||||
this.socket!.on('data', (chunk) => {
|
this.socket?.on('data', (chunk) => {
|
||||||
buffer += chunk;
|
buffer += chunk;
|
||||||
const data = buffer.split('\r\n');
|
const data = buffer.split('\r\n');
|
||||||
buffer = data.pop();
|
buffer = data.pop();
|
||||||
|
|
||||||
data.forEach((line: string) => {
|
data.forEach((line: string) => {
|
||||||
if (line.indexOf('PING') === 0) {
|
if (line.indexOf('PING') === 0) {
|
||||||
this.socket!.write('PONG' + line.substring(4) + '\r\n');
|
this.socket?.write('PONG' + line.substring(4) + '\r\n');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"name": "irc",
|
"name": "irc",
|
||||||
"description": "IRC Service for Squeebot 3",
|
"description": "IRC Service for Squeebot 3",
|
||||||
"tags": ["service", "irc"],
|
"tags": ["service", "irc"],
|
||||||
"version": "1.1.3",
|
"version": "1.2.0",
|
||||||
"dependencies": ["control?"],
|
"dependencies": ["control?"],
|
||||||
"npmDependencies": []
|
"npmDependencies": []
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ import { logger } from '@squeebot/core/lib/core';
|
|||||||
import { IIRCMessage, IRC } from './irc';
|
import { IIRCMessage, IRC } from './irc';
|
||||||
|
|
||||||
import { IRCFormatter } from './format';
|
import { IRCFormatter } from './format';
|
||||||
|
import { IIRCLine } from './parser';
|
||||||
|
|
||||||
class IRCMessage implements IMessage {
|
class IRCMessage implements IMessage {
|
||||||
public time: Date = new Date();
|
public time: Date = new Date();
|
||||||
@ -95,26 +96,28 @@ class IRCProtocol extends Protocol {
|
|||||||
this.emit('stopped');
|
this.emit('stopped');
|
||||||
}
|
}
|
||||||
|
|
||||||
private validateNick(nickname: string, cb: Function): void {
|
private async validateNick(nickname: string): Promise<boolean> {
|
||||||
if (!this.config.nickserv || !this.config.nickserv.enabled) {
|
if (!this.config.irc.nickserv || !this.config.irc.nickserv.enabled) {
|
||||||
return cb(true); // Assume the user is authentic
|
return true; // Assume the user is authentic
|
||||||
}
|
}
|
||||||
|
|
||||||
let stop = false;
|
return new Promise((resolve) => {
|
||||||
const promiseTimeout = setTimeout(() => {
|
let stop = false;
|
||||||
stop = true;
|
const promiseTimeout = setTimeout(() => {
|
||||||
cb(false);
|
stop = true;
|
||||||
}, 4000);
|
resolve(false);
|
||||||
|
}, 4000);
|
||||||
|
|
||||||
this.irc.emit('testnick', {
|
this.irc.emit('testnick', {
|
||||||
nickname,
|
nickname,
|
||||||
func: (result: boolean) => {
|
func: (result: boolean) => {
|
||||||
clearTimeout(promiseTimeout);
|
clearTimeout(promiseTimeout);
|
||||||
if (stop) {
|
if (stop) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
resolve(result);
|
||||||
}
|
}
|
||||||
cb(result);
|
});
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,7 +178,7 @@ class IRCProtocol extends Protocol {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.irc.on('message', (msg: IIRCMessage) => {
|
this.irc.on('message', (msg: IIRCMessage) => {
|
||||||
this.validateNick(msg.nickname, (valid: boolean) => {
|
this.validateNick(msg.nickname).then((valid: boolean) => {
|
||||||
const to = msg.to === this.irc.options.nick ? msg.nickname : msg.to;
|
const to = msg.to === this.irc.options.nick ? msg.nickname : msg.to;
|
||||||
const newMessage = new IRCMessage(
|
const newMessage = new IRCMessage(
|
||||||
EMessageType.message,
|
EMessageType.message,
|
||||||
@ -197,11 +200,11 @@ class IRCProtocol extends Protocol {
|
|||||||
public resolve(message: IMessage, ...data: any[]): void {
|
public resolve(message: IMessage, ...data: any[]): void {
|
||||||
const response = this.parseMessage(...data);
|
const response = this.parseMessage(...data);
|
||||||
|
|
||||||
if (!this.irc.alive || !response) {
|
if (!this.irc.alive || !response || !message.target) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.irc.message(message.target!.id, response);
|
this.irc.message(message.target.id, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async sendTo(target: string, ...data: any[]): Promise<boolean> {
|
public async sendTo(target: string, ...data: any[]): Promise<boolean> {
|
||||||
@ -313,7 +316,7 @@ class IRCServicePlugin extends Plugin {
|
|||||||
unloadEventHandler(plugin: string | Plugin): void {
|
unloadEventHandler(plugin: string | Plugin): void {
|
||||||
if (plugin === this.name || plugin === this) {
|
if (plugin === this.name || plugin === this) {
|
||||||
logger.debug('[%s]', this.name, 'shutting down..');
|
logger.debug('[%s]', this.name, 'shutting down..');
|
||||||
this.service!.stopAll().then(() =>
|
this.service?.stopAll().then(() =>
|
||||||
this.emit('pluginUnloaded', this));
|
this.emit('pluginUnloaded', this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,17 @@
|
|||||||
import {
|
import {
|
||||||
Plugin,
|
Plugin,
|
||||||
EventListener,
|
EventListener,
|
||||||
Configurable,
|
|
||||||
InjectService,
|
|
||||||
Auto
|
|
||||||
} from '@squeebot/core/lib/plugin';
|
} from '@squeebot/core/lib/plugin';
|
||||||
|
|
||||||
import { EMessageType, IMessage, IMessageTarget, Protocol } from '@squeebot/core/lib/types';
|
import { IMessage } from '@squeebot/core/lib/types';
|
||||||
|
|
||||||
import { logger } from '@squeebot/core/lib/core';
|
import { logger } from '@squeebot/core/lib/core';
|
||||||
|
|
||||||
class MyPlugin extends Plugin {
|
class MyPlugin extends Plugin {
|
||||||
@Auto()
|
|
||||||
initialize(): void {
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventListener('message')
|
@EventListener('message')
|
||||||
messageHandler(msg: IMessage): void {
|
messageHandler(msg: IMessage): void {
|
||||||
if (msg.data.indexOf('Squeebot') !== -1) {
|
if (msg.data.indexOf('Squeebot') !== -1 && msg.sender) {
|
||||||
msg.resolve('Hello %s!', msg.sender!.name);
|
msg.resolve('Hello %s!', msg.sender.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2476
package-lock.json
generated
2476
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -13,5 +13,10 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@squeebot/core": "^3.3.1",
|
"@squeebot/core": "^3.3.1",
|
||||||
"typescript": "^4.4.2"
|
"typescript": "^4.4.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^16.11.13",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.7.0",
|
||||||
|
"eslint": "^8.4.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"plugins": [
|
"plugins": [
|
||||||
{
|
{
|
||||||
"name": "irc",
|
"name": "irc",
|
||||||
"version": "1.1.3"
|
"version": "1.2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ircprototest",
|
"name": "ircprototest",
|
||||||
|
122
tslint.json
122
tslint.json
@ -1,122 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "tslint:recommended",
|
|
||||||
"rules": {
|
|
||||||
"align": {
|
|
||||||
"options": [
|
|
||||||
"parameters",
|
|
||||||
"statements"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"array-type": false,
|
|
||||||
"arrow-return-shorthand": true,
|
|
||||||
"curly": true,
|
|
||||||
"deprecation": {
|
|
||||||
"severity": "warning"
|
|
||||||
},
|
|
||||||
"eofline": true,
|
|
||||||
"import-spacing": true,
|
|
||||||
"indent": {
|
|
||||||
"options": [
|
|
||||||
"spaces"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"max-classes-per-file": false,
|
|
||||||
"max-line-length": [
|
|
||||||
true,
|
|
||||||
140
|
|
||||||
],
|
|
||||||
"member-ordering": [
|
|
||||||
true,
|
|
||||||
{
|
|
||||||
"order": [
|
|
||||||
"static-field",
|
|
||||||
"instance-field",
|
|
||||||
"static-method",
|
|
||||||
"instance-method"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"no-console": [
|
|
||||||
true,
|
|
||||||
"debug",
|
|
||||||
"info",
|
|
||||||
"time",
|
|
||||||
"timeEnd",
|
|
||||||
"trace"
|
|
||||||
],
|
|
||||||
"no-empty": false,
|
|
||||||
"no-inferrable-types": [
|
|
||||||
true,
|
|
||||||
"ignore-params"
|
|
||||||
],
|
|
||||||
"no-non-null-assertion": false,
|
|
||||||
"no-redundant-jsdoc": true,
|
|
||||||
"no-switch-case-fall-through": true,
|
|
||||||
"no-var-requires": false,
|
|
||||||
"object-literal-key-quotes": [
|
|
||||||
true,
|
|
||||||
"as-needed"
|
|
||||||
],
|
|
||||||
"quotemark": [
|
|
||||||
true,
|
|
||||||
"single"
|
|
||||||
],
|
|
||||||
"semicolon": {
|
|
||||||
"options": [
|
|
||||||
"always"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"space-before-function-paren": {
|
|
||||||
"options": {
|
|
||||||
"anonymous": "never",
|
|
||||||
"asyncArrow": "always",
|
|
||||||
"constructor": "never",
|
|
||||||
"method": "never",
|
|
||||||
"named": "never"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"typedef": [
|
|
||||||
true,
|
|
||||||
"call-signature"
|
|
||||||
],
|
|
||||||
"forin": false,
|
|
||||||
"ban-types": {
|
|
||||||
"function": false
|
|
||||||
},
|
|
||||||
"typedef-whitespace": {
|
|
||||||
"options": [
|
|
||||||
{
|
|
||||||
"call-signature": "nospace",
|
|
||||||
"index-signature": "nospace",
|
|
||||||
"parameter": "nospace",
|
|
||||||
"property-declaration": "nospace",
|
|
||||||
"variable-declaration": "nospace"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"call-signature": "onespace",
|
|
||||||
"index-signature": "onespace",
|
|
||||||
"parameter": "onespace",
|
|
||||||
"property-declaration": "onespace",
|
|
||||||
"variable-declaration": "onespace"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"variable-name": {
|
|
||||||
"options": [
|
|
||||||
"ban-keywords",
|
|
||||||
"check-format",
|
|
||||||
"allow-pascal-case"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"whitespace": {
|
|
||||||
"options": [
|
|
||||||
"check-branch",
|
|
||||||
"check-decl",
|
|
||||||
"check-operator",
|
|
||||||
"check-separator",
|
|
||||||
"check-type",
|
|
||||||
"check-typecast"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user