Greasy Fork Total Downloads

Shows a user's total downloads.

当前为 2024-07-11 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Greasy Fork Total Downloads
  3. // @namespace -
  4. // @version 1.1.0
  5. // @description Shows a user's total downloads.
  6. // @author NotYou
  7. // @include *://greasyfork.org/*/users/*
  8. // @include *://sleazyfork.org/*/users/*
  9. // @match *://greasyfork.org/*/users/*
  10. // @match *://sleazyfork.org/*/users/*
  11. // @license GPL-3.0
  12. // @run-at document-body
  13. // @grant GM_xmlhttpRequest
  14. // @require https://update.greasyfork.org/scripts/445697/1244619/Greasy%20Fork%20API.js
  15. // ==/UserScript==
  16.  
  17. ~function(GreasyFork) {
  18. class Installs {
  19. static async getData(userId) {
  20. const userData = await GreasyFork.getUserData(userId)
  21.  
  22. return userData.all_listable_scripts.reduce((acc, curr) => {
  23. acc.total += curr.total_installs
  24. acc.daily += curr.daily_installs
  25.  
  26. return acc
  27. }, {
  28. total: 0,
  29. daily: 0
  30. })
  31. }
  32. }
  33.  
  34. class User {
  35. static getId(url) {
  36. const match = url.match(/https?:\/\/(greasyfork|sleazyfork)\.org\/[a-zA-Z]+(\-[a-zA-Z]+)?\/users\/(?<userId>\d+)/)
  37.  
  38. if (match) {
  39. const { userId } = match.groups
  40.  
  41. return userId
  42. } else {
  43. return '1'
  44. }
  45. }
  46.  
  47. static getLocale(languageSelectorLocale) {
  48. return languageSelectorLocale ? languageSelectorLocale.value || 'en-US' : 'en-US'
  49. }
  50. }
  51.  
  52. class Stat {
  53. static createItem(data, locale, text, color) {
  54. const node = document.createElement('span')
  55. node.style.fontSize = '15px'
  56. node.style.borderRadius = '3px'
  57. node.style.backgroundColor = 'rgb(45, 45, 45)'
  58. node.style.color = 'rgb(255, 255, 255)'
  59. node.style.margin = '0 4px'
  60. node.style.padding = '0 4px'
  61. node.style.display = 'inline-flex'
  62. node.style.alignItems = 'center'
  63. node.style.gap = '4px'
  64. node.style.outline = `2px solid ${color}`
  65. node.textContent = data.toLocaleString(locale) + ' ' + text
  66.  
  67. const circle = document.createElement('span')
  68. circle.style.width = '8px'
  69. circle.style.height = '8px'
  70. circle.style.borderRadius = '50%'
  71. circle.style.background = color
  72.  
  73. node.prepend(circle)
  74.  
  75. return node
  76. }
  77. }
  78.  
  79. class Main {
  80. static init() {
  81. window.addEventListener('DOMContentLoaded', async () => {
  82. const { href } = location
  83. const $languageSelectorLocale = document.querySelector('#language-selector-locale')
  84. const userId = User.getId(href)
  85. const userLocale = User.getLocale($languageSelectorLocale)
  86. const installsData = await Installs.getData(userId)
  87. const { total, daily } = installsData
  88. const $total = Stat.createItem(total, userLocale, 'Installs', 'rgb(123, 23, 23)')
  89. const $daily = Stat.createItem(daily, userLocale, 'Daily Installs', 'rgb(185, 32, 32)')
  90. const $header = document.querySelector('div.sidebarred-main-content h3:first-child')
  91.  
  92. $header.appendChild($total)
  93. $header.appendChild($daily)
  94. })
  95. }
  96. }
  97.  
  98. Main.init()
  99. }(GreasyFork)
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.