DPPVAF2025

Personal score viewer for Derpibooru April Fool's 2025

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name        DPPVAF2025
// @namespace   io.github.poneyclairdelune.derpi2025Viewer
// @match       https://derpibooru.org/profiles/*
// @homepage    https://github.com/PoneyClairDeLune/custom-utils/blob/main/derpibooru/dppvaf2025.user.js
// @grant       none
// @version     0.3.4
// @author      -
// @description Personal score viewer for Derpibooru April Fool's 2025
// @run-at      document-idle
// @license     GNU AGPL v3.0
// ==/UserScript==
"use strict";

const scoreClassRender = [[25000, 'max'], [10000, 'afk'], [5000, 'sweat'], [2500, 'idk'], [1500, 's'], [900, 'a'], [600, 'b'], [400, 'c'], [250, 'd'], [100, 'e'], [0, 'f']];
const getScoreClassRender = (score, isCheater) => {
  if (isCheater) {
    return 'cheater';
  };
  for (let nibble of scoreClassRender) {
    if (score >= nibble[0]) {
      return nibble[1];
    };
  };
  return 'cheater';
};
const scoreClassTier = [[5000, 'True Gamer'], [2500, 'Diamond'], [1500, 'Platinum'], [900, 'Gold'], [400, 'Silver'], [1, 'Bronze'], [0, 'Blank']];
const getScoreClassTier = (score, isCheater) => {
  if (isCheater) {
    return "Cheetah";
  };
  for (let nibble of scoreClassTier) {
    if (score >= nibble[0]) {
      return nibble[1];
    };
  };
  return "Cheetah";
};
const achievementDetails = JSON.parse(`[{"n":"Page Loader","d":"Load any page","p":5,"i":false},{"n":"Achievement Viewer","d":"View your achievements","p":5,"i":false},{"n":"Do Nothing 1","d":"Do nothing for 5 seconds","p":5,"i":false},{"n":"Do Nothing 2","d":"Do nothing for 1 minute","p":10,"i":false},{"n":"Do Nothing 3","d":"Do nothing for 10 minutes","p":20,"i":false},{"n":"Do Nothing 4","d":"Do nothing for 30 minutes","p":100,"i":false},{"n":"Do Nothing 5","d":"Do nothing for 1 hour","p":500,"i":false},{"n":"Do Nothing 6","d":"Do nothing for 2 hours","p":1000,"i":false},{"n":"Do Nothing 7","d":"Do nothing for 6 hours","p":2500,"i":false},{"n":"Touch Grass","d":"Do nothing for a day","p":5000,"i":false},{"n":"Mouse Mover","d":"Move the mouse! Or finger.","p":5,"i":false},{"n":"Secret Achievement","d":"Very sneaky...","p":99,"i":true},{"n":"Clicker","d":"You sure love clicking something!","p":5,"i":false},{"n":"Touchscreen User","d":"You can touch! Wow!","p":5,"i":false},{"n":"The First of Many","d":"The image where the journey began","p":5,"i":false},{"n":"Nice","d":"Seks number is very funny","p":5,"i":false},{"n":"Image Viewer","d":"View any image!","p":5,"i":false},{"n":"Khajit Has the Wares","d":"...if you have the coin","p":5,"i":false},{"n":"What a bunch of losers","d":"Visit the site staff page","p":5,"i":false},{"n":"Index Get","d":"That's a lot of zeroes...","p":10,"i":false},{"n":"Resetter","d":"Reset all your achievements","p":10,"i":false},{"n":"Uploader","d":"You're gonna upload, right? Right?","p":5,"i":false},{"n":"Debater","d":"Visit the forums","p":5,"i":false},{"n":"Clicker 2","d":"Click 5 times, impressive achievement","p":5,"i":false},{"n":"Clicker 3","d":"Click 20 times, keep going...","p":10,"i":false},{"n":"Clicker 4","d":"Click 100 times, yes, more!","p":20,"i":false},{"n":"Clicker 5","d":"Click 500 times, almost there!","p":30,"i":false},{"n":"Clicker God","d":"Click 1000 times, ahh, bliss!","p":50,"i":false},{"n":"Upvoter","d":"Upvote something!","p":10,"i":false},{"n":"Upvoter 2","d":"Upvote 10 images!","p":20,"i":false},{"n":"Upvoter 3","d":"Upvote 50 images!","p":30,"i":false},{"n":"Upvoter God","d":"Upvote 100 images!","p":50,"i":false},{"n":"Mouse Mover 2","d":"Move the mouse over 1000 pixels","p":5,"i":false},{"n":"Mouse Mover 3","d":"Move the mouse over 10K pixels","p":10,"i":false},{"n":"Mouse Mover 4","d":"Move the mouse over 100K pixels","p":20,"i":false},{"n":"Mouse Mover 5","d":"Move the mouse over 1M pixels","p":30,"i":false},{"n":"The Great Mouser","d":"Move the mouse over 10M pixels","p":50,"i":false},{"n":"Mouse Mover Infinity","d":"Move the mouse a bit too hard","p":1,"i":true},{"n":"Wait, that's just the homepage","d":"Always has been","p":5,"i":false},{"n":"Home, sweet home","d":"Visit the homepage","p":5,"i":false},{"n":"Exhibitionist","d":"View the galleries list","p":5,"i":false},{"n":"Mom look I am on TV","d":"View the livestreams directory","p":5,"i":false},{"n":"Seeker","d":"Search for something!","p":5,"i":false},{"n":"Reverse Seeker","d":"Search for an image which you already have","p":5,"i":false},{"n":"Wall of Green","d":"Visit the tags directory","p":5,"i":false},{"n":"Sensational Headlines","d":"View recent comments","p":5,"i":false},{"n":"Trendy Brandy","d":"View currently trending images","p":5,"i":false},{"n":"Manuscripts of the Ancients","d":"View a static page","p":5,"i":false},{"n":"Read the Rules","d":"Seriously, read them, carefully.","p":10,"i":false},{"n":"Page Loader 2","d":"Load 5 pages","p":10,"i":false},{"n":"Page Loader 3","d":"Load 20 pages","p":15,"i":false},{"n":"Page Loader 4","d":"Load 50 pages","p":20,"i":false},{"n":"Page Loader 5","d":"Load 500 pages","p":30,"i":false},{"n":"Page Loader God","d":"Load 1000 pages","p":50,"i":false},{"n":"Faver","d":"Favorite something!","p":10,"i":false},{"n":"Faver 2","d":"Favorite 10 images!","p":20,"i":false},{"n":"Faver 3","d":"Favorite 50 images!","p":30,"i":false},{"n":"Faver God","d":"Favorite 100 images!","p":50,"i":false},{"n":"I swear I'm 18","d":"Visit the filters page","p":5,"i":false},{"n":"Private Communications","d":"Visit the private messages page","p":5,"i":false},{"n":"Latest Happenings","d":"At least these don't make that chirping noise...","p":5,"i":false},{"n":"It's you!","d":"Visit your own user profile","p":10,"i":false},{"n":"Stalker Behavior","d":"Stalk someone's user profile","p":5,"i":false},{"n":"Tag Editor","d":"Edit some tags","p":10,"i":false},{"n":"Tagger 2","d":"Edit tags 5 times","p":20,"i":false},{"n":"Tagger 3","d":"Edit tags 20 times","p":30,"i":false},{"n":"Tagger 4","d":"Edit tags 50 times","p":50,"i":false},{"n":"Tag God","d":"Edit tags 100 times","p":100,"i":false},{"n":"Eww Anthro","d":"...but seriously if you don't like it, just filter it, rather than commenting on it, you know who you are.","p":5,"i":false},{"n":"Spicy Browsing","d":"Let's hope you're not at work","p":5,"i":false},{"n":"Fearless Browsing","d":"Use the 'Everything' filter","p":5,"i":false},{"n":"Shameless Plug","d":"Locate the artist tags of the site admins","p":10,"i":false},{"n":"Furry!","d":"Fluffy critters, these things... fluffy critters","p":5,"i":false},{"n":"Gamer","d":"Input the Konami code","p":30,"i":false},{"n":"True Gamer","d":"Input the full Konami code","p":50,"i":false},{"n":"Best Pony","d":"Type the name of the best pony","p":5,"i":false},{"n":"The Other Best Pony","d":"Type the name of the ACTUAL best pony","p":10,"i":false},{"n":"Cry About It","d":"Complain about the event","p":0,"i":false},{"n":"Thanks","d":"Praise the event","p":10,"i":false},{"n":"Eww Politics","d":"Say something political","p":5,"i":false},{"n":"😳","d":"L-Lewd...","p":10,"i":false},{"n":"Pepper","d":"Spot a repper","p":10,"i":false},{"n":"Scroller","d":"Scroll the page","p":5,"i":false},{"n":"Scroller 2","d":"Scroll 1000 pixels","p":5,"i":false},{"n":"Scroller 3","d":"Scroll 10K pixels","p":15,"i":false},{"n":"Scroller 4","d":"Scroll 100K pixels","p":20,"i":false},{"n":"Scroller 5","d":"Scroll 1M pixels","p":30,"i":false},{"n":"Scroller God","d":"Scroll 10M pixels","p":50,"i":false},{"n":"Downvote = Ban","d":"Locate the artist tags of the site staff","p":10,"i":false},{"n":"Help Me","d":"Site staff provide many opportunities for contacting them","p":5,"i":false},{"n":"Thorty Dorra Plz","d":"Consider the benefits of the Derpibooru Premium subscription!","p":5,"i":false},{"n":"Upvoter Overlord","d":"Upvote 1000 images!","p":150,"i":false},{"n":"Faver Overlord","d":"Favorite 1000 images!","p":150,"i":false},{"n":"Upvoter Infinity","d":"Upvote 10000 images!","p":500,"i":false},{"n":"Faver Infinity","d":"Favorite 10000 images!","p":500,"i":false},{"n":"Tag Overlord","d":"Edit tags 250 times","p":250,"i":false},{"n":"The Living Tag","d":"Edit tags 1000 times","p":1000,"i":false},{"n":"Commenter","d":"Post a comment","p":5,"i":false},{"n":"Wall Poster","d":"If you get this achievement you are holding it wrong","p":1,"i":true},{"n":"Commenter 2","d":"Post 5 comments","p":10,"i":false},{"n":"Commenter 3","d":"Post 10 comments","p":15,"i":false},{"n":"Commenter 4","d":"Post 25 comments","p":30,"i":false},{"n":"Commenter 5","d":"Post 50 comments","p":75,"i":false},{"n":"Commenter God","d":"Post 100 comments","p":150,"i":false},{"n":"Poster","d":"Post a reply to a forum topic","p":5,"i":false},{"n":"Poster 2","d":"Post 5 replies to forum topics","p":10,"i":false},{"n":"Poster 3","d":"Post 10 replies to forum topics","p":15,"i":false},{"n":"Poster 4","d":"Post 25 replies to forum topics","p":30,"i":false},{"n":"Poster 5","d":"Post 50 replies to forum topics","p":75,"i":false},{"n":"Poster God","d":"Post 100 replies to forum topics","p":150,"i":false},{"n":"The Beginning","d":"Your journey begins! Unlock any achievement.","p":5,"i":false},{"n":"The Plot Thickens","d":"You earned enough points for a silver trophy, keep it up!","p":10,"i":false},{"n":"Getting Stronger","d":"At 900 points you are eligible for a gold trophy, you really are good at this.","p":20,"i":false},{"n":"Hard Stuck Plat","d":"Platinum trophy is obtained at 1500 points! I bet you hope you don't get stuck at this level.","p":30,"i":false},{"n":"DIAMONDS!!!","d":"Your quest has led you to obtain the diamond trophy at 2500 point!","p":50,"i":false},{"n":"The One","d":"You are the one true gamer (5000 points).","p":100,"i":false},{"n":"IT'S OVER 9000!!!","d":"Obtain more than 9000 points.","p":250,"i":false},{"n":"Journey's End","d":"Unlock every single other achievement.","p":11020,"i":false}]`);
const calculateAchievements = () => {
  let totalScore = 0;
  let isCheater = false;
  let clientSet = new Set();
  for (let e of localStorage.getItem("achievements").split(",")) {
    let achievementId = parseInt(e);
    if (Number.isNaN(e) || e === null || e === undefined) {
      continue;
    };
    let tA = achievementDetails[achievementId];
    if (tA) {
      if (tA.i) {
        console.debug(`Cheetah found: ${e} @ ${tA.p}pt (${tA.n})`);
        isCheater = true;
      };
      totalScore += tA.p;
    } else {
      console.debug(`Invalid achievement found: ${e}`);
      isCheater = true;
    };
  };
  return [totalScore, isCheater];
};
const statsDetails = {
  "ach_mousedistance": "Mouse travelled",
  "ach_scroll": "Mouse scrolled",
  "ach_mouseclicks": "Mouse clicks",
  "ach_pageloads": "Page loads",
  "ach_tagedits": "Tag edits",
  "ach_faves": "Faves",
  "ach_upvotes": "Upvotes",
  "ach_comments": "Comments",
  "ach_posts": "Forum posts"
};

const createDiv = (classList, content) => {
  let el = document.createElement("div");
  if (classList?.length > 0) {
    for (let e of classList) {
      el.classList.add(e);
    };
  };
  if (content?.length > 0) {
    for (let e of content) {
      el.append(e);
    };
  };
  return el;
};
const renderAchTree = () => {
  let renderTitle = createDiv(["block__header"]);
  renderTitle.innerHTML = `<span class="block__header__title">April Fool's 2025 Achievements Earned</span>`;
  let renderList = [], renderedAchievements = 0;
  let achList = localStorage.getItem("achievements").split(",").map((e) => {return parseInt(e)}).sort((a, b) => {return a - b;}).sort((a, b) => {return (achievementDetails[b]?.p ?? 0) - (achievementDetails[a]?.p ?? 0)});
  for (let achId of achList) {
    let achObj = achievementDetails[achId];
    if (!achObj) {
      continue;
    };
    let e0 = document.createElement("b");
    e0.append(achObj.n);
    let e = createDiv(["block__content", "alternating-color"], [e0, ` (${achObj.p} pt): ${achObj.d}`]);
    if (achObj.i) {
      e.classList.add("d2v-ach-honeypot");
    };
    renderList.push(e);
    renderedAchievements ++;
  };
  renderTitle.append(`(${renderedAchievements}/115+3)`);
  return createDiv(["block"], [renderTitle, createDiv(["block__content"], [createDiv(["block"], renderList)])]);
};
const renderStatTree = () => {
  let renderTitle = createDiv(["block__header"]);
  renderTitle.innerHTML = `<span class="block__header__title">April Fool's 2025 Statistics</span>`;
  let renderList = [];
  for (let key in statsDetails) {
    let e0 = document.createElement("b");
    e0.append(statsDetails[key]);
    renderList.push(createDiv(["block__content", "alternating-color"], [e0, `: ${localStorage.getItem(key) ?? "0"}`]));
  };
  return createDiv(["block"], [renderTitle, createDiv(["block__content"], [createDiv(["block"], renderList)])]);
};

let scoreVerdict = calculateAchievements();
let scoreMount = document.createElement("div");
scoreMount.classList.add("d2v-rank");
scoreMount.classList.add(`d2v-rank-${getScoreClassRender(... scoreVerdict)}`);
let avatarMounter = document.querySelector("div.profile-top__avatar");
let achListMounter = document.querySelector("div.column-layout__main");
if (avatarMounter.querySelector("a")) {
  scoreMount.innerHTML = `<span><b>Points</b>: ${scoreVerdict[0]}</span><br/><span><b>Rank</b>: ${getScoreClassTier(... scoreVerdict)}</span>`;
  avatarMounter.appendChild(scoreMount);
  achListMounter.appendChild(renderStatTree());
  achListMounter.appendChild(renderAchTree());
  let styles = document.createElement("style");
  styles.innerHTML = `.d2v-ach-honeypot {outline: 1px solid #f00}.d2v-rank {padding: 4px;text-align: center;color: #ddd;margin: 2px;}.d2v-rank-f {background: #317a7a;}.d2v-rank-e {background: #1a6b28;}.d2v-rank-d {background: #1d3163;}.d2v-rank-c {background: #431d63;}.d2v-rank-b {background: #631d41;}.d2v-rank-a {background: #967b02;}.d2v-rank-s {background: #c24b07;}.d2v-rank-idk {background: linear-gradient(30deg, #ad0802, #dd3502, #f08a36);}.d2v-rank-sweat {background: linear-gradient(to right, #940101, #832c04, #8f8f00, #008100, #094088, #850b85);}.d2v-rank-afk {background: linear-gradient(to right, #850b85, #6803c7, #2806bd);}@keyframes gradient {0% {background-position: 0% 50%;}50% {background-position: 100% 50%;}100% {background-position: 0% 50%;}}.d2v-rank-max{background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);background-size: 400% 400%;animation: gradient 15s ease infinite;font-weight: bold;}.d2v-rank-cheater{background: #801c26;}`;
  document.head.appendChild(styles);
};