oh lordy lord

master
Kit Kasune 2 weeks ago
parent db54eab0ae
commit fb7c7249d0
  1. 3
      .gitignore
  2. 6
      .idea/jsLibraryMappings.xml
  3. 2
      bot/runtime/commands/dev/reload.js
  4. 0
      bot/runtime/commands/misc/commands.js.test
  5. 12
      bot/runtime/commands/misc/ping.js
  6. 38
      bot/runtime/events/messageCreate.js
  7. 10
      bot/runtime/events/ready.js
  8. 53
      bot/startup/collect/commands.js
  9. 46
      bot/startup/collect/events.js
  10. 8
      bot/startup/run/collect.js
  11. 20
      bot/startup/run/getflags.js
  12. 12
      bot/startup/run/hello.js
  13. 21
      bot/startup/run/login.js
  14. 24
      bot/startup/run/setstatus.js
  15. 24
      db/connect.js
  16. 11
      json/randresp.json
  17. 3165
      package-lock.json
  18. 11
      util/log/errorhandler.js
  19. 14
      util/log/getlevel.js
  20. 5
      util/log/levels.json
  21. 37
      util/log/log.js
  22. 18
      util/log/ora.js
  23. 20
      util/log/types.js
  24. 13
      util/misc/nodehandlers.js
  25. 22
      util/misc/setutils.js
  26. 7
      util/misc/wait.js
  27. 25
      util/ts/src/tag.ts
  28. 63
      util/ts/src/tagfilter.ts
  29. 9
      util/ts/tag.d.ts
  30. 21
      util/ts/tag.js
  31. 10
      util/ts/tagfilter.d.ts
  32. 77
      util/ts/tagfilter.js
  33. 11
      util/ts/tsconfig.json

3
.gitignore vendored

@ -1 +1,2 @@
json/auth.json
json/auth.json
node_modules/

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptLibraryMappings">
<includedPredefinedLibrary name="Node.js Core" />
</component>
</project>

@ -12,7 +12,7 @@ module.exports = {
.setTitle("Help -> System Reloading")
.setDescription("Reloads the system extensions by refreshing all command and event files into client without terminating the node process.")
.addFields(
[{name: "Syntax", value: "`reload [log]`. Adding 'log' will log to the console as though the bot were in startup."},
[{name: "Syntax", value: "`reload`. Optionally, specify the name or alias of a command you'd like reloaded."},
{name: "Notice", value: "This command is only available to developers."}]
),
category: 'Developer',

@ -0,0 +1,12 @@
module.exports = {
name: "ping",
aliases: ["p"],
syntax: '`ping`',
category: 'Misc',
info: "Provides latency information for debugging purposes; Ensures the bot is working.",
help: null,
guildOnly: false,
async run(client, message, args, cmd) {
message.reply("Pong! This is Senko you're speaking with \\*tips hat*");
} //TODO provide actual latency info
};

@ -0,0 +1,38 @@
const chalk = require('chalk');
const {Embed, EmbedBuilder} = require('discord.js');
module.exports = async (client, message) => {
if (!message.content || !message.content.length) {return;} //privileged intent fallback //TODO edit for privileged intent
let prefix = client.basePrefix; //TODO prefixes
if ([`<@${client.user.id}>`, `<@!${client.user.id}>`].includes(message.content.trim())) { //Ping hello
message.channel.send({embeds: [client.embeds.base()
.setTitle(client.utils.gr(client.config.randResp.pinghello))
.setDescription(`You've reached ${client.config.options.dev ? "a developer (beta) instance of" : ''} Senko! My prefix here is \`${prefix}\`, and you can use the \`help\` command to get started.`)
]});
} //TODO random senko img on ping
let cmd = {};
cmd.msg = message.content.toLowerCase().trim(); //i believe in shitty naming conventions :D
let prefixUsed = cmd.msg.startsWith(client.basePrefix) ? client.basePrefix //standard default/dev client prefix
: cmd.msg.startsWith(`<@${client.user.id}>`) ? `<@${client.user.id}>` //mention prefix
: cmd.msg.startsWith(`<@!${client.user.id}>`) ? `<@!${client.user.id}>` //nicknamed mention prefix
: null //no prefix used
cmd.prefix = prefixUsed;
if (!cmd.prefix) {return;} // ----------> PREFIXED GATEWAY <----------
cmd.msg = cmd.msg.slice(prefixUsed.length);
let args = cmd.msg.split(/\s+/gm); //"args" is split by ALL WHITESPACE AND IS LOWERCASED
cmd.name = args.shift(); //the command without the prefix
cmd.msg = args.join(" ");
cmd.args = message.content.trim().slice(prefixUsed.length).trim().split(/ +/gm).slice(1); //args but preserves text state and newlines
let cmdToRun = client.commands.get(cmd.name) || client.commands.get(client.aliases.get(cmd.name));
if (!cmdToRun) {return;}
try {cmdToRun.run(client, message, args, cmd).catch(e => client.error(`There was an error in the ${cmdToRun.name} command.`, 0, 1, e, '\n'));}
catch (e) {client.error(`There was an error in the ${cmdToRun.name} command.`, 0, 1, e, '\n');}
};

@ -0,0 +1,10 @@
module.exports = async client => {
client.basePrefix = client.config.options.dev ? client.config.options.prefix || client.config.bot.devPrefix : client.config.bot.prefix;
//await require('../../../api/index')(client);
require('../../startup/run/hello')(client); // startup info
require('../../startup/run/setstatus')(client);
client.log(client.utils.gr(client.config.randResp.cliloaded), {color: "#78d9f8", source: client.config.bot.consoleName}, true, true); //senko doing some more complaining
};

@ -0,0 +1,53 @@
const fs = require('fs');
const chalk = require('chalk');
const {Collection} = require('discord.js');
const commandsDirName = './bot/runtime/commands';
module.exports = async client => {
client.aliases = new Collection(); //THIS SHIT WAS ALREADY FUCKING EMPTY
let dirErrors = []; let fileErrors = []; //collect error objects to output them all at the end
let readDirs = []; //list of dirs to print at the end
let conflictingAliases = {};
client.log('Loading commands...', {source: 'boot', color: 'blue'}, 0, 1);
const readDir = dir => { //when you're trying to comment your code but realize you have good variable naming for once and don't need to :D
let dirRead;
try {dirRead = fs.readdirSync(dir);}
catch (e) {
client.error(`Failed to read directory ${chalk.white(dir)}`);
return dirErrors.push([`Unable to read directory ${chalk.white(dir)}. Error:`, e]);
}
let files = dirRead.filter(item => item.endsWith('.js'));
let folders = dirRead.filter(item => fs.lstatSync(`${dir}/${item}`).isDirectory());
files.forEach(file => {
try {
const command = require(`../../../${dir.slice(2)}/${file}`);
client.commands.set(command.name, command);
if (command.aliases) {command.aliases.forEach(alias => {
if (client.aliases.has(alias)) {
if (conflictingAliases[alias]) {conflictingAliases[alias].push(command.name);} //object of alias conflictions keyed by alias -> array[command names]
else {conflictingAliases[alias] = [command.name];}
}
client.aliases.set(alias, command.name);
});}
client.log(`Loaded ${chalk.white(command.name)} with ${chalk.white(`${command.aliases ? command.aliases.length : 0}`)} alias${command.aliases && command.aliases.length === 1 ? '' : 'es'}.`, {color: 'blueBright', source: 'boot', sourceColor: 'blue'});
}
catch (e) {
client.error(`Failed to read file ${chalk.white(file)}`);
return fileErrors.push([`Unable to read file ${chalk.white(file)}. Error:`, e]);
}
});
readDirs.push(`${dir.split('/').slice(4).join('/')}/`); // "commands/..."
return folders.forEach(folder => readDir(`${dir}/${folder}`)); //recurse infinitely
};
readDir(commandsDirName);
console.log("");
dirErrors.forEach(error => client.error(error[0], 0, 0, 1, error[1]));
fileErrors.forEach(error => client.error(error[0], 0, 0, 1, error[1]));
readDirs.forEach(dir => client.log(`Read from directory ${chalk.green(dir)}`, {source: 'proc'}));
console.log('');
Object.keys(conflictingAliases).forEach(alias => client.warn(`Alias ${chalk.white(alias)} appears on ${client.utils.as(conflictingAliases[alias].length, 'command')} ${chalk.white(conflictingAliases[alias].join(chalk.yellow(', ')))}`));
if (Object.keys(conflictingAliases).length) {console.log('')};
client.log(`Loaded ${chalk.white(client.commands.size)} command${client.utils.s(client.commands.size)}!`, {color: 'blue', source: 'boot'}, 0, 1);
};

@ -0,0 +1,46 @@
const fs = require('fs');
const chalk = require('chalk');
const {Collection} = require('discord.js');
const eventsDirName = './bot/runtime/events';
module.exports = async client => {
//client.aliases = new Collection(); //THIS SHIT EMPTY
let dirErrors = []; let fileErrors = []; //collect error objects to output them all at the end
let readDirs = []; //list of dirs to print at the end
let totalEvents = 0;
client.log('Loading events...', {source: 'boot', color: 'blue'}, 0, 1);
const readDir = dir => {
let dirRead;
try {dirRead = fs.readdirSync(dir);}
catch (e) {
client.error(`Failed to read directory ${chalk.white(dir)}`);
return dirErrors.push([`Unable to read directory ${chalk.white(dir)}. Error:`, e]);
}
let files = dirRead.filter(item => item.endsWith('.js'));
let folders = dirRead.filter(item => fs.lstatSync(`${dir}/${item}`).isDirectory());
files.forEach(file => {
try {
const event = require(`../../../${dir.slice(2)}/${file}`);
const eventName = file.split('.')[0];
client.removeAllListeners(eventName);
client.on(eventName, event.bind(null, client));
client.log(`Loaded event ${chalk.white(eventName)}`, {color: 'blueBright', source: 'boot', sourceColor: 'blue'});
totalEvents++;
}
catch (e) {
client.error(`Failed to read file ${chalk.white(file)}`);
return fileErrors.push([`Unable to read file ${chalk.white(file)}. Error:`, e]);
}
});
readDirs.push(`${dir.split('/').slice(4).join('/')}/`); // "events/..."
return folders.forEach(folder => readDir(`${dir}/${folder}`)); //recurse infinitely
};
readDir(eventsDirName);
console.log("");
dirErrors.forEach(error => client.error(error[0], 0, 0, 1, error[1]));
fileErrors.forEach(error => client.error(error[0], 0, 0, 1, error[1]));
readDirs.forEach(dir => client.log(`Read from directory ${chalk.green(dir)}`, {source: 'proc'}));
client.log(`Loaded ${chalk.white(totalEvents)} event${client.utils.s(totalEvents)}!`, {color: 'blue', source: 'boot'}, 1, 1);
};

@ -0,0 +1,8 @@
const {Collection} = require("discord.js");
module.exports = async client => {
for (const x of ['commands', 'events']) {
client[x] = new Collection();
await require(`../collect/${x}`)(client);
}
};

@ -0,0 +1,20 @@
const chalk = require('chalk');
const {Tag, TagFilter} = require('../../../util/ts/tagfilter');
module.exports = client => {
const options = new TagFilter([
new Tag(['dev', 'd', 'developer', 'test'], 'dev', 'toggle'),
new Tag(['prefix', 'devprefix', 'p'], 'prefix', 'append')
]).test(process.argv.slice(2).join(" "));
client.config.options = {};
if (Object.keys(options).length) { //log and set options
client.log(`${chalk.gray.bold("Arguments detected.")}`, {source: 'args'}, 0, 1);
Object.keys(options).forEach(arg => {
client.config.options[arg] = options[arg];
client.log(`${chalk.gray.bold(arg)}${chalk.gray(':')} ${chalk.blue(options[arg])}`, {source: 'args'});
});
console.log('');
}
};

@ -0,0 +1,12 @@
const moment = require("moment");
const chalk = require('chalk');
const os = require('os');
const gs = require('gradient-string');
module.exports = client => {
client.log(`Logged in as ${gs.instagram(client.user.username)}. ${chalk.greenBright(`[${chalk.grey(client.user.id)}]`)}`);
client.log(`Time: ${chalk.blueBright(moment().format('MMMM d, YYYY - HH:MM:SS'))}`);
client.log(`This ${chalk.blue('heap')} has ${chalk.blueBright((process.memoryUsage().heapTotal / (1024 ** 2)).toFixed(2))}MB allocated; The ${chalk.blue('machine')} has ${chalk.blueBright((os.totalmem() / (1024 ** 3)).toFixed(2))}GB (${chalk.blueBright((os.freemem() / (1024 ** 3)).toFixed(2))}GB free)`);
client.log(`Running on ${chalk.blueBright(client.guilds.cache.size)} ${chalk.blue("servers")} and interacting with about ${chalk.blueBright(client.users.cache.size)} ${chalk.blue("users")}.`);
client.log(`Listening for prefix ${chalk.greenBright(client.basePrefix)} || ${chalk.greenBright(`${client.basePrefix}help`)} to get started!`);
};

@ -0,0 +1,21 @@
const chalk = require('chalk');
const ora = require('../../../util/log/ora');
module.exports = async (client) => {
const t = Date.now();
client.misc = {};
client.misc.dscconnected = true;
await ora(`Waking up Natsuki... ${chalk.blueBright.bold.underline("(Connecting to Discord...)")}`,
client.login(client.auth.token)
).catch((e) => {
client.error("Failed to connect to Discord!! Error below.", 0, 0, true, e);
client.misc.dscconnected = false;
});
if (!client.misc.dscconnected) {
client.warn("Discord not connected, considering runtime to be unusable and exiting.", 0, true, true);
throw new Error();
}
return client.success(`Connected to Discord in ${chalk.white(`${Date.now() - t}ms`)}.`, 0, 0, 1);
};

@ -0,0 +1,24 @@
module.exports = client => {
const prefix = client.basePrefix;
const statuses = {
"PLAYING": [
`with fluffy tails!`, `with some new recipes`,
`cleaning up PRs' rooms`, `cleaning up TLs' rooms`,
`with Kitsuu's sanity (I won't stop crashing)`
],
"WATCHING": [
`over the lovely members of LHT!`, `my tail get fluffed`,
`tonight's dinner cook`, `LHT staff do great work!`
]
};
try {if (client.misc.statusTimeout) {clearTimeout(client.misc.statusTimeout)};} catch {}
const setStatus = () => {
let type = Object.keys(statuses)[Math.floor(Math.random() * Object.keys(statuses).length)];
if (type === "PLAYING") {client.user.setActivity(statuses[type][Math.floor(Math.random() * statuses[type].length)] + " | " + prefix + "help");}
else {client.user.setActivity(statuses[type][Math.floor(Math.random() * statuses[type].length)] + " | " + prefix + "help", {type: type});}
};
setStatus();
client.misc.statusTimeout = setTimeout(setStatus, 14400000);
};

@ -0,0 +1,24 @@
const chalk = require('chalk');
const mongoose = require('mongoose');
const ora = require('../util/log/ora');
module.exports = async client => {
if (!client.misc) {client.misc = {};}
const auth = client.auth;
const t = Date.now();
client.misc.dbconnected = true;
await ora(chalk.blueBright.bold.underline("Connecting to MongoDB..."),
mongoose.connect(`mongodb+srv://${auth.database.user}:${auth.database.password}@${auth.database.cluster}.uqyvv.mongodb.net/test`, {
dbName: auth.database.name //TODO research mongo connect options
})
).catch((e) => {
client.error("Failed to connect to mongoose!! Error below.", 0, 0, true, e);
client.misc.dbconnected = false;
});
if (!client.misc.dbconnected) {
client.warn("Database not connected, considering runtime to be unusable and exiting.", 0, true, true);
throw new Error();
}
return client.success(`Connected to Mongo Database in ${chalk.white(`${Date.now() - t}ms`)}.`, 0, 0, 1);
};

@ -0,0 +1,11 @@
{
"clistart": [
"Let me go wake Senko real quick..."
],
"cliloaded": [
"*rubs tired eyes* Senko reporting for duty..."
],
"pinghello": [
"You rang?", " That's me, teehee", "\"At your service, milord,\" she says in a posh accent"
]
}

3165
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -0,0 +1,11 @@
const chalk = require('chalk');
module.exports = (client, e, p) => {
console.log(`#######################################\n\n[${chalk.grey(client.config.bot.consoleName)}] >> ${chalk.hex('#78d9f8')("Well this is awkward.")}\n`);
console.log(`${chalk.bold.redBright.underline(`There was an error that killed ${client.utils.ps(client.config.bot.name)} process.`)}\n${chalk.redBright("See available stack trace and error information below.")}\n`);
if (p) {
client.log("This exception originates from an unhandled, uncaught promise rejection. Ya doofus.", 0, 0, 1);
}
console.error(e);
console.log(`\n#######################################`);
};

@ -0,0 +1,14 @@
const config = require('../../json/config.json');
const levels = require('./levels.json');
const validStrings = Object.keys(levels);
const getLevel = (level) => {
if (typeof level === 'number') {
if (level <= 0) {return 0;}
if (level > 3) {return 3;}
return Math.floor(level);
} else {
const levelM = `${level}`.trim().toUpperCase();
return validStrings.includes(levelM) ? levels[levelM] : typeof config.log.defaultLevel === 'number' ? getLevel(config.log.defaultLevel) : 1;
}
};

@ -0,0 +1,5 @@
{
"TOP": 0,
"STANDARD": 1,
"VERBOSE": 2
}

@ -0,0 +1,37 @@
const chalk = require('chalk');
const getLevel = require('./getlevel');
const types = require('./types');
const config = require('../../json/config.json');
let defaultOptions = {
color: "white",
source: "USER",
sourceColor: "gray",
level: typeof config.log.defaultLevel === 'number' ? config.log.defaultLevel : 1,
suffix: " >> "
};
const tlog = (client) => (message = "Test Log", options = {}, prenl = false, postnl = false, ...multcons) => {
let opt = {};
if (typeof options !== 'object') {options = {};}
opt.color = options.color || defaultOptions.color;
opt.level = ['string', 'number'].includes(typeof options.level) ? options.level : defaultOptions.level;
opt.suffix = typeof options.suffix === 'string' ? options.suffix : defaultOptions.suffix;
opt.source = options.source || defaultOptions.source;
opt.sourceColor = options.sourceColor || defaultOptions.sourceColor;
try {if (client.config.logLevel < opt.level) {return;}}
catch {
client.config.logLevel = getLevel(client.config.logLevel);
if (client.config.logLevel < opt.level) {return;}
}
console.log(`${prenl ? '\n' : ''}${(opt.sourceColor.startsWith('#') ? chalk.hex(opt.sourceColor) : chalk[opt.sourceColor])(`[${opt.source.toUpperCase()}]`)}${opt.suffix}${options.nc || options.noColor ? message : (opt.color.startsWith('#') ? chalk.hex(opt.color) : chalk[opt.color])(message)}${postnl ? '\n' : ''}`, ...multcons);
};
module.exports = (client) => {
return {
log: tlog(client),
...types(tlog(client))
};
};

@ -0,0 +1,18 @@
const ora = require('ora');
module.exports = async (text, promise, callback) => {
return new Promise(async (resolve, reject) => {
let spin = ora(text).start();
return await promise
.catch(e => {
spin.stop();
spin.clear();
return reject(e)
})
.then((...args) => {
spin.stop();
spin.clear();
return callback ? resolve(callback(spin, args)) : resolve(true);
});
});
};

@ -0,0 +1,20 @@
module.exports = (log) => { return {
error: (message, options, prenl, postnl, ...multcons) => log(message, {
color: 'redBright',
source: 'err!',
sourceColor: 'red',
level: 0
}, prenl, postnl, ...multcons),
warn: (message, options, prenl, postnl, ...multcons) => log(message, {
color: 'yellowBright',
source: 'warn',
sourceColor: 'yellow',
level: 1
}, prenl, postnl, ...multcons),
success: (message, options, prenl, postnl, ...multcons) => log(message, {
color: 'greenBright',
source: 'proc' || options && options.source,
sourceColor: 'green',
level: options && typeof options.level !== 'undefined' ? options.level : 0
}, prenl, postnl, ...multcons)
}};

@ -0,0 +1,13 @@
const errorhandler = require("../log/errorhandler");
const chalk = require('chalk');
module.exports = client => {
process.on('unhandledRejection', (e, p) => { //nested promise rejections like to be icky so this should catch them all
errorhandler(client, e, p);
return process.exit(1); //i guess this handler does keep the event loop running but i'll adopt a zero-tolerance policy for unhandled rejections
}); // gotta catch 'em all
process.on('exit', code => {
client.log("Back to sleepies...", {color: "#78d9f8", source: client.config.bot.consoleName}, true);
return console.log(chalk.grey(`Exit code ${chalk.white(code)}`));
});
};

@ -0,0 +1,22 @@
module.exports = client => {
client.utils = {}; //small collection of basic string manipulation utilities so prettier strings are easier
//pluralize most strings based on a number
client.utils.s = num => num === 1 ? '' : 's';
//pluralize but pass in the text to make plural
client.utils.as = (num, text) => `${text}${client.utils.s(num)}`;
// "a" or "an" based on the provided string, caps to begin with capital letter
client.utils.an = (text, caps) => `${caps ? 'A' : 'a'}${['a', 'e', 'i', 'o', 'u'].includes(text.toLowerCase().trim().slice(0, 1)) ? 'n' : ''} ${text}`;
//capitalize a string automatically, "a" if rest of string should be automatically lowercased
client.utils.c = (text, a=true) => `${text.slice(0, 1).toUpperCase()}${a ? text.slice(1).toLowerCase() : text.slice(1)}`;
//split text into words and autocap each one
client.utils.ca = (text, a=true) => text.split(/\s+/gm).map(t => client.utils.c(t, a)).join(" ");
//format a moment-presice-range object
client.utils.sm = (mpr, ago=true) => `${mpr.years ? `${mpr.years} year${client.utils.s(mpr.years)} ` : ''}${mpr.months ? `${mpr.months} month${client.utils.s(mpr.months)} ` : ''}${mpr.days} day${client.utils.s(mpr.days)}${ago ? ' ago' : ''}`;
//add a grammatically correct possessive indicator to the end of a word/string
client.utils.p = (text) => text.endsWith('s') ? "'" : "'s";
//possessivise but pass in the text to possessivize
client.utils.ps = (text) => `${text}${client.utils.p(text)}`;
//random element of array
client.utils.gr = list => list[Math.floor(Math.random() * list.length)];
};

@ -0,0 +1,7 @@
module.exports = (time) => {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(null);
}, time);
});
};

@ -0,0 +1,25 @@
export class Tag {
triggers: string[] = [];
tagName: string;
filterType: TagFilterType;
constructor(triggers: string[], tagName: string, filterType: TagFilterType) {
let trigger: string; for (trigger of triggers) {
this.triggers.push(
trigger.trim().startsWith("-") ? trigger.trim() : `-${trigger.trim()}`
);
}
this.tagName = tagName;
this.filterType = filterType;
};
public addTrigger(trigger: string): Tag {
this.triggers.push(
trigger.trim().startsWith("-") ? trigger.trim() : `-${trigger.trim()}`
);
return this;
};
}
type TagFilterType = "append" | "toggle" | "listAppend";

@ -0,0 +1,63 @@
import {Tag} from "./tag";
export {Tag};
export class TagFilter {
tags: Tag[];
triggers: Map<String, String>;
filterTypes: Map<String, TagFilterType>;
constructor(tags: Tag[]) {
this.tags = tags;
this.triggers = new Map<String, String>();
this.filterTypes = new Map<String, TagFilterType>();
let tag: Tag;
for (tag of this.tags) {
let trigger: string; for (trigger of tag.triggers) {
this.triggers.set(trigger, tag.tagName);
}
if (!this.filterTypes.has(tag.tagName)) {this.filterTypes.set(tag.tagName, tag.filterType);}
}
}
public test(text: string): object {
var filtered: object = {};
var reading: string = null;
var filterType: TagFilterType;
var ticks = {};
let words = text.trim().split(/\s+/g);
let word: string; for (word of words) {
if (word.startsWith('-') && word.length > 1 && this.triggers.has(word.trim())) {
filterType = this.filterTypes.get(this.triggers.get(word.trim()));
reading = !['append', 'listAppend'].includes(filterType) ? null : word.trim();
if (!reading) {filtered[`${this.triggers.get(word.trim())}`] = true;}
else {filtered[`${this.triggers.get(reading)}`] = filterType == 'append' ? '' : Array.isArray(filtered[`${this.triggers.get(reading)}`]) ? filtered[`${this.triggers.get(reading)}`] : [];}
if (filterType == "listAppend") {
if (ticks[`${this.triggers.get(word.trim())}`] && ticks[`${this.triggers.get(word.trim())}`].length) {filtered[`${this.triggers.get(word.trim())}`].push(ticks[`${this.triggers.get(word.trim())}`]);}
ticks[`${this.triggers.get(word.trim())}`] = '';
}
}
else if (reading) {
if (filterType == "listAppend") {ticks[`${this.triggers.get(reading)}`] += ` ${word}`;}
else {filtered[`${this.triggers.get(reading)}`] = `${filtered[`${this.triggers.get(reading)}`]} ${word}`;}
}
}
let tick: string; for (tick of Object.keys(ticks)) {
if (ticks[tick].length) {filtered[tick].push(ticks[tick]);}
}
let key: string; for (key of Object.keys(filtered)) {
if (typeof filtered[key] == 'string') {filtered[key] = filtered[key].trim();}
else if (Array.isArray(filtered[key])) {
let subkey: string; for (subkey of filtered[key]) {
filtered[key][filtered[key].indexOf(subkey)] = subkey.trim();
}
}
}
return filtered;
};
}
type TagFilterType = "append" | "toggle" | "listAppend";

9
util/ts/tag.d.ts vendored

@ -0,0 +1,9 @@
export declare class Tag {
triggers: string[];
tagName: string;
filterType: TagFilterType;
constructor(triggers: string[], tagName: string, filterType: TagFilterType);
addTrigger(trigger: string): Tag;
}
declare type TagFilterType = "append" | "toggle" | "listAppend";
export {};

@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Tag = void 0;
class Tag {
constructor(triggers, tagName, filterType) {
this.triggers = [];
let trigger;
for (trigger of triggers) {
this.triggers.push(trigger.trim().startsWith("-") ? trigger.trim() : `-${trigger.trim()}`);
}
this.tagName = tagName;
this.filterType = filterType;
}
;
addTrigger(trigger) {
this.triggers.push(trigger.trim().startsWith("-") ? trigger.trim() : `-${trigger.trim()}`);
return this;
}
;
}
exports.Tag = Tag;

@ -0,0 +1,10 @@
import { Tag } from "./tag";
export { Tag };
export declare class TagFilter {
tags: Tag[];
triggers: Map<String, String>;
filterTypes: Map<String, TagFilterType>;
constructor(tags: Tag[]);
test(text: string): object;
}
declare type TagFilterType = "append" | "toggle" | "listAppend";

@ -0,0 +1,77 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TagFilter = exports.Tag = void 0;
const tag_1 = require("./tag");
Object.defineProperty(exports, "Tag", { enumerable: true, get: function () { return tag_1.Tag; } });
class TagFilter {
constructor(tags) {
this.tags = tags;
this.triggers = new Map();
this.filterTypes = new Map();
let tag;
for (tag of this.tags) {
let trigger;
for (trigger of tag.triggers) {
this.triggers.set(trigger, tag.tagName);
}
if (!this.filterTypes.has(tag.tagName)) {
this.filterTypes.set(tag.tagName, tag.filterType);
}
}
}
test(text) {
var filtered = {};
var reading = null;
var filterType;
var ticks = {};
let words = text.trim().split(/\s+/g);
let word;
for (word of words) {
if (word.startsWith('-') && word.length > 1 && this.triggers.has(word.trim())) {
filterType = this.filterTypes.get(this.triggers.get(word.trim()));
reading = !['append', 'listAppend'].includes(filterType) ? null : word.trim();
if (!reading) {
filtered[`${this.triggers.get(word.trim())}`] = true;
}
else {
filtered[`${this.triggers.get(reading)}`] = filterType == 'append' ? '' : Array.isArray(filtered[`${this.triggers.get(reading)}`]) ? filtered[`${this.triggers.get(reading)}`] : [];
}
if (filterType == "listAppend") {
if (ticks[`${this.triggers.get(word.trim())}`] && ticks[`${this.triggers.get(word.trim())}`].length) {
filtered[`${this.triggers.get(word.trim())}`].push(ticks[`${this.triggers.get(word.trim())}`]);
}
ticks[`${this.triggers.get(word.trim())}`] = '';
}
}
else if (reading) {
if (filterType == "listAppend") {
ticks[`${this.triggers.get(reading)}`] += ` ${word}`;
}
else {
filtered[`${this.triggers.get(reading)}`] = `${filtered[`${this.triggers.get(reading)}`]} ${word}`;
}
}
}
let tick;
for (tick of Object.keys(ticks)) {
if (ticks[tick].length) {
filtered[tick].push(ticks[tick]);
}
}
let key;
for (key of Object.keys(filtered)) {
if (typeof filtered[key] == 'string') {
filtered[key] = filtered[key].trim();
}
else if (Array.isArray(filtered[key])) {
let subkey;
for (subkey of filtered[key]) {
filtered[key][filtered[key].indexOf(subkey)] = subkey.trim();
}
}
}
return filtered;
}
;
}
exports.TagFilter = TagFilter;

@ -0,0 +1,11 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": ["es2017", "es6", "dom"],
"target": "es2017",
"declaration": true,
"outDir": "./"
},
"include": ["src/**/*"],
"exclude": []
}
Loading…
Cancel
Save