Skip to content

Instantly share code, notes, and snippets.

@aolkin
Last active July 24, 2024 03:35
Show Gist options
  • Save aolkin/84c1a35f0fc51c5e1f8e70d70fe1f184 to your computer and use it in GitHub Desktop.
Save aolkin/84c1a35f0fc51c5e1f8e70d70fe1f184 to your computer and use it in GitHub Desktop.
Filter D&D Beypnd by Owned Sources
// ==UserScript==
// @name D&D Beyond Source Filter
// @namespace https://www.dndbeyond.com/
// @version 2024-07-23
// @description Filter D&D Beypnd by owned sources
// @author aolkin@
// @match https://www.dndbeyond.com/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=dndbeyond.com
// @grant none
// @run-at context-menu
// ==/UserScript==
async function getOwnedSources() {
const parser = new DOMParser();
const response = await fetch("https://www.dndbeyond.com/account/licenses");
const html = parser.parseFromString(await response.text(), "text/html");
const rows = html.querySelectorAll(".listing-rpguser-license-map tbody tr");
return Array.from(rows).map(row => row.getElementsByTagName("td")[3].innerText.trim());
}
async function filterLibrary(sources) {
const sourceOptions = document.getElementById("form-field-filter-source").querySelectorAll("option");
const sourceMap = Object.fromEntries(Array.from(sourceOptions).map(option => [option.innerText.trim(), option.value]));
const sourceIds = new Set(sources.filter(name => name in sourceMap).map(name => sourceMap[name]));
console.log(sourceMap, sources, sourceIds);
const params = new URLSearchParams(document.location.search.slice(1));
for (var source of sourceIds) {
params.append("filter-source", source);
}
document.location.search = "?" + params.toString();
}
function filterEncounterBuilder(sources) {
const sourceOptions = document.getElementsByClassName("qa-monster-filters_source")[0]
.querySelectorAll(".qa-input-checkbox_label");
for (var option of sourceOptions) {
const label = option.querySelector(".input-checkbox__text").innerHTML;
const input = option.querySelector(".qa-input-checkbox_input");
if (input.checked !== sources.includes(label)) {
input.click();
}
// console.log(label, input.checked, sources.includes(label));
}
}
(async function() {
'use strict';
const sources = await getOwnedSources();
if (document.location.pathname.includes("encounter-builder")) {
await filterEncounterBuilder(sources);
} else {
await filterLibrary(sources);
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment