Skip to content

Instantly share code, notes, and snippets.

@Ustice
Last active April 19, 2021 15:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Ustice/d9e80c7dbd072603969409db7524e164 to your computer and use it in GitHub Desktop.
Save Ustice/d9e80c7dbd072603969409db7524e164 to your computer and use it in GitHub Desktop.
D&D Beyond automatic fixed sidebar
// ==UserScript==
// @name D&D Beyond fixed sidebar
// @version 6
// @grant none
// @include /^(https://www.dndbeyond.com/profile/[^/]*/characters/.*|https://www.dndbeyond.com/characters/.*)$/
// ==/UserScript==
const clickElement = (query) => {
console.log('Clicking ' + query)
const element = document.querySelector(query)
element?.click()
return element
}
const noop = () => {}
const runUnless = (fn) => (test) => test ? fn(test) : undefined
const keepTrying = (fn = noop, options) => new Promise((resolve, reject) => {
let timeout, interval
const defaults = { checkEvery: 500, stopAfter: 5000, delayBy: 0 }
const { checkEvery, stopAfter, delayBy } = { ...defaults, ...options }
const start = () => {
console.log('Starting action')
timeout = setTimeout(halt, stopAfter ?? 5000)
interval = setInterval(retry, checkEvery ?? 500)
}
const retry = () => {
console.log('Retrying')
try {
return runUnless(stop)(fn())
}
catch (error) {
console.error(error)
return halt()
}
}
const reset = () => {
console.log('Resetting')
clearInterval(interval)
clearTimeout(timeout)
}
const stop = (result) => {
console.log('Stopping')
reset()
resolve(result)
}
const halt = () => {
console.log('Aborting')
reset()
reject(new Error(`Timeout after ${ stopAfter }ms.`))
}
setTimeout(start, delayBy ?? 0)
})
const onLoad = async () => {
console.log('Setting up character sheet')
const showSidebar = () => clickElement('.ct-sidebar__control--expand')
const moveSidebarLeft = () => clickElement('.ct-sidebar__control--left')
const setSidebarToFixed = () => clickElement('.ct-sidebar__control--fixed')
const lockSidebar = () => clickElement('.ct-sidebar__control--unlock')
const openGameLog = () => clickElement('.ct-character-header__group--game-log')
const openFeaturesAndTraits = () => clickElement('.ct-primary-box__tab--features')
await keepTrying(showSidebar)
await Promise.all([
keepTrying(moveSidebarLeft),
keepTrying(setSidebarToFixed),
keepTrying(openGameLog),
])
await Promise.all([
keepTrying(lockSidebar),
keepTrying(openFeaturesAndTraits),
])
}
window.addEventListener('load', onLoad, false)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment