Easier 1up b37
Forked from https://gist.github.com/TypeA2/bff1474c0f4ca2188cf21897d4e4b2dd
This is a userscript written for users below level 37. Additionally, it allows you to 1up related posts from the same source.
Show
// ==UserScript== // @name Easier 1up b37 // @namespace https://danbooru.donmai.us/forum_topics/8502 // @match *://*.donmai.us/uploads/* // @grant none // @version 0.0.1-fork // @author Sibyl // @description 1.0.3 2024-06-19 (upstream), 2024-12-10 (current) // Forked from https://gist.github.com/TypeA2/bff1474c0f4ca2188cf21897d4e4b2dd // @run-at document-end // ==/UserScript== const CUSTOM_THUMBNAIL = 23609685; // Custom thumbnail for banned posts with media asset ID const easier1Up = { iconHash: document.querySelector("a#close-notice-link use").href.baseVal.split(/-|\./)[1], tagsField: document.querySelector("#post_tag_string"), async init() { let thumbnailData = JSON.parse(localStorage.getItem("easier_1up_b37")); if (!thumbnailData || thumbnailData.id !== CUSTOM_THUMBNAIL) { let resp = await (await fetch(`/media_assets/${CUSTOM_THUMBNAIL}.json`)).json(); if (!resp || resp.error) { thumbnailData = { id: 23609685, url: "https://cdn.donmai.us/180x180/3e/3c/3e3c7baac2a12a0936ba1f62a46a3478.jpg", width: 180, height: 135 }; } else { thumbnailData = resp.variants.filter(v => v.type === "180x180")[0]; thumbnailData.id = resp.id; } localStorage.setItem("easier_1up_b37", JSON.stringify(thumbnailData)); } this.thumbnail = thumbnailData; const relatedPosts = document.querySelector("#related-posts-by-source p.fineprint a"); if (relatedPosts) { const shownCount = Number(relatedPosts.innerText.split(" ")[0]); let articles = document.querySelectorAll("#related-posts-by-source article"); if ((articles.length === 5 && shownCount > 5) || articles.length === shownCount); else { const url = new URL(relatedPosts.href); url.pathname = "/posts.json"; url.searchParams.append("limit", 5); fetch(url) .then(resp => resp.json()) .then(json => { articles = this.updateArticles(json, articles, true); articles.forEach(el => { const div = document.createElement("div"); this.addButton(el, div); el.querySelector(".post-preview-container").nextElementSibling.appendChild(div); }); }); } } const similar = document.getElementById("iqdb-similar"); this.observer = new MutationObserver(ms => ms.forEach(m => m.addedNodes.forEach(this.process.bind(this)))); this.observer.observe(similar, { subtree: true, childList: true }); }, async process(node) { if (node.className !== "iqdb-posts") return; let articles = node.querySelectorAll("#iqdb-similar article"); let shownCount = articles.length; let iqdbNoPostFound = shownCount === 0 && document.querySelector(".post-gallery-grid > p:only-child"); if (!iqdbNoPostFound && shownCount !== 5) { let iqdbResults = await this.iqdbReq(); if (iqdbResults.length !== shownCount) articles = this.updateArticles(iqdbResults, articles); } for (const post of articles) { const div = post.querySelector(".iqdb-similarity-score").parentElement; this.addButton(post, div); } this.observer?.disconnect(); }, copyTags(post, isParent) { const tags = post.dataset.tags.split(" ").filter(t => t === "social_commentary" || t.indexOf("commentary") == -1); document.querySelector(`input.radio_buttons[value='${post.dataset.rating}']`).checked = true; if (isParent) { document.getElementById("post_parent_id").value = post.dataset.id; } else tags.push("child:" + post.dataset.id); this.tagsField.value = tags.join(" ") + " "; this.tagsField.dispatchEvent(new InputEvent("input", { bubbles: true })); document.querySelector(".source-tab").click(); Danbooru.Utility.notice("Successfully copied tags. Please check the commentary tags."); }, addButton(post, div) { const setParent = document.createElement("a"); setParent.classList.add("inactive-link"); setParent.href = "#"; setParent.innerText = "parent"; setParent.addEventListener("click", e => { e.preventDefault(); this.copyTags(post, true); }); const setChild = document.createElement("a"); setChild.classList.add("inactive-link"); setChild.href = "#"; setChild.innerText = "child"; setChild.addEventListener("click", e => { e.preventDefault(); this.copyTags(post, false); }); div.children.length && div.appendChild(document.createTextNode(" | ")); div.appendChild(setParent); div.appendChild(document.createTextNode(" | ")); div.appendChild(setChild); }, async iqdbReq() { try { let mid = document.getElementById("media_asset_id").value; let resp = await ( await fetch(`/iqdb_queries.json?limit=5&search%5Bmedia_asset_id%5D=${mid}&search%5Bsimilarity%5D=50&search%5Bhigh_similarity%5D=70`) ).json(); if (Array.isArray(resp)) return resp; else throw new Error(JSON.stringify(resp)); } catch (e) { console.error("Error:", e); } }, updateArticles(posts, currentPosts, relatedSection = false) { currentPosts = Array.from(currentPosts); const currentPostIds = currentPosts.map(el => { return Number(el.getAttribute("data-id")); }); currentPostIds.push(0); let idx = 0, postsLength = posts.length; currentPostIds.forEach((pid, index) => { let htmlToInsert = ""; for (; idx < postsLength; idx++) { let post = relatedSection ? posts[idx] : posts[idx].post; if (post.id !== pid) { if (post.is_banned) htmlToInsert += relatedSection ? this.render(post) : this.render(post, posts[idx].score); } else break; } if (htmlToInsert) { if (pid === 0) { const prefix = relatedSection ? "#related-posts-by-source" : ".iqdb-posts"; document.querySelector(prefix + " .posts-container").insertAdjacentHTML("beforeend", htmlToInsert); } else currentPosts[index].insertAdjacentHTML("beforebegin", htmlToInsert); } }); const prefix = relatedSection ? "#related-posts-by-source" : "#iqdb-similar"; return document.querySelectorAll(prefix + " article"); }, render( { id, uploader_id, score, rating, tag_string, is_pending, is_flagged, is_deleted, has_children, parent_id, source, media_asset: { id: mid, image_width, image_height, file_size, file_ext } }, similarity ) { const dataFlag = is_pending ? "pending" : is_flagged ? "flagged" : is_deleted ? "deleted" : ""; const classList = ["post-preview", "post-preview-fit-compact", "post-preview-180"]; is_pending && classList.push("post-status-pending"); is_flagged && classList.push("post-status-flagged"); is_deleted && classList.push("post-status-deleted"); has_children && classList.push("post-status-has-children"); parent_id && classList.push("post-status-has-parent"); similarity && classList.push(similarity < 70 ? "iqdb-low-similarity hidden" : "iqdb-high-similarity"); const { url, width, height } = this.thumbnail; const similarityHtml = similarity ? `<div><a class="inactive-link iqdb-similarity-score" href="/iqdb_queries?post_id=${id}">${similarity.toFixed(0)}% similar</a></div>` : ""; return `<article id="post_${id}" class="${classList.join( " " )}" data-id="${id}" data-tags="${tag_string}" data-rating="${rating}" data-flags="${dataFlag}" data-score="${score}" data-uploader-id="${uploader_id}"> <div class="post-preview-container"> <a class="post-preview-link" draggable="false" href="/posts/${id}"> <picture><img src="${url}" width="${width}" height="${height}" class="post-preview-image" title="" alt="post #${id}"draggable="false" aria-expanded="false" data-title="${tag_string} rating:${rating} score:${score}"></picture> </a></div><div class="text-xs text-center mt-1"><div> <a rel="external noreferrer nofollow" title="${source}" class="inline-block align-top" href="${source}"> <svg class="icon svg-icon globe-icon h-4" viewBox="0 0 512 512"><use fill="currentColor" href="/packs/static/icons-${this.iconHash}.svg#globe"></use></svg> </a> <a href="/media_assets/${mid}">${this.formatBytes(file_size)} .${file_ext}, ${image_width}×${image_height}</a></div>${similarityHtml}</div> </article>`; }, formatBytes(bytes) { if (bytes === 0) return "0 Bytes"; const units = ["Bytes", "KB", "MB"]; const k = 1024; const i = Math.floor(Math.log(bytes) / Math.log(k)); const value = bytes / Math.pow(k, i); const formattedValue = value % 1 === 0 ? value.toFixed(0) : value.toFixed(2); return `${formattedValue} ${units[i]}`; } }; easier1Up.init();
Get a better experience by using it with the script in forum #312212.
Updated