// ==UserScript== // @name AO3: Auto Pseud // @version 1.0.1 // @description Assign pseuds based on fandoms when commenting and bookmarking works // @author BlackBatCat // @match *://archiveofourown.org/users/*/pseuds/*/edit // @match *://archiveofourown.org/users/*/pseuds/*/bookmarks* // @match *://archiveofourown.org/works* // @match *://archiveofourown.org/chapters/* // @match *://archiveofourown.org/collections/*/bookmarks // @license MIT // @run-at document-end // @namespace https://greasyfork.org/users/1498004 // @downloadURL https://update.greasyfork.icu/scripts/556232/AO3%3A%20Auto%20Pseud.user.js // @updateURL https://update.greasyfork.icu/scripts/556232/AO3%3A%20Auto%20Pseud.meta.js // ==/UserScript== console.log("[AO3: Auto Pseud] loaded."); (function () { "use strict"; // Storage key const STORAGE_KEY = "ao3_auto_pseud_config"; // Page detection regex const WORKS_PAGE_REGEX = /^https?:\/\/archiveofourown\.org\/(?:.*\/)?(works|chapters)(\/|$)/; const PSEUD_EDIT_REGEX = /^https?:\/\/archiveofourown\.org\/users\/.*\/pseuds\/.*\/edit$/; const BOOKMARKS_PAGE_REGEX = /^https?:\/\/archiveofourown\.org\/(?:collections\/.*\/)?(?:users\/.*\/(?:pseuds\/.*\/)?)?bookmarks(?:\/.*)?$/; // Get the entire config object function getConfig() { try { const config = JSON.parse(localStorage.getItem(STORAGE_KEY) || "{}"); if (!config.pseuds) config.pseuds = {}; if (config.enableComments === undefined) config.enableComments = false; if (config.enableBookmarks === undefined) config.enableBookmarks = false; return config; } catch (e) { console.error("[AO3: Auto Pseud] Error loading config:", e); return { pseuds: {}, enableComments: false, enableBookmarks: false }; } } // Save the entire config object function saveConfig(config) { try { localStorage.setItem(STORAGE_KEY, JSON.stringify(config)); } catch (e) { console.error("[AO3: Auto Pseud] Error saving config:", e); } } // Get current pseud name from URL function getCurrentPseudName() { const urlParts = window.location.pathname.split("/"); const pseudIndex = urlParts.indexOf("pseuds"); return pseudIndex !== -1 ? urlParts[pseudIndex + 1] : null; } // Get stored fandoms for current pseud function getStoredFandoms(pseudName) { const config = getConfig(); return config.pseuds[pseudName]?.fandoms || []; } // Save fandoms for current pseud function saveFandomsForPseud(pseudName, fandoms) { const config = getConfig(); if (!config.pseuds[pseudName]) { config.pseuds[pseudName] = {}; } config.pseuds[pseudName].fandoms = fandoms; saveConfig(config); } // Get pseud ID for a given pseud name function getPseudIdByName(pseudName) { const config = getConfig(); return config.pseuds[pseudName]?.id || null; } // Save pseud name to ID mapping function savePseudNameMapping(pseudName, pseudId) { const config = getConfig(); if (!config.pseuds[pseudName]) { config.pseuds[pseudName] = {}; } config.pseuds[pseudName].id = pseudId; saveConfig(config); } // Find which pseud should be used for given fandoms function findMatchingPseud(workFandoms) { try { const config = getConfig(); for (const [pseudName, pseudData] of Object.entries(config.pseuds)) { const pseudFandoms = pseudData.fandoms || []; const pseudId = pseudData.id; if (!pseudId) continue; for (const workFandom of workFandoms) { if (pseudFandoms.includes(workFandom)) { return pseudId; } } } return null; } catch (e) { console.error("[AO3: Auto Pseud] Error finding matching pseud:", e); return null; } } // ==================== PSEUD EDIT PAGE ==================== // Show the fandom help modal function showFandomHelpModal() { // Remove any existing modal/background const oldModal = document.getElementById("modal-wrap"); if (oldModal) oldModal.parentNode.removeChild(oldModal); const oldBg = document.getElementById("modal-background"); if (oldBg) oldBg.parentNode.removeChild(oldBg); // AO3 native modal uses overlay first, then modal-wrap const background = document.createElement("div"); background.id = "modal-background"; background.className = "modal-closer"; background.style.display = "block"; background.style.position = "fixed"; background.style.top = "0"; background.style.left = "0"; background.style.width = "100%"; background.style.height = "100%"; background.style.backgroundColor = "rgba(0,0,0,0.5)"; background.style.zIndex = "1000"; document.body.appendChild(background); const modalWrap = document.createElement("div"); modalWrap.id = "modal-wrap"; modalWrap.className = "modal-closer"; modalWrap.style.display = "block"; modalWrap.style.position = "fixed"; modalWrap.style.top = "50%"; modalWrap.style.left = "50%"; modalWrap.style.transform = "translate(-50%, -50%)"; modalWrap.style.zIndex = "1001"; modalWrap.innerHTML = `
Associate fandoms with this pseud. When you comment on or bookmark works in these fandoms, this pseud will be suggested automatically.