Skip to content

Instantly share code, notes, and snippets.

@hurbeana
Created December 20, 2024 09:10
Show Gist options
  • Save hurbeana/394eb5c552c30ee2d699b2236849efcb to your computer and use it in GitHub Desktop.
Save hurbeana/394eb5c552c30ee2d699b2236849efcb to your computer and use it in GitHub Desktop.
violentmonkey tailscale magicdns reroller
/* globals jQuery, $, $x */
// ==UserScript==
// @name Tailscale Reroller
// @namespace Violentmonkey Scripts
// @match https://login.tailscale.com/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=tailscale.com
// @require https://code.jquery.com/jquery-3.7.1.min.js
// @require https://code.jquery.com/ui/1.14.1/jquery-ui.js
// @require https://raw.githubusercontent.com/uzairfarooq/arrive/master/minified/arrive.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/mark.js/8.11.1/jquery.mark.es6.min.js
// @grant none
// @version 1.0
// @author hurbeana
// @description 18/12/2024, 12:58:37
// @grant GM_setValue
// @grant GM_getValue
// ==/UserScript==
(async () => {
"use strict";
jQuery(document).ready(($) => {
$.noConflict();
class CheckBoxUI {
constructor(insertAfter) {
insertAfter.after(this.toggle);
this.checkbox = this.toggle.find("input").eq(0);
this.checkbox.change(this.chkChange);
}
toggle = $(
'<div class="flex ml-2"><span data-state="closed"><input type="checkbox" class="toggle toggle-large"></span><span class="ml-2">Start/Stop</span></div>'
);
get checked() {
return this.checkbox.is(":checked");
}
set checked(val) {
this.checkbox.prop("checked", val);
}
chkChange = () => {
this.checked = this.checkbox.is(":checked");
};
}
class SearchEntries {
constructor(addAfter) {
this.boxEntries.hide();
this.searchWords = GM_getValue("searchWords", []);
console.log("Loaded words", this.searchWords);
addAfter.after(this.boxGrey, this.boxEntries);
this.ul = this.boxEntries.children("ul").eq(0);
this.searchWords.forEach(this.addToBox);
}
boxGrey = $(
'<div class="rounded-md border dark:border-gray-700 mt-4 bg-gray-0 dark:bg-gray-900 p-6 mb-4"><div class="flex justify-center"><div class="w-full text-center max-w-xl text-gray-500 dark:text-gray-400">No favorite words added</div></div></div>'
);
boxEntries = $(
'<div class="border rounded-md mt-4 mb-4"><ul class="divide-y"></ul></div>'
);
elem = $(
'<li class="flex justify-between items-center gap-4 h-14 px-4"></li>'
);
lis = [];
append = (word) => {
if (this.searchWords.includes(word)) {
return false;
}
this.searchWords.push(word);
this.addToBox(word);
GM_setValue("searchWords", this.searchWords);
console.log(this.searchWords);
return true;
};
addToBox = (word) => {
let new_li = this.elem.clone();
new_li.text(word);
let closeButton = $(
'<button class="close-btn ml-auto text-red-500">X</button>'
);
closeButton.click(() => {
this.removeEntry(word, new_li);
});
new_li.append(closeButton);
console.log("adding word", word);
this.ul.append(new_li);
if (this.boxGrey.is(":visible")) {
this.boxGrey.hide();
this.boxEntries.show();
}
};
removeEntry = (word, liElement) => {
this.searchWords = this.searchWords.filter((w) => w !== word);
GM_setValue("searchWords", this.searchWords);
liElement.remove();
console.log("Removed word:", word);
if (this.searchWords.length === 0) {
this.boxEntries.hide();
this.boxGrey.show();
}
};
activeElem = () => {
return this.boxEntries;
};
}
let sleep = async (ms) => new Promise((r) => setTimeout(r, ms));
class Reroller {
constructor(checkbox, searches, rerollButton) {
this.options = [];
this.observed = GM_getValue("observed", {});
this.searches = searches;
this.rerollButton = rerollButton;
this.checkbox = checkbox;
this.fetchlb();
this.checkbox.checkbox.change(this.checkboxChange);
}
checkboxChange = () => {
console.log("Started search");
this.rerollButton.click();
if (this.checkbox.checked) this.checkResults();
};
fetchlb = () => {
let header = $('header:contains("Rename")');
let form = header.next("form");
let labels = form.find("label");
let texts = [];
labels.each(function () {
let l = $(this);
texts.push({
e: l,
t: l.text().replace(".ts.net", ""),
});
});
this.options = texts;
this.checkResults();
};
labelObserver = (input) => {
let jqe = $(input);
let text = jqe.text().replace(".ts.net", "");
this.options.push({
e: jqe,
t: text,
});
//console.log(this.options.length, this.options[this.options.length - 1]);
this.checkResults();
};
checkResults = () => {
if (this.options.length >= 4) {
console.log("Have more than 4 words:", this.options);
this.options.forEach((v) => {
this.searches.searchWords.forEach((s) => {
let sp = v.t.split("-");
sp.forEach((x) => {
if (x in this.observed) {
this.observed[x]++;
} else {
this.observed[x] = 1;
}
if (x === s) {
this.checkbox.checked = false;
v.e.css("background-color", "yellow");
const orderedObserved = Object.entries(this.observed)
.sort(([, a], [, b]) => a - b)
.reduce((r, [k, v]) => ({ ...r, [k]: v }), {});
GM_setValue("observed", orderedObserved);
}
});
});
});
this.options = [];
if (this.checkbox.checked) {
console.log("We are running, clicking");
this.rerollButton.click();
}
} else {
console.log("Dont have more than 4 words:", this.options);
}
};
}
let rerollButton, searches, searchWords, checkbox;
let instr = $('<p class="mb-2">Enter desired words to be found:</p>');
let inp = $(
'<input id="reroll-inp" class="input z-10" placeholder="goblin" value="">'
);
inp.keypress((e) => {
console.log(e);
var id = e.key;
var text = inp.val();
if (id === "Enter" && text) {
if (searches.append(text)) {
inp.val("");
}
return false;
}
return true;
});
$(document.body).arrive("span.max-w-full", async (x) => {
if (x.innerHTML === "Re-roll options") {
rerollButton = $(x).parent();
let elemBefore = rerollButton.prev();
elemBefore.after(instr, inp);
searches = new SearchEntries(inp);
checkbox = new CheckBoxUI(searches.activeElem());
let reroller = new Reroller(checkbox, searches, rerollButton);
let header = $('header:contains("Rename")');
let form = header.next("form");
form.arrive("label", reroller.labelObserver);
}
});
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment