您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Save search queries
// ==UserScript== // @name Rule34 Save Search // @description Save search queries // @namespace User_314159_R34SS // @version 0.55 // @author User_314159 // @license MIT // @match https://rule34.xxx/index.php?page=post&s=list* // @icon https://www.google.com/s2/favicons?sz=64&domain=rule34.xxx // @grant none // ==/UserScript== // display logic function get_search() { let contents = document.getElementById("content"); if (contents.getElementsByClassName("image-list")[0] != undefined) { let search_bar = contents.querySelector('input[name="tags"]'); if (search_bar.value != "") { return [true, search_bar.value]; } } return [false, ""]; } //io function getSavedSearches() { // gets the localstorage array and parses it into an actual array, creates a new one if there is no key in localStorage let artists; if (localStorage.getItem('rule34SavedSearches') === null) { console.log('generated new saved array'); artists = []; saveSearches(artists); } else { artists = JSON.parse(localStorage.getItem('rule34SavedSearches')); } return artists; } function deleteSearch(search) { // deletes the specified search out of the array and saves it let artists = getSavedSearches(); let target = artists.indexOf(search); artists.splice(target, 1); saveSearches(artists); console.log('Deleted ' + search); } function saveSearches(searches) { // saves an updated version of the searches to local storage localStorage.setItem('rule34SavedSearches', JSON.stringify(searches)); } function addSearch(search) { let searches = getSavedSearches(); search = sortStr(search); if(searches.includes(search)) { return; } searches.push(search); searches.sort(); saveSearches(searches); } function exportSearches() { // gets the local storage and logs it to the console as a string let searches = localStorage.getItem('rule34SavedSearches'); console.log(searches); // Don't need to stringify here the localstorage got it stringified navigator.clipboard.writeText(searches); alert("Copied searches to clipboard"); } function importSearches() { // takes an inputted array string and overwrites the local storage with it let input = window.prompt("Enter previously exported searches"); // window.prompt seems to return a double-escaped string let data = JSON.parse(input); // due to this, we need to de-escape twice to get the actual json let current_searches = getSavedSearches(); for(let index = 0; index < data.length; index++) { if(current_searches.includes(data[index])) { continue; } else { current_searches.push(data[index]); console.log("New search: " + data[index]); } } localStorage.setItem('rule34SavedSearches', JSON.stringify(current_searches)); } //sorting function sortStr(string) { //this btw relies on the fact that rule34 only has lowercase tags cuz it sorts all uppercase before the lowercase letters (i.e. I, X, a, b, ...) let split_str = string.split(' '); let sortable = []; let non_sortable = []; let bracketed = false; for(let i = 0; i < split_str.length; i++) { // this iterates over each token (thing separated by a space) and if its contained in brackets, it won't get sorted switch (split_str[i]) { case "(": bracketed = true; non_sortable.push(split_str[i]); break; case ")": bracketed = false; non_sortable.push(split_str[i]); break; default: if(bracketed){ non_sortable.push(split_str[i]); } else { sortable.push(split_str[i]); } break; } } return sortable.sort().join(' ') + ' ' + non_sortable.join(' '); } // button logic function createButton(name, width) { let button = document.createElement("button"); button.innerHTML = name; button.style.width = width; return button; } function createA(target) { let href = createLink(target); let a = document.createElement("a"); a.href = href; a.innerHTML = target; a.style.overflow = "hidden"; return a; } function createLink(target) { return "index.php?page=post&s=list&tags=" + target + "&is_saved_search"; } function createAddButton(search) { let button = createButton("Save search", "100%"); button.addEventListener("click", function() { addSearch(search); //window.location.href = createLink(search); }); return button; } function createDeleteButton(search) { let button = createButton("Delete search", "100%"); button.addEventListener("click", function() { deleteSearch(search); window.location.href = createLink(search).replace("&is_saved_search", ""); }); return button; } function createExportButton() { let button = createButton("Export", "100%"); button.addEventListener("click", function() { exportSearches(); }); return button; } function createImportButton() { let button = createButton("Import", "100%"); button.addEventListener("click", function() { importSearches(); }); return button; } function createDeleteAllButton() { let button = createButton("Delete all", "100%"); button.addEventListener("click", function() { if(window.confirm("WARNING: This will delete all saved searches and cannot be undone")) { if(window.confirm("Are you sure?")) { localStorage.removeItem("rule34SavedSearches"); console.log("removed localStorage 'rule34SavedSearches' key"); return; } } console.log("Reset was aborted"); }); return button; } function generateSearchList() { let collapsable = document.createElement("details"); let collapsable_name = document.createElement("summary"); collapsable_name.innerHTML = "Saved"; collapsable.style.maxHeight = "50vh"; collapsable.style.overflow = "hidden scroll"; collapsable.style.textOverflow = "ellipsis"; collapsable.style.whiteSpace = "nowrap"; collapsable.style.scrollbarWidth = "thin"; collapsable.appendChild(collapsable_name); let searches = getSavedSearches(); let linebreak = document.createElement("br"); for (let i = 0; i < searches.length; i++) { collapsable.appendChild(createA(searches[i])); collapsable.appendChild(linebreak.cloneNode()); } return collapsable; } function generateDevOptions() { let collapsable = document.createElement("details"); let collapsable_name = document.createElement("summary"); collapsable_name.innerHTML = "Dev Options"; collapsable.style.overflow = "hidden scroll"; collapsable.style.textOverflow = "ellipsis"; collapsable.style.whiteSpace = "nowrap"; collapsable.style.scrollbarWidth = "thin"; collapsable.appendChild(collapsable_name); let linebreak = document.createElement("br"); collapsable.appendChild(createImportButton()); collapsable.appendChild(linebreak.cloneNode()); collapsable.appendChild(createExportButton()); collapsable.appendChild(linebreak.cloneNode()); collapsable.appendChild(createDeleteAllButton()); collapsable.appendChild(linebreak.cloneNode()); return collapsable; } (function() { 'use strict'; let [search_not_empty, search_value] = get_search(); let search_bar = document.getElementsByClassName("tag-search")[0]; let collapsable = generateSearchList(); if (search_not_empty && !window.location.href.includes("&is_saved_search")) { let addButton = createAddButton(search_value); search_bar.append(addButton); } if (window.location.href.includes("&is_saved_search")) { let deleteButton = createDeleteButton(search_value); search_bar.append(deleteButton); } let tag_sidebar = document.getElementById("tag-sidebar"); tag_sidebar.append(generateDevOptions()); search_bar.append(collapsable); })();