User:Moonythedwarf/libavtools.js

"use strict"; // libavtools /REQUIRES/ a modern browser. IE won't cut it. // It may be possible to remove references to caching code in the future, but the cache provides a massive load-time save.

// Replace all for .. in .. with // for (let [key, value] of Object.entries(...))

if (window.avtools === undefined) {

let avt = {}; window.avtools = avt;

avt.Edit = class { constructor(editor, target_page, net_change, revision_id, timestamp, prev_revision_id, diff) { this.editor = editor; /* String */ this.target_page = target_page; /* String */ this.net_change = net_change; /* Integer */ this.revision_id = revision_id; /* Integer */ this.timestamp = timestamp; this.prev_revision_id = prev_revision_id; /* Integer */ this.diff = diff /* ?????? TODO: figure out diff format to use. */	} };

avt.programmatic_filters = {};

avt.programmatic_filters.is_mostly_caps = function (_, target) { const len = target.match(/[A-Z]/gu); return { "is_match": ((len ? len.length : 0) > (target.length/4)), "progfilt_results": {} }; // if over half of target is caps, it's a match. }

avt.MatchFilter = class { constructor(name, config) { if (config.regex && config.programmatic_check) { throw new Error("Cannot match " + name + "using both regex and programmatic check!"); }		if (config.regex) { this.regex = new RegExp(config.regex, config.flags ? config.flags : "gui"); } else if (config.programmatic_check) { this.check_func = avt.programmatic_filters[config.programmatic_check]; if (!this.check_func) { throw new Error(name + "specifies an invaild programmatic check!"); }		} else { /* ignore, likely a placeholder. */		}		this.show_matches = config.show_matches; this.severity = config.severity; }	match(target) { let match = {}; if (this.regex) { let nreg = new RegExp(this.regex); // duplicate.. let m;			match.regex_results = []; while ((m = nreg.exec(target)) !== null) { match.regex_results.push({res: m, index: m.index, lastIndex: nreg.lastIndex}); }			if (match.regex_results[0] !== undefined) { match.is_match = true; } else { match.is_match = false; }			if (this.show_matches === false) { match.regex_results = undefined; }		} else { match = this.check_func(this.flags, target); }		return match; } }

avt.avtools_central_config = "User:Moonythedwarf/libavtools/global_config.json"; avt.avtools_user_config = "Special:MyPage/libavtools/config.json";

avt.load_json_file = async function (wikilink) { let req = new Request(`${mw.util.wikiScript("index")}?title=${wikilink}&action=raw&ctype=text/json`); let res = await avt.__cache.match(req); // JS error handling much? if (res === undefined ) { let resp = await fetch(req); await avt.__cache.put(req, resp); return (await avt.__cache.match(req)).text; }	return res.text }

avt.load_multiple_json_files = async function (links) { let loaded_files = []; for (const i in links) { loaded_files.push(avt.load_json_file(links[i])); }	return (Promise.all(loaded_files)).then(a => a.filter(val => val !== "" ? true : false)); }

avt.load_avtools_config = async function { if (avt.config !== undefined) { return; }	const global_config = JSON.parse(await avt.load_json_file(avt.avtools_central_config)); const lc_data = await avt.load_json_file(avt.avtools_user_config); const local_config = JSON.parse(lc_data? lc_data : "{}"); let final_config = {}; //FIX: Crude. Will need proper precedence rules later. for (const i in global_config) { if (local_config[i] !== undefined) { final_config[i] = local_config[i]; } else { final_config[i] = global_config[i]; }	}	avt.config = final_config; }

avt.load_filters = function (list) { let filters = {}; for (let fname in list) { for (let i in list[fname]) { filters[i] = new avt.MatchFilter(fname, list[fname][i]); }	}	return filters; }

avt.match_against_filters = function (filters, target) { let matches = {}; let severity = 0; for (const filtname in filters) { const filtmatches = filters[filtname].match(target); if (filtmatches.is_match) { matches[filtname] = filtmatches; severity += filters[filtname].severity; }	}	return { matches, severity }; }

avt.load_username_filters = async function { let loaded_files = (await avt.load_multiple_json_files(avt.config.username_filters)).map(i => JSON.parse(i)); avt.username_filters = avt.load_filters(loaded_files); }

avt.load_content_filters = async function { let loaded_files = (await avt.load_multiple_json_files(avt.config.content_filters)).map(i => JSON.parse(i)); avt.content_filters = avt.load_filters(loaded_files); }

avt.load_summary_filters = async function { let loaded_files = (await avt.load_multiple_json_files(avt.config.summary_filters)).map(i => JSON.parse(i)); avt.summary_filters = avt.load_filters(loaded_files); }

avt.load_all_filters = async function (config) { return Promise.all([		avt.load_summary_filters,		avt.load_content_filters,		avt.load_username_filters,	]); }

avt.wipe_cache = async function { for (let v of await avt.__cache.keys) { await avt.__cache.delete(v); //snip! } }

avt.load_libavtools_core = async function { avt.__cache = await caches.open("avtcache"); await avt.load_avtools_config; };

avt.load_libavtools_filters = async function { if (avt.config === undefined) { throw new Error("Attempted to load libavtools filters before core!"); }	await avt.load_all_filters; }

$(async => {	try {		await avt.load_libavtools_core;	} catch (e) {		mw.notify(e)	} })

}