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;
}
}