- // ==UserScript==
- // @name CC直播间净化
- // @description 隐藏CC直播页面中的大部分广告, 并且当直播结束跳转其他直播间时, 自动关闭页面
- // @name:en CCLiveClean
- // @description:en Hide almost CC live Element.
- // @author Yiero
- // @version 1.1.0
- // @match https://cc.163.com/*
- // @match https://act/m/daily/anchor_end_countdown/*
- // @grant GM_addStyle
- // @grant GM_setValue
- // @grant GM_getValue
- // @grant GM_deleteValue
- // @grant GM_listValues
- // @grant GM_registerMenuCommand
- // @grant GM_unregisterMenuCommand
- // @run-at document-start
- // @icon https://cc.163.com/favicon.ico
- // @namespace https://github.com/AliubYiero/TamperMonkeyScripts/
- // @license GPL
- // ==/UserScript==
- var __defProp = Object.defineProperty;
-
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {
- enumerable: true,
- configurable: true,
- writable: true,
- value: value
- }) : obj[key] = value;
-
- var __publicField = (obj, key, value) => {
- __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
- return value;
- };
-
- class Info {
- constructor(projectName) {
- __publicField(this, "projectName");
- __publicField(this, "header");
- this.projectName = projectName;
- this.header = `[${projectName}]`;
- }
- log(...msg) {
- (() => {})(...this.contentInfo(...msg));
- }
- info(...msg) {
- console.info(...this.contentInfo(...msg));
- }
- warn(...msg) {
- console.warn(...this.contentInfo(...msg));
- }
- error(...msg) {
- console.error(...this.contentInfo(...msg));
- }
- contentInfo(...msg) {
- return [ this.header, `[${(new Date).toLocaleString("zh-ch")}]`, ...msg ];
- }
- }
-
- class CSSRule {
- constructor() {
- __publicField(this, "cssRuleSet", new Set);
- __publicField(this, "styleDom", document.createElement("style"));
- }
- push(selector, rule) {
- let ruleString = "";
- for (let ruleKey in rule) {
- const ruleValue = rule[ruleKey];
- ruleString += `${ruleKey}:${ruleValue};`;
- }
- this.cssRuleSet.add(`${selector} {${ruleString}}`);
- }
- pushImportant(selector, rule) {
- let ruleString = "";
- for (let ruleKey in rule) {
- let ruleValue = rule[ruleKey];
- if (typeof ruleValue === "string") {
- ruleValue = ruleValue.replace("!important", "");
- }
- ruleString += `${ruleKey}:${ruleValue} !important;`;
- }
- this.cssRuleSet.add(`${selector} {${ruleString}}`);
- }
- pushHide(selector) {
- this.pushImportant(selector, {
- display: "none"
- });
- }
- pushHideList(selectorList) {
- selectorList.forEach((selector => {
- this.pushImportant(selector, {
- display: "none"
- });
- }));
- }
- pushList(ruleList) {
- ruleList.forEach((({selector: selector, rule: rule}) => {
- this.push(selector, rule);
- }));
- }
- pushImportantList(ruleList) {
- ruleList.forEach((({selector: selector, rule: rule}) => {
- this.pushImportant(selector, rule);
- }));
- }
- submit() {
- this.removeAll();
- new Info("AddStyle").log(Array.from(this.cssRuleSet).join(" "));
- this.styleDom = GM_addStyle(Array.from(this.cssRuleSet).join(" "));
- }
- removeAll() {
- if (this.styleDom) {
- this.styleDom.remove();
- }
- }
- }
-
- const hideSelectorList = {
- main: [ ".ad-ct", "#webChat", "#js-side-nav", ".index-module_container_1pK9d", "::-webkit-scrollbar" ],
- headerNav: [ ".menu-location", "#my-follow, #my-record, #download, #menu-be-anchor", "#guard-head-avatar-red-dot-msg, .red-dot" ],
- danmuBar: [ "#room-tabs", "#gift-banner", ".gift-simp-banner", ".room-boardcast", ".activity-notify", ".gift_item", ".chat-msg-folder" ],
- liveTitle: [ "#achievement, .live-type, .live-guard, .live-fans-badge-diamond, .anchor-friends", "#plugins2374, #plugins9970, #plugins9670, #plugins9977, #plugins9412, #plugins9997, #plugins9089, #plugins6666, #plugins9217, #plugins2511, #plugins1609, #plugins9913, #plugins1016, #plugins14, #plugins5985, #plugins1353, #plugins1, #plugins9321 " ],
- live: [ "#recommend-module", "#live_left_bottom_box_wrap", ".video-watermark", "#new-player-banner, #player-banner, #new-player-banner, #mounts_player, #mounts_banner", ".gameH5Theater .user-tool-bar" ]
- };
-
- const anchor_end_countdownHideSelectorList = {
- live: [ ".ui-wrap" ]
- };
-
- const prefSelectorList = {
- main: {
- ".room-main-container": {
- "margin-top": "20px"
- }
- },
- headerNav: {
- ".user-do": {
- "margin-right": "50%",
- transform: "translateX(50%)"
- }
- },
- live: {
- ".page-right-container": {
- width: "100%"
- },
- "#live_player": {
- height: "100%"
- }
- },
- danmuBar: {
- ".chat-list-short": {
- height: "calc(100% - 110px)"
- },
- "#chat-list-con": {
- height: "100%"
- }
- }
- };
-
- function addCCNewStyle() {
- const cssRule = new CSSRule;
- cssRule.pushHideList(Object.values(hideSelectorList).flat());
- const transformedPrefSelectorList = Object.entries(Object.values(prefSelectorList).flat().reduce(((result, current) => ({
- ...result,
- ...current
- })))).map((([selector, rule]) => ({
- selector: selector,
- rule: rule
- })));
- cssRule.pushImportantList(transformedPrefSelectorList);
- cssRule.submit();
- }
-
- function addCCIframeNewStyle() {
- const cssRule = new CSSRule;
- cssRule.pushHideList(Object.values(anchor_end_countdownHideSelectorList).flat());
- cssRule.submit();
- }
-
- function freshListenerPushState(callback, s = 1) {
- let _pushState = window.history.pushState;
- window.history.pushState = function() {
- setTimeout(callback, s * 1e3);
- return _pushState.apply(this, arguments);
- };
- }
-
- const live = {
- id: "",
- historyId: ""
- };
-
- Object.defineProperty(live, "id", {
- get() {
- const liveIdMatch = document.URL.match(/https:\/\/cc.163.com\/(\d+)/);
- if (liveIdMatch && liveIdMatch[1]) {
- const liveId = liveIdMatch[1];
- sessionStorage.setItem("localLiveId", liveId);
- return liveId;
- }
- return "";
- }
- });
-
- Object.defineProperty(live, "historyId", {
- get() {
- return sessionStorage.getItem("localLiveId") || "";
- }
- });
-
- function equalLiveId() {
- freshListenerPushState((() => {
- if (live.historyId !== live.id) {
- window.close();
- }
- }));
- }
-
- function getElement(parent = document.body, selector, timeoutPerSecond = 0, getElementDelayPerSecond = 0) {
- return new Promise((resolve => {
- let result = parent.querySelector(selector);
- if (result) {
- return resolve(result);
- }
- let timer;
- const mutationObserver = window.MutationObserver || window.WebkitMutationObserver || window.MozMutationObserver;
- if (mutationObserver) {
- const observer = new 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)), getElementDelayPerSecond * 1e3);
- }
- }
- }
- }
- }));
- observer.observe(parent, {
- childList: true,
- subtree: true
- });
- if (timeoutPerSecond > 0) {
- timer = setTimeout((() => {
- observer.disconnect();
- return resolve(null);
- }), timeoutPerSecond * 1e3);
- }
- }
- }));
- }
-
- document.querySelector.bind(document);
-
- const getEls = document.querySelectorAll.bind(document);
-
- async function selectOriginBanSetting() {
- await getElement(document.body, ".ban-effect-list", 0, 1);
- const banList = getEls(".ban-effect-list > li:not(.selected)");
- banList.forEach((banItem => {
- banItem.click();
- }));
- }
-
- function isMatchURL(...regExpList) {
- const matchResultList = [];
- regExpList.forEach((regExp => {
- if (typeof regExp === "string") {
- regExp = new RegExp(regExp);
- }
- matchResultList.push(!!document.URL.match(regExp));
- }));
- return matchResultList.includes(true);
- }
-
- class EntryBranch {
- constructor() {
- __publicField(this, "branchList", []);
- }
- add(condition, callback) {
- this.branchList.push([ condition, callback ]);
- }
- run() {
- const entry = this.branchList.find((entry2 => entry2[0]()));
- if (entry) {
- entry[1]();
- }
- }
- }
-
- class GMConfigMenu {
- constructor(callback) {
- __publicField(this, "menuId", 0);
- __publicField(this, "callback");
- this.callback = callback;
- }
- open(title) {
- if (this.menuId) {
- this.close();
- }
- this.menuId = GM_registerMenuCommand(title, this.callback);
- }
- close() {
- GM_unregisterMenuCommand(this.menuId);
- this.menuId = 0;
- }
- }
-
- class GMStorage {
- constructor(key) {
- __publicField(this, "key");
- this.key = key;
- }
- set(value) {
- dispatchEvent(new CustomEvent("GMStorageUpdate", {
- detail: {
- newValue: value,
- oldValue: this.get(),
- target: this.key
- }
- }));
- GM_setValue(this.key, value);
- }
- get(defaultValue = null) {
- return GM_getValue(this.key, defaultValue);
- }
- remove() {
- dispatchEvent(new CustomEvent("GMStorageUpdate", {
- detail: {
- newValue: null,
- oldValue: this.get(),
- target: this.key
- }
- }));
- GM_deleteValue(this.key);
- }
- }
-
- class WhiteList extends GMStorage {
- constructor() {
- super("liveIdWhiteList");
- }
- get whiteList() {
- return this.get([ 361433, 239802416 ]);
- }
- add(liveId) {
- const whiteList2 = this.whiteList;
- whiteList2.push(liveId);
- this.set(whiteList2);
- }
- has(liveId) {
- return this.whiteList.includes(liveId);
- }
- delete(liveId) {
- this.set(this.whiteList.filter((whiteLiveId => whiteLiveId !== liveId)));
- }
- }
-
- const whiteList = new WhiteList;
-
- function disabledNotWhiteListUrl(liveId) {
- if (!whiteList.has(liveId)) {
- window.close();
- return;
- }
- }
-
- function registerConfigBtn(liveId) {
- new GMConfigMenu((() => {
- const result = prompt(`输入需要添加白名单的直播间的数字Id (网页地址中的数字Id):\n当前白名单:\n[${whiteList.whiteList.join(", ")}]`);
- if (result) {
- whiteList.add(Number(result));
- }
- })).open("添加直播间白名单");
- new GMConfigMenu((() => {
- const result = prompt(`输入需要删除白名单的直播间数字Id(网页地址中的数字Id):\n当前白名单:\n[${whiteList.whiteList.join(", ")}]`, String(liveId || whiteList.whiteList[0] || ""));
- if (result) {
- whiteList.delete(Number(result));
- }
- })).open("删除直播间白名单");
- }
-
- async function mainPageEntry() {
- disabledNotWhiteListUrl(Number(live.id));
- registerConfigBtn(Number(live.id));
- addCCNewStyle();
- await selectOriginBanSetting();
- equalLiveId();
- }
-
- function iframeEntry() {
- addCCIframeNewStyle();
- }
-
- (async () => {
- const entryBranch = new EntryBranch;
- entryBranch.add((() => isMatchURL(/^https?:\/\/cc.163.com\/$/)), registerConfigBtn);
- entryBranch.add((() => isMatchURL(/^https?:\/\/cc.163.com\/(\d+)/)), mainPageEntry);
- entryBranch.add((() => isMatchURL("act/m/daily/anchor_end_countdown/index.html")), iframeEntry);
- entryBranch.run();
- })();