@Ciaran
A remark on that: Make no mistake, I didn’t mean to criticize anyone involved with the event for doing it the way they are doing it, just in case it came across as such.
The suggestion is purely with the intent to ease the workload for the people who are doing all these things manually right now.
This took longer than I hoped, Javascript is not my forté, but it works. Tested in Firefox and Chrome with Violentmonkey v2.12.7
In action video (everything filter, contains some nudity)
If anyone wants to improve this somehow, by all means please go ahead. This is just a base to show how it could work.
Code:
// ==UserScript==
// @name Derpibooru Badge Helper
// @namespace Derpibooru
// @match
https://derpibooru.org/*
// @run-at document-idle
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_deleteValue
// @grant GM_listValues
// @grant GM_xmlhttpRequest
// ==/UserScript==
console.log(“Badge Helper Running”);
// Export and Import data functionality
createExportImport();
// Uploader
var uploader_span = document.querySelector(“span[class=image_uploader]”);
if (uploader_span) {
console.log(uploader_span);
// Check if there’s an account linked
var anchor_element = uploader_span.querySelector(“a”);
if (anchor_element){
// Uploaded with an account, create the STORE THIS ACCOUNT button
var account_name = anchor_element.textContent;
var new_button = createStoreAccountButton(account_name);
// Display it
uploader\_span.appendChild\(new\_button\);
}
}
// Artist tags
var tag_div = document.querySelector(“div[class=tag-list]”);
if (tag_div) {
console.log(tag_div);
// Get all artist tags
var artist_tag_anchors = tag_div.querySelectorAll(“a[href*=’artist-colon’][class=tag__name”);
console.log(artist_tag_anchors);
for (var artist_anchor of artist_tag_anchors){
// Parse the artist tag page and possibly create and display the storage button for this tag
var account\_name = handleArtistTag\(artist\_anchor.href, artist\_anchor.closest\("span"\)\);
}
}
/**
* Reads the given url and extracts the associated user account for this tag - if it exists - and displays a store button for it
* @param tag_url url of an artist tag to parse
* @param parent element to append new buttons to as children
*/
function handleArtistTag(tag_url, parent){
// Load the given url
GM_xmlhttpRequest({
method: “GET”,
url: tag_url,
onload: function(response) {
if (response.status == 200){
// Create document from reply to ease parsing
var response_doc = new DOMParser().parseFromString(response.responseText, “text/html”);
var tag_info_div = response_doc.querySelector(“div[class=tag-info__more]”);
if (tag_info_div){
// Check if there’s a userpage link on this artist tag page
// Get all fitting anchors and all strongs, the anchor right after a strong announcing "Associated users:" is the right one
// This is in case there might be more than one profile link at an artist tag in a description somewhere
var selected\_elements = tag\_info\_div.querySelectorAll\("strong, a\[href\*='/profiles/'\]"\);
for \(var i = 0; i \< selected\_elements.length; i++\){
var cur\_elem = selected\_elements\[i\];
if \(cur\_elem.nodeName === "STRONG" && cur\_elem.textContent.includes\("Associated users:"\)\){
// This is the right one, next element is the user account anchor
var account\_name = selected\_elements\[i+1\].textContent;
// Display the button to save it
var new\_button = createStoreAccountButton\(account\_name\)
parent.insertBefore\(new\_button, parent.firstChild\);
}
}
}
}
}
});
}
/**
* Creates and returns a button to store the given account name on click
* @param account_name String containing the account name to display and store on button click
* @return the created button
*/
function createStoreAccountButton(account_name){
// New button
var new_button = document.createElement(“button”);
new_button.textContent = “Store “ + account_name;
// On click store it
new_button.onclick = async function(){
GM_setValue(account_name, true);
console.log(“Stored “ + account_name);
this.textContent = “STORED “ + account_name;
}
return new_button;
}
/**
* Displays an export and import button at the start of the page, that can be used to export or import script data
*/
function createExportImport(){
// Get HTML body
var body_elem = document.getElementsByTagName(“body”)[0];
/*
* EXPORT
*/
var export_button = document.createElement(“button”);
export_button.textContent = “Export Badge Data”;
// On click display current data
export_button.onclick = async function(){
// Get all stored keys
var stored\_keys = GM\_listValues\(\);
// Make a list
var list\_form = "";
for \(var key of stored\_keys\){
list\_form += key + ",";
}
// Now show it to user
console.log\(list\_form\);
prompt\("Badge Data Stored", list\_form.substring\(0, list\_form.length - 1\)\);
}
// Display the button
body_elem.insertBefore(export_button, body_elem.firstChild);
/*
* IMPORT
*/
var import_button = document.createElement(“button”);
import_button.textContent = “Import Badge Data”;
// On click prompt user for new data
import_button.onclick = async function(){
// Prompt user for input
var prompt_result = prompt(“Provide Data To Import”, “Put Previously Exported Data Here, insert spaces to purge all”);
if (prompt_result){
// Delete all currently stored keys before storing user submitted ones
for \(var key of GM\_listValues\(\)\){
GM\_deleteValue\(key\);
}
// Split the list to store the individual names
var split\_result = prompt\_result.split\(","\);
if \(split\_result.length \> 1\){
// Now store the new data
for \(var i = 0; i \< split\_result.length; i++\){
GM\_setValue\(split\_result\[i\], true\);
}
}
// Done. Inform the user
alert\("Given data imported."\);
}
}
// Display the button
body_elem.insertBefore(import_button, body_elem.firstChild);
}