您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
Allows for autofilled bookmark summary and tags on Ao3. Currently does not include series bookmarks but is planned. Feel free to request features: I will implement if I have the time & ability.
当前为
// ==UserScript== // @name Ao3 Auto Bookmarker // @description Allows for autofilled bookmark summary and tags on Ao3. Currently does not include series bookmarks but is planned. Feel free to request features: I will implement if I have the time & ability. // @namespace Ao3 // @match http*://archiveofourown.org/works/* // @match http*://archiveofourown.org/series/* // @grant none // @version 1.0 // @author Legovil // @license MIT // @downloadURL // ==/UserScript== // Set the true or false value of each setting to change whether the bookmark auto generates the option. const Settings = new Map([ ["GenerateTitleNote", true], ["GenerateSummaryNote", true], ["CheckRecBox", false], ["CheckPrivateBox", false], ["GetRating", true], ["GetArchiveWarnings", true], ["GetCategoryTags", true], ["GetFandomTags", true], ["GetRelationshipTags", true], ["GetCharacterTags", true], ["GetAdditionalTags", true], ["GenerateWordCountTag", true], ["AppendToExistingNote", true], ["AppendToExistingTags", false], ["UsingAo3Extensions", true] ]); // Edit these comma delimited numbers to change the auto word count tag boundaries (e.g. 1000 - 5000). const WordCountBounds = [1000, 5000, 10000, 50000, 100000, 500000]; // Bookmark type enum. const BookmarkType = Object.freeze({ Work: 'Work', Series: 'Series' }); (function() { 'use strict'; const bookmarkType = CheckIfWorkOrSeries(window.location.href); if (Object.is(bookmarkType, BookmarkType.Series)) { console.error("Not generating bookmark. Series bookmarks are not yet implemented."); return; } if (Object.is(bookmarkType, null)) { console.error("Bookmark type not found. Cancelling bookmark generation."); return; } GenerateNotes(); GenerateTags(); HandleCheckBoxes(); })(); function CheckIfWorkOrSeries(url) { if (url.includes("/works/")) { console.log("Found Work Bookmark."); return BookmarkType.Work; } if (url.includes("/series/")) { console.log("Found Series Bookmark."); return BookmarkType.Series; } return null; } function GenerateNotes() { const notesElement = document.getElementById("bookmark_notes"); let note = ""; if (Object.is(notesElement, null)) { console.error("Notes element not found. Cancelling notes generation."); return; } note += GenerateTitleNote(); note += GenerateSummaryNote(); if (Settings.get("AppendToExistingNote")) { notesElement.value += `\n\n${note}`; } else { notesElement.value = note; } } function GenerateTitleNote() { if (!Settings.get("GenerateTitleNote")) { console.log("Not generating title note."); return ""; } console.log("Generating title note."); const title = document.getElementsByClassName("title heading")[0]; if (Object.is(title, undefined)) { console.warn("Title not found. Cancelling Title Note generation."); return ""; } const byline = document.getElementsByClassName("byline heading")[0].getElementsByTagName('a')[0]; if (Object.is(byline, undefined)) { console.warn("Byline not found. Cancelling Title Note generation."); return ""; } return `${title.innerHTML.link(window.location.href)} by ${byline.outerHTML}.`; } function GenerateSummaryNote() { if (!Settings.get("GenerateSummaryNote")) { console.log("Not generating summary note."); return; } const summary = document.getElementsByClassName("summary module")[0].getElementsByClassName("userstuff")[0]; if (Object.is(summary, undefined)) { console.warn("No summary found. Cancelling summary note generation."); return ""; } return `\n\nSummary: ${summary.innerText}`; } function GenerateTags() { let tagsElement = document.getElementById("bookmark_tag_string_autocomplete"); if (Object.is(tagsElement, null)) { console.error("Tags element not found. Cancelling bookmark tag generation."); return; } let tags = Settings.get("AppendToExistingTags") ? `${tagsElement.value}, ` : ""; tags += Settings.get("GetArchiveWarnings") ? GetTagsFromString("warning tags") : ""; tags += Settings.get("GetCategoryTags") ? GetTagsFromString("category tags") : ""; tags += Settings.get("GetFandomTags") ? GetTagsFromString("fandom tags") : ""; tags += Settings.get("GetRelationshipTags") ? GetTagsFromString("relationship tags") : ""; tags += Settings.get("GetCharacterTags") ? GetTagsFromString("character tags") : ""; tags += Settings.get("GetAdditionalTags") ? GetTagsFromString("freeform tags") : ""; tags += GenerateWordCountTag(); tagsElement.value = tags; } function GetTagsFromString(tagClassName) { const tagList = document.getElementsByClassName(tagClassName)[1].getElementsByClassName("tag"); if (Object.is(tagList, null) || tagList.length == 0) { console.error(`Tags element not found. Cancelling ${tagClassName} generation.`); return ""; } let tags = ""; for (const tag of tagList) { tags += `${tag.text}, `; } return tags; } function GenerateWordCountTag() { if (!Settings.get("GenerateWordCountTag")) { console.log("Not generating word count tag.") return; } const wordCountElement = Settings.get("UsingAo3Extensions") ? document.getElementsByClassName("words")[2] : document.getElementsByClassName("words")[1]; if (Object.is(wordCountElement, null) || wordCountElement.innerText === "Words:") { console.error("Word count not found. Cancelling word count tag generation. Check to see if Ao3 Extensions setting is toggled correctly."); return; } const wordCount = wordCountElement.innerText.replaceAll(",", ""); let lowerBound = WordCountBounds[0]; if (wordCount < lowerBound) { return `< ${lowerBound}`; } for (const upperBound of WordCountBounds) { if (wordCount < upperBound) { return `${lowerBound} - ${upperBound - 1}` } lowerBound = upperBound; } return `> ${WordCountBounds[WordCountBounds.length - 1]}`; } function HandleCheckBoxes() { const recBox = document.getElementById("bookmark_rec"); if (Settings.get("CheckRecBox") && !Object.is(recBox, undefined)) { console.log("Checking rec box."); recBox.checked = true; } const privateBox = document.getElementById("bookmark_private"); if (Settings.get("CheckPrivateBox") && !Object.is(privateBox, undefined)) { console.log("Checking private box."); privateBox.checked = true; } }