Skip to content
This repository has been archived by the owner on May 22, 2024. It is now read-only.

Commit

Permalink
Merge pull request #6 from kyranet/dev
Browse files Browse the repository at this point in the history
Linter monitor
  • Loading branch information
kyranet authored May 31, 2018
2 parents f5484a6 + a0a671e commit 1318920
Show file tree
Hide file tree
Showing 4 changed files with 188 additions and 1 deletion.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "smii",
"version": "1.1.0",
"version": "2.0.0",
"description": "Canvas-Constructor helper bot",
"main": "src/Smii.mjs",
"scripts": {
Expand Down
12 changes: 12 additions & 0 deletions src/lib/Linter/Linter.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import rules from './rules';
import { default as eslint } from 'eslint';

export const CODEBLOCK_REGEXP = /```(?:js|javascript)([\s\S]+)```/;

export function checkErrors(code) {
return eslint.linter.verify(code, rules);
}

export function fixErrors(code) {
return eslint.linter.verifyAndFix(code, rules);
}
75 changes: 75 additions & 0 deletions src/lib/Linter/rules.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
export default {
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module'
},
rules: {
'getter-return': 'error',
'no-alert': 'error',
'no-array-constructor': 'error',
'no-buffer-constructor': 'error',
'no-caller': 'error',
'no-catch-shadow': 'error',
'no-class-assign': 'error',
'no-compare-neg-zero': 'error',
'no-cond-assign': 'error',
'no-const-assign': 'error',
'no-constant-condition': 'error',
'no-control-regex': 'error',
'no-debugger': 'error',
'no-delete-var': 'error',
'no-div-regex': 'error',
'no-dupe-args': 'error',
'no-dupe-class-members': 'error',
'no-dupe-keys': 'error',
'no-duplicate-case': 'error',
'no-duplicate-imports': 'error',
'no-empty-character-class': 'error',
'no-empty': 'error',
'no-eval': 'error',
'no-ex-assign': 'error',
'no-extra-label': 'error',
'no-extra-semi': 'error',
'no-floating-decimal': 'error',
'no-global-assign': 'error',
'no-implicit-globals': 'error',
'no-inner-declarations': 'error',
'no-invalid-regexp': 'error',
'no-invalid-this': 'error',
'no-iterator': 'error',
'no-lone-blocks': 'error',
'no-lonely-if': 'error',
'no-mixed-requires': 'error',
'no-new-func': 'error',
'no-new-object': 'error',
'no-new-require': 'error',
'no-regex-spaces': 'error',
'no-shadow': 'error',
'no-this-before-super': 'error',
'no-undef-init': 'error',
'no-undefined': 'error',
'no-unexpected-multiline': 'error',
'no-unmodified-loop-condition': 'error',
'no-unneeded-ternary': 'error',
'no-unreachable': 'error',
'no-unsafe-finally': 'error',
'no-unused-vars': 'error',
'no-use-before-define': 'error',
'no-useless-constructor': 'error',
'no-useless-escape': 'error',
'no-useless-rename': 'error',
'no-useless-return': 'error',
'no-var': 'error',
'no-with': 'error',
'prefer-const': 'error',
'prefer-numeric-literals': 'error',
'prefer-rest-params': 'error',
'prefer-spread': 'error',
'require-yield': 'error',
'rest-spread-spacing': 'error',
'symbol-description': 'error',
'use-isnan': 'error',
'valid-typeof': 'error',
yoda: 'error'
}
};
100 changes: 100 additions & 0 deletions src/monitors/linter.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { Monitor as KlasaMonitor, RichDisplay, util } from 'klasa';
import { default as Discord } from 'discord.js';
import {
CODEBLOCK_REGEXP,
checkErrors
} from '../lib/Linter/Linter';

const { MessageEmbed, Permissions: { FLAGS } } = Discord;

export default class Monitor extends KlasaMonitor {

constructor(...args) {
super(...args, { ignoreOthers: false, ignoreEdits: false });

this.handlers = new Map();
}

async run(message) {
if (!message.guild
|| !message.channel.permissionsFor(message.guild.me).has(FLAGS.MANAGE_MESSAGES)
|| !message.guild.configs.supportChannels.includes(message.channel.id)
|| !CODEBLOCK_REGEXP.test(message.content)) return;

const oldHandler = this.handlers.get(message.author.id);
if (oldHandler)
await oldHandler.handler.stop();

const code = CODEBLOCK_REGEXP.exec(message.content)[1].trim();
const errors = checkErrors(code);
if (!errors.length) {
if (message.reactions.has('451517251464593411')) await message.reactions.removeAll();
await message.react('greenTick:451517251317923851');
return;
}

if (message.reactions.has('451517251317923851')) await message.reactions.removeAll();

if (!oldHandler || oldHandler.message !== message) {
await message.react('redCross:451517251464593411');
await message.react('πŸ”');
const reactions = await message.awaitReactions((reaction, user) => user.id === message.author.id && reaction.emoji.name === 'πŸ”', { time: 15000, max: 1 });
if (message.deleted) return;
if (!reactions.size) {
const reaction = message.reactions.get('πŸ”');
if (reaction && reaction.users.has(this.client.user.id)) await reaction.users.remove(this.client.user).catch(() => null);
return;
} else {
const reaction = message.reactions.get('πŸ”');
if (reaction && reaction.users.has(message.author.id)) await reaction.users.remove(message.author).catch(() => null);
}
}

const richDisplay = new RichDisplay(new MessageEmbed()
.setColor(0xFF7327)
.setAuthor(this.client.user.username, this.client.user.avatarURL({ size: 64 }))
.setTitle('ESLint Errors'));
for (const error of errors) {
richDisplay.addPage(template => template.setDescription([
`[\`${error.ruleId || 'Parsing Error'}\`] (Severity ${error.severity}) at ${
this._displayRanges(error.line, error.endLine)}:${
this._displayRanges(error.column, error.endColumn)
}\n\`\`${error.message}\`\`${this._displayText(code, error.line, error.endLine, error.column, error.endColumn)}`
].join('\n')));
}
const handler = await richDisplay.run(
await message.channel.send('<:canvasconstructor:451438332375728128> | Please wait...'),
{ filter: (_, user) => user.id === message.author.id });

this.handlers.set(message.author.id, { handler, message });
handler.once('end', () => {
this.handlers.delete(message.author.id);
if (!handler.message.deleted) handler.message.delete().catch(() => null);
if (!message.deleted) {
const reaction = message.reactions.get('πŸ”');
if (reaction && reaction.users.has(this.client.user.id)) reaction.users.remove(this.client.user).catch(() => null);
}
});
}

_displayRanges(start, end) {
if (typeof end !== 'number') return start;
if (start === end) return start;
return `${start}-${end}`;
}

_displayText(code, line, endLine = line, column, endColumn = column) {
const singleLine = typeof endLine !== 'number' || line === endLine;
if (singleLine) {
const extractedLine = code.split('\n')[line - 1];
if (extractedLine.length) return `\n${util.codeBlock('js', `${extractedLine}\n${' '.repeat(column - 1)}${'^'.repeat(endColumn - column)}`)}`;
}
return '';
}

async init() {
if (!this.client.gateways.guilds.schema.has('supportChannels'))
await this.client.gateways.guilds.schema.add('supportChannels', { array: true, type: 'textchannel' });
}

}

0 comments on commit 1318920

Please sign in to comment.