Last active
November 10, 2024 20:55
-
-
Save Tarrgon/e8357b5f8139e494acb6a587c6b9e9c8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name Blacklist Categories | |
| // @namespace http://tampermonkey.net/ | |
| // @version 1.1 | |
| // @description E621 blacklist categories and switching | |
| // @author Tarrgon | |
| // @match https://e621.net/* | |
| // @match https://e926.net/* | |
| // @icon https://www.google.com/s2/favicons?sz=64&domain=e621.net | |
| // @grant GM_addElement | |
| // @grant GM.setValue | |
| // @grant GM.getValue | |
| // @grant GM.deleteValue | |
| // @grant GM_addStyle | |
| // @require https://unpkg.com/hotkeys-js/dist/hotkeys.min.js | |
| // @run-at document-end | |
| // ==/UserScript== | |
| let blacklistTextInput = null | |
| GM_addStyle(` | |
| .bc-category-button { | |
| background-color: #142642; | |
| margin-right: 0.3rem; | |
| margin-top: 0.3rem; | |
| } | |
| .bc-category-button.bc-category-enabled { | |
| outline: 2px solid lime; | |
| } | |
| `) | |
| let categoryCache = null | |
| async function loadHotkeys() { | |
| let keys = (await GM.getValue("hotkeys")) || [] | |
| for (let hotkey of keys) { | |
| console.log("Loading hotkey", hotkey) | |
| hotkeys(hotkey.sequence, async (event) => { | |
| event.preventDefault() | |
| await toggleCategory(hotkey.name) | |
| reloadBlacklist() | |
| }) | |
| } | |
| } | |
| async function toggleCategory(name) { | |
| let curContent = JSON.parse($("meta[name=blacklisted-tags]").attr("content") || "[]") | |
| let category = await getCategoryByName(name) | |
| if (!category) return | |
| let text = curContent.join("\n") | |
| let isActive = await determineIfCategoryIsActive(name, text) | |
| if (!isActive) { | |
| text += `\n# [[${category.name}]]\n${category.blacklist}\n# [[end ${category.name}]]\n` | |
| text = text.trimStart() | |
| } else { | |
| let startIndex = text.indexOf(`# [[${category.name}]]`) | |
| let endIndex = text.indexOf(`# [[end ${category.name}]]`) | |
| if (startIndex == -1 || endIndex == -1) return | |
| endIndex += `# [[end ${category.name}]]`.length | |
| text = text.slice(0, startIndex) + text.slice(endIndex + 2) | |
| text = text.trimStart() | |
| } | |
| $("meta[name=blacklisted-tags]").attr("content", JSON.stringify(text.split(/\n\r?/))) | |
| if (blacklistTextInput) blacklistTextInput.value = text | |
| } | |
| async function getExistingCategories() { | |
| if (categoryCache) return categoryCache | |
| categoryCache = (await GM.getValue("categories")) || [] | |
| return categoryCache | |
| } | |
| async function saveCategory(name, category) { | |
| let categories = await getExistingCategories() | |
| let categoryIndex = categories.findIndex(c => c.name == name) | |
| if (categoryIndex != -1) categories[categoryIndex] = category | |
| else categories.push(category) | |
| await GM.setValue("categories", categories) | |
| } | |
| async function removeCategory(name) { | |
| let categories = await getExistingCategories() | |
| let categoryIndex = categories.findIndex(c => c.name == name) | |
| if (categoryIndex == -1) return | |
| categories.splice(categoryIndex, 1) | |
| await GM.setValue("categories", categories) | |
| } | |
| async function getCategoryByName(name) { | |
| let categories = await getExistingCategories() | |
| return categories.find(c => c.name == name) | |
| } | |
| async function fixActiveAndSave(text) { | |
| let categories = await getExistingCategories() | |
| for (let button of document.querySelectorAll(".bc-category-button")) { | |
| let category = categories.find(c => c.name == button.getAttribute("data-category")) | |
| if (!category) continue | |
| if (determineIfCategoryIsActive(category.name)) { | |
| category.isActive = true | |
| button.classList.add("bc-category-enabled") | |
| } else { | |
| category.isActive = false | |
| button.classList.remove("bc-category-enabled") | |
| } | |
| } | |
| let split = text.split("\n") | |
| let blacklistText = "" | |
| let curCategory = null | |
| for (let item of split) { | |
| let match | |
| if ((match = /# \[\[(.*)\]\]/.exec(item))) { | |
| if (match[1].startsWith("end")) { | |
| curCategory.blacklist = blacklistText.trim() | |
| curCategory = null | |
| blacklistText = "" | |
| } else { | |
| curCategory = categories.find(c => c.name == match[1]) | |
| } | |
| } else if (curCategory) { | |
| blacklistText += item + "\n" | |
| } | |
| } | |
| await GM.setValue("categories", categories) | |
| } | |
| function reloadBlacklist() { | |
| // $.ajax("/users/" + Danbooru.Utility.meta("current-user-id") + ".json", { | |
| // method: "PUT", | |
| // data: { | |
| // "user[blacklisted_tags]": $("meta[name=blacklisted-tags]").attr("content") || "[]", | |
| // }, | |
| // }).done(function () { | |
| // Danbooru.Utility.notice("Blacklist updated") | |
| // }).fail(function () { | |
| // Danbooru.Utility.error("Failed to update blacklist") | |
| // }) | |
| Danbooru.Blacklist.regenerate_filters() | |
| Danbooru.Blacklist.add_posts($(".post-preview")) | |
| Danbooru.Blacklist.update_visibility() | |
| } | |
| function determineIfCategoryIsActive(name, overrideText = null) { | |
| return (overrideText ?? blacklistTextInput.value).indexOf(`# [[${name}]]`) != -1 | |
| } | |
| function showHotkeyDialogue() { | |
| } | |
| function categoryButtonFromCategory(category) { | |
| let button = document.createElement("button") | |
| button.classList.add("button", "bc-category-button") | |
| category.isActive = determineIfCategoryIsActive(category.name, JSON.parse($("meta[name=blacklisted-tags]").attr("content")).join("\n")) | |
| if (category.isActive) button.classList.add("bc-category-enabled") | |
| button.innerText = category.name | |
| button.setAttribute("data-category", category.name) | |
| button.addEventListener("click", (e) => { | |
| console.log(e) | |
| e.preventDefault() | |
| category.isActive = !category.isActive | |
| button.classList.toggle("bc-category-enabled") | |
| if (category.isActive) { | |
| blacklistTextInput.value += `\n# [[${category.name}]]\n${category.blacklist}\n# [[end ${category.name}]]\n` | |
| blacklistTextInput.value = blacklistTextInput.value.trimStart() | |
| } else { | |
| let startIndex = blacklistTextInput.value.indexOf(`# [[${category.name}]]`) | |
| let endIndex = blacklistTextInput.value.indexOf(`# [[end ${category.name}]]`) | |
| if (startIndex == -1 || endIndex == -1) return | |
| endIndex += `# [[end ${category.name}]]`.length | |
| blacklistTextInput.value = blacklistTextInput.value.slice(0, startIndex) + blacklistTextInput.value.slice(endIndex + 2) | |
| blacklistTextInput.value = blacklistTextInput.value.trimStart() | |
| } | |
| }) | |
| button.addEventListener("mousedown", (e) => { | |
| if (e.button != 1) return | |
| e.preventDefault() | |
| e.stopImmediatePropagation() | |
| showHotkeyDialogue() | |
| }) | |
| button.addEventListener("contextmenu", async (e) => { | |
| e.preventDefault() | |
| e.stopImmediatePropagation() | |
| if (!confirm(`Delete ${category.name}?`)) return | |
| removeCategory(category.name) | |
| button.remove() | |
| }) | |
| saveCategory(category.name, category) | |
| return button | |
| } | |
| function newCategoryButton() { | |
| let button = document.createElement("button") | |
| button.classList.add("button", "bc-category-button") | |
| button.innerText = "Add Category" | |
| button.addEventListener("click", (e) => { | |
| e.preventDefault() | |
| e.stopImmediatePropagation() | |
| let name = prompt("Category name?").toLowerCase() | |
| let category = { | |
| name, | |
| blacklist: "", | |
| isActive: true | |
| } | |
| blacklistTextInput.value += `\n# [[${category.name}]]\n\n# [[end ${category.name}]]\n` | |
| blacklistTextInput.value = blacklistTextInput.value.trimStart() | |
| saveCategory(name, category) | |
| button.before(categoryButtonFromCategory(category)) | |
| }) | |
| return button | |
| } | |
| async function addPrimaryCategorySwitcher() { | |
| let blacklistedTagsDiv = document.querySelector(".user_blacklisted_tags") | |
| blacklistTextInput = blacklistedTagsDiv.querySelector("#user_blacklisted_tags") | |
| blacklistTextInput.addEventListener("input", () => { | |
| fixActiveAndSave(blacklistTextInput.value.trim()) | |
| }) | |
| let hint = blacklistedTagsDiv.querySelector(".hint") | |
| let container = document.createElement("div") | |
| container.style.paddingTop = "0.25rem" | |
| for (let category of await getExistingCategories()) { | |
| container.append(categoryButtonFromCategory(category)) | |
| } | |
| container.append(newCategoryButton()) | |
| hint.before(container) | |
| } | |
| async function addSecondaryCategorySwitcher() { | |
| let box = document.getElementById("blacklist-edit-dialog") | |
| if (!box) return | |
| blacklistTextInput = box.querySelector("#blacklist-edit") | |
| blacklistTextInput.addEventListener("input", () => { | |
| fixActiveAndSave(blacklistTextInput.value.trim()) | |
| }) | |
| let saveButton = box.querySelector("#blacklist-save") | |
| let container = document.createElement("div") | |
| container.style.paddingTop = "0.25rem" | |
| container.style.gridColumnStart = "1" | |
| container.style.gridColumnEnd = "3" | |
| for (let category of await getExistingCategories()) { | |
| let button = categoryButtonFromCategory(category) | |
| container.append(button) | |
| } | |
| container.append(newCategoryButton()) | |
| saveButton.before(container) | |
| saveButton.style.gridColumnStart = "1" | |
| container.after(document.createElement("br")) | |
| } | |
| (async function () { | |
| let url = window.location.href | |
| if (url.match(/users\/.*\/edit/)) { | |
| addPrimaryCategorySwitcher() | |
| } else { | |
| addSecondaryCategorySwitcher() | |
| } | |
| loadHotkeys() | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment