Greasy Fork is available in English.

哔哩哔哩新版首页排版调整和去广告(bilibili)

对新版B站首页的每行显示的视频数量进行调整, 同时删除所有广告, 并可设置屏蔽内容 (大尺寸屏幕每行将显示更多的视频)

  1. // ==UserScript==
  2. // @name 哔哩哔哩新版首页排版调整和去广告(bilibili)
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.9.15
  5. // @author Ling2Ling4
  6. // @description 对新版B站首页的每行显示的视频数量进行调整, 同时删除所有广告, 并可设置屏蔽内容 (大尺寸屏幕每行将显示更多的视频)
  7. // @license MIT
  8. // @icon data:image/png;base64,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
  9. // @match *://www.bilibili.com/*
  10. // @exclude *://www.bilibili.com/all*
  11. // @exclude *://www.bilibili.com/anime*
  12. // @exclude *://www.bilibili.com/pgc*
  13. // @exclude *://t.bilibili.com/*
  14. // @exclude *://www.bilibili.com/opus*
  15. // @exclude *://www.bilibili.com/live*
  16. // @exclude *://www.bilibili.com/article*
  17. // @exclude *://www.bilibili.com/upuser*
  18. // @exclude *://www.bilibili.com/match*
  19. // @exclude *://www.bilibili.com/platform*
  20. // @exclude *://www.bilibili.com/bangumi*
  21. // @exclude *://www.bilibili.com/cheese*
  22. // @grant GM_setValue
  23. // @grant GM_getValue
  24. // @grant GM_registerMenuCommand
  25. // @grant window.onurlchange
  26. // @noframes
  27. // @compatible chrome
  28. // @compatible edge
  29. // @compatible firefox
  30. // ==/UserScript==
  31.  
  32. (() => {
  33. "use strict";
  34. const info = {
  35. scriptUrl:
  36. "https://greasyfork.org/zh-CN/users/1196880-ling2ling4#user-script-list",
  37. apiUrl:
  38. "https://api.bilibili.com/x/web-interface/wbi/index/top/feed/rcmd",
  39. logoUrl:
  40. "https://i0.hdslb.com/bfs/archive/c8fd97a40bf79f03e7b76cbc87236f612caef7b2.png",
  41. imgDetails: "@672w_378h_1c_!web-home-common-cover",
  42. loadVideoNum: 10,
  43. marginTop1: 24,
  44. marginTop2: 24,
  45. clickMinInterval: 200,
  46. testNetInterval: 4,
  47. netSpeed: { value: 0, lastValue: 0 },
  48. baseNetSpeed: 65,
  49. refreshLoopFnInfo: {
  50. interval: 40,
  51. svgNum: 12,
  52. rollNum: 20,
  53. rollNum2: 20,
  54. addNumMultiple: 0.8,
  55. maxAddNum: 25,
  56. },
  57. isRemoveDelDom: !1,
  58. isScriptRefresh: !1,
  59. pageName: "",
  60. keyBase: "setting_",
  61. zoom: window.devicePixelRatio,
  62. otherAdCssDomId: "otherAdCss",
  63. homeClassList: {
  64. 标题: "h3 a",
  65. 作者: "bili-video-card__info--bottom",
  66. 分类: "floor-title",
  67. author: "bili-video-card__info--author",
  68. carousel: "recommended-swipe",
  69. vDom: ["container", "no-banner-container", "is-version8"],
  70. video: "feed-card",
  71. nav: "bili-header__bar",
  72. banner: "bili-header__banner",
  73. btn: "roll-btn",
  74. btn2: "flexible-roll-btn",
  75. specialCard: "floor-single-card",
  76. addVideo: "add-video",
  77. delUpBtn: "ll-del-up-btn",
  78. videoTime: "bili-video-card__stats__duration",
  79. },
  80. homeSelector: {
  81. rbBtnAd: { selector: ".palette-button-wrap .adcard-content", type: "" },
  82. rbCardAd: { selector: ".adcard", value: "adcard", type: "class" },
  83. },
  84. homeDelClassList: {
  85. 广告: [
  86. "bili-video-card__info--ad",
  87. { value: "bili-video-card__mask", content: "广告" },
  88. ],
  89. 推广: "bili-video-card__info--creative-ad",
  90. 特殊: "floor-single-card",
  91. 直播: "living",
  92. 番剧: "分类=番剧",
  93. 综艺: "分类=综艺",
  94. 课堂: "分类=课堂",
  95. 漫画: "分类=漫画",
  96. 国创: "分类=国创",
  97. 电影: "分类=电影",
  98. 纪录片: "分类=纪录片",
  99. 电视剧: "分类=电视剧",
  100. },
  101. iconSvg: {
  102. blacklist:
  103. '<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1704699843965" style="svgStyleFlag" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="941" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M512.090917 1024a512 512 0 1 1 512.090917-512 512.045459 512.045459 0 0 1-512.090917 512zM91.599041 511.249933a419.446329 419.446329 0 0 0 682.083282 327.301785L184.107254 248.931191a417.400693 417.400693 0 0 0-92.417296 262.296013zM511.295392 91.6445a417.627985 417.627985 0 0 0-261.386842 91.599041l589.393235 589.256859A419.287224 419.287224 0 0 0 511.386309 91.62177z" p-id="942"></path></svg>',
  104. },
  105. txt: { delUpBtnTT: "屏蔽该up的所有视频, 屏蔽后可在插件的屏蔽设置中修改" },
  106. events: { rollSvg: !1, roll: !1, roll2: !1, resize: !1, wheel: !1 },
  107. btnDoms: {},
  108. errKeyArr: ["", 2, 3],
  109. errKeyInfo: {
  110. disNum: "setting_err_disNum",
  111. errNum: "setting_err_num",
  112. errTime: "setting_err_time",
  113. isTip: "setting_err_isTip",
  114. },
  115. disErrTipNum: 3,
  116. errTipNum: 15,
  117. errTipInterval: 2,
  118. errNumReset: 5,
  119. videoInfo: {
  120. startTime: 500,
  121. pathInterval: 500,
  122. interval: 1e3,
  123. timeoutNum: 8,
  124. selector: {
  125. playerContainer: {
  126. value: "#bilibili-player .bpx-player-container",
  127. flag: "bpx-state-paused",
  128. },
  129. likeBtn: {
  130. value: "#app .video-toolbar-container .video-like",
  131. flag: "on",
  132. },
  133. curTime: { value: ".bpx-player-ctrl-time-current" },
  134. ttTime: { value: ".bpx-player-ctrl-time-duration" },
  135. },
  136. classList: { videoPaused: "", likeBtn: "on" },
  137. delDom: [
  138. {
  139. name: "几乎全部广告",
  140. pre: ".",
  141. str: "ad-report",
  142. type: "ad",
  143. isAll: !0,
  144. },
  145. { name: "横幅广告", pre: "#", str: "bannerAd" },
  146. { name: "活动广告", pre: "#", str: "slide_ad", type: "ad" },
  147. { name: "视频广告", pre: ".", str: "video-card-ad-small" },
  148. { name: "右下广告", pre: "#", str: "right-bottom-banner" },
  149. {
  150. name: "横幅通告",
  151. pre: ".",
  152. str: "bili-comments-header-renderer reply-notice",
  153. type: "ad",
  154. },
  155. {
  156. name: "横幅通告",
  157. pre: "",
  158. value: "bili-comments-notice",
  159. selector: "bili-comments-notice",
  160. type: "ad",
  161. v: "v240713",
  162. shadowRootPath: [
  163. [
  164. {
  165. type: "ele",
  166. selector: "bili-comments",
  167. value: "bili-comments",
  168. },
  169. {
  170. type: "ele",
  171. selector: "bili-comments-header-renderer",
  172. value: "bili-comments-header-renderer",
  173. },
  174. ],
  175. ],
  176. },
  177. {
  178. name: "游戏推荐",
  179. pre: ".",
  180. str: "video-page-game-card-small",
  181. type: "other",
  182. },
  183. { name: "活动推广", pre: "#", str: "activity_vote", type: "other" },
  184. {
  185. name: "直播推广",
  186. pre: ".",
  187. str: "pop-live-small-mode",
  188. type: "other",
  189. },
  190. ],
  191. },
  192. },
  193. keyBase = info.keyBase,
  194. settings = {
  195. isCarousel: {
  196. value: !0,
  197. base: !0,
  198. key: keyBase + "isCarousel",
  199. txt: "是否显示轮播图 (修改后需要调整排列规则才能达到预期效果,轮播图占两个视频的宽度,所以每行显示视频数加减2即可)",
  200. type: "首页",
  201. valType: "boolean",
  202. compType: "radio",
  203. valueText: { true: "显示轮播图", false: "隐藏轮播图" },
  204. },
  205. delOtherAd: {
  206. value: ["rbBtnAd", "rbCardAd"],
  207. base: ["rbBtnAd", "rbCardAd"],
  208. key: keyBase + "delOtherAd",
  209. txt: "请勾选要删除的非视频类广告",
  210. type: "首页",
  211. valType: "array",
  212. compType: "checkbox",
  213. valueText: { rbBtnAd: "右下角按钮广告", rbCardAd: "右下角卡片广告" },
  214. },
  215. isRefreshLast: {
  216. value: !1,
  217. base: !1,
  218. key: keyBase + "isRefreshLast",
  219. txt: '是否在刷新视频时刷新掉最后的"直播"类视频 (新视频为普通视频)',
  220. type: "首页",
  221. valType: "boolean",
  222. compType: "radio",
  223. valueText: {
  224. true: "刷新掉'直播'类视频",
  225. false: "保留末尾的'直播'类视频",
  226. },
  227. },
  228. isAutoLayout: {
  229. value: !0,
  230. base: !0,
  231. key: keyBase + "isAutoLayout",
  232. txt: "是否根据缩放自动调整视频布局",
  233. type: "首页",
  234. valType: "boolean",
  235. compType: "radio",
  236. valueText: {
  237. true: "缩放时自动调整布局",
  238. false: "仅窗口变化时调整布局",
  239. },
  240. },
  241. isLoadOne: {
  242. value: !0,
  243. base: !0,
  244. key: keyBase + "isLoadOne",
  245. txt: "是否在进入网站时加载前三行的全部视频, 开启后前三行将不会出现预加载视频",
  246. type: "首页",
  247. valType: "boolean",
  248. compType: "radio",
  249. valueText: {
  250. true: "加载视口的全部视频",
  251. false: "保留视口的预加载视频",
  252. },
  253. },
  254. isDelUpBtn: {
  255. value: !0,
  256. base: !0,
  257. key: keyBase + "isDelUpBtn",
  258. txt: "是否在鼠标移入一个视频区域时显示屏蔽该up所有视频的按钮",
  259. type: "首页",
  260. valType: "boolean",
  261. compType: "radio",
  262. valueText: { true: "显示屏蔽up的按钮", false: "不显示屏蔽up的按钮" },
  263. },
  264. isReorderVideo: {
  265. value: !0,
  266. base: !0,
  267. valType: "boolean",
  268. key: keyBase + "isReorderVideo",
  269. txt: "是否按照排列规则调整布局 (每行能够显示更多视频)",
  270. type: "排列规则",
  271. compType: "radio",
  272. valueText: {
  273. true: "按照排列规则调整布局",
  274. false: "使用原来的视频排列",
  275. },
  276. },
  277. videoNumRule: {
  278. title: "排列规则",
  279. value: "0,1300,2\n1300,1800,3\n1800,3000,4\n3000,3700,5\n3700,6300,6",
  280. base: "0,1300,2\n1300,1800,3\n1800,3000,4\n3000,3700,5\n3700,6300,6",
  281. base2: "0,1300,4\n1300,1800,5\n1800,3000,6\n3000,3700,7\n3700,6300,8",
  282. key: keyBase + "videoNumRule",
  283. txt: "视频排列规则, 每条规则用 ; 分隔 或 换行书写. 未包含的尺寸将按照初始方式排列 (轮播图会影响视频的排列)\n 示例: 1300,1800,3; 1800,3000,4 表示浏览器宽度在1300~1800像素时每行显示3个视频(前两行), 1800~3000像素每行4个视频",
  284. type: "排列规则",
  285. valType: "string",
  286. compType: "textarea",
  287. compH: "120px",
  288. },
  289. delClassArr: {
  290. value: "广告, 推广",
  291. base: "广告, 推广",
  292. key: keyBase + "delClassArr",
  293. title: "屏蔽设置",
  294. txt: "可根据需要自行修改, 可自定义, 每项用 , 分隔 或 换行书写\n例如: 广告, 推广, 直播, 作者==零泠丶\n----可选:\n广告、推广、特殊、直播、番剧、综艺、课堂、漫画、国创、电影、纪录片、电视剧 (注: '特殊'包含了它右边所有的)\n----自定义:\n1. 标题=xxx, 可屏蔽标题含xxx的视频, xxx部分支持&&运算符, 如: 标题=A&&B, 表示屏蔽标题同时含有A B内容的视频\n2. 作者=xxx, 可屏蔽作者名和发布日期中含xxx的视频, 若书写为\"作者==xxx\"则表示屏蔽作者xxx的视频",
  295. type: "屏蔽设置",
  296. valType: "string",
  297. compType: "textarea",
  298. compH: "100px",
  299. },
  300. minVideoTime: {
  301. value: "",
  302. base: "",
  303. key: keyBase + "minVideoTime",
  304. title: "按时长屏蔽",
  305. txt: "请设置视频的屏蔽时长, 小于等于该时长的视频将被屏蔽\n示例:\n30 屏蔽小于等于30秒的视频\n12:30 屏蔽小于等于12分30秒的视频\n12分30秒 ...",
  306. type: "屏蔽设置",
  307. valType: "string",
  308. compType: "textarea",
  309. compH: "30px",
  310. },
  311. video_isDelAd: {
  312. groupTitle2: "广告屏蔽设置",
  313. value: !0,
  314. base: !0,
  315. key: keyBase + "video_isDelAd",
  316. txt: "是否删除视频页的广告",
  317. type: "视频页",
  318. valType: "boolean",
  319. compType: "radio",
  320. valueText: { true: "删除广告", false: "保留广告" },
  321. },
  322. video_delSetting: {
  323. value: "部分广告",
  324. base: "部分广告",
  325. key: keyBase + "video_delSetting",
  326. txt: "可根据需要自行修改, 每项用 , 分隔 (该设置仅在删除广告时生效)\n例如: 部分广告, 活动推广\n----可选:\n全部广告: 所有直接广告和间接广告\n部分广告: 所有直接广告 (横幅广告,活动广告,视频广告,右下广告,横幅通告)\n横幅广告: 视频下方的横幅广告\n活动广告: 右侧视频列表上方的广告\n视频广告: 右侧视频列表上方的小视频广告\n右下广告: 右侧视频列表下方的广告\n横幅通告: 评论区上方的横幅通告\n游戏推荐: 视频右侧的视频的相关游戏推荐\n活动推广: 评论区上方的活动推广\n直播推广: 右侧视频列表下方的直播推广",
  327. type: "视频页",
  328. valType: "string",
  329. compType: "textarea",
  330. compH: "30px",
  331. },
  332. video_isAutoLike: {
  333. groupTitle2: "自动点赞设置",
  334. value: !1,
  335. base: !1,
  336. key: keyBase + "video_isAutoLike",
  337. txt: "是否在播放视频后自动给视频点赞",
  338. type: "视频页",
  339. valType: "boolean",
  340. compType: "radio",
  341. valueText: { true: "播放后点赞", false: "关闭该功能" },
  342. },
  343. video_autoLike: {
  344. value: "50%",
  345. base: "50%",
  346. key: keyBase + "video_autoLike",
  347. txt: "视频播放到什么位置后自动给视频点赞, 可书写百分比, 也可书写分钟或秒 \n例如:\n80% 表示视频播放完80%后自动点赞\n2分钟 表示视频播放2分钟后自动点赞(视频需要大于2分钟)",
  348. type: "视频页",
  349. valType: "string",
  350. compType: "textarea",
  351. compH: "30px",
  352. },
  353. isClearAd: {
  354. value: !0,
  355. base: !0,
  356. key: keyBase + "isClearAd",
  357. txt: "首页: 是否删除广告, 若不删除则会将所有广告移至视频列表的最后",
  358. type: "其他设置",
  359. valType: "boolean",
  360. compType: "radio",
  361. valueText: { true: "删除广告", false: "广告后移" },
  362. },
  363. isTrueEnd: {
  364. value: !1,
  365. base: !1,
  366. key: keyBase + "isTrueEnd",
  367. txt: "首页: 是否将广告移至预加载视频的后面, 关闭后广告将放置在预加载视频的前面 一般视频的后面 (仅在不删除广告时生效)",
  368. type: "其他设置",
  369. valType: "boolean",
  370. compType: "radio",
  371. valueText: { true: "放置页尾", false: "放置预加载视频前" },
  372. },
  373. isTestNetSpeed: {
  374. value: !0,
  375. base: !0,
  376. key: keyBase + "isTestNetSpeed",
  377. txt: "首页: 是否检测网速, 并根据网速调整'判断是否采用脚本刷新全部视频'的最大间隔时间,开启后在网速较低时不那么容易出现刷新按钮失效的bug",
  378. type: "其他设置",
  379. valType: "boolean",
  380. compType: "radio",
  381. valueText: { true: "测试网速", false: "不测试网速" },
  382. },
  383. addVideoNum: {
  384. value: 0,
  385. base: 0,
  386. valType: "number",
  387. key: keyBase + "addVideoNum",
  388. txt: "首页: 加载用于填充视口空白视频的视频数量, 0表示自动计算数量 (自动计算时可能会因为屏蔽了部分视频导致视口区域还留有空白视频)",
  389. type: "其他设置",
  390. compType: "textarea",
  391. compH: "30px",
  392. },
  393. homeDelAdTime: {
  394. value: 0,
  395. base: 0,
  396. valType: "number",
  397. key: keyBase + "homeDelAdTime",
  398. txt: "首页: 点击换一换按钮并加载完新视频后 进行广告屏蔽的间隔时间, 0表示立即屏蔽 (毫秒, 1秒=1000毫秒)",
  399. type: "其他设置",
  400. compType: "textarea",
  401. compH: "30px",
  402. },
  403. };
  404. function getValue({
  405. base,
  406. key,
  407. valType = "string",
  408. isReSet = !0,
  409. getValue = null,
  410. setValue = null,
  411. getVal = null,
  412. setVal = null,
  413. } = {}) {
  414. getValue && (getVal = getValue), setValue && (setVal = setValue);
  415. let val = getVal ? getVal(key) : localStorage.getItem(key);
  416. return (
  417. void 0 !== base &&
  418. null == val &&
  419. ((val = base),
  420. isReSet &&
  421. ("string" != typeof base && (base = JSON.stringify(base)),
  422. setVal ? setVal(key, base) : localStorage.setItem(key, base))),
  423. (valType = valType.toLowerCase()),
  424. "string" == typeof val
  425. ? "string" === valType
  426. ? val
  427. : "boolean" === valType || "number" === valType
  428. ? JSON.parse(val)
  429. : "object" === valType
  430. ? val
  431. ? JSON.parse(val)
  432. : {}
  433. : "array" === valType
  434. ? val
  435. ? JSON.parse(val)
  436. : []
  437. : val
  438. : val
  439. );
  440. }
  441. function getData() {
  442. for (const valName in settings) {
  443. const setting = settings[valName];
  444. setting.value = getValue({
  445. base: setting.base,
  446. key: setting.key,
  447. valType: setting.valType,
  448. getVal: GM_getValue,
  449. setVal: GM_setValue,
  450. });
  451. }
  452. return settings;
  453. }
  454. const utils = {
  455. getW(isAutoLayout) {
  456. let width =
  457. window.innerWidth ||
  458. document.documentElement.clientWidth ||
  459. document.body.clientWidth;
  460. return (
  461. console.log("浏览器实际宽度:", width * window.devicePixelRatio),
  462. console.log("浏览器像素宽度:", width * info.zoom),
  463. !isAutoLayout && (width *= window.devicePixelRatio),
  464. width
  465. );
  466. },
  467. getValue(key, defa = null) {
  468. let value = GM_getValue(key);
  469. return null == value ? defa : value;
  470. },
  471. boolTxt: (val) => (val ? "是 (确定)" : "否 (取消)"),
  472. strToDom(str) {
  473. let tmpDom = document.createElement("div");
  474. tmpDom.innerHTML = str;
  475. const dom = tmpDom.children[0];
  476. return (tmpDom = null), dom;
  477. },
  478. formatDate(timestamp, { delimiter = "-", isYear = !1, isAlign = !0 } = {}) {
  479. if (!timestamp) return -1;
  480. const date = new Date(timestamp),
  481. year = date.getFullYear();
  482. let month = (date.getMonth() + 1).toString(),
  483. day = date.getDate().toString();
  484. return (
  485. isAlign &&
  486. ((month = month.padStart(2, "0")), (day = day.padStart(2, "0"))),
  487. (isYear ? year + delimiter : "") + month + delimiter + day
  488. );
  489. },
  490. formatTime(time, { delimiter = ":", isAlign = !0 } = {}) {
  491. if (!time) return -1;
  492. let h = Math.floor(time / 60 / 60),
  493. m = Math.floor((time / 60) % 60),
  494. s = Math.floor(time % 60);
  495. return (
  496. isAlign &&
  497. ((h = h ? h.toString().padStart(2, "0") : ""),
  498. (m = m.toString().padStart(2, "0")),
  499. (s = s.toString().padStart(2, "0"))),
  500. (h ? h + delimiter : "") + m + delimiter + s
  501. );
  502. },
  503. async request(url, options = {}) {
  504. options.method = options.method || "GET";
  505. try {
  506. const res = await fetch(url, options);
  507. if (!res.ok) throw new Error(`HTTP error! Status: ${res.status}`);
  508. return await res.json();
  509. } catch (error) {
  510. throw error;
  511. }
  512. },
  513. errHandle({ e = null, errTxt = "", logTxt = "", key = "" } = {}) {
  514. key && (key = "_" + key);
  515. let errNum = GM_getValue(info.errKeyInfo.errNum) || 0;
  516. if (errNum >= info.errTipNum) return;
  517. let disErrNum = GM_getValue(info.errKeyInfo.disNum + key) || 0;
  518. const curTime = Date.now();
  519. let disS =
  520. (curTime - (GM_getValue(info.errKeyInfo.errTime + key) || curTime)) /
  521. 1e3;
  522. if (((disS = 0 === disS ? 5 : disS), disS < 5)) return;
  523. let flag = GM_getValue(info.errKeyInfo.isTip + key);
  524. (flag = void 0 === flag || flag),
  525. e && console.log(e),
  526. console.log(logTxt || errTxt),
  527. disS >= 60 * info.errTipInterval * 60 &&
  528. ((flag = !0),
  529. GM_setValue(info.errKeyInfo.isTip + key, !0),
  530. GM_setValue(info.errKeyInfo.disNum + key, 0)),
  531. flag &&
  532. disErrNum <= info.disErrTipNum &&
  533. disS < (info.errTipInterval / 10) * 60 * 60 &&
  534. (errNum++,
  535. disErrNum++,
  536. GM_setValue(info.errKeyInfo.errNum, errNum),
  537. GM_setValue(info.errKeyInfo.disNum + key, disErrNum),
  538. GM_setValue(info.errKeyInfo.errTime + key, curTime),
  539. alert(errTxt),
  540. disErrNum === info.disErrTipNum &&
  541. GM_setValue(info.errKeyInfo.isTip + key, !1));
  542. },
  543. resetErrInfo() {
  544. const curTime = Date.now();
  545. (curTime -
  546. info.errKeyArr.reduce((a, b) => {
  547. const t = +GM_getValue(info.errKeyInfo.errTime + b);
  548. return t < a ? t : a;
  549. }, curTime)) /
  550. 1e3 >=
  551. 24 * info.errNumReset * 60 * 60 &&
  552. (GM_setValue(info.errKeyInfo.errNum, 0),
  553. info.errKeyArr.forEach((key) => {
  554. key && (key = "_" + key),
  555. GM_setValue(info.errKeyInfo.disNum + key, 0);
  556. }));
  557. },
  558. getPathDom(classObj, pathArr, baseDom = document, isGetAll = !1) {
  559. if (!pathArr) return;
  560. const resultArr = [];
  561. let target;
  562. 0 === pathArr.length && pathArr.push([]), (pathArr = [...pathArr]);
  563. for (let i = 0; i < pathArr.length; i++) {
  564. const path = pathArr[i];
  565. let dom = path.baseDom || baseDom || document,
  566. isContinue = !1;
  567. for (let j = 0; j < path.length; j++) {
  568. const item = path[j];
  569. if (item.multiple) {
  570. let doms = dom.querySelectorAll(item.selector);
  571. if (0 === doms.length) return;
  572. doms = [].slice.call(doms);
  573. const addArr = path.slice(j + 1);
  574. doms.forEach((addBaseDom) => {
  575. const curAddArr = [...addArr];
  576. (curAddArr.baseDom = addBaseDom.shadowRoot || addBaseDom),
  577. pathArr.push(curAddArr);
  578. }),
  579. (isContinue = !0);
  580. break;
  581. }
  582. if (((dom = dom.querySelector(item.selector)), !dom)) break;
  583. dom = dom.shadowRoot || dom;
  584. }
  585. if (
  586. dom &&
  587. !isContinue &&
  588. ((target = dom.querySelector(classObj.selector)), target)
  589. ) {
  590. if (!isGetAll) return target;
  591. resultArr.push(target);
  592. }
  593. }
  594. return isGetAll ? resultArr : target;
  595. },
  596. };
  597. function textToTime(str) {
  598. if ((str += "").includes(":")) {
  599. const tArr = str.split(":"),
  600. len = tArr.length;
  601. let h = 0,
  602. m = 0,
  603. s = 0;
  604. 3 === len
  605. ? ((h = +tArr[0]), (m = +tArr[1]), (s = +tArr[2]))
  606. : 2 === len
  607. ? ((m = +tArr[0]), (s = +tArr[1]))
  608. : (s = +tArr[0]),
  609. (str = 60 * h * 60 + 60 * m + s);
  610. }
  611. return +str;
  612. }
  613. function timeStringToSeconds(timeString) {
  614. let seconds = 0;
  615. const hmsMatch = timeString.match(
  616. /^(\d{1,2})(?::(\d{1,2}))?(?::(\d{1,2}))?$/
  617. );
  618. if (hmsMatch) {
  619. const hours = Number(hmsMatch[1] || 0),
  620. minutes = Number(hmsMatch[2] || 0),
  621. secs = Number(hmsMatch[3] || 0);
  622. return (
  623. (seconds =
  624. void 0 === hmsMatch[2]
  625. ? hours
  626. : void 0 === hmsMatch[3]
  627. ? 60 * hours + minutes
  628. : 3600 * hours + 60 * minutes + secs),
  629. seconds
  630. );
  631. }
  632. const hmsChineseMatch1 = timeString.match(
  633. /(?:(\d+)小时)?(?:(\d+)分钟)?(?:(\d+)秒)?/
  634. );
  635. if (hmsChineseMatch1 && hmsChineseMatch1[0]) {
  636. return (
  637. (seconds =
  638. 3600 * Number(hmsChineseMatch1[1] || 0) +
  639. 60 * Number(hmsChineseMatch1[2] || 0) +
  640. Number(hmsChineseMatch1[3] || 0)),
  641. seconds
  642. );
  643. }
  644. const hmsChineseMatch2 = timeString.match(
  645. /(?:(\d+)时)?(?:(\d+)分)?(?:(\d+)秒)?/
  646. );
  647. if (hmsChineseMatch2 && hmsChineseMatch2[0]) {
  648. return (
  649. (seconds =
  650. 3600 * Number(hmsChineseMatch2[1] || 0) +
  651. 60 * Number(hmsChineseMatch2[2] || 0) +
  652. Number(hmsChineseMatch2[3] || 0)),
  653. seconds
  654. );
  655. }
  656. throw new Error("无效的时间格式");
  657. }
  658. const videoObj = {
  659. info: {
  660. isDelAd: null,
  661. delSetting: null,
  662. base_isDelAd: null,
  663. base_delSetting: null,
  664. startTime: info.videoInfo.startTime,
  665. pathInterval: info.videoInfo.pathInterval,
  666. interval: info.videoInfo.interval,
  667. timeoutNum: info.videoInfo.timeoutNum,
  668. isVideoLiked: !1,
  669. likeTimer: null,
  670. },
  671. doms: {
  672. ad: [],
  673. playerContainer: null,
  674. likeBtn: null,
  675. curTime: null,
  676. ttTime: null,
  677. },
  678. delDom: info.videoInfo.delDom,
  679. initValue() {
  680. (this.info.isDelAd = settings.video_isDelAd.value),
  681. (this.info.delSetting = settings.video_delSetting.value),
  682. (this.info.base_isDelAd = settings.video_isDelAd.base),
  683. (this.info.base_delSetting = settings.video_delSetting.base);
  684. },
  685. getAdInfo() {
  686. if (this.info.delSetting.includes("全部广告"))
  687. return this.delDom.filter(
  688. (item) => "ad" === item.type || "other" === item.type
  689. );
  690. if ("部分广告" === this.info.delSetting)
  691. return this.delDom.filter(
  692. (item) => "ad" === item.type || "other" !== item.type
  693. );
  694. {
  695. let arr = this.delDom.filter((item) =>
  696. this.info.delSetting.includes(item.name)
  697. );
  698. if (this.info.delSetting.includes("部分广告")) {
  699. const arr2 = this.delDom.filter((item) => {
  700. if (!arr.includes(item))
  701. return "ad" === item.type || "other" !== item.type;
  702. });
  703. arr = arr.concat(arr2);
  704. }
  705. return 0 === arr.length
  706. ? (utils.errHandle({
  707. errTxt: `插件设置的广告屏蔽设置中 '${GM_getValue(
  708. "setting_video_delSetting"
  709. )}' 格式书写错误`,
  710. key: info.errKeyArr[2],
  711. }),
  712. -1)
  713. : arr;
  714. }
  715. },
  716. getAd() {
  717. const ad = [],
  718. delAdInfo = this.getAdInfo();
  719. -1 !== delAdInfo
  720. ? (delAdInfo.forEach((item) => {
  721. let adList = [];
  722. if ("." === item.pre)
  723. if (item.isAll)
  724. (adList = document.querySelectorAll(item.pre + item.str)),
  725. (adList = [].slice.call(adList));
  726. else {
  727. const dom = document.querySelector(item.pre + item.str);
  728. dom && adList.push(dom);
  729. }
  730. else if (item.v) {
  731. const ele = utils.getPathDom(item, item.shadowRootPath);
  732. ele && adList.push(ele);
  733. } else {
  734. const ele = document.querySelector(item.pre + item.str);
  735. ele && adList.push(ele);
  736. }
  737. adList.length > 0 &&
  738. adList.forEach((adDom) => {
  739. ad.push(adDom);
  740. });
  741. }),
  742. (this.doms.ad = this.info.isDelAd
  743. ? ad.filter((item) => "none" !== item.style.display)
  744. : ad))
  745. : (this.doms.ad = []);
  746. },
  747. delAd() {
  748. this.doms.ad.forEach((item) => {
  749. "none" !== item.style.display && (item.style.display = "none");
  750. });
  751. },
  752. showAd() {
  753. this.doms.ad.forEach((item) => {
  754. "none" === item.style.display && (item.style.display = "");
  755. });
  756. },
  757. updateData() {
  758. (this.info.isDelAd = settings.video_isDelAd.value),
  759. (this.info.delSetting = settings.video_delSetting.value);
  760. },
  761. autoLike() {
  762. if (settings.video_isAutoLike.value) {
  763. const selector = info.videoInfo.selector,
  764. doms = this.doms,
  765. getDom = () => {
  766. let playerContainer = doms.playerContainer;
  767. if (!playerContainer) {
  768. if (
  769. ((playerContainer = document.querySelector(
  770. selector.playerContainer.value
  771. )),
  772. !playerContainer)
  773. )
  774. return console.log("未获取到视频播放器的dom"), -1;
  775. doms.playerContainer = playerContainer;
  776. }
  777. return doms.likeBtn ||
  778. ((doms.likeBtn = document.querySelector(selector.likeBtn.value)),
  779. doms.likeBtn)
  780. ? doms.curTime ||
  781. ((doms.curTime = playerContainer.querySelector(
  782. selector.curTime.value
  783. )),
  784. doms.curTime)
  785. ? doms.ttTime ||
  786. ((doms.ttTime = playerContainer.querySelector(
  787. selector.ttTime.value
  788. )),
  789. doms.ttTime)
  790. ? void 0
  791. : (console.log("未获取到视频总时间的dom"), -1)
  792. : (console.log("未获取到当前播放时间的dom"), -1)
  793. : (console.log("未获取到点赞按钮的dom"), -1);
  794. };
  795. let likeStart = !1;
  796. const clickHandle = () => {
  797. if (likeStart) return;
  798. if (this.info.isVideoLiked) return;
  799. const playerClass = selector.playerContainer.flag,
  800. likeBtnClass = selector.likeBtn.flag,
  801. timer = this.info.likeTimer;
  802. timer && clearInterval(timer), (likeStart = !0);
  803. let isDoms = !1,
  804. num = 0;
  805. this.info.likeTimer = setInterval(() => {
  806. let f,
  807. likeBtn = doms.likeBtn,
  808. isLiked = likeBtn && likeBtn.classList.contains(likeBtnClass);
  809. if (isLiked || this.info.isVideoLiked)
  810. return (
  811. !isLiked && this.info.isVideoLiked && doms.likeBtn.click(),
  812. clearInterval(this.info.likeTimer),
  813. (this.info.likeTimer = null),
  814. void (this.info.isVideoLiked = !0)
  815. );
  816. if ((isDoms || ((f = getDom()), num++), num > 5))
  817. return (
  818. clearInterval(this.info.likeTimer),
  819. void (this.info.likeTimer = null)
  820. );
  821. if (-1 === f) return;
  822. isDoms = !0;
  823. const player = doms.playerContainer;
  824. if (
  825. ((likeBtn = doms.likeBtn),
  826. (isLiked = likeBtn.classList.contains(likeBtnClass)),
  827. !player.classList.contains(playerClass) && !isLiked)
  828. ) {
  829. (() => {
  830. let isNeedLike = !1;
  831. const curTimeS = textToTime(doms.curTime.innerText),
  832. ttTimeS = textToTime(doms.ttTime.innerText),
  833. autoLikeStr = settings.video_autoLike.value;
  834. let targetTime = parseInt(autoLikeStr) || 0;
  835. return (
  836. autoLikeStr.includes("分") || autoLikeStr.includes("min")
  837. ? (targetTime *= 60)
  838. : autoLikeStr.includes("秒") ||
  839. autoLikeStr.includes("s") ||
  840. (targetTime = (targetTime / 100) * ttTimeS),
  841. curTimeS + 1 >= targetTime && (isNeedLike = !0),
  842. !!isNeedLike &&
  843. (doms.likeBtn.click(), console.log("给视频点赞"), !0)
  844. );
  845. })() && (this.info.isVideoLiked = !0);
  846. }
  847. }, 1e3);
  848. };
  849. document.addEventListener("click", clickHandle, !0);
  850. }
  851. },
  852. init() {
  853. if ((this.initValue(), this.autoLike(), !this.info.isDelAd)) return;
  854. let i = 0;
  855. const timer = setInterval(() => {
  856. i++,
  857. this.getAd(),
  858. i > this.info.timeoutNum && clearInterval(timer),
  859. this.delAd();
  860. }, this.info.interval);
  861. utils.resetErrInfo();
  862. },
  863. };
  864. const baseCfg = {
  865. state: "",
  866. isEditing: !1,
  867. hasSelectedPage: !1,
  868. param: {
  869. id: "ll_edit_wrap",
  870. box: document.body,
  871. classBase: "ll_edit_",
  872. w: "500px",
  873. h: "",
  874. contentH: "450px",
  875. bg: "rgba(0, 0, 0, 0.15)",
  876. color: "#333",
  877. fontSize: "15px",
  878. fontFamily:
  879. "PingFang SC, HarmonyOS_Regular, Helvetica Neue, Microsoft YaHei, sans-serif",
  880. zIndex: 11e3,
  881. resetTt: "重置当前页的所有设置为默认值",
  882. isShowMenu: !1,
  883. isScrollStyle: !0,
  884. isResetBtn: !0,
  885. isOnlyResetCurPage: !0,
  886. showPage: void 0,
  887. isIntervalRun: !1,
  888. interval: 1e3,
  889. page: [],
  890. callback: {
  891. resetBefore: null,
  892. reset: null,
  893. confirmBefore: null,
  894. finished: null,
  895. interval: null,
  896. cancelBefore: null,
  897. cancelled: null,
  898. },
  899. },
  900. },
  901. cfg = {
  902. version: "v1.2.2",
  903. isEditing: baseCfg.isEditing,
  904. hasSelectedPage: baseCfg.hasSelectedPage,
  905. timer: null,
  906. interval: 1e3,
  907. param: {},
  908. tempParam: {},
  909. allData: {},
  910. oldData: {},
  911. lastData: {},
  912. baseData: {},
  913. controls: {},
  914. doms: { page: [] },
  915. editText: {},
  916. };
  917. const css = function getCss() {
  918. const param = cfg.param,
  919. cBase = (param.page, param.classBase),
  920. baseStart = `#${param.id} .${cBase}`,
  921. fSize = param.fontSize ? param.fontSize : "14px",
  922. css = `#${
  923. param.id
  924. } {\n position: fixed;\n left: 0;\n top: 0;\n width: 100%;\n height: 100%;\n z-index: ${
  925. param.zIndex || 11e3
  926. };\n background: ${
  927. param.bg || "rgba(0, 0, 0, 0.12)"
  928. };\n display: none;\n}\n${baseStart}box {\n text-align: initial;\n letter-spacing: 1px;\n position: relative;\n width: ${
  929. param.w || "450px"
  930. };\n ${
  931. param.h ? "max-height:" + param.h : ""
  932. };\n margin: auto;\n color: ${
  933. param.color || "#333"
  934. };\n background: #fff;\n font-size: ${fSize};\n line-height: normal;\n font-family: ${
  935. param.fontFamily ||
  936. "PingFang SC, HarmonyOS_Regular, Helvetica Neue, Microsoft YaHei, sans-serif"
  937. };\n border: 3px solid #dfedfe;\n border-radius: 10px;\n box-sizing: border-box;\n padding: 14px 8px 10px 15px;\n overflow: hidden;\n overflow-y: auto;\n}\n${baseStart}menu {\n font-weight: bold;\n font-size: ${
  938. parseInt(fSize) + 1
  939. }px;\n display: flex;\n flex-wrap: wrap;\n gap: 0 8px;\n}\n${baseStart}menu-item {\n margin-bottom: 8px;\n border: 1px solid #dfedfe;\n color: #9ecaff;\n background: #eef6ff;\n border-radius: 6px;\n padding: 6px 10px;\n cursor: pointer;\n}\n${baseStart}menu-item:hover {\n color: #65aaff;\n background: #dfedfe;\n border: 1px solid #dfedfe;\n}\n${baseStart}menu-item.active {\n color: #65aaff;\n background: #dfedfe;\n border: 1px solid #dfedfe;\n}\n${baseStart}page-box {\n max-height: ${
  940. param.contentH || ""
  941. };\n padding-right: 7px;\n margin-bottom: 8px;\n overflow: hidden;\n overflow-y: auto;\n}\n${baseStart}page {\n display: none;\n}\n${baseStart}page.curPage {\n display: block;\n}\n${baseStart}comp {\n margin-bottom: 8px;\n}\n${baseStart}comp:last-child {\n margin-bottom: 2px;\n}\n${baseStart}tt {\n font-weight: bold;\n font-size: ${
  942. parseInt(fSize) + 6
  943. }px;\n margin-top: 4px;\n}\n${baseStart}tt2 {\n font-weight: bold;\n font-size: ${
  944. parseInt(fSize) + 4
  945. }px;\n margin-top: 3px;\n margin-bottom: 7px;\n}\n${baseStart}tt3 {\n font-weight: bold;\n font-size: ${
  946. parseInt(fSize) + 2
  947. }px;\n margin-top: 2px;\n margin-bottom: 6px;\n}\n${baseStart}desc {\n line-height: 1.5;\n}\n${baseStart}comp-tt {\n font-weight: bold;\n font-size: ${
  948. parseInt(fSize) + 1
  949. }px;\n line-height: 1.5;\n}\n${baseStart}comp-desc {\n line-height: 1.5;\n}\n${baseStart}rd-arr {\n line-height: 22px;\n}\n${baseStart}rd-arr label {\n margin-right: 6px;\n cursor: pointer;\n}\n${baseStart}rd-arr input {\n vertical-align: -2px;\n cursor: pointer;\n}\n${baseStart}rd-arr span {\n color: #666;\n margin-left: 2px;\n}\n#${
  950. param.id
  951. } textarea {\n width: 100%;\n max-width: 100%;\n max-height: 300px;\n border-radius: 6px;\n line-height: normal;\n padding: 5px 7px;\n outline-color: #cee4ff;\n border: 1px solid #aaa;\n box-sizing: border-box;\n font-size: ${
  952. parseInt(fSize) - 2
  953. }px;\n font-family: PingFang SC, HarmonyOS_Regular, Helvetica Neue, Microsoft YaHei, sans-serif;\n /* 保留空格 */\n white-space: pre-wrap;\n /* 允许词内换行 */\n word-break: break-all;\n letter-spacing: 1px;\n overflow: hidden;\n overflow-y: auto;\n}\n#${
  954. param.id
  955. } textarea::placeholder {\n color: #bbb;\n}\n${baseStart}ta-desc {\n margin-bottom: 3px;\n}\n${baseStart}btn-box {\n display: flex;\n justify-content: flex-end;\n}\n${baseStart}btn-box button {\n font-size: 16px;\n line-height: normal;\n color: #65aaff;\n background: #dfedfe;\n outline: none;\n border: none;\n border-radius: 6px;\n padding: 8px 16px;\n box-sizing: border-box;\n cursor: pointer;\n}\n${baseStart}btn-box .${cBase}reset-btn {\n position: absolute;\n left: 15px;\n bottom: 10px;\n color: #888;\n background: #f4f4f4;\n margin-right: 15px;\n}\n${baseStart}btn-box .${cBase}reset-btn:hover {\n color: #666;\n background: #eee;\n}\n${baseStart}btn-box .${cBase}cancel-btn {\n color: #888;\n background: #f4f4f4;\n margin-right: 15px;\n}\n${baseStart}btn-box .${cBase}cancel-btn:hover {\n color: #666;\n background: #eee;\n}\n${baseStart}btn-box .${cBase}confirm-btn {\n margin-right: 7px;\n}\n${baseStart}btn-box .${cBase}confirm-btn:hover {\n background: #cee4ff;\n}\n`;
  956. return param.isScrollStyle
  957. ? css +
  958. "\n.ll-scroll-style-1::-webkit-scrollbar,\n.ll-scroll-style-1 ::-webkit-scrollbar {\n width: 8px;\n}\n.ll-scroll-style-1-size-2::-webkit-scrollbar,\n.ll-scroll-style-1 .ll-scroll-style-1-size-2::-webkit-scrollbar {\n width: 10px;\n}\n.ll-scroll-style-1-size-3::-webkit-scrollbar,\n.ll-scroll-style-1 .ll-scroll-style-1-size-3::-webkit-scrollbar {\n width: 12px;\n}\n.ll-scroll-style-1::-webkit-scrollbar-thumb,\n.ll-scroll-style-1 ::-webkit-scrollbar-thumb {\n border-radius: 10px;\n -webkit-box-shadow: inset 0 0 8px rgba(0, 0, 0, 0.05);\n opacity: 0.2;\n background: #daedff;\n}\n.ll-scroll-style-1::-webkit-scrollbar-track,\n.ll-scroll-style-1 ::-webkit-scrollbar-track {\n -webkit-box-shadow: inset 0 0 8px rgba(0, 0, 0, 0.08);\n border-radius: 0;\n background: #fff;\n border-radius: 5px;\n}"
  959. : css;
  960. };
  961. const editArea_html = function getHTML() {
  962. function getCompHTML({ info, active = "", id }) {
  963. let type = info.type;
  964. if (
  965. ((type = {
  966. menuTitle: "mtt",
  967. title: "tt",
  968. title2: "tt2",
  969. title3: "tt3",
  970. desc: "ds",
  971. radio: "rd",
  972. checkbox: "cb",
  973. textarea: "ta",
  974. mtt: "mtt",
  975. tt: "tt",
  976. tt2: "tt2",
  977. tt3: "tt3",
  978. ds: "ds",
  979. rd: "rd",
  980. cb: "cb",
  981. ta: "ta",
  982. }[type]),
  983. (id = 0 === id ? "0" : id || ""),
  984. 0 === info.value && (info.value = "0"),
  985. !type)
  986. )
  987. return console.log("不存在的组件类型"), !1;
  988. let title = "",
  989. desc = "",
  990. ctrlTt = "";
  991. switch (
  992. (["tt", "tt2", "tt3", "ds", "mtt"].includes(type) ||
  993. ((title = info.title
  994. ? `<div class="${cBase}comp-tt ${cBase}${type}-tt" title="${
  995. info.tt || ""
  996. }">${info.title}</div>`
  997. : ""),
  998. (desc = info.desc
  999. ? `<div class="${cBase}comp-desc ${cBase}${type}-desc">${info.desc}</div>`
  1000. : "")),
  1001. type)
  1002. ) {
  1003. case "mtt":
  1004. return (
  1005. (info.value = info.value || ""),
  1006. info.value
  1007. ? `<div class="${cBase}menu-item ${active || ""}" title="${
  1008. info.tt || ""
  1009. }">${info.value}</div>`
  1010. : ""
  1011. );
  1012. case "tt":
  1013. case "tt2":
  1014. case "tt3":
  1015. return (
  1016. (info.value = info.value || ""),
  1017. info.value
  1018. ? `<div class="${cBase}${type} ${cBase}comp" title="${
  1019. info.tt || ""
  1020. }">${info.value}</div>`
  1021. : ""
  1022. );
  1023. case "ds":
  1024. return (
  1025. (info.value = info.value || ""),
  1026. info.value
  1027. ? `<div class="${cBase}desc ${cBase}comp" title="${
  1028. info.descTt || ""
  1029. }">${info.value}</div>`
  1030. : ""
  1031. );
  1032. case "rd":
  1033. const name = info.name || info.id + new Date().getTime();
  1034. (ctrlTt = info.ctrlTt || ""),
  1035. ctrlTt && (ctrlTt = `title="${ctrlTt}"`);
  1036. let radio = `<div class="${cBase}rd ${cBase}rd-arr" ${ctrlTt}>`;
  1037. if (void 0 === info.value && info.radioList[0]) {
  1038. const obj = info.radioList[0];
  1039. info.value = void 0 === obj.value ? obj.text : obj.value;
  1040. }
  1041. return (
  1042. info.radioList.forEach((item, i) => {
  1043. void 0 === item.value && (info.radioList[i].value = item.text),
  1044. void 0 === item.text && (info.radioList[i].text = item.value);
  1045. const value = item.value;
  1046. let tt = item.tt || "";
  1047. tt && (tt = `title="${tt}"`);
  1048. let selected = "";
  1049. info.value + "" == item.value + "" && (selected = "checked"),
  1050. (radio += `<label ${tt}><input ${selected} type="radio" name="${name}" data-val="${value}" data-cpid="${id}"><span>${item.text}</span></label>`);
  1051. }),
  1052. (radio += "</div>"),
  1053. `<div class="${cBase}comp ${cBase}ctrl ${cBase}rd-box" data-type="${type}" data-cpid="${id}">${title}${desc}${radio}</div>`
  1054. );
  1055. case "cb":
  1056. const name2 = info.name || new Date().getTime();
  1057. if (
  1058. ((ctrlTt = info.ctrlTt || ""),
  1059. ctrlTt && (ctrlTt = `title="${ctrlTt}"`),
  1060. void 0 === info.value && info.radioList[0])
  1061. ) {
  1062. const obj = info.radioList[0];
  1063. info.value = void 0 === obj.value ? obj.text : obj.value;
  1064. }
  1065. let checkbox = `<div class="${cBase}cb ${cBase}rd-arr" ${ctrlTt}>`;
  1066. return (
  1067. info.radioList.forEach((item, i) => {
  1068. void 0 === item.value && (info.radioList[i].value = item.text),
  1069. void 0 === item.text && (info.radioList[i].text = item.value);
  1070. const value = item.value;
  1071. let tt = item.tt || "";
  1072. tt && (tt = `title="${tt}"`);
  1073. let selected = "";
  1074. info.value.includes(value) && (selected = "checked"),
  1075. (checkbox += `<label ${tt}><input ${selected} type="checkbox" name="${name2}" data-val="${value}" data-cpid="${id}"><span>${item.text}</span></label>`);
  1076. }),
  1077. (checkbox += "</div>"),
  1078. `<div class="${cBase}comp ${cBase}ctrl ${cBase}cb-box" data-type="${type}" data-cpid="${id}">${title}${desc}${checkbox}</div>`
  1079. );
  1080. case "ta":
  1081. const taH = `height:${info.height || "30px"};`,
  1082. style = `style="${
  1083. info.width ? "width:" + info.width + ";" : ""
  1084. }${taH}${
  1085. info.fontSize ? "font-size:" + info.fontSize + ";" : ""
  1086. }${
  1087. info.fontFamily ? "font-family:" + info.fontFamily + ";" : ""
  1088. }"`,
  1089. textarea = `<textarea class="${cBase}ta" ${style} data-cpid="${id}" placeholder="${
  1090. info.ph || ""
  1091. }" title="${info.ctrlTt || "拖动右下角可调节宽高"}"></textarea>`;
  1092. return `<div class="${cBase}comp ${cBase}ctrl ${cBase}ta-box" data-type="${type}" data-cpid="${id}">${title}${desc}${textarea}</div>`;
  1093. }
  1094. }
  1095. const param = cfg.param,
  1096. page = param.page,
  1097. cBase = param.classBase,
  1098. isMenu = 1 !== page.length;
  1099. let menu = `<div class="${cBase}menu">`,
  1100. pageHTML = `<div class="${cBase}page-box ll-scroll-style-1 ll-scroll-style-1-size-2">`;
  1101. page.forEach((curPage, index) => {
  1102. let pgid = curPage.id || index;
  1103. (pgid += ""), (cfg.allData[pgid] = {}), (cfg.baseData[pgid] = {});
  1104. let pageFlag = "";
  1105. if (
  1106. (cfg.hasSelectedPage ||
  1107. ((void 0 === param.showPage || pgid === param.showPage + "") &&
  1108. ((pageFlag = "curPage"), (cfg.hasSelectedPage = !0))),
  1109. (pageHTML += `<div class="${cBase}page ${pageFlag}" data-pgid="${pgid}">`),
  1110. curPage.components)
  1111. ) {
  1112. let compIndex = 0;
  1113. if (isMenu || param.isShowMenu) {
  1114. let curMenu = curPage.components.find(
  1115. (item) => "menuTitle" === item.type
  1116. );
  1117. curMenu || (curMenu = { type: "menuTitle", value: pgid }),
  1118. (menu += getCompHTML({
  1119. info: curMenu,
  1120. active: pageFlag ? "active" : "",
  1121. }));
  1122. }
  1123. curPage.components.forEach((item) => {
  1124. const cpid = item.id || compIndex;
  1125. "menuTitle" !== item.type &&
  1126. (pageHTML += getCompHTML({ info: item, id: cpid })),
  1127. ["title", "title2", "title3", "desc", "menuTitle"].includes(
  1128. item.type
  1129. ) ||
  1130. ((item.base = void 0 === item.base ? item.value : item.base),
  1131. (cfg.allData[pgid][cpid] = item.value),
  1132. (cfg.baseData[pgid][cpid] = item.base),
  1133. compIndex++);
  1134. });
  1135. }
  1136. pageHTML += "</div>";
  1137. }),
  1138. (pageHTML += "</div>"),
  1139. isMenu || param.isShowMenu ? (menu += "</div>") : (menu = "");
  1140. const resetBtn = param.isResetBtn
  1141. ? `<button class="${cBase}reset-btn" title="${
  1142. param.resetTt || "重置所有设置为默认值"
  1143. }">重置</button>`
  1144. : "",
  1145. btnBox = `<div class="${cBase}btn-box">\n${resetBtn}\n<button class="${cBase}cancel-btn">取 消</button>\n<button class="${cBase}confirm-btn">确 认</button>\n</div>`;
  1146. return `<div class="${cBase}box ll-scroll-style-1 ll-scroll-style-1-size-3" data-version="${cfg.version}">\n${menu}\n${pageHTML}\n${btnBox}\n</div>`;
  1147. },
  1148. baseParam = baseCfg.param,
  1149. controls = cfg.controls,
  1150. doms = cfg.doms;
  1151. function createEditEle({
  1152. id = baseParam.id,
  1153. box = baseParam.box,
  1154. classBase = baseParam.classBase,
  1155. w = baseParam.w,
  1156. h = baseParam.h,
  1157. contentH = baseParam.contentH,
  1158. bg = baseParam.bg,
  1159. color = baseParam.color,
  1160. fontSize = baseParam.fontSize,
  1161. fontFamily = baseParam.fontFamily,
  1162. zIndex = baseParam.zIndex,
  1163. resetTt = baseParam.resetTt,
  1164. isShowMenu = baseParam.isShowMenu,
  1165. isScrollStyle = baseParam.isScrollStyle,
  1166. isResetBtn = baseParam.isResetBtn,
  1167. isOnlyResetCurPage = baseParam.isOnlyResetCurPage,
  1168. showPage = baseParam.showPage,
  1169. isIntervalRun = baseParam.isIntervalRun,
  1170. interval = baseParam.interval,
  1171. page = [],
  1172. callback = baseParam.callback,
  1173. } = {}) {
  1174. (cfg.state = baseCfg.state),
  1175. (cfg.isEditing = baseCfg.isEditing),
  1176. (cfg.hasSelectedPage = baseCfg.hasSelectedPage),
  1177. (cfg.param = { ...baseParam });
  1178. const param = cfg.param;
  1179. (box = box || document.body),
  1180. (param.id = id),
  1181. (param.box = box),
  1182. (param.classBase = classBase),
  1183. (param.w = w),
  1184. (param.h = h),
  1185. (param.contentH = contentH),
  1186. (param.bg = bg),
  1187. (param.color = color),
  1188. (param.fontSize = fontSize),
  1189. (param.fontFamily = fontFamily),
  1190. (param.zIndex = zIndex),
  1191. (param.resetTt = resetTt),
  1192. (param.isShowMenu = isShowMenu),
  1193. (param.isScrollStyle = isScrollStyle),
  1194. (param.isResetBtn = isResetBtn),
  1195. (param.isOnlyResetCurPage = isOnlyResetCurPage),
  1196. (param.showPage = showPage),
  1197. (param.isIntervalRun = isIntervalRun),
  1198. (param.interval = interval),
  1199. (param.page = page),
  1200. (param.callback = callback),
  1201. (cfg.interval = interval),
  1202. (cfg.callback = callback);
  1203. const html = editArea_html();
  1204. return (
  1205. box.querySelector(`#${param.classBase}${param.id}-css`) ||
  1206. (function addCss(cssText, box = document.body, id = "") {
  1207. const style = document.createElement("style");
  1208. return (
  1209. id && (style.id = id),
  1210. box.appendChild(style),
  1211. (style.innerHTML = cssText),
  1212. style
  1213. );
  1214. })(css(), box, param.classBase + param.id + "-css"),
  1215. (doms.wrap = (function createEle({
  1216. className = "",
  1217. id = "",
  1218. title = "",
  1219. css,
  1220. box = document.body,
  1221. type = "div",
  1222. } = {}) {
  1223. const ele = document.createElement(type);
  1224. return (
  1225. id && (ele.id = id),
  1226. className && (ele.className = className),
  1227. title && (ele.title = title),
  1228. css && (ele.style.cssText = css),
  1229. box.appendChild(ele),
  1230. ele
  1231. );
  1232. })({ className: id, id })),
  1233. (doms.wrap.innerHTML = html),
  1234. (function getDoms() {
  1235. const param = cfg.param,
  1236. cBase = param.classBase;
  1237. (doms.box = doms.wrap.querySelector(`.${cBase}box`)),
  1238. (doms.cancel = doms.box.querySelector(`.${cBase}cancel-btn`)),
  1239. (doms.confirm = doms.box.querySelector(`.${cBase}confirm-btn`));
  1240. const isMenu = 1 !== param.page.length;
  1241. (isMenu || param.isShowMenu) &&
  1242. ((doms.menu = doms.box.querySelector(`.${cBase}menu`)),
  1243. (doms.menus = [].slice.call(
  1244. doms.menu.querySelectorAll(`.${cBase}menu-item`)
  1245. )));
  1246. const pages = [].slice.call(doms.box.querySelectorAll(`.${cBase}page`));
  1247. (doms.page = []),
  1248. param.isResetBtn &&
  1249. (doms.reset = doms.box.querySelector(`.${cBase}reset-btn`));
  1250. pages.forEach((curPage, index) => {
  1251. cfg.hasSelectedPage ||
  1252. (curPage.classList.add("curPage"),
  1253. (isMenu || param.isShowMenu) &&
  1254. doms.menus[0].classList.add("active"),
  1255. (cfg.hasSelectedPage = !0));
  1256. const page = {},
  1257. pgid = curPage.dataset.pgid;
  1258. (page.pgid = curPage.pgid = pgid),
  1259. (page.controls = [].slice.call(
  1260. curPage.querySelectorAll(`.${cBase}ctrl`)
  1261. )),
  1262. (page.ele = curPage),
  1263. doms.page.push(page),
  1264. (isMenu || param.isShowMenu) &&
  1265. (doms.menus[index].settingsPage = curPage);
  1266. const ctrls = {};
  1267. (controls[pgid] = ctrls),
  1268. page.controls.forEach((item, i) => {
  1269. const cpid = item.dataset.cpid,
  1270. cType = item.dataset.type;
  1271. let dom;
  1272. (item.cpid = cpid),
  1273. "rd" === cType || "cb" === cType
  1274. ? ((dom = [].slice.call(item.querySelectorAll("input"))),
  1275. (dom.compType = cType))
  1276. : "ta" === cType &&
  1277. ((dom = item.querySelector("textarea")),
  1278. (dom.compType = cType),
  1279. (dom.value = cfg.allData[pgid][cpid])),
  1280. (ctrls[cpid] = dom);
  1281. });
  1282. });
  1283. })(),
  1284. cfg.timer && clearInterval(cfg.timer),
  1285. (function bindEvents() {
  1286. const param = cfg.param;
  1287. function menuHandle(e) {
  1288. const dom = e.target,
  1289. cBase = param.classBase;
  1290. if (dom.classList.contains(`${cBase}menu-item`)) {
  1291. const old = doms.menu.querySelector(".active");
  1292. old.classList.remove("active"),
  1293. old.settingsPage.classList.remove("curPage"),
  1294. dom.classList.add("active"),
  1295. dom.settingsPage.classList.add("curPage");
  1296. }
  1297. }
  1298. function cancelEdit(e) {
  1299. const cBase = param.classBase;
  1300. if (
  1301. (e.stopPropagation(),
  1302. e.target.className !== `${cBase}wrap` &&
  1303. e.target.className !== `${cBase}cancel-btn`)
  1304. )
  1305. return;
  1306. const callback = cfg.callback;
  1307. !1 !== runCallback(callback.cancelBefore) &&
  1308. (showEditArea(!1),
  1309. setCompValue(cfg.oldData),
  1310. param.isIntervalRun &&
  1311. (setCompValue(cfg.oldData), (cfg.allData = cfg.oldData)),
  1312. runCallback(callback.cancelled));
  1313. }
  1314. function confirmEdit() {
  1315. const callback = cfg.callback,
  1316. data = getAllData();
  1317. (cfg.allData = data),
  1318. !1 !== runCallback(callback.confirmBefore, data) &&
  1319. (showEditArea(!1),
  1320. (cfg.state = "finished"),
  1321. runCallback(callback.finished, data),
  1322. (cfg.state = ""));
  1323. }
  1324. function resetEdit() {
  1325. const callback = cfg.callback,
  1326. data = getAllData();
  1327. !1 !== runCallback(callback.resetBefore, data) &&
  1328. (!(function resetEditData(isOnlyPage = !1) {
  1329. const param = cfg.param;
  1330. if (param.isResetBtn)
  1331. if (isOnlyPage) {
  1332. const data = getAllData(),
  1333. curMenu = doms.menu.querySelector(".active");
  1334. (data[curMenu.innerText] = cfg.baseData[curMenu.innerText]),
  1335. setCompValue(data);
  1336. } else setCompValue(cfg.baseData);
  1337. })(param.isOnlyResetCurPage),
  1338. runCallback(callback.reset, data));
  1339. }
  1340. doms.menu && doms.menu.addEventListener("click", menuHandle),
  1341. doms.wrap.addEventListener("click", cancelEdit),
  1342. doms.cancel.addEventListener("click", cancelEdit),
  1343. doms.confirm.addEventListener("click", confirmEdit),
  1344. doms.reset && doms.reset.addEventListener("click", resetEdit);
  1345. })(),
  1346. (cfg.state = "created"),
  1347. cfg
  1348. );
  1349. }
  1350. function getAllData() {
  1351. function getCompItem(pgid, cpid) {
  1352. if (!controls[pgid]) return;
  1353. const ctrl = controls[pgid][cpid];
  1354. if (ctrl) {
  1355. if (!Array.isArray(ctrl)) return ctrl.value;
  1356. if ("rd" === ctrl.compType) {
  1357. const result = ctrl.find((item) => item.checked).dataset.val;
  1358. return "false" !== result && ("true" === result || result);
  1359. }
  1360. if ("cb" === ctrl.compType) {
  1361. return ctrl
  1362. .filter((item) => item.checked)
  1363. .map((item) => {
  1364. const value = item.dataset.val;
  1365. return "false" !== value && ("true" === value || value);
  1366. });
  1367. }
  1368. }
  1369. }
  1370. const data = {};
  1371. if (0 === arguments.length) {
  1372. for (const key in controls) {
  1373. const page = controls[key];
  1374. data[key] = {};
  1375. for (const key2 in page) data[key][key2] = getCompItem(key, key2);
  1376. }
  1377. return data;
  1378. }
  1379. if (1 === arguments.length) {
  1380. const ctrls = arguments[0];
  1381. for (const pgid in ctrls) {
  1382. data[pgid] = {};
  1383. controls[pgid].forEach((cpid) => {
  1384. data[pgid][cpid] = getCompItem(pgid, cpid);
  1385. });
  1386. }
  1387. return cfg.allData;
  1388. }
  1389. return getCompItem(arguments[0], arguments[1]);
  1390. }
  1391. function setCompValue() {
  1392. function setCompItem(pgid, cpid, value) {
  1393. if (!controls[pgid]) return;
  1394. const ctrl = controls[pgid][cpid];
  1395. if (ctrl)
  1396. if (Array.isArray(ctrl)) {
  1397. if ("rd" === ctrl.compType) {
  1398. const selected = ctrl.find((item) => item.checked);
  1399. selected && (selected.checked = !1);
  1400. const select = ctrl.find((item) => item.dataset.val === value + "");
  1401. select && (select.checked = !0);
  1402. } else if ("cb" === ctrl.compType) {
  1403. if (
  1404. (ctrl
  1405. .filter((item) => item.checked)
  1406. .forEach((item) => {
  1407. item.checked = !1;
  1408. }),
  1409. Array.isArray(value))
  1410. )
  1411. value.forEach((val) => {
  1412. const select = ctrl.find(
  1413. (item) => item.dataset.val === val + ""
  1414. );
  1415. select && (select.checked = !0);
  1416. });
  1417. else {
  1418. const select = ctrl.find(
  1419. (item) => item.dataset.val === value + ""
  1420. );
  1421. select && (select.checked = !0);
  1422. }
  1423. }
  1424. } else ctrl.value = value;
  1425. }
  1426. if (1 === arguments.length) {
  1427. const data = arguments[0];
  1428. for (const key in data) {
  1429. const pageData = data[key];
  1430. for (const key2 in pageData) {
  1431. setCompItem(key, key2, pageData[key2]);
  1432. }
  1433. }
  1434. } else {
  1435. setCompItem(arguments[0], arguments[1], arguments[2]);
  1436. }
  1437. }
  1438. function showEditArea(isShow = !0, callback = null) {
  1439. if (
  1440. (cfg.param.isIntervalRun &&
  1441. (cfg.timer && clearInterval(cfg.timer),
  1442. (cfg.timer = setInterval(() => {
  1443. const data = getAllData(),
  1444. oldType = cfg.state;
  1445. (cfg.state = "interval"),
  1446. runCallback(cfg.callback.interval, data),
  1447. (cfg.state = oldType),
  1448. (cfg.lastData = data);
  1449. }, cfg.interval))),
  1450. (cfg.state = "created"),
  1451. isShow)
  1452. ) {
  1453. if (((cfg.oldData = getAllData()), "function" == typeof callback)) {
  1454. if (!1 === callback(cfg.oldData, cfg.oldData, cfg.baseData)) return;
  1455. }
  1456. cfg.state = "show";
  1457. }
  1458. (cfg.isEditing = isShow),
  1459. (doms.wrap.style.display = isShow ? "block" : "none"),
  1460. isShow &&
  1461. !doms.box.style.top &&
  1462. (doms.box.style.top =
  1463. window.innerHeight / 2 - doms.box.clientHeight / 2 + "px"),
  1464. callback && (cfg.callback = callback);
  1465. }
  1466. function runCallback(callback, data) {
  1467. let result;
  1468. if (callback) {
  1469. data || (data = getAllData());
  1470. const func = callback;
  1471. Array.isArray(func)
  1472. ? func.curFn
  1473. ? ((result = func[curFn](data, cfg.oldData, cfg.baseData)),
  1474. (func.curFn = null))
  1475. : func.forEach((fn) => {
  1476. result = fn(data, cfg.oldData, cfg.baseData);
  1477. })
  1478. : "function" == typeof callback &&
  1479. (result = func(data, cfg.oldData, cfg.baseData));
  1480. }
  1481. return result;
  1482. }
  1483. function toPageObj({ settings, param = {}, otherPageName = "无分类" } = {}) {
  1484. param = { ...param };
  1485. const pageArr = [],
  1486. menuList = [];
  1487. let isOtherType = !1;
  1488. for (let key in settings) {
  1489. const item = settings[key];
  1490. item.type
  1491. ? menuList.includes(item.type) || menuList.push(item.type)
  1492. : isOtherType || (isOtherType = !0);
  1493. }
  1494. return (
  1495. isOtherType && menuList.push(otherPageName),
  1496. menuList.forEach((menuTt) => {
  1497. const components = [],
  1498. page = { id: menuTt, components },
  1499. arr = [];
  1500. for (let key in settings) {
  1501. const item = settings[key];
  1502. menuTt === otherPageName
  1503. ? item.type || arr.push(item)
  1504. : item.type === menuTt && arr.push(item);
  1505. }
  1506. arr.forEach((item) => {
  1507. let desc = item.desc || item.txt || "";
  1508. desc && (desc = desc.replaceAll("\n", "<br>").trim());
  1509. let comp,
  1510. base = item.base;
  1511. if (
  1512. (Array.isArray(base) && (base = base.join(", ")), item.groupTitle1)
  1513. ) {
  1514. const comp = {
  1515. id: item.key + "-gTt1",
  1516. type: "title",
  1517. value: item.groupTitle1,
  1518. };
  1519. components.push(comp);
  1520. }
  1521. if (item.groupTitle2) {
  1522. const comp = {
  1523. id: item.key + "-gTt2",
  1524. type: "title2",
  1525. value: item.groupTitle2,
  1526. };
  1527. components.push(comp);
  1528. }
  1529. if (item.groupTitle3) {
  1530. const comp = {
  1531. id: item.key + "-gTt3",
  1532. type: "title3",
  1533. value: item.groupTitle3,
  1534. };
  1535. components.push(comp);
  1536. }
  1537. if (item.groupDesc) {
  1538. const comp = {
  1539. id: item.key + "-gDesc",
  1540. type: "desc",
  1541. value: item.groupDesc,
  1542. };
  1543. components.push(comp);
  1544. }
  1545. if (
  1546. (["menuTitle", "title", "desc", "title2", "title3"].includes(
  1547. item.compType
  1548. )
  1549. ? ((comp = { ...item }),
  1550. (comp.type = comp.compType),
  1551. (comp.desc = desc))
  1552. : (comp = {
  1553. id: item.key,
  1554. type: item.compType,
  1555. tt: item.tt || "",
  1556. title: item.title || "",
  1557. desc,
  1558. descTt: item.descTt || "",
  1559. name: item.key,
  1560. value: item.value,
  1561. base: item.base,
  1562. }),
  1563. "textarea" === comp.type)
  1564. )
  1565. (comp.ph = base),
  1566. (comp.width = item.compW),
  1567. (comp.height = item.compH),
  1568. (comp.ctrlTt = "默认: " + base);
  1569. else if ("radio" === comp.type || "checkbox" === comp.type) {
  1570. let str = "默认: ";
  1571. if ("checkbox" === comp.type) {
  1572. let arr = item.base;
  1573. Array.isArray(arr) || (arr = arr.split(/,|,/)),
  1574. arr.forEach((val, i) => {
  1575. 0 !== i && (str += ", "), (val = val.trim());
  1576. let valTxt = item.valueText[val];
  1577. void 0 === valTxt && (valTxt = val), (str += valTxt);
  1578. });
  1579. } else {
  1580. let val = item.valueText[item.base];
  1581. void 0 === val && (val = item.base), (str += val);
  1582. }
  1583. comp.ctrlTt = str;
  1584. }
  1585. if (item.valueText) {
  1586. comp.radioList = [];
  1587. for (let key in item.valueText) {
  1588. const rd = { text: item.valueText[key], value: key };
  1589. comp.radioList.push(rd);
  1590. }
  1591. }
  1592. components.push(comp);
  1593. }),
  1594. pageArr.push(page);
  1595. }),
  1596. (param.page = pageArr),
  1597. param
  1598. );
  1599. }
  1600. const intervalLoopFunc = function ({
  1601. fn,
  1602. breakFn,
  1603. num = 10,
  1604. interval = 100,
  1605. isStartRun = !0,
  1606. successFn,
  1607. finishedFn,
  1608. } = {}) {
  1609. if (fn)
  1610. if (isStartRun && breakFn && breakFn())
  1611. fn(), successFn && successFn(), finishedFn && finishedFn();
  1612. else {
  1613. let i = isStartRun ? 1 : 0;
  1614. const timer = setInterval(() => {
  1615. if (breakFn && breakFn())
  1616. return (
  1617. fn(),
  1618. successFn && successFn(),
  1619. finishedFn && finishedFn(),
  1620. void clearInterval(timer)
  1621. );
  1622. i++, i >= num && (finishedFn && finishedFn(), clearInterval(timer));
  1623. }, interval);
  1624. }
  1625. };
  1626. function getRandom(min, max) {
  1627. return Math.floor(Math.random() * (max - min + 1) + min);
  1628. }
  1629. const icons = {
  1630. base: {
  1631. color: "#666",
  1632. width: "100%",
  1633. height: "80%",
  1634. marginTop: "10%",
  1635. html: "",
  1636. },
  1637. lishi: {
  1638. color: "#8a8a8a",
  1639. width: "100%",
  1640. height: "80%",
  1641. marginTop: "10%",
  1642. html: '<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1700314086069" style="svgStyleFlag" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4255" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M512.5 98.29c-227.84 0-412.54 184.7-412.54 412.54s184.7 412.54 412.54 412.54 412.54-184.7 412.54-412.54S740.34 98.29 512.5 98.29z m249.28 661.82c-32.4 32.4-70.1 57.82-112.08 75.58-43.42 18.37-89.59 27.68-137.21 27.68-47.62 0-93.78-9.31-137.2-27.68-41.97-17.75-79.68-43.18-112.08-75.58-32.4-32.4-57.82-70.1-75.58-112.08-18.37-43.42-27.68-89.59-27.68-137.21 0-47.62 9.31-93.78 27.68-137.21 17.75-41.97 43.18-79.68 75.58-112.08s70.1-57.82 112.08-75.58c43.42-18.37 89.59-27.68 137.21-27.68 47.62 0 93.78 9.31 137.21 27.68 41.97 17.75 79.68 43.18 112.08 75.58s57.82 70.1 75.58 112.08c18.37 43.42 27.68 89.59 27.68 137.21 0 47.62-9.31 93.78-27.68 137.21-17.77 41.97-43.19 79.68-75.59 112.08z" p-id="4256"></path><path d="M738.68 674.81L542 497.48V248.27c0-16.57-13.43-30-30-30s-30 13.43-30 30v262.55c0 8.5 3.6 16.59 9.91 22.28L698.5 719.37a29.906 29.906 0 0 0 20.08 7.72c8.2 0 16.37-3.34 22.29-9.91 11.1-12.3 10.12-31.27-2.19-42.37z" p-id="4257"></path></svg>',
  1643. },
  1644. shoucang: {
  1645. color: "#fe9850",
  1646. width: "100%",
  1647. height: "80%",
  1648. marginTop: "10%",
  1649. html: '<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1700314090785" style="svgStyleFlag" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4405" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M949.888 457.258667c26.069333-29.824 13.866667-67.52-24.789333-76.309334L681.728 325.546667l-127.786667-214.677334c-20.266667-34.069333-59.925333-34.090667-80.213333 0l-127.786667 214.677334-243.370666 55.381333c-38.442667 8.746667-50.858667 46.506667-24.789334 76.309333l164.394667 188.053334-22.613333 248.917333c-3.584 39.466667 28.458667 62.805333 64.896 47.146667l237.781333-102.037334a21.333333 21.333333 0 0 0-16.810667-39.210666L267.626667 902.186667c-6.698667 2.88-6.229333 3.221333-5.568-4.096l24.277333-267.093334-176.426667-201.813333c-4.757333-5.461333-4.906667-5.034667 2.133334-6.634667l261.205333-59.434666 137.152-230.4c3.733333-6.293333 3.136-6.293333 6.869333 0l137.173334 230.4 261.205333 59.434666c7.125333 1.621333 6.954667 1.088 2.133333 6.613334l-176.426666 201.813333 24.256 267.093333a21.333333 21.333333 0 1 0 42.496-3.84l-22.613334-248.917333 164.394667-188.053333z" p-id="4406"></path></svg>',
  1650. },
  1651. };
  1652. const classList = info.homeClassList,
  1653. delClassList = info.homeDelClassList;
  1654. let vDom,
  1655. nav,
  1656. banner,
  1657. carousel,
  1658. otherAdCssDom,
  1659. base_videoNumRule,
  1660. base_videoNumRule2,
  1661. isClearAd,
  1662. isTrueEnd,
  1663. isAutoLayout,
  1664. isLoadOne,
  1665. isCarousel,
  1666. videoNumRule,
  1667. delClassArr;
  1668. const apiUrl = info.apiUrl,
  1669. imgDetails = info.imgDetails,
  1670. queryNum = 0,
  1671. marginTop1 = info.marginTop1,
  1672. marginTop2 = info.marginTop2,
  1673. zoom = info.zoom;
  1674. let cssDom,
  1675. cssText,
  1676. oldCssText,
  1677. w,
  1678. isChange = !1,
  1679. rowVideoNum = 3,
  1680. videoNum = 0,
  1681. newVideoNum = 0,
  1682. firstAdIndex = 0,
  1683. pageZoom = 1,
  1684. loadNum = 0,
  1685. fresh_idx = getRandom(0, 3e3),
  1686. curDelNum = 0,
  1687. scriptRefreshFlag = 0,
  1688. refreshFlag = 0,
  1689. isScriptRefresh = !1,
  1690. hasDelUpBtn = !1,
  1691. isCanMarkOldVideo = !0,
  1692. isNeedMarkOldVideo = !1;
  1693. window.location.pathname;
  1694. function main(isLoads = !0) {
  1695. !(function initValue() {
  1696. (isChange = !1),
  1697. (rowVideoNum = 3),
  1698. (videoNum = 0),
  1699. (newVideoNum = 0),
  1700. (firstAdIndex = 0),
  1701. (pageZoom = 1);
  1702. })(),
  1703. delOtherAd(),
  1704. (isLoads && (loadNum++, loadNum > 3)) ||
  1705. (updateData(),
  1706. (function home_getDoms() {
  1707. if (vDom && nav && banner && carousel)
  1708. return void (isCarousel || showCarousel(!1));
  1709. "string" == typeof classList.vDom
  1710. ? (vDom = document.querySelector("." + classList.vDom))
  1711. : classList.vDom.forEach((item) => {
  1712. !vDom && (vDom = document.querySelector("." + item));
  1713. });
  1714. if (!vDom) {
  1715. const dom = document.querySelector("." + classList.video);
  1716. if ((dom && (vDom = dom.parentElement), !vDom)) return;
  1717. }
  1718. (carousel = vDom.querySelector("." + classList.carousel)),
  1719. (nav = document.querySelector("." + classList.nav)),
  1720. (banner = document.querySelector("." + classList.banner)),
  1721. (videoNumRule = (function home_getValue(key, defa = "") {
  1722. let value = GM_getValue(key);
  1723. return null == value ? defa : value;
  1724. })(
  1725. "setting_videoNumRule",
  1726. carousel && isCarousel ? base_videoNumRule2 : base_videoNumRule
  1727. )),
  1728. "string" == typeof videoNumRule &&
  1729. (videoNumRule = getVideoNumRule(videoNumRule));
  1730. isCarousel || showCarousel(!1);
  1731. })(),
  1732. vDom || !isLoads
  1733. ? ((loadNum = 0),
  1734. (w = utils.getW(isAutoLayout)),
  1735. zoomPage(),
  1736. setStyle(),
  1737. addDelUpBtnCss(),
  1738. bindDelUpBtnEvent(),
  1739. intervalLoopFunc({
  1740. breakFn: hasPreloadVideo,
  1741. fn: function adFunc() {
  1742. (videoNum = getVideoNum()),
  1743. delAd(getAd(queryNum, delClassArr)),
  1744. loadBlankVideo(() => {
  1745. markOldVideo(), createDelUpBtn();
  1746. });
  1747. },
  1748. successFn: () => {
  1749. intervalLoopFunc({ breakFn: hasSpecialVideo, fn: delAdFn });
  1750. },
  1751. interval: 50,
  1752. num: 15,
  1753. }),
  1754. utils.resetErrInfo(),
  1755. (function home_bindEvents() {
  1756. let adArr,
  1757. timer,
  1758. timer2,
  1759. timer3,
  1760. rollBtn = info.btnDoms.rollBtn,
  1761. btnSvg = info.btnDoms.btnSvg,
  1762. rollBtn2 = info.btnDoms.rollBtn2;
  1763. function bindEventBreakFn() {
  1764. if (
  1765. (rollBtn ||
  1766. (rollBtn = document.querySelector(
  1767. "button." + classList.btn
  1768. )),
  1769. btnSvg || (btnSvg = rollBtn && rollBtn.querySelector("svg")),
  1770. rollBtn2 ||
  1771. (rollBtn2 = document.querySelector("." + classList.btn2)),
  1772. (info.btnDoms.rollBtn = rollBtn),
  1773. (info.btnDoms.btnSvg = btnSvg),
  1774. (info.btnDoms.rollBtn2 = rollBtn2),
  1775. rollBtn)
  1776. )
  1777. return !0;
  1778. }
  1779. function bindBtnEvents() {
  1780. let curRefreshFlag;
  1781. const breakFn = () =>
  1782. !vDom.children[1].getAttribute("oldvideo"),
  1783. fn = () => {
  1784. getVideoNum(),
  1785. (adArr = getAd(
  1786. 3 * rowVideoNum + (carousel ? 2 : 0) + 3,
  1787. delClassArr,
  1788. getFirstAdIndex()
  1789. )),
  1790. delAd(adArr);
  1791. },
  1792. refreshAfterFn = () => {
  1793. refreshFlag === curRefreshFlag &&
  1794. (markOldVideo(), createDelUpBtn());
  1795. },
  1796. finishedFn = () => {
  1797. (curRefreshFlag = refreshFlag),
  1798. refreshVideo(refreshAfterFn);
  1799. },
  1800. getAddNum = () => {
  1801. if (!settings.isTestNetSpeed || 0 === info.netSpeed.value)
  1802. return 0;
  1803. let addNum = Math.ceil(
  1804. (info.baseNetSpeed - info.netSpeed.value) *
  1805. info.refreshLoopFnInfo.addNumMultiple
  1806. );
  1807. return (
  1808. (!addNum || addNum < 0) && (addNum = 0),
  1809. addNum > info.refreshLoopFnInfo.maxAddNum &&
  1810. (addNum = info.refreshLoopFnInfo.maxAddNum),
  1811. addNum
  1812. );
  1813. };
  1814. if (((btnSvg = null), btnSvg && !info.events.rollSvg))
  1815. (info.events.rollSvg = !0),
  1816. btnSvg.addEventListener("transitionrun", () => {
  1817. markOldVideo();
  1818. }),
  1819. btnSvg.addEventListener("transitionend", () => {
  1820. refreshFlag++,
  1821. console.log("刷新视频"),
  1822. markOldVideo(),
  1823. info.isScriptRefresh
  1824. ? refreshVideo(refreshAfterFn)
  1825. : setTimeout(() => {
  1826. intervalLoopFunc({
  1827. fn,
  1828. breakFn,
  1829. interval: info.refreshLoopFnInfo.interval,
  1830. num:
  1831. info.refreshLoopFnInfo.svgNum + getAddNum(),
  1832. finishedFn,
  1833. });
  1834. }, +settings.homeDelAdTime.value);
  1835. });
  1836. else if (!info.events.roll) {
  1837. info.events.roll = !0;
  1838. const throttleRollClickHandle = (function throttle(
  1839. fn,
  1840. interval
  1841. ) {
  1842. let lastTime = 0;
  1843. return function () {
  1844. let nowTime = new Date().getTime();
  1845. const args = arguments;
  1846. interval - (nowTime - lastTime) <= 0 &&
  1847. (fn.apply(this, args), (lastTime = nowTime));
  1848. };
  1849. })(() => {
  1850. refreshFlag++,
  1851. markOldVideo(),
  1852. console.log("刷新视频"),
  1853. info.isScriptRefresh
  1854. ? refreshVideo(refreshAfterFn)
  1855. : setTimeout(() => {
  1856. intervalLoopFunc({
  1857. breakFn,
  1858. fn,
  1859. finishedFn,
  1860. interval: info.refreshLoopFnInfo.interval,
  1861. num: info.refreshLoopFnInfo.rollNum + getAddNum(),
  1862. });
  1863. }, 100 + settings.homeDelAdTime.value);
  1864. }, info.clickMinInterval);
  1865. rollBtn.addEventListener("click", throttleRollClickHandle);
  1866. }
  1867. if (rollBtn2 && !info.events.roll2) {
  1868. info.events.roll2 = !0;
  1869. const breakFn2 = () => {
  1870. const dom = vDom.children[1],
  1871. isA = dom.querySelector("a");
  1872. return !dom.getAttribute("oldvideo") && isA;
  1873. },
  1874. btnFn2 = () => {
  1875. (videoNum = getVideoNum()),
  1876. (adArr = getAd(queryNum, delClassArr, 1, !!isTrueEnd)),
  1877. delAd(adArr, !0),
  1878. loadBlankVideo(refreshAfterFn);
  1879. },
  1880. finishedFn2 = () => {};
  1881. rollBtn2.addEventListener("click", () => {
  1882. refreshFlag++,
  1883. markOldVideo(),
  1884. console.log("刷新全部视频"),
  1885. isScriptRefresh
  1886. ? refreshVideo(refreshAfterFn)
  1887. : setTimeout(() => {
  1888. intervalLoopFunc({
  1889. breakFn: breakFn2,
  1890. fn: btnFn2,
  1891. finishedFn: finishedFn2,
  1892. interval: info.refreshLoopFnInfo.interval,
  1893. num:
  1894. info.refreshLoopFnInfo.rollNum2 + getAddNum(),
  1895. });
  1896. }, 200 + settings.homeDelAdTime.value);
  1897. });
  1898. }
  1899. }
  1900. function bindBtnEventFn() {
  1901. intervalLoopFunc({
  1902. breakFn: bindEventBreakFn,
  1903. fn: bindBtnEvents,
  1904. successFn: () => {
  1905. console.log("已获取刷新按钮");
  1906. },
  1907. interval: 300,
  1908. });
  1909. }
  1910. bindBtnEventFn(),
  1911. info.events.resize ||
  1912. ((info.events.resize = !0),
  1913. window.addEventListener("resize", () => {
  1914. timer && clearTimeout(timer),
  1915. (timer = setTimeout(() => {
  1916. const newW = utils.getW(isAutoLayout);
  1917. newW > w && delAdFn(),
  1918. (w = newW),
  1919. zoomPage(),
  1920. setStyle();
  1921. }, 400));
  1922. }));
  1923. info.events.wheel ||
  1924. ((info.events.wheel = !0),
  1925. window.addEventListener("wheel", () => {
  1926. rollBtn2 || bindBtnEventFn(),
  1927. timer2 && clearTimeout(timer2),
  1928. timer3 && clearTimeout(timer3),
  1929. (timer2 = setTimeout(() => {
  1930. delAdFn(timer3);
  1931. }, 600)),
  1932. (timer3 = setTimeout(() => {
  1933. delAdFn();
  1934. }, 1500));
  1935. }));
  1936. })(),
  1937. setTimeout(() => {
  1938. settings.isTestNetSpeed && testNetworkSpeed(5),
  1939. setInterval(() => {
  1940. settings.isTestNetSpeed && testNetworkSpeed(5);
  1941. }, 6e4 * info.testNetInterval);
  1942. }, 4e3),
  1943. (document.testNetworkSpeed = testNetworkSpeed))
  1944. : setTimeout(() => {
  1945. main();
  1946. }, 500));
  1947. }
  1948. function zoomPage() {
  1949. if (document.getBoxObjectFor) return;
  1950. const rootDom = document.documentElement;
  1951. if (!settings.isReorderVideo.value)
  1952. return (pageZoom = 1), void (rootDom.style.zoom = 1);
  1953. let rate = rootDom.scrollWidth / getMainW();
  1954. function getMainW() {
  1955. let navW = nav ? nav.scrollWidth : 0;
  1956. return navW > (banner ? banner.scrollWidth : 0)
  1957. ? navW
  1958. : rootDom.clientWidth;
  1959. }
  1960. !document.body.style.overflow &&
  1961. (document.body.style.overflow = "hidden auto"),
  1962. rate > 1
  1963. ? ((pageZoom *= 1 / rate), (rootDom.style.zoom = pageZoom))
  1964. : ((pageZoom = 1),
  1965. (rootDom.style.zoom = 1),
  1966. (rate = rootDom.scrollWidth / getMainW()),
  1967. rate > 1 &&
  1968. ((pageZoom *= 1 / rate), (rootDom.style.zoom = pageZoom)));
  1969. }
  1970. function getAd(queryNum, delClassArr, startIndex = 1, isAll = !1, vList) {
  1971. curDelNum = 0;
  1972. const arr = [];
  1973. delClassArr.forEach(() => {
  1974. arr.push([]);
  1975. }),
  1976. vList || (vList = vDom.children);
  1977. const vLen = vList.length;
  1978. let len = newVideoNum < vLen ? newVideoNum : vLen;
  1979. (len = isAll || len > vLen ? vLen : len),
  1980. (queryNum = queryNum || len),
  1981. (queryNum += startIndex) > len && (queryNum = len);
  1982. for (let i = startIndex; i < queryNum; i++) {
  1983. const vItem = vList[i];
  1984. if (vItem) {
  1985. if (!isAll && !vItem.querySelector("a")) break;
  1986. for (let j = 0; j < delClassArr.length; j++)
  1987. if (isChecked(vItem, delClassArr[j])) {
  1988. (vItem.isNeedDelete = !0), arr[j].push(vItem);
  1989. break;
  1990. }
  1991. }
  1992. }
  1993. return arr;
  1994. }
  1995. function delAd(adArr, isDel = !1, isDelJudge = !0) {
  1996. function delItem(item) {
  1997. curDelNum++;
  1998. const h3 = item.querySelector("h3") || item.querySelector(".title");
  1999. isClearAd || isDel
  2000. ? (console.log("删除视频:", h3 && h3.innerText, item),
  2001. vDom.appendChild(item),
  2002. (item.style.display = "none"),
  2003. isRemove &&
  2004. setTimeout(() => {
  2005. item.remove();
  2006. }, 1e3),
  2007. newVideoNum--,
  2008. videoNum--)
  2009. : (console.log("后移视频:", h3 && h3.innerText, item),
  2010. isTrueEnd
  2011. ? (newVideoNum--,
  2012. videoNum--,
  2013. (item.style.display = "block"),
  2014. vDom.appendChild(item))
  2015. : ((item.style.display = "block"),
  2016. vDom.insertBefore(item, vDom.children[newVideoNum])));
  2017. }
  2018. function isDeletable() {
  2019. if (!isNeedDelJudege) return !0;
  2020. let len = info.loadVideoNum + 1;
  2021. const vList = vDom.children;
  2022. for (let i = firstAdIndex + 1; i < len; i++) {
  2023. const item = vList[i];
  2024. if (!item) return !0;
  2025. if (item.getAttribute("oldvideo")) return !1;
  2026. }
  2027. return (isNeedDelJudege = !1), !0;
  2028. }
  2029. let isNeedDelJudege = isDelJudge;
  2030. curDelNum = 0;
  2031. const isRemove = info.isRemoveDelDom;
  2032. for (let i = adArr.length - 1; i >= 0; i--) {
  2033. adArr[i].forEach((item) => {
  2034. isNeedDelJudege
  2035. ? ((isCanMarkOldVideo = !1),
  2036. intervalLoopFunc({
  2037. fn: () => {
  2038. delItem(item);
  2039. },
  2040. breakFn: isDeletable,
  2041. finishedFn: () => {
  2042. (isCanMarkOldVideo = !0), isNeedMarkOldVideo && markOldVideo();
  2043. },
  2044. interval: 50,
  2045. num: 10,
  2046. }))
  2047. : delItem(item);
  2048. });
  2049. }
  2050. }
  2051. function markOldVideo(len) {
  2052. if (!isCanMarkOldVideo) return void (isNeedMarkOldVideo = !0);
  2053. (isNeedMarkOldVideo = !1),
  2054. (len = len || getFillVideoNum() || info.loadVideoNum);
  2055. const vList = vDom.children;
  2056. for (let i = 1; i < len + 1; i++) {
  2057. const item = vList[i];
  2058. if (!item || !item.querySelector("a")) break;
  2059. item.setAttribute("oldvideo", "true");
  2060. }
  2061. }
  2062. function delAdFn(timer = null) {
  2063. if ((getVideoNum(), newVideoNum > videoNum)) {
  2064. return (
  2065. delAd(
  2066. getAd(
  2067. queryNum,
  2068. delClassArr,
  2069. isTrueEnd ? videoNum : getFirstAdIndex()
  2070. ),
  2071. !1,
  2072. !1
  2073. ),
  2074. (videoNum = newVideoNum),
  2075. timer && clearTimeout(timer),
  2076. createDelUpBtn(),
  2077. !0
  2078. );
  2079. }
  2080. }
  2081. function setStyle() {
  2082. if (!settings.isReorderVideo.value)
  2083. return cssDom && cssDom.remove(), (cssDom = null), void (oldCssText = "");
  2084. if (
  2085. ((isChange = !1),
  2086. videoNumRule.forEach((item) => {
  2087. !(function setVideoNum(vRule) {
  2088. const min =
  2089. (vRule = vRule.map((i) => +i.trim()))[0] /
  2090. (isAutoLayout ? zoom : 1),
  2091. max = vRule[1] / (isAutoLayout ? zoom : 1),
  2092. num = vRule[2];
  2093. (0 === min || min) && max && num
  2094. ? (w >= min &&
  2095. w < max &&
  2096. ((cssText = carousel
  2097. ? `.container {grid-template-columns: repeat(${
  2098. num + 2
  2099. },1fr) !important}\n.container>div:nth-child(n){margin-top:${marginTop2}px !important}\n.container>div:nth-child(-n+${
  2100. 3 * num + 2 + 1
  2101. }){margin-top:${marginTop1}px !important;display:block !important}\n.container>div:first-child{display:${
  2102. isCarousel ? "block" : "none"
  2103. } !important}\n.container>div:nth-child(-n+${
  2104. 2 * (num + 1) - 1
  2105. }){margin-top:0px !important}`
  2106. : `.container {grid-template-columns: repeat(${num},1fr) !important}\n.container>div:nth-child(n){margin-top:${marginTop2}px !important}\n.container>div:nth-child(${
  2107. 3 * num + 1
  2108. }){display:block !important}\n `),
  2109. (isChange = !0),
  2110. (rowVideoNum = num)),
  2111. isChange || ((cssText = ""), (rowVideoNum = carousel ? 5 : 3)))
  2112. : utils.errHandle({
  2113. errTxt: `插件设置的视频排列规则设置中 '${vRule.join(
  2114. ""
  2115. )}' 格式书写错误`,
  2116. key: info.errKeyArr[1],
  2117. });
  2118. })(item);
  2119. }),
  2120. isChange)
  2121. ) {
  2122. let isCssDom = !!cssDom;
  2123. isCssDom ||
  2124. ((cssDom = document.createElement("style")),
  2125. cssDom.setAttribute("type", "text/css")),
  2126. oldCssText !== cssText && (cssDom.innerHTML = cssText),
  2127. (oldCssText = cssText),
  2128. !isCssDom && document.head.appendChild(cssDom);
  2129. } else !isChange && cssDom && ((oldCssText = ""), (cssDom.innerHTML = ""));
  2130. }
  2131. function getVideoNum() {
  2132. const vArr = vDom.children,
  2133. len = vArr.length;
  2134. let i;
  2135. for (i = 1; i < len; i++) {
  2136. if (!vArr[i].querySelector("a")) return (newVideoNum = i), i;
  2137. }
  2138. return (newVideoNum = i), i;
  2139. }
  2140. function getFirstAdIndex() {
  2141. const vArr = vDom.children,
  2142. len = vArr.length;
  2143. firstAdIndex = 0;
  2144. for (let i = 1; i < len; i++) {
  2145. const vItem = vArr[i];
  2146. for (let j = 0; j < delClassArr.length; j++)
  2147. if (isChecked(vItem, delClassArr[j])) return (firstAdIndex = i), i;
  2148. if (!vItem.querySelector("a")) return 0;
  2149. }
  2150. return 0;
  2151. }
  2152. function hasPreloadVideo() {
  2153. const vArr = vDom.children,
  2154. lastDom = vArr[vArr.length - 1];
  2155. return !(!lastDom || lastDom.querySelector("a"));
  2156. }
  2157. function hasSpecialVideo(range = 0) {
  2158. const vClass = info.homeClassList.specialCard;
  2159. let len = vDom.children.length;
  2160. range && range < len && (len = range);
  2161. for (let i = 1; i < len; i++) {
  2162. const item = vDom.children[i];
  2163. if (item.classList.contains(vClass))
  2164. return !!item.querySelector("a") && i;
  2165. }
  2166. return !1;
  2167. }
  2168. function isChecked(vEle, delStr) {
  2169. function custom(txt, type, selector) {
  2170. const dom = vEle.querySelector(selector);
  2171. if (!dom) return;
  2172. const domTxt = dom.innerText;
  2173. txt = txt.replace(type, "");
  2174. let f = !1;
  2175. if ("作者==" !== type) {
  2176. {
  2177. const txtArr = txt.split("&&");
  2178. if (!txtArr[0]) return;
  2179. txtArr.forEach((item) => {
  2180. f = f || domTxt.includes(item);
  2181. });
  2182. }
  2183. flag = f;
  2184. } else flag = domTxt === txt;
  2185. }
  2186. let flag = !1;
  2187. if (settings.minVideoTime.value) {
  2188. const minTime = timeStringToSeconds(settings.minVideoTime.value),
  2189. timeDom = vEle.querySelector("." + info.homeClassList.videoTime);
  2190. let time = 99999;
  2191. if (
  2192. (timeDom && (time = timeStringToSeconds(timeDom.innerText)),
  2193. time <= minTime)
  2194. )
  2195. return !0;
  2196. }
  2197. const map = classList;
  2198. if (
  2199. ((delStr = delStr.trim()),
  2200. (delStr = delClassList[delStr] || delStr).includes("标题="))
  2201. )
  2202. custom(delStr, "标题=", map.标题);
  2203. else if (delStr.includes("作者=="))
  2204. custom(delStr, "作者==", "." + map.author);
  2205. else if (delStr.includes("作者=")) custom(delStr, "作者=", "." + map.作者);
  2206. else if (delStr.includes("分类=")) custom(delStr, "分类=", "." + map.分类);
  2207. else {
  2208. if (delStr.includes("json=")) {
  2209. delStr = delStr.replace("json=", "").replaceAll("$1$", ",");
  2210. try {
  2211. delStr = JSON.parse(delStr);
  2212. } catch (e) {
  2213. console.log(e),
  2214. utils.errHandle({
  2215. errTxt: `插件设置的屏蔽设置中 '${delStr}' 格式书写错误, 请在<>中按照json语法进行书写`,
  2216. e,
  2217. });
  2218. }
  2219. }
  2220. try {
  2221. Array.isArray(delStr) || (delStr = [delStr]),
  2222. (flag = delStr.some((item) => {
  2223. if ("object" == typeof item) {
  2224. const target = vEle.querySelector("." + item.value);
  2225. if (target) {
  2226. if (item.content) return target.innerText === item.content;
  2227. if (item.include)
  2228. return target.innerText.includes(item.include);
  2229. }
  2230. return !1;
  2231. }
  2232. return (
  2233. vEle.classList.contains(item) || vEle.querySelector("." + item)
  2234. );
  2235. }));
  2236. } catch (e) {
  2237. console.log(e),
  2238. utils.errHandle({
  2239. errTxt: `插件设置的屏蔽设置中 '${delStr}' 格式书写错误, 自定义格式应以 '标题=' '作者=' 开头`,
  2240. e,
  2241. });
  2242. }
  2243. }
  2244. return flag;
  2245. }
  2246. function createVideoDom(data) {
  2247. function formatNum(num) {
  2248. return num > 1e8
  2249. ? (num / 1e8).toFixed(1) + "亿"
  2250. : num > 1e4
  2251. ? (num / 1e4).toFixed(1) + "万"
  2252. : "" + num;
  2253. }
  2254. function videoDom(item, reportStr) {
  2255. if (item.business_info) return -1;
  2256. const like = Math.floor(item.stat.like / 1e4),
  2257. likeHTML =
  2258. like > 1
  2259. ? `<div class="bili-video-card__info--icon-text">${like}万点赞</div>`
  2260. : "",
  2261. upIconHTML = likeHTML
  2262. ? ""
  2263. : '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24" width="24"\n height="24" fill="currentColor" class="bili-video-card__info--owner__up">\x3c!--[--\x3e\n <path\n d="M6.15 8.24805C6.5642 8.24805 6.9 8.58383 6.9 8.99805L6.9 12.7741C6.9 13.5881 7.55988 14.248 8.3739 14.248C9.18791 14.248 9.8478 13.5881 9.8478 12.7741L9.8478 8.99805C9.8478 8.58383 10.1836 8.24805 10.5978 8.24805C11.012 8.24805 11.3478 8.58383 11.3478 8.99805L11.3478 12.7741C11.3478 14.41655 10.01635 15.748 8.3739 15.748C6.73146 15.748 5.4 14.41655 5.4 12.7741L5.4 8.99805C5.4 8.58383 5.73578 8.24805 6.15 8.24805z"\n fill="currentColor"></path>\n <path\n d="M12.6522 8.99805C12.6522 8.58383 12.98795 8.24805 13.4022 8.24805L15.725 8.24805C17.31285 8.24805 18.6 9.53522 18.6 11.123C18.6 12.71085 17.31285 13.998 15.725 13.998L14.1522 13.998L14.1522 14.998C14.1522 15.4122 13.8164 15.748 13.4022 15.748C12.98795 15.748 12.6522 15.4122 12.6522 14.998L12.6522 8.99805zM14.1522 12.498L15.725 12.498C16.4844 12.498 17.1 11.8824 17.1 11.123C17.1 10.36365 16.4844 9.74804 15.725 9.74804L14.1522 9.74804L14.1522 12.498z"\n fill="currentColor"></path>\n <path\n d="M12 4.99805C9.48178 4.99805 7.283 5.12616 5.73089 5.25202C4.65221 5.33949 3.81611 6.16352 3.72 7.23254C3.60607 8.4998 3.5 10.171 3.5 11.998C3.5 13.8251 3.60607 15.4963 3.72 16.76355C3.81611 17.83255 4.65221 18.6566 5.73089 18.7441C7.283 18.8699 9.48178 18.998 12 18.998C14.5185 18.998 16.7174 18.8699 18.2696 18.74405C19.3481 18.65655 20.184 17.8328 20.2801 16.76405C20.394 15.4973 20.5 13.82645 20.5 11.998C20.5 10.16965 20.394 8.49877 20.2801 7.23205C20.184 6.1633 19.3481 5.33952 18.2696 5.25205C16.7174 5.12618 14.5185 4.99805 12 4.99805zM5.60965 3.75693C7.19232 3.62859 9.43258 3.49805 12 3.49805C14.5677 3.49805 16.8081 3.62861 18.3908 3.75696C20.1881 3.90272 21.6118 5.29278 21.7741 7.09773C21.8909 8.3969 22 10.11405 22 11.998C22 13.88205 21.8909 15.5992 21.7741 16.8984C21.6118 18.7033 20.1881 20.09335 18.3908 20.23915C16.8081 20.3675 14.5677 20.498 12 20.498C9.43258 20.498 7.19232 20.3675 5.60965 20.2392C3.81206 20.0934 2.38831 18.70295 2.22603 16.8979C2.10918 15.5982 2 13.8808 2 11.998C2 10.1153 2.10918 8.39787 2.22603 7.09823C2.38831 5.29312 3.81206 3.90269 5.60965 3.75693z"\n fill="currentColor"></path>\x3c!--]--\x3e\n</svg>',
  2264. html = `<div data-v-7ae03d4e="" class="bili-video-card is-rcmd ${
  2265. info.homeClassList.addVideo || ""
  2266. }" data-report="tianma.${reportStr}.click"\n style="--cover-radio: 56.25%;">\n <div class="bili-video-card__wrap __scale-wrap"><a href="${
  2267. item.uri
  2268. }" target="_blank" data-spmid="333.1007"\n data-mod="tianma.${reportStr}" data-idx="click">\n <div class="bili-video-card__image __scale-player-wrap bili-video-card__image--hover">\n <div class="bili-video-card__image--wrap">\n <div class="bili-watch-later" style="display: none;"><svg class="bili-watch-later__icon">\n <use xlink:href="#widget-watch-later"></use>\n </svg><span class="bili-watch-later__tip" style="display: none;"></span></div>\n <picture class="v-img bili-video-card__cover">\n <source\n srcset="${item.pic.replace(
  2269. "http:",
  2270. ""
  2271. )}${imgDetails}.avif"\n type="image/avif">\n <source\n srcset="${item.pic.replace(
  2272. "http:",
  2273. ""
  2274. )}${imgDetails}.webp"\n type="image/webp"><img\n src="${item.pic.replace(
  2275. "http:",
  2276. ""
  2277. )}${imgDetails}"\n alt="${
  2278. item.title
  2279. }" loading="eager" onload=""\n onerror="typeof window.imgOnError === 'function' && window.imgOnError(this)">\n </picture>\n <div class="v-inline-player"></div>\n </div>\n <div class="bili-video-card__mask">\n <div class="bili-video-card__stats">\n <div class="bili-video-card__stats--left"><span class="bili-video-card__stats--item"><svg\n xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"\n width="24" height="24" fill="#ffffff" class="bili-video-card__stats--icon">\n <path\n d="M12 4.99805C9.48178 4.99805 7.283 5.12616 5.73089 5.25202C4.65221 5.33949 3.81611 6.16352 3.72 7.23254C3.60607 8.4998 3.5 10.171 3.5 11.998C3.5 13.8251 3.60607 15.4963 3.72 16.76355C3.81611 17.83255 4.65221 18.6566 5.73089 18.7441C7.283 18.8699 9.48178 18.998 12 18.998C14.5185 18.998 16.7174 18.8699 18.2696 18.74405C19.3481 18.65655 20.184 17.8328 20.2801 16.76405C20.394 15.4973 20.5 13.82645 20.5 11.998C20.5 10.16965 20.394 8.49877 20.2801 7.23205C20.184 6.1633 19.3481 5.33952 18.2696 5.25205C16.7174 5.12618 14.5185 4.99805 12 4.99805zM5.60965 3.75693C7.19232 3.62859 9.43258 3.49805 12 3.49805C14.5677 3.49805 16.8081 3.62861 18.3908 3.75696C20.1881 3.90272 21.6118 5.29278 21.7741 7.09773C21.8909 8.3969 22 10.11405 22 11.998C22 13.88205 21.8909 15.5992 21.7741 16.8984C21.6118 18.7033 20.1881 20.09335 18.3908 20.23915C16.8081 20.3675 14.5677 20.498 12 20.498C9.43258 20.498 7.19232 20.3675 5.60965 20.2392C3.81206 20.0934 2.38831 18.70295 2.22603 16.8979C2.10918 15.5982 2 13.8808 2 11.998C2 10.1153 2.10918 8.39787 2.22603 7.09823C2.38831 5.29312 3.81206 3.90269 5.60965 3.75693z"\n fill="currentColor"></path>\n <path\n d="M14.7138 10.96875C15.50765 11.4271 15.50765 12.573 14.71375 13.0313L11.5362 14.8659C10.74235 15.3242 9.75 14.7513 9.75001 13.8346L9.75001 10.1655C9.75001 9.24881 10.74235 8.67587 11.5362 9.13422L14.7138 10.96875z"\n fill="currentColor"></path>\n </svg><span class="bili-video-card__stats--text">${formatNum(
  2280. item.stat.view
  2281. )}</span></span><span\n class="bili-video-card__stats--item"><svg xmlns="http://www.w3.org/2000/svg"\n xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24" width="24" height="24" fill="#ffffff"\n class="bili-video-card__stats--icon">\n <path\n d="M12 4.99805C9.48178 4.99805 7.283 5.12616 5.73089 5.25202C4.65221 5.33949 3.81611 6.16352 3.72 7.23254C3.60607 8.4998 3.5 10.171 3.5 11.998C3.5 13.8251 3.60607 15.4963 3.72 16.76355C3.81611 17.83255 4.65221 18.6566 5.73089 18.7441C7.283 18.8699 9.48178 18.998 12 18.998C14.5185 18.998 16.7174 18.8699 18.2696 18.74405C19.3481 18.65655 20.184 17.8328 20.2801 16.76405C20.394 15.4973 20.5 13.82645 20.5 11.998C20.5 10.16965 20.394 8.49877 20.2801 7.23205C20.184 6.1633 19.3481 5.33952 18.2696 5.25205C16.7174 5.12618 14.5185 4.99805 12 4.99805zM5.60965 3.75693C7.19232 3.62859 9.43258 3.49805 12 3.49805C14.5677 3.49805 16.8081 3.62861 18.3908 3.75696C20.1881 3.90272 21.6118 5.29278 21.7741 7.09773C21.8909 8.3969 22 10.11405 22 11.998C22 13.88205 21.8909 15.5992 21.7741 16.8984C21.6118 18.7033 20.1881 20.09335 18.3908 20.23915C16.8081 20.3675 14.5677 20.498 12 20.498C9.43258 20.498 7.19232 20.3675 5.60965 20.2392C3.81206 20.0934 2.38831 18.70295 2.22603 16.8979C2.10918 15.5982 2 13.8808 2 11.998C2 10.1153 2.10918 8.39787 2.22603 7.09823C2.38831 5.29312 3.81206 3.90269 5.60965 3.75693z"\n fill="currentColor"></path>\n <path\n d="M15.875 10.75L9.875 10.75C9.46079 10.75 9.125 10.4142 9.125 10C9.125 9.58579 9.46079 9.25 9.875 9.25L15.875 9.25C16.2892 9.25 16.625 9.58579 16.625 10C16.625 10.4142 16.2892 10.75 15.875 10.75z"\n fill="currentColor"></path>\n <path\n d="M17.375 14.75L11.375 14.75C10.9608 14.75 10.625 14.4142 10.625 14C10.625 13.5858 10.9608 13.25 11.375 13.25L17.375 13.25C17.7892 13.25 18.125 13.5858 18.125 14C18.125 14.4142 17.7892 14.75 17.375 14.75z"\n fill="currentColor"></path>\n <path\n d="M7.875 10C7.875 10.4142 7.53921 10.75 7.125 10.75L6.625 10.75C6.21079 10.75 5.875 10.4142 5.875 10C5.875 9.58579 6.21079 9.25 6.625 9.25L7.125 9.25C7.53921 9.25 7.875 9.58579 7.875 10z"\n fill="currentColor"></path>\n <path\n d="M9.375 14C9.375 14.4142 9.03921 14.75 8.625 14.75L8.125 14.75C7.71079 14.75 7.375 14.4142 7.375 14C7.375 13.5858 7.71079 13.25 8.125 13.25L8.625 13.25C9.03921 13.25 9.375 13.5858 9.375 14z"\n fill="currentColor"></path>\n </svg><span class="bili-video-card__stats--text">${formatNum(
  2282. item.stat.danmaku
  2283. )}</span></span></div><span\n class="bili-video-card__stats__duration">${utils.formatTime(
  2284. item.duration
  2285. )}</span>\n </div>\n </div>\n </div>\n </a>\n <div class="bili-video-card__info __scale-disable">\x3c!----\x3e\n <div class="bili-video-card__info--right">\n <h3 class="bili-video-card__info--tit" title="${
  2286. item.title
  2287. }">\n <a href="${
  2288. item.uri
  2289. }?spm_id_from=333.1007.tianma.${reportStr}.click" target="_blank" data-spmid="333.1007"\n data-mod="tianma.${reportStr}" data-idx="click">${
  2290. item.title
  2291. }\n </a>\n </h3>\n <div class="bili-video-card__info--bottom">\n ${likeHTML}\n <a class="bili-video-card__info--owner" href="//space.bilibili.com/${
  2292. item.owner.mid
  2293. }" target="_blank"\n data-spmid="333.1007" data-mod="tianma.${reportStr}" data-idx="click">\n ${upIconHTML}\n <span class="bili-video-card__info--author" title="${
  2294. item.owner.name
  2295. }">${
  2296. item.owner.name
  2297. }</span>\n <span class="bili-video-card__info--date" ${(function formatDate(
  2298. t
  2299. ) {
  2300. const date = new Date(),
  2301. oldDate = new Date(1e3 * t),
  2302. dis = Math.floor(date.getTime() / 1e3) - t;
  2303. return date.getFullYear() !== oldDate.getFullYear()
  2304. ? utils.formatDate(1e3 * t, { isYear: !0, isAlign: !1 })
  2305. : dis < 60
  2306. ? "刚刚"
  2307. : dis < 3600
  2308. ? Math.floor(dis / 60 / 60) + "分钟前"
  2309. : dis < 86400
  2310. ? Math.floor(dis / 60 / 60) + "小时前"
  2311. : date.getDate() - oldDate.getDate() == 1
  2312. ? "昨天"
  2313. : utils.formatDate(1e3 * t, { isAlign: !1 });
  2314. })(
  2315. item.pubdate
  2316. )}</span>\n </a>\n </div>\n </div>\n </div>\n </div>\n</div>`;
  2317. return utils.strToDom(html);
  2318. }
  2319. const videoList = [];
  2320. let num = 10;
  2321. return (
  2322. data.forEach((item, index) => {
  2323. num++;
  2324. const dom = videoDom(item, `4-${index + 1}-${num}`);
  2325. -1 !== dom && videoList.push(dom);
  2326. }),
  2327. videoList
  2328. );
  2329. }
  2330. function getFillVideoNum() {
  2331. return isCarousel ? 3 * rowVideoNum + 2 : 3 * rowVideoNum;
  2332. }
  2333. async function requestVideos(num, isDelAd = !0) {
  2334. if (num <= 0) return null;
  2335. const params = new URLSearchParams({
  2336. web_location: 1430650,
  2337. y_num: 4,
  2338. fresh_type: 4,
  2339. feed_version: "V8",
  2340. fresh_idx_1h: 1,
  2341. fetch_row: 4,
  2342. fresh_idx,
  2343. brush: 1,
  2344. homepage_ver: 1,
  2345. ps: num,
  2346. last_y_num: 5,
  2347. screen: window.innerWidth + "-" + window.innerHeight,
  2348. wts: Math.floor(new Date().getTime() / 1e3),
  2349. });
  2350. fresh_idx += getRandom(1, 10);
  2351. const data = await utils.request(`${apiUrl}?${params}`);
  2352. if (data.data.item) {
  2353. let vList = createVideoDom(data.data.item);
  2354. if (isDelAd) {
  2355. getVideoNum();
  2356. delAd(getAd(num, delClassArr, 0, !1, vList), !1, !1), getVideoNum();
  2357. }
  2358. return (vList = vList.filter((i) => !i.isNeedDelete)), vList;
  2359. }
  2360. return null;
  2361. }
  2362. async function loadBlankVideo(callBack = null) {
  2363. if (!isLoadOne) return void (callBack && callBack());
  2364. let specialIndex;
  2365. try {
  2366. specialIndex = hasSpecialVideo();
  2367. const newNum =
  2368. settings.addVideoNum.value ||
  2369. (() => {
  2370. const dis = specialIndex ? 0 : -1;
  2371. return isCarousel
  2372. ? 3 * rowVideoNum + 2 - (newVideoNum - 1) + dis
  2373. : 3 * rowVideoNum - (newVideoNum - 1) + dis;
  2374. })(),
  2375. vList = await requestVideos(newNum);
  2376. if (((specialIndex = hasSpecialVideo()), vList)) {
  2377. const insertIndex = specialIndex || newVideoNum;
  2378. for (let i = vList.length - 1; i >= 0; i--)
  2379. vDom.insertBefore(vList[i], vDom.children[insertIndex]);
  2380. }
  2381. callBack && callBack();
  2382. } catch (e) {
  2383. console.log(e),
  2384. setTimeout(() => {
  2385. document.documentElement.scrollTo(0, 400),
  2386. setTimeout(() => {
  2387. document.documentElement.scrollTo(0, 0),
  2388. setTimeout(() => {
  2389. delAdFn(), callBack && callBack();
  2390. }, 800);
  2391. }, 20);
  2392. }, 1e3);
  2393. }
  2394. }
  2395. async function refreshVideo(callBack = null) {
  2396. if (!isLoadOne) return void (callBack && callBack());
  2397. scriptRefreshFlag++;
  2398. const curFlag = scriptRefreshFlag;
  2399. let vList,
  2400. target,
  2401. num = 0,
  2402. isDelSpecialDom = !1,
  2403. hasSpecialDom = !1,
  2404. isOldVideos = !1;
  2405. const vClass = info.homeClassList.addVideo,
  2406. specialClass = info.homeClassList.specialCard,
  2407. fillNum = getFillVideoNum(),
  2408. removeArr = [];
  2409. let specialDom;
  2410. const vNum = getVideoNum();
  2411. for (let i = 1; i < vNum; i++) {
  2412. const item = vDom.children[i];
  2413. if (!item || !item.querySelector("a")) break;
  2414. if (i <= fillNum + 2) {
  2415. if (item.classList.contains(specialClass)) {
  2416. (specialDom = item),
  2417. (hasSpecialDom = !0),
  2418. (num += fillNum - i),
  2419. settings.isRefreshLast.value && ((isDelSpecialDom = !0), num++);
  2420. break;
  2421. }
  2422. } else {
  2423. if (
  2424. (!isOldVideos && item.getAttribute("oldvideo") && (isOldVideos = !0),
  2425. !isOldVideos)
  2426. )
  2427. break;
  2428. if (item.classList.contains(specialClass)) {
  2429. (specialDom = item),
  2430. (hasSpecialDom = !0),
  2431. settings.isRefreshLast.value && (isDelSpecialDom = !0);
  2432. break;
  2433. }
  2434. }
  2435. }
  2436. if (vDom.children[1].getAttribute("oldvideo")) {
  2437. isScriptRefresh && (info.isScriptRefresh = !0),
  2438. (isScriptRefresh = !0),
  2439. (num = fillNum - 1),
  2440. isDelSpecialDom && num++,
  2441. console.log(`加载${num}个视频`);
  2442. for (let i = fillNum; i >= 1; i--) {
  2443. const item = vDom.children[i];
  2444. item &&
  2445. item.querySelector("a") &&
  2446. !item.classList.contains(specialClass) &&
  2447. removeArr.push(item);
  2448. }
  2449. target = vDom.children[1];
  2450. } else {
  2451. if (((isScriptRefresh = !1), (info.isScriptRefresh = !1), isOldVideos)) {
  2452. (num = 0),
  2453. hasSpecialDom
  2454. ? ((target = specialDom), num--, isDelSpecialDom && num++)
  2455. : (target = vDom.children[info.loadVideoNum + 1]);
  2456. for (let i = fillNum + 1; i < vNum; i++) {
  2457. const item = vDom.children[i];
  2458. if (!item || item.isNeedDelete || !item.getAttribute("oldvideo"))
  2459. break;
  2460. item.classList.contains(vClass)
  2461. ? removeArr.push(item)
  2462. : item.classList.contains(specialClass) || removeArr.push(item);
  2463. }
  2464. } else
  2465. hasSpecialDom
  2466. ? (target = specialDom)
  2467. : ((vNum <= fillNum + 1 || vNum <= fillNum + 1 + 2) &&
  2468. (num += fillNum + 1 - vNum),
  2469. (target = vDom.children[info.loadVideoNum + 1]));
  2470. const endIndex = isOldVideos ? fillNum : fillNum + 2;
  2471. for (let i = 1; i <= endIndex; i++) {
  2472. const item = vDom.children[i];
  2473. if (!item) break;
  2474. if (item.classList.contains(specialClass)) break;
  2475. (item.classList.contains(vClass) || item.getAttribute("oldvideo")) &&
  2476. (num++, removeArr.push(item));
  2477. }
  2478. }
  2479. try {
  2480. if (
  2481. ((vList = await requestVideos(num)),
  2482. vList && curFlag === scriptRefreshFlag)
  2483. ) {
  2484. if ((vList.length != num && (num = vList.length), target))
  2485. for (let i = 0; i < num; i++) vDom.insertBefore(vList[i], target);
  2486. removeArr.forEach((i) => i.remove()),
  2487. isDelSpecialDom && specialDom.remove();
  2488. }
  2489. callBack && callBack();
  2490. } catch (e) {
  2491. console.log("视频请求失败"), console.log(e), callBack && callBack();
  2492. }
  2493. }
  2494. function testNetworkSpeed(iterations) {
  2495. let totalSpeed = 0;
  2496. function runTest(interval = 0) {
  2497. return new Promise((resolve, reject) => {
  2498. let startTime, endTime;
  2499. setTimeout(() => {
  2500. let urlWithTimestamp = info.logoUrl + "?t=" + new Date().getTime();
  2501. (startTime = performance.now()),
  2502. fetch(urlWithTimestamp)
  2503. .then((response) => {
  2504. if (!response.ok) throw new Error("Network request failed");
  2505. endTime = performance.now();
  2506. let duration = (endTime - startTime) / 1e3,
  2507. speed = (
  2508. response.headers.get("content-length") /
  2509. 1024 /
  2510. duration
  2511. ).toFixed(2);
  2512. (totalSpeed += parseFloat(speed)), resolve();
  2513. })
  2514. .catch((error) => {
  2515. console.error("Error:", error), reject(error);
  2516. });
  2517. }, interval);
  2518. });
  2519. }
  2520. let promises = [],
  2521. interval = 0;
  2522. for (let i = 0; i < iterations; i++)
  2523. promises.push(runTest(interval)), (interval += 1e3);
  2524. Promise.all(promises)
  2525. .then(() => {
  2526. const speedStr = (totalSpeed / iterations).toFixed(2),
  2527. netSpeed = +speedStr,
  2528. avgSpeed = 0.6 * netSpeed + 0.4 * (info.netSpeed.value || netSpeed);
  2529. (info.netSpeed.value = avgSpeed),
  2530. console.log(
  2531. `当前网速: ${speedStr}KB/s, 平均网速: ${avgSpeed.toFixed(2)}KB/s`
  2532. );
  2533. })
  2534. .catch((error) => {
  2535. console.error("Error during testing:", error);
  2536. });
  2537. }
  2538. function getDelClassArr(value) {
  2539. const obj = (function extractBracesContent(str) {
  2540. const matches = [],
  2541. regex = /<([^>]+)>/g;
  2542. let cleanString = str;
  2543. return (
  2544. (cleanString = cleanString.replace(
  2545. regex,
  2546. (match, group) => (matches.push(group), "")
  2547. )),
  2548. { newStr: cleanString.trim(), matches }
  2549. );
  2550. })(value);
  2551. value = obj.newStr;
  2552. return (
  2553. obj.matches.forEach((item) => {
  2554. (item = "json=" + item.replaceAll(",", "$1$")),
  2555. (value = value + "," + item);
  2556. }),
  2557. (value = value
  2558. .replaceAll(";", ",")
  2559. .replaceAll(";", ",")
  2560. .replaceAll(",", ",")
  2561. .replaceAll(",\n", "\n")
  2562. .replaceAll("\n", ",\n")).split(",")
  2563. );
  2564. }
  2565. function getVideoNumRule(value) {
  2566. return (value = (value = value
  2567. .replaceAll(";", ";")
  2568. .replaceAll(";\n", ";")
  2569. .replaceAll("\n", ";\n")).split(";")).map((item) => item.split(/,|,/));
  2570. }
  2571. function updateData() {
  2572. (isClearAd = settings.isClearAd.value),
  2573. (isTrueEnd = settings.isTrueEnd.value),
  2574. (isAutoLayout = settings.isAutoLayout.value),
  2575. (isLoadOne = settings.isLoadOne.value),
  2576. (isCarousel = settings.isCarousel.value),
  2577. (videoNumRule = getVideoNumRule(settings.videoNumRule.value)),
  2578. (delClassArr = getDelClassArr(settings.delClassArr.value)),
  2579. (base_videoNumRule = getVideoNumRule(settings.videoNumRule.base)),
  2580. (base_videoNumRule2 = getVideoNumRule(settings.videoNumRule.base2));
  2581. }
  2582. function showCarousel(isShow = !0) {
  2583. carousel || (carousel = vDom.querySelector("." + classList.carousel)),
  2584. carousel && (carousel.style.display = isShow ? "block" : "none"),
  2585. isShow || (carousel = !1);
  2586. }
  2587. function createDelUpBtn() {
  2588. if (!settings.isDelUpBtn.value) return;
  2589. const vList = vDom.children,
  2590. len = vList.length,
  2591. upClass = info.homeClassList["作者"],
  2592. svg = (function getIconHTML({
  2593. name = "",
  2594. svg,
  2595. color,
  2596. width,
  2597. height,
  2598. marginTop,
  2599. css = "",
  2600. } = {}) {
  2601. let icon;
  2602. if (
  2603. (svg
  2604. ? ((icon = { ...icons.base }), (icon.html = svg))
  2605. : (icon = icons[name]),
  2606. icon)
  2607. )
  2608. return (
  2609. (css += `\nfill:${color || icon.color || icons.base.fill};\nwidth:${
  2610. width || icon.width || icons.base.width
  2611. };\nheight:${
  2612. height || icon.height || icons.base.height
  2613. };\nmargin-top:${
  2614. marginTop || icon.marginTop || icons.base.marginTop
  2615. };`),
  2616. icon.html.replace("svgStyleFlag", css)
  2617. );
  2618. })({
  2619. svg: info.iconSvg.blacklist,
  2620. color: "rgb(148, 153, 160)",
  2621. width: "12px",
  2622. height: "12px",
  2623. marginTop: "1px",
  2624. }),
  2625. createBtn = () => {
  2626. const btn = document.createElement("span");
  2627. return (
  2628. (btn.className = info.homeClassList.delUpBtn),
  2629. (btn.title = info.txt.delUpBtnTT),
  2630. (btn.innerHTML = svg),
  2631. btn
  2632. );
  2633. };
  2634. for (let i = 1; i < len; i++) {
  2635. const item = vList[i];
  2636. if (item.hasDelUpBtn) continue;
  2637. if (!item.querySelector("a")) break;
  2638. const up = item.querySelector(`.${upClass}`);
  2639. up && (up.appendChild(createBtn()), (item.hasDelUpBtn = !0));
  2640. }
  2641. }
  2642. function addDelUpBtnCss() {
  2643. if (!settings.isDelUpBtn.value) return;
  2644. if (hasDelUpBtn) return;
  2645. const style = document.createElement("style");
  2646. document.head.appendChild(style);
  2647. const selector = "." + [].slice.call(vDom.classList).join(".");
  2648. style.innerHTML = `${selector} > div:hover .${info.homeClassList.delUpBtn} {\n opacity: 1;\n}\n.${info.homeClassList.delUpBtn} {\n opacity: 0;\n display: flex;\n margin-left: 8px;\n cursor: pointer;\n transition: opacity 0.5s;\n}`;
  2649. }
  2650. function bindDelUpBtnEvent() {
  2651. if (!settings.isDelUpBtn.value) return;
  2652. if (hasDelUpBtn) return;
  2653. const btnClass = info.homeClassList.delUpBtn;
  2654. vDom.addEventListener("click", (e) => {
  2655. let target = e.target,
  2656. flag = target.classList.contains(btnClass);
  2657. if (
  2658. (flag ||
  2659. ((target = target.parentElement),
  2660. (flag = target.classList.contains(btnClass)),
  2661. flag ||
  2662. ((target = target.parentElement),
  2663. (flag = target.classList.contains(btnClass)))),
  2664. flag)
  2665. ) {
  2666. if (
  2667. !((dom) => {
  2668. const author = dom.parentElement.querySelector(
  2669. `.${info.homeClassList.author}`
  2670. );
  2671. if (!author) return !1;
  2672. const str = `\n作者==${author.innerText}`,
  2673. newDelText = settings.delClassArr.value + str;
  2674. return (
  2675. (delClassArr = getDelClassArr(newDelText)),
  2676. GM_setValue(settings.delClassArr.key, newDelText),
  2677. !0
  2678. );
  2679. })(target)
  2680. )
  2681. return;
  2682. delAd(getAd(queryNum, delClassArr), !1, !1);
  2683. }
  2684. }),
  2685. (hasDelUpBtn = !0);
  2686. }
  2687. function delOtherAd() {
  2688. let cssText,
  2689. isDel = !0,
  2690. delAdList = settings.delOtherAd.value;
  2691. 0 === delAdList.length && (isDel = !1),
  2692. (delAdList = delAdList.map((item) => info.homeSelector[item].selector)),
  2693. (cssText = isDel ? `${delAdList.join(",")}{display:none}` : ""),
  2694. otherAdCssDom ||
  2695. ((otherAdCssDom = document.createElement("style")),
  2696. (otherAdCssDom.id = info.otherAdCssDomId),
  2697. document.body.appendChild(otherAdCssDom)),
  2698. (otherAdCssDom.innerHTML = cssText);
  2699. }
  2700. function setValue({
  2701. value,
  2702. base,
  2703. key,
  2704. verification = null,
  2705. getValue = null,
  2706. setValue = null,
  2707. getVal = null,
  2708. setVal = null,
  2709. } = {}) {
  2710. getValue && (getVal = getValue), setValue && (setVal = setValue);
  2711. let f = !1;
  2712. try {
  2713. (getVal !== GM_getValue && setVal !== GM_setValue) || (f = !0);
  2714. } catch (e) {}
  2715. let newVal = value,
  2716. oldVal = getVal ? getVal(key) : localStorage.getItem(key);
  2717. return (
  2718. void 0 !== base &&
  2719. null == oldVal &&
  2720. ((oldVal = base),
  2721. "string" == typeof base || f || (base = JSON.stringify(base)),
  2722. setVal ? setVal(key, base) : localStorage.setItem(key, base)),
  2723. null !== newVal &&
  2724. ("function" != typeof verification ||
  2725. ((newVal = verification(newVal, oldVal, base)), null !== newVal)) &&
  2726. newVal !== oldVal &&
  2727. ("string" == typeof newVal || f || (newVal = JSON.stringify(newVal)),
  2728. setVal ? setVal(key, newVal) : localStorage.setItem(key, newVal),
  2729. !0)
  2730. );
  2731. }
  2732. function showSettings() {
  2733. let showPage;
  2734. "首页" === info.pageName
  2735. ? (showPage = "基础设置")
  2736. : "视频" === info.pageName && (showPage = "视频页"),
  2737. (info.settingsArea = (function createEdit({
  2738. settings,
  2739. param = {},
  2740. oldEditCfg,
  2741. updateDataFn,
  2742. isNewEdit = !0,
  2743. isSyncOtherPage = !0,
  2744. otherPageName = "无分类",
  2745. } = {}) {
  2746. let oldSettings, curSettings;
  2747. updateDataFn &&
  2748. isSyncOtherPage &&
  2749. ((oldSettings = JSON.stringify(settings)),
  2750. (settings = updateDataFn() || settings),
  2751. (curSettings = JSON.stringify(settings)));
  2752. const editInfo = { settings, param, otherPageName };
  2753. if (oldEditCfg) {
  2754. if (isNewEdit)
  2755. return (
  2756. oldEditCfg.doms.wrap.remove(), createEditEle(toPageObj(editInfo))
  2757. );
  2758. isSyncOtherPage &&
  2759. updateDataFn &&
  2760. oldSettings !== curSettings &&
  2761. (oldEditCfg.doms.wrap.remove(),
  2762. (oldEditCfg = createEditEle(toPageObj(editInfo)))),
  2763. isSyncOtherPage &&
  2764. !updateDataFn &&
  2765. (oldEditCfg.doms.wrap.remove(),
  2766. (oldEditCfg = createEditEle(toPageObj(editInfo))));
  2767. } else oldEditCfg = createEditEle(toPageObj(editInfo));
  2768. return oldEditCfg;
  2769. })({
  2770. settings,
  2771. param: {
  2772. resetTt: "重置当前页的所有设置为默认值",
  2773. isOnlyResetCurPage: !0,
  2774. showPage,
  2775. },
  2776. oldEditCfg: info.settingsArea,
  2777. updateDataFn: getData,
  2778. })),
  2779. updateData(),
  2780. videoObj.updateData();
  2781. const callback = {
  2782. resetBefore: () => confirm("是否重置当前页的所有设置为默认值?"),
  2783. confirmBefore: () => {},
  2784. finished: (data) => {
  2785. console.log(data);
  2786. if (
  2787. !(function isValueChange(type = "auto") {
  2788. const param = cfg.param,
  2789. curData = getAllData(),
  2790. curDataStr = JSON.stringify(curData);
  2791. let oldDataStr;
  2792. return (
  2793. "auto" === type &&
  2794. ("interval" === cfg.state &&
  2795. param.isIntervalRun &&
  2796. (type = "interval_current"),
  2797. "finished" === cfg.state && (type = "auto")),
  2798. (oldDataStr =
  2799. "interval_current" === type
  2800. ? JSON.stringify(cfg.lastData)
  2801. : "base_current" === type
  2802. ? JSON.stringify(cfg.baseData)
  2803. : JSON.stringify(cfg.oldData)),
  2804. "{}" !== oldDataStr && curDataStr !== oldDataStr
  2805. );
  2806. })()
  2807. )
  2808. return;
  2809. const changeObj = {};
  2810. for (const key in settings) changeObj[key] = !1;
  2811. for (const pageName in data) {
  2812. const page = data[pageName];
  2813. for (const key in page) {
  2814. const value = page[key];
  2815. let verifyFn;
  2816. const flag = key.replace(info.keyBase, ""),
  2817. item = settings[flag];
  2818. switch (key) {
  2819. case settings.homeDelAdTime.key:
  2820. verifyFn = (newVal) =>
  2821. (newVal = +newVal) >= 0
  2822. ? newVal
  2823. : settings.homeDelAdTime.base;
  2824. break;
  2825. case settings.addVideoNum.key:
  2826. verifyFn = (newVal) =>
  2827. (newVal = +newVal) >= 0 ? newVal : settings.addVideoNum.base;
  2828. break;
  2829. case settings.videoNumRule.key:
  2830. verifyFn = (newVal) => newVal.replaceAll(" ", "").toLowerCase();
  2831. break;
  2832. case settings.delClassArr.key:
  2833. verifyFn = (newVal) => newVal.replaceAll(" ", "");
  2834. break;
  2835. case settings.minVideoTime.key:
  2836. verifyFn = (newVal, oldVal) => {
  2837. if ("" === newVal) return "";
  2838. try {
  2839. timeStringToSeconds(newVal);
  2840. return newVal;
  2841. } catch (e) {
  2842. return oldVal;
  2843. }
  2844. };
  2845. break;
  2846. case settings.video_delSetting.key:
  2847. verifyFn = (newVal) => newVal.replaceAll(" ", "");
  2848. }
  2849. if (!item) return void console.log("设置的数据对应的对象获取失败");
  2850. changeObj[flag] = setValue({
  2851. value,
  2852. base: item.base,
  2853. key,
  2854. verification: verifyFn,
  2855. getValue: GM_getValue,
  2856. setValue: GM_setValue,
  2857. });
  2858. }
  2859. }
  2860. getData();
  2861. const changeArr = (function getTrueArr(obj) {
  2862. const arr = [];
  2863. for (const key in obj) obj[key] && arr.push(key);
  2864. return arr;
  2865. })(changeObj);
  2866. if ("视频" === info.pageName)
  2867. (changeArr.includes("video_delSetting") ||
  2868. changeArr.includes("video_isDelAd")) &&
  2869. (videoObj.updateData(),
  2870. videoObj.getAd(),
  2871. settings.video_isDelAd.value
  2872. ? videoObj.delAd()
  2873. : videoObj.showAd()),
  2874. changeArr.includes("video_isAutoLike") && videoObj.autoLike();
  2875. else if ("首页" === info.pageName) {
  2876. (function hasCommonItems(arr1, arr2) {
  2877. for (let i = 0; i < arr1.length; i++)
  2878. if (arr2.includes(arr1[i])) return !0;
  2879. return !1;
  2880. })(changeArr, [
  2881. "isCarousel",
  2882. "isAutoLayout",
  2883. "isClearAd",
  2884. "isTrueEnd",
  2885. "isLoadOne",
  2886. ])
  2887. ? main(!1)
  2888. : (updateData(),
  2889. changeArr.includes("isReorderVideo") && setStyle(),
  2890. changeArr.includes("videoNumRule") &&
  2891. (function rearrange(rule) {
  2892. (videoNumRule = getVideoNumRule(rule)),
  2893. zoomPage(),
  2894. setStyle();
  2895. })(settings.videoNumRule.value),
  2896. (changeArr.includes("delClassArr") ||
  2897. changeArr.includes("minVideoTime")) &&
  2898. (function updateVideo(delClass) {
  2899. (delClassArr = getDelClassArr(delClass)),
  2900. delAd(getAd(queryNum, delClassArr), !1, !1);
  2901. })(settings.delClassArr.value),
  2902. changeArr.includes("isDelUpBtn") &&
  2903. settings.isDelUpBtn.value &&
  2904. (createDelUpBtn(), addDelUpBtnCss(), bindDelUpBtnEvent()),
  2905. changeArr.includes("delOtherAd") && delOtherAd());
  2906. }
  2907. },
  2908. };
  2909. showEditArea(!0, callback);
  2910. }
  2911. let pageName = (function getBiliPageType() {
  2912. const url = window.location.href,
  2913. hostname = window.location.hostname,
  2914. pathname = window.location.pathname;
  2915. return "www.bilibili.com" !== hostname ||
  2916. ("/" !== pathname && "/index.html" !== pathname)
  2917. ? url.includes("www.bilibili.com/video") ||
  2918. url.includes("www.bilibili.com/list")
  2919. ? "视频"
  2920. : "search.bilibili.com" === hostname
  2921. ? "搜索"
  2922. : "space.bilibili.com" === hostname
  2923. ? "主页"
  2924. : url.includes("t.bilibili.com") ||
  2925. url.includes("www.bilibili.com/opus")
  2926. ? "动态"
  2927. : url.includes("www.bilibili.com/read")
  2928. ? "专栏"
  2929. : url.includes("www.bilibili.com/bangumi")
  2930. ? "番剧"
  2931. : "live.bilibili.com" === hostname
  2932. ? "直播"
  2933. : "message.bilibili.com" === hostname && "/" === pathname
  2934. ? "消息"
  2935. : "其他"
  2936. : "首页";
  2937. })(window.location);
  2938. if (
  2939. ((info.pageName = pageName),
  2940. ("首页" !== pageName && "视频" !== pageName) ||
  2941. (getData(),
  2942. GM_registerMenuCommand("设置", () => {
  2943. showSettings();
  2944. }),
  2945. GM_registerMenuCommand("脚本主页", () => {
  2946. !(function openUrl(url) {
  2947. let tempALink = document.createElement("a");
  2948. tempALink.setAttribute("target", "_blank"),
  2949. tempALink.setAttribute("id", "openWin"),
  2950. tempALink.setAttribute("href", url),
  2951. document.body.appendChild(tempALink),
  2952. document.getElementById("openWin").click(),
  2953. document.body.removeChild(tempALink),
  2954. tempALink.remove();
  2955. })(info.scriptUrl);
  2956. })),
  2957. "首页" === pageName)
  2958. )
  2959. main();
  2960. else if ("视频" === pageName) {
  2961. setTimeout(() => {
  2962. videoObj.init();
  2963. }, videoObj.info.startTime);
  2964. let url = window.location.href;
  2965. const pathInterval = videoObj.info.pathInterval;
  2966. setInterval(() => {
  2967. url !== window.location.href &&
  2968. ((url = window.location.href),
  2969. setTimeout(() => {
  2970. videoObj.init();
  2971. }, videoObj.info.startTime));
  2972. }, pathInterval);
  2973. }
  2974. })();