How to delete spam fans in Weibo in batches?
The js code of Lemon Zombie is as follows
/* eslint-disable no-unused-vars */ /* eslint-disable no-extra-semi */ /* eslint-disable no-console */ // ==UserScript== // @name Lemon Essence Zombie Scavenger One-click Zombie Fan Cleanup Assistant v2023.06.30 // @namespace https://blog.csdn.net/wangwei490202517/category_10507403.html?spm=1001.2014.3001.5482 // @version 1.0.9 // @description Delete zombie fans in batches with one click: interest recommendation, mutual attention, inactive users, spam nicknames, etc. // @author echo_wx:WZMSLR // @match https://weibo.com/* // @icon https://tva2.sinaimg.cn/crop.2.18.304.304.180/ad573135jw8f33qt1c74sj208k08z75q.jpg?KID=imgbed,tva & amp;Expires=1671381776 & amp;ssig=du6gqkc8OF // @license MIT // @grant none // ==/UserScript== let removeTargetFans = false; /*Whether to delete eligible fans, default off*/ let deepSearchMode =false; /*Whether to enable deep cleaning mode*/ let ignoreLikes = true; /*Whether to ignore the user's recent likes*/ let minDayCount = 180; /*minimum inactive days*/ let fansMinCount = 2; /*Minimum number of fans*/ let weiboMinCount = 3; /*Minimum number of Weibo*/ let totalCount = 0; let checkIsFromRecommended = true; /*Check whether to follow the recommendation*/ let checkIsInactive = true; /* Whether to check for inactive users*/ let checkFansOrWeibo = false; /*Whether to judge only the number of fans or Weibo*/ let checkIsFollowing =true; /*Check whether to follow each other*/ let checkIsDefaultIcon = false; /* Whether to check the default icon */ let checkIsNormalFollowed = false; /*Check whether to follow the source*/ let isError = false; let isRunning = false; let userID = 0; let zeroFanPageCount = 0; function clearLog() { let logger = document. querySelector("p. logger"); logger.innerHTML = ""; } function logError(msg){ let logger = document. querySelector("p. logger"); let parent = logger. parentElement; logger.innerHTML + ="<span style='color: Crimson; font-weight:bold;'>" + msg + "</span><br>"; parent.scrollTop = parent.scrollHeight; } function logSuccessMsg(msg){ let logger = document. querySelector("p. logger"); let parent = logger. parentElement; logger.innerHTML + ="<pre style='tab-size: 15em; color: forestgreen;'>" + msg + "
“;
parent.scrollTop = parent.scrollHeight;
}
function logImportantMsg(msg)
{
let logger = document. querySelector(“p. logger”);
let parent = logger. parentElement;
logger.innerHTML + =”
" + msg + "
“;
parent.scrollTop = parent.scrollHeight;
}
function logMsg(msg){
let logger = document. querySelector(“p. logger”);
let parent = logger. parentElement;
logger.innerHTML + =”
" + msg + "
“;
parent.scrollTop = parent.scrollHeight;
}
async function removeFanMainFunc() {
const delay = ms => new Promise(res => setTimeout(res, ms));
const minute = 1000 * 60;
const hour = minute * 60;
const day = hour * 24;
clearTimeout();
isError = false;
let startIndex = 0;
let pageIndex = 1;
while(true) {
if(!isRunning)
{
if (removeTargetFans)
logError(“[WX:WZMSLR] The user exited the program. A total of ” + totalCount + ” suspected zombie fans have been cleaned up”);
else
logError(“[WX:WZMSLR] The user has exited the program. A total of ” + totalCount + ” suspected zombie fans have been found”);
break;
}
await delay(300);
let fanListJson = await fetch(
‘https://weibo.com/ajax/friendships/friends?relate=fans & amp;count=20 & amp;type=fans & amp;fansSortType=followTime’ +
‘ &page=’ + pageIndex +
‘ &uid=’ + userID,
{
method: “GET”,
}).then(response => response.json())
.catch((e) => {
});
if (fanListJson == null || fanListJson.ok != 1 || fanListJson[‘users’].length === 0) {
fanListJson = await fetch(
‘https://weibo.com/ajax/friendships/friends?relate=fans & amp;count=20 & amp;type=fans & amp;fansSortType=followTime’ +
‘ &page=’ + pageIndex +
‘ &uid=’ + userID,
{
method: “GET”,
}).then(response => response.json())
.catch((e) => {
});
if (fanListJson == null || fanListJson.ok != 1) {
if (removeTargetFans)
logError(“[WX:WZMSLR] The request is abnormal, exit the program. A total of ” + totalCount + ” suspected zombie fans have been cleaned up”);
else
logError(“[WX:WZMSLR] The request is abnormal, exit the program. A total of ” + totalCount + ” suspected zombie fans have been found”);
break;
}
}
let fans = fanListJson[‘users’];
let count = 0;
for (let i = startIndex; i < fans. length; i ++ ) {
if(!isRunning)
{
if (removeTargetFans)
logError("[Lemon Essence] Reminder: The user exits the program. A total of " + totalCount + " suspected zombie fans have been cleaned up");
else
logError("[Lemon Essence] Reminder: The user exits the program. A total of " + totalCount + " suspected zombie fans have been found");
return;
}
let isFromRecommended = false;
let isInactive = false;
let isFollowing = false;
let isDefaultIcon = false;
let isNormalFollowed = false;
let isIrrelevant = false;
let fansCount, weiboCount;
/* follow source */
let originSrc = fans[i]['origin_source_info'];
isNormalFollowed = originSrc != null & amp; & amp; originSrc['text'] !== "interest recommendation" & amp; & amp; originSrc['text'] !== "Weibo recommend";
/*Is it iron powder*/
if(fans[i]. fansIcon != null)
{
if(fans[i].fansIcon == "loyal_fans")
continue;
}
/*Is it a non-recommended member*/
if (isNormalFollowed & amp; & amp; (fans[i]['mbtype'] === 12))
continue;
/*Follow whether the source is a recommendation of interest*/
if (checkIsFromRecommended) {
isFromRecommended = originSrc != null & amp; & amp; originSrc['text'] === "interest recommendation";
}
let fanID = fans[i]['id'];
let fanName = fans[i]['name'];
/*Number of fans and number of Weibo*/
if (checkIsInactive) {
fansCount = fans[i]['followers_count'];
weiboCount = fans[i]['statuses_count'];
if (checkFansOrWeibo)
isInactive = fansCount < fansMinCount || weiboCount < weiboMinCount;
else
isInactive = fansCount < fansMinCount & amp; & amp; weiboCount < weiboMinCount || weiboCount === 0 || fansCount === 0;
}
/*Is it the default avatar*/
if (checkIsDefaultIcon) {
let icon = fans[i]['avatar_hd'];
isDefaultIcon = icon != null & amp; & amp; icon.includes("/default/images/default_avatar_");
}
/*Whether to pay attention to each other*/
if (checkIsFollowing) {
isFollowing = fans[i]['following'];
}
let isZombie = false;
if (!isFollowing)
if (!checkIsNormalFollowed || (checkIsNormalFollowed & amp; & amp; !isNormalFollowed))
if (isDefaultIcon || isFromRecommended || isInactive || isDefaultIcon || (deepSearchMode & amp; & amp; weiboCount === 0))
isZombie = true;
/*deep inspection*/
if (deepSearchMode & amp; & amp; !isFollowing & amp; & amp; !isZombie) {
await delay(600);
let weiboJson = await fetch('https://weibo.com/ajax/statuses/mymblog?page=1 & amp;feature=0 & amp;uid=' + fanID, {
method: "GET",
}).then(response => response.json())
.catch((e) => {
});
if (weiboJson == null || weiboJson.ok != 1) {
await delay(800);
weiboJson = await fetch(‘https://weibo.com/ajax/statuses/mymblog?page=1 & amp;feature=0 & amp;uid=’ + fanID, {
method: “GET”,
}).then(response => response.json())
.catch((e) => {
});
if (weiboJson == null || weiboJson.ok != 1) {
logError(fanName + “The homepage request failed, skipping the check”);
continue;
}
}
let weiboList = weiboJson. data[‘list’];
let invalidWeiboCount = 0;
let validWeiboCount = 0;
let currDate = Date.now();
for (let index = 0; index < weiboList. length; index ++ ) {
let currWeibo = weiboList[index];
let weiboSrc = currWeibo['source'];
if(weiboSrc != null & amp; & amp; weiboSrc.includes("birthday news"))
continue;
if (weiboSrc != null & amp; & amp; (weiboSrc.includes("fishing ground") ||
weiboSrc.includes("Activity") || weiboSrc.includes("Forest") || weiboSrc.includes("Weibo Points") ||
weiboSrc.includes("Alipay") || weiboSrc.includes("Taobao") || weiboSrc.includes("Baba Farm") ||
weiboSrc.includes("Task") || weiboSrc.includes("Sign in") || weiboSrc.includes("Sina Games") ||
weiboSrc.includes("Weibo Game") || weiboSrc.includes("Red Envelope") || weiboSrc.includes("Weibo Member") ||
weiboSrc.includes("Weibo Sports") || weiboSrc.includes("Panda Guardian") || weiboSrc.includes("Diantao"))) {
invalidWeiboCount++;
continue;
}
if (ignoreLikes & amp; & amp; currWeibo['title'] != null & amp; & amp; currWeibo['title']['text'].includes("like") )
continue;
let createTime = currWeibo['created_at'];
if (currWeibo['retweeted_status'] != null) {
createTime = currWeibo['retweeted_status']['created_at'];
}
if (Math. round((currDate - new Date(createTime)) / day) <= minDayCount) {
validWeiboCount++;
}
invalidWeiboCount--;
}
if (invalidWeiboCount > 3) {
isIrrelevant = true;
isZombie = true;
}
if (validWeiboCount < 3) {
isInactive = true;
isZombie = true;
}
}
await delay(300);
if (is Zombie) {
let reason = "reason: ";
if (isFromRecommended)
reason + = "interest recommendation";
if (isInactive)
reason + = "Inactive user";
if (is Irrelevant)
reason + = "Irrelevant user";
if (isDefaultIcon)
reason + = "default avatar";
if (removeTargetFans) {
let fData = new FormData();
fData.append("uid", fanID);
fData.append("_t", "0");
const json = await fetch('/aj/f/remove?ajwvr=6 &__rnd=' + Math.round(new Date().getTime()), {
method: "POST",
body: fData
}).then(response => response.json())
.catch((e) => {
});
if (json != null & & json.code == 100000) {
logSuccessMsg(“【WX:WZMSLR】Prompt:” + fanName + “\tdelete successfully ” + reason);
count + + ;
totalCount++;
} else
logError(“【WX:WZMSLR】Prompt: ” + fanName + “\tdeletion failed “);
} else {
logMsg(“【WX:WZMSLR】Prompt: ” + fanName + “→Suspected Zombie Fan ” + reason);
count + + ;
totalCount++;
}
}
}
if (fans. length > 0) {
startIndex = 0;
zeroFanPageCount = 0;
if (removeTargetFans) {
logImportantMsg(“【WX:WZMSLR】reminder: page ” + pageIndex + ” deleted ” + count + ” followers”);
if (count > 0) {
startIndex = fans. length – count;
if (startIndex < 0) startIndex = 0;
} else {
pageIndex++;
}
} else {
logImportantMsg("【WX:WZMSLR】reminder: " + count + " suspected zombie followers were found on page " + pageIndex + "");
pageIndex++;
}
} else {
if(zeroFanPageCount < 5)
{
zeroFanPageCount++;
pageIndex++;
} else {
if (removeTargetFans)
logError("[Lemon Essence] has reached the upper limit of the fan list, exit the program. A total of " + totalCount + " suspected zombie fans have been cleaned up");
else
logError("[Lemon Essence] has reached the upper limit of the fan list, exit the program. A total of " + totalCount + " suspected zombie fans have been found");
break;
}
}
}
StopFunc();
}
function RemoveFans(startIndex){
let p = new Promise(function(){removeFanMainFunc(startIndex)});
}
let InitParameters = () =>
{
checkIsFromRecommended = document.body.querySelector(“input#checkIsFromRecommended”).checked;
checkIsFollowing = document.body.querySelector(“input#checkIsFollowing”).checked;
checkIsNormalFollowed = document.body.querySelector(“input#checkIsNormalFollowed”).checked;
checkIsDefaultIcon = document.body.querySelector(“input#checkIsDefaultIcon”).checked;
checkIsInactive = document.body.querySelector(“input#checkIsInactive”).checked;
checkFansOrWeibo = document.body.querySelector(“input#checkFansOrWeibo”).checked;
fansMinCount = parseInt(document.body.querySelector(“input#fansMinCount”).value);
weiboMinCount = parseInt(document.body.querySelector(“input#weiboMinCount”).value);
deepSearchMode = document.body.querySelector(“input#deepSearchMode”).checked;
ignoreLikes = document.body.querySelector(“input#ignoreLikes”).checked;
minDayCount = parseInt(document.body.querySelector(“input#minDayCount”).value);
};
let StartCheckFans = () =>
{
SetMode(“running”);
InitParameters();
clearLog();
totalCount = 0;
removeTargetFans = false;
isRunning = true;
RemoveFans(0);
};
let StartRemoveFans = () =>
{
SetMode(“running”);
InitParameters();
clearLog();
totalCount = 0;
removeTargetFans = true;
isRunning = true;
RemoveFans(0);
};
let StopFunc = () =>
{
SetMode(“ready”);
clearInterval();
clearTimeout();
isRunning = false;
};
let SetDeepSearchParam = () => {
let disable = document.body.querySelector(“input#deepSearchMode”).checked === false;
let params = document.body.querySelectorAll(“input.DeepSearchParam”);
for(let i = 0; i < params. length; i ++ )
params[i].disabled = disable;
};
let SetMode = (mode) =>{
let params = document.querySelector(“div.parameter”).querySelectorAll(“input”);
let readyPanel = document. querySelector(“div. ready”);
let runningPanel = document. querySelector(“div. running”);
if(mode === “running”)
{
for(let i = 0; i < params. length; i ++ ) params[i]. disabled = true;
readyPanel.style.display = "none";
runningPanel.style.display = "";
}
else if(mode === "ready")
{
for(let i = 0; i < params. length; i ++ ) params[i]. disabled = false;
runningPanel.style.display = "none";
readyPanel.style.display = "";
}
};
let ReplaceHTML = () =>
{
let list = document.querySelector(“div.woo-box-flex.woo-tab-nav”)?.querySelectorAll(“a”);
let href = document. location. href;
if(list == null || list. length !== 5) {
if(document.location.href.includes(“https://weibo.com/u/”))
{
userID = document.location.href.replace(“https://weibo.com/u/”, “”);
let numIndex = 0;
for(numIndex = 0; numIndex < userID. length; numIndex ++ )
{
if(userID[numIndex] < '0' || userID[numIndex] > ‘9’)
break;
}
userID = userID. slice(0, numIndex);
} else {
console.error(“Unable to find the user id, please open the Weibo homepage and run the code”);
return;
}
}else{
userID = list[4].href.replace(“https://weibo.com/u/”, “”);
href = “https://weibo.com/u/page/follow/” + userID + “?relate=fans”;
}
document.head.innerHTML = ‘
let body = ‘
Lemon Zombie Scavenger< span style="font-size: 20px;">v2023.06.22
Quick powder clearing parameters-blogger Weibo@时我I didn’t hold back
Clear interested recommended users | Exclude mutual follow | Only check by referral follow |
Clear inactive users | Minimum number of fans | Clear if any condition is met |
Minimum Weibo number | ||
Clear default avatar user |
Deep powder cleaning parameters-blogger Weibo@I didn’t hold back at that time
Open Deep clean powder | Minimum inactive days: | Ignore the user’s recent likes |
‘;
document.body.innerHTML = body.replaceAll(‘ο’, ‘o’);
let iframe = document.body.querySelector(‘iframe.web’);
iframe.src = href;
iframe.onload=()=>{ iframe.contentDocument.body.querySelector(“div[node-type=outer]”)?.remove(); }
}
ReplaceHTML();