Skip to content

Commit 424302c

Browse files
deploy: 0fbd379
0 parents  commit 424302c

12 files changed

Lines changed: 1602 additions & 0 deletions

.nojekyll

Whitespace-only changes.

bilibili/bilibili-block.user.js

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
// ==UserScript==
2+
// @name 屏蔽B站营销视频和推广视频
3+
// @name:zh-CN 屏蔽B站营销视频和推广视频
4+
// @name:zh-TW 屏蔽B站营销视频和推广视频
5+
// @name:en Block Bilibili's marketing videos and promotional videos
6+
// @namespace http://tampermonkey.net/
7+
// @version 2.8
8+
// @description 屏蔽部分B站(bilibili)主页推荐的视频卡片,屏蔽up主粉丝少于一定数量的,屏蔽直播与右侧推广,屏蔽带广告标签的
9+
// @description:zh-CN 屏蔽部分B站(bilibili)主页推荐的视频卡片,屏蔽up主粉丝少于一定数量的,屏蔽直播与右侧推广,屏蔽带广告标签的
10+
// @description:zh-TW 遮罩部分B站(bilibili)主頁推薦的視頻卡片,遮罩up主粉絲少於一定數量的,遮罩直播與右側推廣,遮罩帶廣告標籤的
11+
// @description:en Block some video cards recommended on the homepage of Bilibili. The rules are to block those from creators with a certain number of small fans, block live streams and right-hand promotion, and block those with advertising tags.
12+
// @author anonymous
13+
// @license GNU General Public License v3.0
14+
// @icon https://www.bilibili.com/favicon.ico
15+
// @match https://www.bilibili.com/
16+
// @match https://www.bilibili.com/?spm_id_from=*
17+
// @grant none
18+
// @downloadURL https://update.greasyfork.org/scripts/467384/%F0%9F%9B%A0%EF%B8%8F%E5%B1%8F%E8%94%BDB%E7%AB%99%E8%90%A5%E9%94%80%E8%A7%86%E9%A2%91.user.js
19+
// @updateURL https://update.greasyfork.org/scripts/467384/%F0%9F%9B%A0%EF%B8%8F%E5%B1%8F%E8%94%BDB%E7%AB%99%E8%90%A5%E9%94%80%E8%A7%86%E9%A2%91.meta.js
20+
// ==/UserScript==
21+
22+
"use strict";
23+
(() => {
24+
var __defProp = Object.defineProperty;
25+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
26+
27+
// src/bilibili-block/index.ts
28+
var FILTER_CLASSES = [".bili-feed-card"];
29+
var FILTER_BLOCK_CLASSES = [".floor-single-card"];
30+
var FILTER_BLOCK_UIDS = [113560378];
31+
var MIN_FOLLOWER = 2e3;
32+
var API_USERDATA = "https://api.bilibili.com/x/relation/stat?vmid=";
33+
var processedCards = 0;
34+
function getUid(card) {
35+
const ownerLink = card.querySelector(
36+
".bili-video-card__info--owner"
37+
);
38+
if (ownerLink) {
39+
const uid = ownerLink.href.split("/").pop();
40+
if (uid && uid.match(/^\d+$/)) {
41+
return Number(uid);
42+
} else {
43+
logMessages += `\u{1F7E2}remove becouse can't get uid: ${processedCards}, uid: ${uid}
44+
`;
45+
return -1;
46+
}
47+
}
48+
logMessages += `\u{1F7E2}remove becouse can't get ownerLink, processedCards: ${processedCards}, ownerLink: ${ownerLink}
49+
`;
50+
return -1;
51+
}
52+
__name(getUid, "getUid");
53+
async function getFollower(uid) {
54+
const response = await fetch(`${API_USERDATA}${uid}`);
55+
logMessages += `\u{1F7E2}getFollower, uid: ${uid}
56+
`;
57+
const data = await response.json();
58+
if (data.code === 0) {
59+
return data.data.follower;
60+
} else {
61+
logMessages += `\u{1F534}getFollower error, uid: ${uid}, message: ${data.message}
62+
`;
63+
return -1;
64+
}
65+
}
66+
__name(getFollower, "getFollower");
67+
async function editCards(card) {
68+
processedCards++;
69+
const uid = getUid(card);
70+
if (uid === -1) {
71+
logMessages += `\u{1F7E2}remove because getUid error, uid: ${uid}
72+
`;
73+
removeCard(card);
74+
return;
75+
}
76+
if (FILTER_BLOCK_UIDS.includes(uid)) {
77+
logMessages += `\u{1F7E2}remove because uid in FILTER_BLOCK_UIDS, uid: ${uid}
78+
`;
79+
removeCard(card);
80+
return;
81+
}
82+
const follower = await getFollower(uid);
83+
if (follower === -1) {
84+
console.log(`\u{1F534}keep because getFollower error, uid: ${uid}`);
85+
return;
86+
}
87+
if (follower < MIN_FOLLOWER) {
88+
logMessages += `\u{1F7E2}remove because follower < ${MIN_FOLLOWER}, uid: ${uid}, follower: ${follower}
89+
`;
90+
removeCard(card);
91+
return;
92+
}
93+
}
94+
__name(editCards, "editCards");
95+
function removeCard(card) {
96+
card.remove();
97+
}
98+
__name(removeCard, "removeCard");
99+
function removeIfBlockByADBlocker(card) {
100+
const cardContent = card.querySelector(".bili-video-card.is-rcmd");
101+
if (!cardContent || cardContent.innerHTML.match(
102+
/<!----><div class=".+?"><\/div><!---->/
103+
)) {
104+
removeCard(card);
105+
return true;
106+
}
107+
return false;
108+
}
109+
__name(removeIfBlockByADBlocker, "removeIfBlockByADBlocker");
110+
var isProcessing = false;
111+
var observer = new IntersectionObserver(
112+
(entries, obs) => {
113+
entries.forEach((entry) => {
114+
if (entry.isIntersecting) {
115+
editCards(entry.target);
116+
obs.unobserve(entry.target);
117+
}
118+
});
119+
},
120+
{ rootMargin: "0px", threshold: 0.2 }
121+
);
122+
function observeNewCards() {
123+
const blockCards = document.querySelectorAll(
124+
FILTER_BLOCK_CLASSES.join(", ")
125+
);
126+
blockCards.forEach((card) => {
127+
removeCard(card);
128+
});
129+
const filterCards = document.querySelectorAll(FILTER_CLASSES.join(", "));
130+
filterCards.forEach((card) => {
131+
if (removeIfBlockByADBlocker(card)) return;
132+
if (card.dataset.processed) return;
133+
observer.observe(card);
134+
card.dataset.processed = "true";
135+
});
136+
}
137+
__name(observeNewCards, "observeNewCards");
138+
var mutationObserver = new MutationObserver((mutations) => {
139+
if (isProcessing) return;
140+
isProcessing = true;
141+
logMessages += `\u{1F913}mutationObserver, mutations: ${mutations.length}
142+
`;
143+
mutations.forEach((mutation) => {
144+
if (mutation.type === "childList") {
145+
observeNewCards();
146+
}
147+
});
148+
isProcessing = false;
149+
});
150+
var container = document.querySelector(".container.is-version8");
151+
if (container) {
152+
mutationObserver.observe(container, {
153+
childList: true
154+
});
155+
}
156+
observeNewCards();
157+
var logMessages = "";
158+
setInterval(() => {
159+
if (logMessages === "") return;
160+
console.log(logMessages);
161+
logMessages = "";
162+
}, 1e4);
163+
})();

campus/evaluation-auto.user.js

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
// ==UserScript==
2+
// @name 评价表自动选择工具
3+
// @namespace http://tampermonkey.net/
4+
// @version 1.0
5+
// @description 自动选择"很好"、"强烈推荐"、"最满意课堂"
6+
// @author XLXZ
7+
// @match *://*/*
8+
// @grant none
9+
// @downloadURL https://xiaolinxiaozhu.github.io/JavaScriptTools/campus/evaluation-auto.user.js
10+
// @updateURL https://xiaolinxiaozhu.github.io/JavaScriptTools/campus/evaluation-auto.user.js
11+
// ==/UserScript==
12+
13+
"use strict";
14+
(() => {
15+
var __defProp = Object.defineProperty;
16+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
17+
18+
// src/evaluation-auto/index.ts
19+
function addButton() {
20+
const button = document.createElement("button");
21+
button.textContent = "\u4E00\u952E\u9009\u62E9";
22+
button.style.cssText = `
23+
position: fixed;
24+
top: 20px;
25+
right: 20px;
26+
z-index: 99999;
27+
padding: 12px 24px;
28+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
29+
color: white;
30+
border: none;
31+
border-radius: 8px;
32+
font-size: 14px;
33+
font-weight: bold;
34+
cursor: pointer;
35+
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
36+
transition: all 0.3s ease;
37+
`;
38+
button.onmouseenter = () => {
39+
button.style.transform = "translateY(-2px)";
40+
button.style.boxShadow = "0 6px 20px rgba(102, 126, 234, 0.6)";
41+
};
42+
button.onmouseleave = () => {
43+
button.style.transform = "translateY(0)";
44+
button.style.boxShadow = "0 4px 15px rgba(102, 126, 234, 0.4)";
45+
};
46+
button.onclick = autoSelect;
47+
document.body.appendChild(button);
48+
}
49+
__name(addButton, "addButton");
50+
function autoSelect() {
51+
let selectedCount = 0;
52+
let strongRecommendName = "";
53+
let bestClassName = "";
54+
const allRadios = document.querySelectorAll(
55+
'input[type="radio"]'
56+
);
57+
allRadios.forEach((radio) => {
58+
const label = radio.closest("label");
59+
if (!label) return;
60+
const labelText = label.textContent?.trim();
61+
if (labelText === "\u5F3A\u70C8\u63A8\u8350") {
62+
radio.click();
63+
selectedCount++;
64+
strongRecommendName = radio.name;
65+
console.log("\u5DF2\u9009\u62E9: \u5F3A\u70C8\u63A8\u8350 (name=" + radio.name + ")");
66+
} else if (labelText === "\u6700\u6EE1\u610F\u8BFE\u5802") {
67+
radio.click();
68+
selectedCount++;
69+
bestClassName = radio.name;
70+
console.log("\u5DF2\u9009\u62E9: \u6700\u6EE1\u610F\u8BFE\u5802 (name=" + radio.name + ")");
71+
}
72+
});
73+
const goodOptions = document.querySelectorAll(
74+
'input[type="radio"][value="1_1.0"][score="1.0"]'
75+
);
76+
goodOptions.forEach((option) => {
77+
if (option.name !== strongRecommendName && option.name !== bestClassName) {
78+
option.click();
79+
selectedCount++;
80+
console.log("\u5DF2\u9009\u62E9: \u5F88\u597D (name=" + option.name + ")");
81+
}
82+
});
83+
if (selectedCount > 0) {
84+
showToast(`\u6210\u529F\u9009\u62E9\u4E86 ${selectedCount} \u4E2A\u9009\u9879\uFF01`);
85+
if (selectedCount === 11) {
86+
setTimeout(() => {
87+
autoSubmit();
88+
}, 500);
89+
}
90+
} else {
91+
showToast("\u672A\u627E\u5230\u53EF\u9009\u62E9\u7684\u9009\u9879", "warning");
92+
}
93+
}
94+
__name(autoSelect, "autoSelect");
95+
function autoSubmit() {
96+
const submitBtn = document.querySelector("a.save");
97+
if (submitBtn) {
98+
submitBtn.click();
99+
showToast("\u6B63\u5728\u63D0\u4EA4...", "success");
100+
setTimeout(() => {
101+
const confirmSelectors = [
102+
"a.layui-layer-btn0",
103+
"a.popBnt_blue",
104+
".layui-layer-btn a:first-child"
105+
];
106+
for (const selector of confirmSelectors) {
107+
const confirmBtn = document.querySelector(
108+
selector
109+
);
110+
if (confirmBtn) {
111+
confirmBtn.click();
112+
console.log("\u5DF2\u70B9\u51FB\u786E\u8BA4\u6309\u94AE: " + selector);
113+
showToast("\u5DF2\u786E\u8BA4\u63D0\u4EA4\uFF01", "success");
114+
return;
115+
}
116+
}
117+
console.log("\u672A\u627E\u5230\u786E\u8BA4\u6309\u94AE");
118+
showToast("\u63D0\u4EA4\u6210\u529F\uFF0C\u8BF7\u624B\u52A8\u786E\u8BA4", "warning");
119+
}, 1e3);
120+
} else {
121+
console.log("\u672A\u627E\u5230\u63D0\u4EA4\u6309\u94AE");
122+
}
123+
}
124+
__name(autoSubmit, "autoSubmit");
125+
function showToast(message, type = "success") {
126+
const toast = document.createElement("div");
127+
toast.textContent = message;
128+
toast.style.cssText = `
129+
position: fixed;
130+
top: 80px;
131+
right: 20px;
132+
z-index: 99999;
133+
padding: 12px 20px;
134+
background: ${type === "success" ? "#10b981" : "#f59e0b"};
135+
color: white;
136+
border-radius: 8px;
137+
font-size: 14px;
138+
font-weight: bold;
139+
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
140+
animation: slideIn 0.3s ease;
141+
`;
142+
if (!document.getElementById("toast-animation")) {
143+
const style = document.createElement("style");
144+
style.id = "toast-animation";
145+
style.textContent = `
146+
@keyframes slideIn {
147+
from {
148+
transform: translateX(100%);
149+
opacity: 0;
150+
}
151+
to {
152+
transform: translateX(0);
153+
opacity: 1;
154+
}
155+
}
156+
@keyframes slideOut {
157+
from {
158+
transform: translateX(0);
159+
opacity: 1;
160+
}
161+
to {
162+
transform: translateX(100%);
163+
opacity: 0;
164+
}
165+
}
166+
`;
167+
document.head.appendChild(style);
168+
}
169+
document.body.appendChild(toast);
170+
setTimeout(() => {
171+
toast.style.animation = "slideOut 0.3s ease";
172+
setTimeout(() => toast.remove(), 300);
173+
}, 3e3);
174+
}
175+
__name(showToast, "showToast");
176+
if (document.readyState === "loading") {
177+
document.addEventListener("DOMContentLoaded", addButton);
178+
} else {
179+
addButton();
180+
}
181+
console.log("\u8BC4\u4EF7\u8868\u81EA\u52A8\u9009\u62E9\u5DE5\u5177\u5DF2\u52A0\u8F7D");
182+
})();

0 commit comments

Comments
 (0)