Steam折扣截止日期查询

查询折扣截止日期

  1. // ==UserScript==
  2. // @name:zh-CN Steam折扣截止日期查询
  3. // @name Steam_Discount_Query
  4. // @namespace https://blog.chrxw.com
  5. // @supportURL https://blog.chrxw.com/scripts.html
  6. // @contributionURL https://afdian.com/@chr233
  7. // @version 1.5
  8. // @description:zh-CN 查询折扣截止日期
  9. // @description Query when the discounts expired
  10. // @author Chr_
  11. // @match https://store.steampowered.com/wishlist/*
  12. // @license AGPL-3.0
  13. // @icon https://blog.chrxw.com/favicon.ico
  14. // @grant GM_addStyle
  15. // ==/UserScript==
  16.  
  17. (async () => {
  18. "use strict";
  19.  
  20. const g_cache = {};
  21.  
  22. //初始化
  23. const t = setInterval(() => {
  24. for (let ele of document.querySelectorAll("div.Panel div[data-index]")) {
  25. addQueryButton(ele);
  26. }
  27. }, 1000);
  28.  
  29. const matchAppId = /app\/(\d+)/;
  30.  
  31. //添加按钮
  32. function addQueryButton(element) {
  33. const oldBtn = element.querySelector("button.sdq_listbtns");
  34. if (oldBtn) {
  35. return;
  36. }
  37.  
  38. const href = element.querySelector("a")?.getAttribute("href");
  39.  
  40. const match = href.match(matchAppId);
  41. if (!match) {
  42. return;
  43. }
  44. const appId = match[1];
  45.  
  46. const btn = document.createElement("button");
  47. btn.addEventListener(
  48. "click",
  49. (e) => {
  50. displaySaleEnds(appId, btn);
  51. e.preventDefault();
  52. },
  53. false
  54. );
  55. btn.className = "sdq_listbtns";
  56. btn.textContent = g_cache[appId] ?? "🔍";
  57.  
  58. if (btn.textContent.search(":") !== -1) {
  59. btn.className += " sdq_listbtns_alert";
  60. }
  61.  
  62. var inner = element.querySelector("div>div");
  63. inner.appendChild(btn);
  64. }
  65.  
  66. //显示折扣结束时间
  67. async function displaySaleEnds(appId, ele) {
  68. ele.enabled = false;
  69. ele.className += " sdq_listbtns_show";
  70. ele.textContent = "🔍……";
  71. fetchSaleEnds(appId)
  72. .then((endDate) => {
  73. ele.textContent = endDate;
  74. g_cache[appId] = endDate;
  75. if (endDate.search(":") !== -1) {
  76. ele.className += " sdq_listbtns_alert";
  77. }
  78. })
  79. .catch((err) => {
  80. let done = showAlert("网络错误", `<p>${err}</p>`, false);
  81. setTimeout(() => {
  82. done.Dismiss();
  83. }, 2000);
  84. dialog.Dismiss();
  85. })
  86. .finally(() => {
  87. ele.enabled = true;
  88. });
  89. }
  90.  
  91. //读取折扣结束时间
  92. function fetchSaleEnds(appId) {
  93. const regSaleEnds = new RegExp(
  94. /<p class="game_purchase_discount_countdown">(.+)<\/p>/,
  95. ""
  96. );
  97. const regDate = new RegExp(/\d+ 月 \d+ 日/, "");
  98. const regTimestamp = new RegExp(
  99. /InitDailyDealTimer\( \$DiscountCountdown, (\d+) \);/,
  100. ""
  101. );
  102.  
  103. return new Promise((resolve, reject) => {
  104. fetch(`https://store.steampowered.com/app/${appId}/?lang=schinese`, {
  105. method: "GET",
  106. credentials: "include",
  107. })
  108. .then(async (response) => {
  109. if (response.ok) {
  110. const html = await response.text();
  111. const saleEnds = html.match(regSaleEnds)?.pop();
  112. let endDate;
  113.  
  114. if (saleEnds) {
  115. endDate = saleEnds.match(regDate)?.pop();
  116. if (!endDate) {
  117. const endsTimestamp = html.match(regTimestamp)?.pop();
  118. const timestamp = parseInt(endsTimestamp) * 1000;
  119. const date = new Date(timestamp);
  120.  
  121. if (date.getDate() === date.getDate()) {
  122. endDate = `${date.getMonth() + 1
  123. } ${date.getDate()} ${date
  124. .getHours()
  125. .toString()
  126. .padStart(2, "0")}:${date
  127. .getMinutes()
  128. .toString()
  129. .padStart(2, "0")}`;
  130. } else {
  131. endDate = "解析失败";
  132. }
  133. }
  134. } else {
  135. endDate = "未打折";
  136. }
  137.  
  138. console.info(endDate);
  139. resolve(endDate);
  140. } else {
  141. resolve("请求失败");
  142. }
  143. })
  144. .catch((err) => {
  145. reject(err);
  146. });
  147. });
  148. }
  149. //显示提示
  150. function showAlert(title, text, succ = true) {
  151. return ShowAlertDialog(`${succ ? "✅" : "❌"}${title}`, text);
  152. }
  153. })();
  154.  
  155. GM_addStyle(`
  156. button.sdq_listbtns {
  157. position: absolute;
  158. z-index: 100;
  159. padding: 1px;
  160. right: 20px;
  161. top: 20px;
  162. }
  163. div.wishlist_row > button.sdq_listbtns {
  164. top: 35%;
  165. right: 33%;
  166. position: absolute;
  167. }
  168. button.sdq_listbtns_show,
  169. div.wishlist_row:hover button.sdq_listbtns {
  170. display: flex;
  171. }
  172. button.sdq_listbtns_alert {
  173. color: red;
  174. }
  175. `);

QingJ © 2025

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