Greasy Fork镜像 支持简体中文。

Pixiv Bookmark Milestone Analytics

Display a dashboard table of times when artworks reach 1000 bookmark milestones. The script must remain running to collect statistics accurately.

  1. // ==UserScript==
  2. // @name Pixiv Bookmark Milestone Analytics
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.3
  5. // @description Display a dashboard table of times when artworks reach 1000 bookmark milestones. The script must remain running to collect statistics accurately.
  6. // @author cro
  7. // @match https://www.pixiv.net/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=pixiv.net
  9. // @grant GM_setValue
  10. // @grant GM_getValue
  11. // @grant GM_addStyle
  12. // ==/UserScript==
  13. /* jshint esversion: 6 */
  14.  
  15. (function() {
  16. 'use strict';
  17. GM_addStyle(".scrolltable { display:block; border-spacing:0px; display:block; overflow:auto; height: 400px; }");
  18. GM_addStyle(".scrolltable td { min-width: 100px; width: 100px; }");
  19.  
  20. let time_interval = 1000 * 60;
  21. let milestone_interval = 1000;
  22. let fetch_headers = {
  23. "headers": {
  24. "accept": "application/json",
  25. "accept-language": "en-US,en;q=0.9,ja;q=0.8",
  26. "sec-ch-ua": "\"Not_A Brand\";v=\"99\", \"Google Chrome\";v=\"109\", \"Chromium\";v=\"109\"",
  27. "sec-ch-ua-mobile": "?0",
  28. "sec-ch-ua-platform": "\"Windows\"",
  29. "sec-fetch-dest": "empty",
  30. "sec-fetch-mode": "cors",
  31. "sec-fetch-site": "same-origin",
  32. },
  33. "referrer": "https://www.pixiv.net/dashboard",
  34. "referrerPolicy": "strict-origin-when-cross-origin",
  35. "body": null,
  36. "method": "GET",
  37. "mode": "cors",
  38. "credentials": "include"
  39. };
  40.  
  41. let settings_key = "cro_pixiv_bma_settings";
  42. let settings = {
  43. order_asc: false,
  44. };
  45. Object.assign(settings, JSON.parse(GM_getValue(settings_key, "{}")));
  46.  
  47. let data_key = "cro_pixiv_bma";
  48. let data = JSON.parse(GM_getValue(data_key, "{}"));
  49. let table = document.createElement("table");
  50. table.id = data_key;
  51. table.classList.add('scrolltable');
  52.  
  53. let order_button = document.createElement("button");
  54.  
  55. let order_button_set_text = () => void(order_button.innerText = `ORDER: ${settings.order_asc ? "ASC" : "DESC"}`);
  56. order_button_set_text();
  57.  
  58. let get_latest_data = function() {
  59. return fetch("https://www.pixiv.net/ajax/dashboard/works/illust/request_strategy?lang=en", fetch_headers);
  60. };
  61.  
  62. let initial_record = function(work) {
  63. return {
  64. title: work.illust.title,
  65. thumbnail: work.illust.url,
  66. last_milestone: 0,
  67. milestones: [],
  68. };
  69. };
  70.  
  71. let update_record = function(record, bookmarks) {
  72. let last_milestone = Math.floor(bookmarks / milestone_interval) * milestone_interval;
  73. if (last_milestone <= record.last_milestone) {
  74. return;
  75. }
  76. record.last_milestone = last_milestone;
  77. record.milestones.push([last_milestone, Date.now()]);
  78. };
  79.  
  80. let update_data = function(pixiv_data) {
  81. pixiv_data.body.data.works.forEach(function(work, index)
  82. {
  83. work.illust = pixiv_data.body.thumbnails.illust[index];
  84.  
  85. if (!(work.workId in data))
  86. {
  87. data[work.workId] = initial_record(work);
  88. }
  89.  
  90. update_record(data[work.workId], work.bookmarkCount);
  91. });
  92.  
  93. GM_setValue(data_key, JSON.stringify(data));
  94. };
  95.  
  96. let update_table = function() {
  97. let scrollTop = table.scrollTop;
  98. let scrollLeft = table.scrollLeft;
  99. table.innerHTML = "";
  100. let ids = Object.keys(data);
  101. ids = ids.sort((a, b) => b - a);
  102. for (let id of ids)
  103. {
  104. let record = data[id];
  105. let row = table.insertRow();
  106. let cell = row.insertCell();
  107. let link = document.createElement('a');
  108. link.href = `/artworks/${id}`;
  109. let thumbnail = document.createElement('img');
  110. thumbnail.src = record.thumbnail;
  111. thumbnail.height = 50;
  112. link.append(thumbnail);
  113. cell.append(link);
  114. cell.style.minWidth = 50;
  115.  
  116. cell = row.insertCell();
  117. link = document.createElement('a');
  118. link.href = `/artworks/${id}`;
  119. link.append(record.title);
  120. cell.append(link);
  121.  
  122. let milestones = [...record.milestones];
  123. if (settings.order_asc == false) {
  124. milestones.reverse();
  125. }
  126.  
  127. for (let [count, timestamp] of milestones)
  128. {
  129. row.insertCell().innerHTML = `${count} - ${new Date(timestamp).toLocaleString()}`;
  130. }
  131. }
  132. table.scrollTop = scrollTop;
  133. table.scrollLeft = scrollLeft;
  134. };
  135.  
  136. let inject_table = function() {
  137. if (window.location.pathname != "/dashboard") {
  138. return;
  139. }
  140. let maybe_table = document.querySelector(`#${data_key}`);
  141. if (!maybe_table) {
  142. let dock = document.querySelector("body");
  143. dock.prepend(table);
  144. dock.prepend(order_button);
  145. }
  146. };
  147.  
  148. order_button.onclick = function() {
  149. settings.order_asc = !settings.order_asc;
  150. GM_setValue(settings_key, JSON.stringify(settings));
  151. order_button_set_text();
  152. update_table();
  153. };
  154.  
  155. let update = function(pixiv_data) {
  156. update_data(pixiv_data);
  157. update_table();
  158. };
  159.  
  160. let process = function() {
  161. if (window.location.pathname != "/dashboard") {
  162. return;
  163. }
  164. get_latest_data()
  165. .then(x => x.json())
  166. .then(x => update(x));
  167. };
  168.  
  169. process();
  170. let interval = setInterval(process, time_interval);
  171. setInterval(inject_table, 1000);
  172. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址