steamAny

steam anywhere

目前为 2022-11-20 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name steamAny
  3. // @namespace tea.pm
  4. // @match https://store.steampowered.com/app/*
  5. // @include *
  6. // @grant GM_setValue
  7. // @grant GM_getValue
  8. // @grant GM_xmlhttpRequest
  9. // @version 1.1
  10. // @author cljnnn
  11. // @license MIT
  12. // @description steam anywhere
  13. // ==/UserScript==
  14.  
  15. function xhr(option) {
  16. return new Promise((resolve, reject) => {
  17. GM_xmlhttpRequest({
  18. ...option,
  19. onerror: reject,
  20. onload: resolve,
  21. });
  22. });
  23. }
  24.  
  25. async function get(endpoint, headers = null) {
  26. try {
  27. console.log(`getting json response:${endpoint}`)
  28. let response = await xhr({
  29. method: "GET",
  30. url: endpoint,
  31. headers: headers
  32. });
  33. response = JSON.parse(response.responseText)
  34. console.log('in get method', `${response}`)
  35. return response;
  36. } catch (e) {
  37. console.error(`error when processing ${endpoint}`, e);
  38. return null;
  39. }
  40. }
  41.  
  42. const update_interval = 1000 * 60 * 60 * 0.5;
  43. async function refreshUserSteam() {
  44. const cached = GM_getValue("steam", null);
  45. if (cached && Date.now() - cached.last_update < update_interval) {
  46. return cached;
  47. }
  48. let webResult = await get(`https://store.steampowered.com/dynamicstore/userdata/?t=${Date.now()}`);
  49. if (webResult) {
  50. let result = {
  51. last_update: Date.now(),
  52. lookup: {}
  53. };
  54. for (const appId of webResult.rgWishlist) {
  55. result.lookup['app/'+appId] = 'wish';
  56. }
  57. for (const subId of webResult.rgOwnedPackages) {
  58. result.lookup['sub/'+subId] = 'owned';
  59. }
  60. for (const appId of webResult.rgOwnedApps) {
  61. result.lookup['app/'+appId] = 'owned';
  62. }
  63. GM_setValue("steam", result);
  64. return result;
  65. }
  66. return cached;
  67. }
  68.  
  69. let userdata = null;
  70. const pattern = /[\W^](store\.steampowered\.com|steamcommunity\.com)\/((app|sub)\/\d+)/;
  71.  
  72. async function handle(node) {
  73. if (node === null || typeof node !== 'object' || !('querySelectorAll' in node)) return;
  74. var links = node.querySelectorAll('a:not(.steam_processed)');
  75. for (const link of links) {
  76. var m = pattern.exec(link.href);
  77. if (!m) continue;
  78. if (userdata === null) userdata = await refreshUserSteam();
  79. if (userdata === null) return;
  80. const gameStatus = userdata.lookup[m[2]];
  81. if (!gameStatus) continue;
  82. let oldStyle = link.getAttribute('style');
  83. oldStyle = oldStyle?oldStyle:"";
  84. if (gameStatus === 'owned') {
  85. link.setAttribute('style', 'background: rgba(56, 142, 60, 0.75) !important; color: white !important;' + oldStyle);
  86. }
  87. if (gameStatus === 'wish') {
  88. link.setAttribute('style', 'background: rgba(2, 136, 209, 0.75) !important; color: white !important;' + oldStyle);
  89. }
  90. link.classList.add('steam_processed');
  91. }
  92. }
  93.  
  94. function action(changes, observer) {
  95. for (let mutation of changes) {
  96. handle(mutation.target);
  97. for (let node of mutation.addedNodes) {
  98. handle(node);
  99. }
  100. }
  101. }
  102.  
  103. var observer = new MutationObserver(action);
  104. observer.observe(document.body, { childList: true, subtree: true });
  105. handle(document.body);

QingJ © 2025

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