您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
批量删除在别人个人资料下的留言
- // ==UserScript==
- // @name Delete_My_Comment
- // @name:zh-CN 批量删除个人资料留言
- // @namespace https://blog.chrxw.com
- // @version 1.1
- // @description 批量删除在别人个人资料下的留言
- // @description:zh-CN 批量删除在别人个人资料下的留言
- // @author Chr_
- // @include /https://steamcommunity\.com/(id|profiles)/[^\/]+/commenthistory/?/
- // @license AGPL-3.0
- // @icon https://blog.chrxw.com/favicon.ico
- // @grant GM_addStyle
- // ==/UserScript==
- (async () => {
- 'use strict';
- let GObjs = {};
- addGui();
- //添加UI
- function addGui() {
- function genBtn(name, foo) {
- const b = document.createElement('button');
- b.textContent = name;
- b.className = 'dmc_btn';
- b.addEventListener('click', foo);
- return b;
- }
- function genDiv(cls) {
- const d = document.createElement('div');
- d.className = cls ?? 'dmc_div';
- return d;
- }
- function genText() {
- const t = document.createElement('textarea');
- t.className = 'dmc_txt';
- return t;
- }
- function genNum() {
- const t = document.createElement('input');
- t.type = 'number';
- t.value = 0;
- t.min = 0;
- t.className = 'dmc_ipt';
- return t;
- }
- function genSpan(txt) {
- const t = document.createElement('span');
- t.textContent = txt;
- t.className = 'dmc_span';
- return t;
- }
- const rightDiv = document.querySelector("div.rightbox");
- const divArea = genDiv('dmc_panel');
- const btnStart = genBtn('开始删除', async () => {
- const startPage = parseInt(iptPage.value);
- if (startPage !== startPage) {
- ShowAlertDialog("错误", "只能输入整数");
- } else {
- const endPage = getPageCount();
- try {
- btnStart.textContent = '执行中';
- btnStart.disabled = true;
- await startDeleteComments(startPage, endPage);
- }
- finally {
- btnStart.textContent = '开始删除';
- btnStart.disabled = false;
- }
- }
- });
- const iptPage = genNum();
- const txtLog = genText();
- const divHide = genDiv('dmc_hide');
- rightDiv.appendChild(divArea);
- divArea.appendChild(btnStart);
- divArea.appendChild(genSpan('开始页码:'));
- divArea.appendChild(iptPage);
- divArea.appendChild(txtLog);
- divArea.appendChild(divHide);
- Object.assign(GObjs, { txtLog, divHide });
- }
- //批量删除留言
- async function startDeleteComments(startPage, endPage) {
- const { divHide, txtLog } = GObjs;
- const genTmp = () => {
- const d = document.createElement('div');
- divHide.appendChild(d);
- return d;
- };
- const log = (msg) => {
- if (txtLog.value) {
- txtLog.value += "\n";
- }
- txtLog.value += msg;
- txtLog.scrollTop = txtLog.scrollHeight;
- };
- log(`1 开始运行, 页码设置: ${startPage} / ${endPage}`);
- const baseUri = location.origin + location.pathname;
- for (let i = startPage; i <= endPage; i++) {
- log(`2 开始读取第 ${i} 页历史记录`);
- const historyUrl = `${baseUri}?p=${i}`;
- const response = await loadPage(historyUrl);
- if (response) {
- const tmp = genTmp();
- tmp.innerHTML = response;
- const links = fetchCommentFromHistory(tmp);
- divHide.removeChild(tmp);
- const count = links.length;
- if (count > 0) {
- log(`3 获取了 ${links.length} 条留言记录`);
- for (let link of links) {
- log('4 开始读取留言');
- const resp = await loadPage(link);
- if (response) {
- const ss = genTmp();
- ss.innerHTML = resp;
- const rst = fetchProfileComments(ss);
- const tasks = [];
- const gids = new Set();
- const cnt = rst.length;
- if (cnt > 0) {
- log(`5 获取了 ${cnt} 条留言记录`);
- for (let [steamid, gid] of rst) {
- if (!gids.has(gid)) {
- gids.add(gid);
- tasks.push(makePromise(steamid, gid));
- }
- }
- if (tasks.length > 0) {
- log(`5 总计 ${tasks.length} 条留言, 开始删除`);
- await Promise.all(tasks);
- } else {
- log('5 未找到可以删除的留言');
- }
- } else {
- log('5 未找到留言记录');
- }
- divHide.removeChild(ss);
- }
- else {
- log('4 读取失败');
- }
- }
- }
- else {
- log('3 无留言记录,跳过');
- }
- } else {
- log('2 读取失败');
- }
- }
- log('1 运行结束');
- function makePromise(steamid, gid) {
- return new Promise((resolve, reject) => {
- deleteComment(steamid, gid)
- .then(() => {
- log(`> 删除留言 ${gid} 成功`);
- }).catch((reason) => {
- log(`> 删除留言 ${gid} 失败`);
- }).finally(() => {
- resolve();
- });
- });
- }
- }
- //获取总页数
- function getPageCount() {
- const pages = document.querySelectorAll("div.pageLinks>a.pagelink");
- if (pages.length === 0) {
- return 0;
- } else {
- const lastPage = parseInt(pages[pages.length - 1].textContent.replace(/[,.]/g, ""));
- return lastPage === lastPage ? lastPage : 0;
- }
- }
- //获取历史留言记录
- function fetchCommentFromHistory(element) {
- const comments = element.querySelectorAll("div.commenthistory_comment:not(.deleted) a");
- const matchLinks = new RegExp(/https:\/\/steamcommunity\.com\/(id|profiles)\/[^\/]+\/?\?tscn=\d+$/g);
- const result = [];
- for (let comment of comments) {
- const href = comment.href;
- if (matchLinks.test(href)) {
- result.push(href);
- }
- }
- return result;
- }
- // 读取网页
- async function loadPage(href) {
- return new Promise((resolve, reject) => {
- fetch(href, {
- method: "GET",
- credentials: "include",
- })
- .then(async (response) => {
- if (response.ok) {
- const data = await response.text();
- resolve(data.trim());
- } else {
- resolve(null);
- }
- }).catch((err) => {
- console.error(err);
- resolve(null);
- });
- });
- }
- // 匹配所有自己的留言
- function fetchProfileComments(element) {
- const comments = element.querySelectorAll("a.actionlink:not(.report_and_hide)");
- const matchLinks = new RegExp(/'(\S+)'/g);
- const result = [];
- for (let comment of comments) {
- const href = comment.href;
- const match = href.match(matchLinks);
- if (match && match.length >= 2) {
- const steamId = match[0].replace("Profile_", "").replace(/'/g, "");
- const commentId = match[1].replace(/'/g, "");
- result.push([steamId, commentId]);
- }
- }
- return result;
- }
- const SessionId = document.cookie.replace(/(?:(?:^|.*;\s*)sessionid\s*\=\s*([^;]*).*$)|^.*$/, "$1");
- // 删除指定留言
- async function deleteComment(steamId, gidComment) {
- const data = {
- "gidcomment": gidComment,
- "start": 0,
- "count": 6,
- "sessionid": SessionId,
- "feature2": -1,
- "lastvisit": 0
- };
- let s = '';
- for (let k in data) {
- s += `${k}=${data[k]}&`;
- }
- return new Promise((resolve, reject) => {
- fetch(`https://steamcommunity.com/comment/Profile/delete/${steamId}/-1/`, {
- method: "POST",
- credentials: "include",
- body: s,
- headers: {
- 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
- },
- })
- .then(async (response) => {
- if (response.ok) {
- const data = await response.json();
- const result = data.success ?? false;
- resolve(result);
- } else {
- resolve(false);
- }
- }).catch((err) => {
- reject(err);
- });
- });
- }
- GM_addStyle(`
- .dmc_panel {
- padding: 15px;
- }
- .dmc_span {
- margin-left: 10px;
- margin-right: 10px;
- }
- .dmc_ipt {
- text-align: center;
- width: 50px;
- }
- .dmc_txt {
- margin-top: 10px;
- width: 100%;
- height: 300px;
- }
- .dmc_hide {
- display: none;
- }
- `);
- })();