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") .setTitle("Help -> System Reloading")
.setDescription("Reloads the system extensions by refreshing all command and event files into client without terminating the node process.") .setDescription("Reloads the system extensions by refreshing all command and event files into client without terminating the node process.")
.addFields( .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."}] {name: "Notice", value: "This command is only available to developers."}]
), ),
category: 'Developer', 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