您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
Allows for autofilled bookmark summary and tags on Ao3.
当前为
// ==UserScript== // @name Ao3 Auto Bookmarker // @description Allows for autofilled bookmark summary and tags on Ao3. // @namespace Ao3 // @match http*://archiveofourown.org/works/* // @match http*://archiveofourown.org/series/* // @grant none // @version 1.1 // @author Legovil // @license MIT // ==/UserScript== // Set the true or false value of each setting to change whether the bookmark auto generates the option. const settings = { 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: false, 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 = CheckBookmarkType(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(bookmarkType); GenerateTags(); HandleCheckBoxes(); })(); function CheckBookmarkType(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(bookmarkType) { const notesElement = document.getElementById("bookmark_notes"); if (!notesElement) { console.error("Notes element not found. Cancelling notes generation."); return; } console.log("Notes element found."); const notes = [ settings.GenerateTitleNote && GenerateTitleNote(bookmarkType), settings.GenerateSummaryNote && GenerateSummaryNote(bookmarkType) ].filter(item => Boolean(item)).join("\n\n"); notesElement.value = settings.AppendToExistingNote ? `${notesElement.value}\n\n${notes}` : notes; } function GenerateTitleNote(bookmarkType) { const titleQuery = (bookmarkType === BookmarkType.Work) ? ".title.heading" : "ul.series a"; const title = document.querySelector(titleQuery); if (!title) { console.warn("Title not found. Cancelling Title Note generation."); return ""; } const bylineQuery = (bookmarkType === BookmarkType.Work) ? ".byline.heading a" : ".series.meta.group a"; const byline = document.querySelector(bylineQuery); if (!byline) { console.warn("Byline not found. Cancelling Title Note generation."); return ""; } return `${title.innerHTML.link(window.location.href)} by ${byline.outerHTML}.`; } function GenerateSummaryNote(bookmarkType) { const summaryQuery = (bookmarkType === BookmarkType.Work) ? ".summary.module .userstuff" : ".series.meta.group .userstuff" const summary = document.querySelector(summaryQuery); if (!summary) { console.warn("No summary found. Cancelling summary note generation."); return ""; } return `Summary: ${summary.innerText}`; } function GenerateTags(bookmarkType) { let tagsElement = document.getElementById("bookmark_tag_string_autocomplete"); if (!tagsElement) { console.error("Tags input element not found. Cancelling bookmark tag generation."); return; } console.log("Tags input element found."); tagsElement.value = [ settings.GetArchiveWarnings && GetTagsFromString("warning tags"), settings.GetCategoryTags && GetTagsFromString("category tags"), settings.GetFandomTags && GetTagsFromString("fandom tags"), settings.GetRelationshipTags && GetTagsFromString("relationship tags"), settings.GetCharacterTags && GetTagsFromString("character tags"), settings.GetAdditionalTags && GetTagsFromString("freeform tags"), settings.GenerateWordCountTag && GenerateWordCountTag() ].filter(item => Boolean(item)).join(', '); } function GetTagsFromString(tagClassName) { const tagList = document.getElementsByClassName(tagClassName)[1]?.getElementsByClassName("tag"); if (!tagList || tagList.length == 0) { console.error(`Tags element not found. Cancelling ${tagClassName} generation.`); return ""; } return Array.from(tagList).map(tag => tag.text).join(', '); } function GenerateWordCountTag() { const wordCountElement = settings.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(",", "").replaceAll(" ",""); console.log(`Word count: ${wordCount}`); let lowerBound = wordCountBounds[0]; if (wordCount < lowerBound) { return `< ${lowerBound}`; } for (const upperBound of wordCountBounds) { if (wordCount < upperBound) { return `${lowerBound} - ${upperBound}` } lowerBound = upperBound; } return `> ${wordCountBounds[wordCountBounds.length - 1]}`; } function HandleCheckBoxes() { const recBox = document.getElementById("bookmark_rec"); if (settings.CheckRecBox && !Object.is(recBox, undefined)) { console.log("Checking rec box."); recBox.checked = true; } const privateBox = document.getElementById("bookmark_private"); if (settings.CheckPrivateBox && !Object.is(privateBox, undefined)) { console.log("Checking private box."); privateBox.checked = true; } }