dbmmods
Version:
A free open source modification collection for Discord Bot Maker.
367 lines (291 loc) • 13 kB
JavaScript
// Created by General Wrex
// My Patreons have made creating this script possible @ https://www.patreon.com/generalwrex
// At the time of editing this script, they are:
// - MitchDaGamer
//
// Thanks so much guys, you allow me to continue to do what i love!
//---------------------------------------------------------------------
module.exports = {
//---------------------------------------------------------------------
// DBM Mods Manager Variables
//
// These are variables that DBM Mods Manager uses to show information
// about the mods for people to see in the list.
//---------------------------------------------------------------------
// Who made the mod (If not set, defaults to "DBM Mods")
author: "General Wrex",
// The version of the mod (Defaults to 1.0.0)
version: "1.0.0",
// A short description to show on the mod line for this mod (Must be on a single line)
short_description: "Parses HTML to store variables",
// If it depends on any other mods by name, ex: WrexMODS if the mod uses something from WrexMods
// {name:'WrexMods',path:'aaa_wrexmods_dependencies_MOD.js'}
depends_on_mods: [
{name:'WrexMODS',path:'aaa_wrexmods_dependencies_MOD.js'}
],
//---------------------------------------------------------------------
//---------------------------------------------------------------------
// Action Name
//
// This is the name of the action displayed in the editor.
//---------------------------------------------------------------------
name: "Parse From Stored Webpage",
//---------------------------------------------------------------------
// Action Section
//
// This is the section the action will fall into.
//---------------------------------------------------------------------
section: "HTML/XML Things",
//---------------------------------------------------------------------
// Action Subtitle
//
// This function generates the subtitle displayed next to the name.
//---------------------------------------------------------------------
subtitle: function(data) {
return ` Var: ${data.varName} Path: ${data.xpath}`;
},
//---------------------------------------------------------------------
// Action Storage Function
//
// Stores the relevant variable info for the editor.
//---------------------------------------------------------------------
variableStorage: function(data, varType) {
const type = parseInt(data.storage);
if(type !== varType) return;
return ([data.varName, 'String']);
},
//---------------------------------------------------------------------
// Action Fields
//
// These are the fields for the action. These fields are customized
// by creating elements with corresponding IDs in the HTML. These
// are also the names of the fields stored in the action's JSON data.
//---------------------------------------------------------------------
fields: ["debugMode", "xpath", "source", "sourceVarName", "storage", "varName"],
//---------------------------------------------------------------------
// Command HTML
//
// This function returns a string containing the HTML used for
// editing actions.
//
// The "isEvent" parameter will be true if this action is being used
// for an event. Due to their nature, events lack certain information,
// so edit the HTML to reflect this.
//
// The "data" parameter stores constants for select elements to use.
// Each is an array: index 0 for commands, index 1 for events.
// The names are: sendTargets, members, roles, channels,
// messages, servers, variables
//---------------------------------------------------------------------
html: function(isEvent, data) {
return `
<div id ="wrexdiv" style="width: 550px; height: 350px; overflow-y: scroll;">
<div>
<p>
<u>Mod Info:</u><br>
Created by General Wrex!<br>
This returns an array of values, be sure to read your Bot Log/Terminal<br>
while constructing command with <b>Debug Mode</b> Enabled.
<p>
<u>Instructions:</u><br>
1. Input a Path into the XPath textarea<br>
2. Test Online: <span class="wrexlink" data-url="https://codebeautify.org/Xpath-Tester">X-Path Tester</span><br>
3. How to get <span class="wrexlink" data-url="https://stackoverflow.com/a/46599584/1422928">XPath from Chrome.</span><br>
</p>
</div>
<div style="float: left; width: 35%;">
Source HTML:<br>
<select id="source" class="round" onchange="glob.variableChange(this, 'sourceVarNameContainer')">
${data.variables[1]}
</select>
</div>
<div id="sourceVarNameContainer" style="display: none; float: right; width: 60%;">
Variable Name:<br>
<input id="sourceVarName" class="round" type="text" list="variableList">
</div><br><br><br>
<div>
XPath: (Supports multiple, split with the <b>|</b> symbol) <br>
<textarea id="xpath" class="round" style="width: 99%; resize: none;" type="textarea" rows="2" cols="20"></textarea><br>
</div>
<div hidden="true">
<button class="tiny compact ui labeled icon button" onclick="glob.checkPath(this)"><i class="plus icon"></i>Check XPath</button><br>
Valid: <text id="valid" style="color: red">Input A Path</text>
</div><br>
<div style="float: left; width: 35%;">
Store In:<br>
<select id="storage" class="round" onchange="glob.variableChange(this, 'varNameContainer')">
${data.variables[0]}
</select>
</div>
<div id="varNameContainer" style="display: none; float: right; width: 60%;">
Storage Variable Name:<br>
<input id="varName" class="round" type="text">
</div><br>
<div style="float: left; width: 30%;">
<br>Debug Mode: (Enable to see verbose printing in the bot console)<br>
<select id="debugMode" class="round">
<option value="1" selected>Enabled</option>
<option value="0" >Disabled</option>
</select>
</div>
</div>
<style>
span.wrexlink {
color: #99b3ff;
text-decoration:underline;
cursor:pointer;
}
span.wrexlink:hover {
color:#4676b9;
}
</style>
`
},
//---------------------------------------------------------------------
// Action Editor Init Code
//
// When the HTML is first applied to the action editor, this code
// is also run. This helps add modifications or setup reactionary
// functions for the DOM elements.
//---------------------------------------------------------------------
init: function() {
const {glob, document} = this;
try {
var WrexMODS = require(require('path').join(__dirname,'aaa_wrexmods_dependencies_MOD.js')).getWrexMods();
var wrexlinks = document.getElementsByClassName("wrexlink")
for(var x = 0; x < wrexlinks.length; x++) {
var wrexlink = wrexlinks[x];
var url = wrexlink.getAttribute('data-url');
if(url){
wrexlink.setAttribute("title", url);
wrexlink.addEventListener("click", function(e){
e.stopImmediatePropagation();
console.log("Launching URL: [" + url + "] in your default browser.")
require('child_process').execSync('start ' + url);
});
}
}
} catch (error) {
// write any init errors to errors.txt in dbm's main directory
require("fs").appendFile("errors.txt", error.stack ? error.stack : error + "\r\n");
}
glob.variableChange(document.getElementById('storage'), 'varNameContainer');
glob.variableChange(document.getElementById('source'), 'sourceVarNameContainer')
},
//---------------------------------------------------------------------
// Action Bot Function
//
// This is the function for the action within the Bot's Action class.
// Keep in mind event calls won't have access to the "msg" parameter,
// so be sure to provide checks for variable existance.
//---------------------------------------------------------------------
action: function(cache) {
try {
var WrexMODS = this.getWrexMods();
const data = cache.actions[cache.index];
const sourceVarName = this.evalMessage(data.sourceVarName, cache);
const source = parseInt(data.source);
const varName = this.evalMessage(data.varName, cache);
const storage = parseInt(data.storage);
const DEBUG = parseInt(data.debugMode);
const myXPath = this.evalMessage(data.xpath, cache);
let html = this.getVariable(source, sourceVarName, cache);
var xpath = WrexMODS.require('xpath')
, dom = WrexMODS.require('xmldom').DOMParser
, ent = WrexMODS.require('ent')
let errors = [];
if(myXPath){
// check for errors
let errored = false;
try {
xpath.evaluate(myXPath, null, null, null);
} catch (error) {
errored = error;
if(!error.toString().includes('nodeType')) console.error(`Invalid XPath: [${myXPath}] (${(error ? error : "")})`);
}
if(html){
let mylocator = {};
let parseLog = {errorLevel: 0};
let doc = new dom({
locator: mylocator,
errorHandler: {
warning: (msg) => {manageXmlParseError(msg,1,parseLog)},
error: (msg) => {manageXmlParseError(msg,2,parseLog); ( DEBUG ? console.log("XMLDOMError: " + msg) : "")},
fatalError: (msg) => {manageXmlParseError(msg,3,parseLog); ( DEBUG ? console.log("FATAL XMLDOMError: " + msg) : "")},
},
}).parseFromString(ent.decode(html));
function manageXmlParseError(msg,errorLevel,errorLog){
if( (errorLog.errorLevel == null) || (errorLog.errorLevel < errorLevel)){
errorLog.errorLevel = errorLevel;
}
if(errorLog[errorLevel.toString()] == null){
errorLog[errorLevel.toString()] = [];
}
errorLog[errorLevel.toString()].push(msg);
}
let nodes = [];
try {
nodes = xpath.select(myXPath, doc);
if(nodes && nodes.length > 0){
var out = [];
nodes.forEach(node => {
var name = node.name || "Text Value";
var value = node.value ? node.value : node.toString();
if(DEBUG) {
console.log("====================================");
console.log("Source String: " + node.toString());
console.log("====================================");
//console.log("Parent Node Name: " + .name);
console.log("Name: " + name);
console.log("Line Number: " + node.lineNumber);
console.log("Column Number: " + node.columnNumber);
console.log("Parsed Value: " + value.trim());
console.log("====================================\n");
}
out.push(value.trim());
})
if(out.length > 1 && DEBUG){
console.log('Stored value(s);\r\n');
for (i = 0; i < out.length; i++) {
console.log('[' + i + '] = ' + out[i]);
}
console.log('\r\nAppend the key that you want to store that value to the variable.');
const storageType = ['', 'tempVars', 'serverVars', 'globalVars'];
var output = storageType[storage]
console.log('Example ${'+output+'("'+ varName +'")} to ${'+output+'("'+ varName +'")[key]}');
console.log(''+ varName +'[key] if not using it as a template\r\n');
}
this.storeValue(out, storage, varName, cache);
if(DEBUG) console.log(`Stored value(s) [${out}] to [${varName}] `)
this.callNextAction(cache);
}else{
console.error(`Could not store a value from path ${myXPath}, Check that the path is valid!\n`);
if(DEBUG) console.info("parsestatus ==> " + parseLog.errorLevel + "\nlocator:" + mylocator.columnNumber + "/" + mylocator.lineNumber );
this.storeValue(errored ? errored : undefined, storage, varName, cache);
this.callNextAction(cache);
}
} catch (error) {
this.storeValue(errored ? errored : undefined, storage, varName, cache);
this.callNextAction(cache);
}
}else{
console.error(`HTML data Is Not Valid!`);
}
}else{
console.error(`Path [${myXPath}] Is Not Valid`);
}
} catch (error) {
console.error("Webpage Things: Error: " + error.stack ? error.stack : error);
}
},
//---------------------------------------------------------------------
// Action Bot Mod
//
// Upon initialization of the bot, this code is run. Using the bot's
// DBM namespace, one can add/modify existing functions if necessary.
// In order to reduce conflictions between mods, be sure to alias
// functions you wish to overwrite.
//---------------------------------------------------------------------
mod: function(DBM) {
}
}; // End of module