Steam 创意工坊自动订阅
// ==UserScript==
// @name Steam 创意工坊自动订阅
// @name:en Steamcommunity Auto Subscribe
// @description Steam 创意工坊自动订阅
// @version 0.1.3
// @author Yiero
// @namespace https://github.com/AliubYiero/TamperMonkeyScripts
// @grant GM_getValue
// @grant GM_notification
// @grant window.close
// @match https://steamcommunity.com/sharedfiles/filedetails/*
// @license GPL-3
// ==/UserScript==
/* ==UserConfig==
配置项:
AppIds:
title: "应用id (多个id通过逗号分隔)\n(打开商店页面, 地址栏中游戏/软件名前的纯数字)"
description: "应用id"
type: text
default: ""
autoClose:
title: "订阅后, 自动关闭页面"
description: "是否在订阅完成后, 自动关闭页面"
type: checkbox
default: false
==/UserConfig== */
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
const getElement = (selector, parent = document.body, timeout = 0) => {
return new Promise((resolve) => {
let result = parent.querySelector(selector);
if (result) {
return resolve(result);
}
let timer;
const observer = new window.MutationObserver((mutations) => {
for (let mutation of mutations) {
for (let addedNode of mutation.addedNodes) {
if (addedNode instanceof Element) {
result = addedNode.matches(selector) ? addedNode : addedNode.querySelector(selector);
if (result) {
observer.disconnect();
timer && clearTimeout(timer);
setTimeout(() => resolve(result), 500);
}
}
}
}
});
observer.observe(parent, {
childList: true,
subtree: true
});
if (timeout > 0) {
timer = setTimeout(() => {
observer.disconnect();
return resolve(null);
}, timeout);
}
});
};
const getPageInfo = () => {
const getAppName = () => {
var _a;
return ((_a = document.querySelector(".apphub_AppName")) == null ? void 0 : _a.textContent) || "";
};
const getAppId = () => {
const shopLinkSelector = '.apphub_OtherSiteInfo > a[href^="https://store.steampowered.com/app/"]';
const shopLink = document.querySelector(shopLinkSelector);
if (!shopLink) {
return -1;
}
const appId = Number(shopLink.dataset.appid);
return appId;
};
const getFileName = () => {
var _a;
return ((_a = document.querySelector(".workshopItemTitle")) == null ? void 0 : _a.textContent) || "";
};
const getUserName = () => {
var _a;
return ((_a = document.querySelector("#account_pulldown")) == null ? void 0 : _a.textContent) || "\u672A\u767B\u5F55\u7528\u6237";
};
return {
appName: getAppName(),
appId: getAppId(),
fileName: getFileName(),
userName: getUserName()
};
};
const notify = (title, text = "") => {
const steamImage = "https://steamcommunity.com/favicon.ico";
GM_notification({
title: `[Steam \u521B\u610F\u5DE5\u574A\u81EA\u52A8\u8BA2\u9605] ${title}`,
text,
image: steamImage,
timeout: 1e3
});
};
const notifySubscribe = (info) => {
const {
appName = "",
appId = -1,
fileName = "",
userName = "",
subscribeAction = "add"
} = info;
const subscribeActionMapper = {
add: "\u5DF2\u6DFB\u52A0\u81F3\u60A8\u7684\u8BA2\u9605\u5939",
remove: "\u5DF2\u4ECE\u60A8\u7684\u8BA2\u9605\u5939\u4E2D\u79FB\u9664"
};
const subscribeStatText = subscribeActionMapper[subscribeAction];
const notifyTitle = `\u8BA2\u9605\u60C5\u51B5\u53D8\u66F4`;
const date = (/* @__PURE__ */ new Date()).toLocaleString();
notify(
notifyTitle,
[
`\u7269\u54C1\u300C${fileName}\u300D${subscribeStatText}. `,
"",
`\u5E94\u7528: ${appName}`,
`\u7528\u6237: ${userName}`,
`\u65E5\u671F: ${date}`
].join("\n")
);
};
class Countdown {
constructor(callback, delayPerMs) {
__publicField(this, "timer", -1);
__publicField(this, "delayPerMs", 2e4);
__publicField(this, "callback");
this.callback = callback;
this.delayPerMs = delayPerMs;
}
start() {
this.timer = setTimeout(this.callback, this.delayPerMs);
}
stop() {
clearTimeout(this.timer);
}
}
const subscribeCountdown = () => {
return new Countdown(() => {
window.location.reload();
}, 15e3);
};
const listenerNodeUpdate = (subscribeTextNode) => {
const pageInfo = getPageInfo();
const autoClose = GM_getValue("\u914D\u7F6E\u9879.autoClose", false);
const subscribeCountdownInstance = subscribeCountdown();
autoClose && subscribeCountdownInstance.start();
const observer = new MutationObserver((records) => {
subscribeCountdownInstance.stop();
const subscribeButtonRecord = records.find((record) => record.target.id === "SubscribeItemOptionAdd");
const isOldSelected = subscribeButtonRecord.oldValue.includes("selected");
const isNewSelected = subscribeButtonRecord.target.classList.contains("selected");
if (!isOldSelected && isNewSelected) {
notifySubscribe({
...pageInfo,
subscribeAction: "remove"
});
observer.disconnect();
return;
}
notifySubscribe({
...pageInfo,
subscribeAction: "add"
});
if (autoClose) {
window.close();
}
observer.disconnect();
});
observer.observe(subscribeTextNode, {
attributeOldValue: true,
subtree: true,
attributeFilter: ["class"]
});
return observer;
};
const subscribeFile = () => {
const subscribeTextSelector = ".subscribeText";
const subscribeTextNode = document.querySelector(subscribeTextSelector);
subscribeTextNode.click();
listenerNodeUpdate(subscribeTextNode);
};
const getUserLoginStat = () => {
const notificationButtonSelector = "#header_notification_area";
return Boolean(document.querySelector(notificationButtonSelector));
};
class AppIdStorage {
/**
* 返回数组
*
* @returns {number[]}
*/
static get() {
const gameIdString = GM_getValue(this.key, "");
const gameIdList = gameIdString.split(/,\s*/).map((item) => Number(item));
return gameIdList;
}
}
__publicField(AppIdStorage, "key", "\u914D\u7F6E\u9879.AppIds");
const containGame = () => {
const { appId } = getPageInfo();
const appIdList = AppIdStorage.get();
return appIdList.includes(appId);
};
const getSubscribeStat = () => {
const selectedSubscribeOptionSelector = ".subscribeText > .selected";
const selectedMapper = {
SubscribeItemOptionAdd: false,
SubscribeItemOptionSubscribed: true
};
const selectedSubscribeOption = document.querySelector(selectedSubscribeOptionSelector);
if (!selectedSubscribeOption) {
return true;
}
const selectedSubscribeOptionId = selectedSubscribeOption.id;
if (!selectedSubscribeOptionId) {
return true;
}
return selectedMapper[selectedSubscribeOptionId];
};
const judgeSubscribePossibility = () => {
const isLogin = getUserLoginStat();
const isSelectApp = containGame();
const isSubscribe = getSubscribeStat();
if (!isLogin) {
notify("Steam \u7528\u6237\u672A\u767B\u5F55", "\u7528\u6237\u672A\u767B\u5F55");
return false;
}
if (!isSelectApp) {
return false;
}
if (isSubscribe) {
notify("\u7269\u54C1\u5DF2\u8BA2\u9605", "\u5F53\u524D\u7269\u54C1\u5DF2\u8BA2\u9605, \u4E0D\u518D\u6267\u884C\u52A8\u4F5C. ");
return false;
}
return true;
};
(async () => {
await getElement(".commentthread_header");
const subscribePossibility = judgeSubscribePossibility();
if (!subscribePossibility) {
return;
}
subscribeFile();
})();