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

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

Fra og med 01.12.2023. Se den nyeste version.

// ==UserScript==
// @name          哔哩哔哩新版首页排版调整和去广告(bilibili)
// @namespace     http://tampermonkey.net/
// @version       1.5.0
// @author        Ling2Ling4
// @description   对新版B站首页的每行显示的视频数量进行调整, 同时删除所有广告, 并可设置屏蔽内容 (大尺寸屏幕每行将显示更多的视频)
// @license MIT
// @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAAlC+aJAAAACXBIWXMAAAsTAAALEwEAmpwYAAAbO0lEQVRogaV6ebClR3Xf75zu/r7vrm+fXctoJM2MGBZJSBaOAMeE1dhACoiNbSHLBrtcxEk5TtnBJnZsjKNyABcBl8ExcWKDMYltyhCzWCkwAu1IIMmj0TYjadY382beu9u3dfc5+ePe9+YtMiRx/3O/2326+2x9uvv0j87/5fvapx4yK1UZrAtVEkZibG7bDV8QFCAijIusfqnq+MOsNqkKFCAQMb5nUdpUIZsrtvQADV2r5fsuVIHbtXMJ+kiTO/LdpL//5jgULUT0nItKvg32aock09DV7pN54/iDQCBAARVMGF+bSrdwu4E7ujje5N/4V9dV6ToZdW12DkZAYpUcqCbKIQncrBVKiaCNnsG0KlSU1RIykAEEKpNZCETZRJw1LknWswMAsll5W2yioM1CrhNl8k26tUHHLQQFGtAGUIFX6FWvvs6ERhrqSTfVcWc1487jDgR9HubGBKujA0Dc7EHkwkU1j7UbSTfbbUsxMiGmVc7jBkkAkIdpyJCw+1qowrlJvYy7EqIDDMhOXIUibLlqjVU21WwYc5MmJ7wQiDa4VtQ1JjbTr1GZLVVxrdNqn9hBHFpOpkABLLo2PRGrmOAjxmsTrAHqNUlXNaKrI68pfGIL9pv5l4sOvjpxura2nseXJqRx3foYEyc6/tS1ShpyKK2UOayiDusk1sgU2wmMAQxiFVEhH6GU1Z5rg2/gQAFJNhpBAb8lLpVbfXFzUbOlas0CE60CaERY+7svawcjAqermnKpHVTyyW+vLJZIWCCYivXrr7/6YBZVZB3L42VxMVQRkAltUCuhJtps+Yv+tNnz1miMblxb6xfgKlHCeUja9pe+X1BMgStAQTTxS2uubLd+6o7aaT7Q9BdfcNlvv4zhw6pmdBLuSDd7/fOo7nuW53MkWltdW1qJV+dMQbmN6o0WCNmahcb9tzUEZT8kDQhPtaZgK/gcbNbNqKCtUfP/gmHaQnRxG8FEO7yqI9kqXrzYjdR+5WSzXVvGSAGoiqph5FX4wH0n0F4oSeDkk48c2bZt5/4kigRdx4CubWT/mLLe6S66Eq9OsWVn1PFORKWZDcpkrriKxIpmE1pVIpKgSFqUmqzsh6T25QziyJLdMvk/GEa+S7kYfESJiYgFk8BKq+6h67biNZlWBZjEvCwEi9wKLjcIYkoQgXgioXMUbFb0XGhbWVa0Q9IMGG2MQrrR9uPv7x1hoAoiKIGxukWsY3Oy5NfHLlqnqbWJaJQ0gWCdjIyU4tE0NAmTpKpllIG6bJDsIFaNNXiI6KAKiowIxfgspwQFTfyAhFREFSKTxUcEUjIWazu2AuxUKxbfSDo+hsCqqkqMqCgrEAAGWyQpQVRrVBVgIQpnKHEAaRSUFbAMIlsbQYjvvW7X2y5trEhsqEg2tNnM7z6w+JcPC3WWlDLSSkdxFpwk/rwvvG1b17B1zZ7K1CtbxAYDMLmN5JrTqXOZFSUWzoKOLqysaFQAKkJslWay6pH3/tMr7nis+cDxs/VMkoSiNs3LYd9yzQ6kQ7WNZ5ZHf/NcVZM9mBU/uH+6svNthCdWhnc816+5cXXLvX5/k7WuzLQFKCN+y8LCS9IKcIgBiUPWuHnXtv/x2HEjKYWqVZ189wsPvvXg1IwbPdB3v/nN3uO9aE0obUfIk4yM1JaZKMZmN+k0brju+plWhhDYuGF/8DdfviOA1TBxVIpJ9ehHXn3dO2/Y/bmnHsobRZZzdE1Uw1fvnf7Qa7ah7MP64z69+8+PL9bb3rx31wdumkHI0SifLPbe/JmHz+blv7h04TdfMY47wlAoyYoZwAxHZhRMUXCOOGj0l0ExWkNh8N6XXfOBl1/xfR25msM7tudf/OHWteZoyV2xljQaBGWpiStxXiWE4rnTx/uRSrXwFXkBGGzGnknF0u/+6E3vuuESt3QykIdjI1ZoCkhJSUdVzKHD1Fcz7XIXirbPgqAXcoOBpqWDyWDTtGqiyJY5qUKPARAo9RYhcZW1tXM+Q+0MBJ6AsKeb3Xr5Pjc4htEiQggVbHNq7769iB4YWRFFGl1HXFcKPZDEF3W0Pvvc08fP5KblyZWswQBOSfrp4NkP/NTr/uV1V2PlRG1i4pvwrVGWGunDL7copyyYxJOrWmlo4gKqM10WTtmmFWzVNGUSlhGWW65EGmbqLK3bdryuIhOIIrMIhBzUEacwBerYapmmEByqRuOZ0P1qsfBgfcnRzhTincSO1KqmZIz2T900l330bS8v4uhDX7znW6dbz8Fce+mskgARoWwMznzoltff+qI5evoZCaGy7KJDqJD4ICkau+5clr8+iZQyy/Y7y+eP2Aoz2+880frawqzQEqetB872F0MXNv3bC+WhxcbIVjY4CxBUU8tw3IgBjMQojLGuhWy5WdLS0uhI7Xe46S/3unfJ7pOuta0RquVnwJmSVfUKo4PzNy2EP7715v3lIswovOqFP/u/jp18PO/k87M7L4Ovk+L8B255y89cu2CO3K+lZfUucUIRVNlQNetBv9X91gpu/cxD3sWamjWlDTvTxehrJ4d3njwWiRNva65hk4Tlb07p1z5zSmyDJbWAVqKfO10wzYziydKi4xOThM+dPIswzDvbQ19vu//kNTde66iRt7J2M33q6ScfP3Ya1hgB2VqDP7S9/afvfu2+uIwLOVrui4eXnlqqG0nvkSf8XMi6o7Mffscr33n9XHzqiBmkkBqkbInhoTFQd+TYVEVMaLkz66IBR9iGhmEtwib1NC1kEu98ow9UJqhx3WBTKGomwhXfBxbQSlZKaROExEiAG2alrbL5aBKjdazrqam5Pft2WUfLS+dOHT0BsYaNulCF1vVzo8+865X7khSnn6UE7/368u88sIisyUmVhGCH527/iR9517V74rOP0LCwFTMqolg003/2xQt3LQ6QdW0QsZWQRxUABisJa6sLtogVhhdANUwCsOMFlrSiAu45VB0EtQCglmi3D4NMkvkw3StGg4X2qO2SKiGpfVpzakYr+aMPP4xQkga2GdiB2z70rp/q/9WtN10iRXEuNEz7V7753O0PLGVWvTsf/VRd93//tlffcmgPPXXEDUcKG8mpeFKBXNzcxBpRPWjs2w/ta1NomfRwb+m/PdMbmJkXtbO3vfSg1UFmsu+cq/7subxi+9LUvvWa/eSbcXy8IeI0H/7YlY23vnjnTu08caH+jYfuP5LPEI3vTiRQZkPUcpSJicEpmOOg/8JtyZ+/6xWXaO7Prpjm9AfufO72e0+hNePdMhUNQv6HP3Hzrddsi08dNr0BgoDHKQEGWMb3D1KoUrQQesWO+d+4cR/KZxHck9nez595YNAfvv7K7b92aDfqPtg8dVn3r8/dVVXFD12+75evmUE5QkoWRFoM33HZzIdvPtAtnkC8cO1ll+ydu/6tX3jkTIw+aZC3pDHYkkAkqSCFrdFbvHGu+6mf/oF9xuTnapNNf/Dr337ffUNqJWTL6OcRBn/09htuO5jIsdNmGBFtZFbAxKhkQELjK6wCQCKxsETqUS326HSL2qZydQI02Jk+8hMSJDQiBWoggmLUAj4EX5F4Bjhl/bGrtnV7IymaJaZxfnRjo/HaffNBenBso00ExAGmBFVgxmBww7T57z/1Q1dyrosnmig/fOfR33ggl/kWW2c9uLjwX976ktsOJcXxIYYkwQZOS2MqUopKCigxpwIGMSFEN4KrrDFAcypO27ht1rez2iGaJjPSBmfTCZIWNygwhA0cTNua7cZss7ZusVluaQb13lQBTqIyqllmRKBW70Igyco0Gk5cUdX9A3PtP77tNfv5Ak4PqEXvu/f4++8/zs3EeYiAivIjP/rinz7Uqc6cy+p64Mh4yergXFUZJ0gNrcBN3z2cP1GfQ9ZIwsgbhspdxYW/PjE/U4RRZ/mRggZFDaU7F8OhRXFVLzP+/tHp5SBQ+40Li//7eFrFCzZY6ux8zcA+/Z6XXv6f918l55+qGlnDdAfcfOWXjjw0rIkyo4NgQ1abmBlfN6/trHz6llceSJo4dwpN/PrdK7/5wCkkjpOaKzJFeP+tV/ybfVeXJ0ZZkG9Gf+fZ4idneDvOa8ySkpH0kc1+wc99eshffPD+/oUB03RSN0Oa1pqjWoZRpA3kYpNONEZ1CB2AAuBQ2SzpCHONClWJtkcIpt61ux06jyyd6tjkmpk9jdh9Eq1fvetbX1r0aKSNumZIcDaaZvTxxZ3R//zx66928MtimH7tobPvv/dU00VJcwnTUg4++rbrfmH/3vzsmWa/ODzi316efyrOPqeDg+3u7DAKh9BIvlLM/8nIPDuzfenYKe0XPk3halBQU6CVI/EsnMBK6zxnZ0kjUaaJgQU7gEvNSrWV5ZBoW8nSrr2HTskOgirOXTGtsymfuhDP9hJqG891M9dgs7qVoVe+eCb5i1uu3ed87A3rRvf37jr23ntPIWsbc86Fdin08TcdeveBufpUSKqVh8vqV6v5nuxObRwgvrFY/FedXtLGl8vuJ4ZTdeJTbt399cfP986ivWSjsG9GRQw5JCHf1cw3jWn6ONBQ8TjbMIWYd+wgOCliE2UbMYEp7KdffuPb77n3bDllsHDm1Ohoa4CslSazXJ/zaYzOirHon7uxaz91yyv2OpMvj0yj89H7Dr/vvhVKLLiIsiPG/A9/+CU/c03iT15I6uaRwvxa2T3Fl83SuQq+5S+5U8qkGhxIpj67Ys902tvrYbOOSh42UKQQFhDCCzq47UVXzWlPmu7hpeoPHu8tNTs3u/zn9l3CklTT9T2nyz/5e1t6832z8aev2Z7gXHQt+/Id/IWbD/3EnY8+ITVp1ohJUddRh5AmSL3LpCivmTF/9OOvvTLJ6/Ojpm3+3jdO/Pv7zsdpl4Y0hDpK/2NvetHPHEzK02VW4YEQbh9ML9v2bDyt2jRSsZ43Jv2yueTzZZwiuyvviXb6zvp0CaPzrpzxSVRduXFh1y/u3Y0Vj66c3N6648j5R1eqV744/fFrBHkFLa+f2/5nzxzTSn7gst3v2tVEmAOaXAz6N2T8Fzddu1N51PA1OYrt0Mglyy0HqeRgq/O5t7/xEKmeLBJrbv/O2X/7wDNlN1oXSCSt6w+/8cDP7+3WJypXJvfU2z9+Wk+ajosNhCTYEWtDNNZUIRjjk4pQg4OpYCoOCaTpbVBbAlbVVDJALGRgY+FqW4KGJqYokwL9KKUrfUsDGNETwgi5oio4qx1G9c5tzalOglgbwARrg7CpQzX9kqnBX/zkgataeTE8inb2/u8s/8r9D8emaYaZ1oXLS9Xbf2Tfv57bg2eRFPT4cPhfF88+kbmQeEXpxJhgdJJHVQ01+zpqDApRgY5v4KyqtkhMYVuSpFkbScppmpoprgUIJm3BLjTCNkPbWm4qDUAZ29yCnUfLoM3W22ioFj+yVQGJkYywOmpVRWN/a/CXb3jl3tDoLdMUbfvwg0d/657FNG1XqZZV5unEh19z9Xu279blHnG4z8X3D9NzzdmQwGiVwBMspEHkNyRkoaoqKiSrKU6imLGy/bveuY8fa06VwyoJjw3PPQtGq/2lM6cvmzJS54nQt/tnT4oia33lzNkDXdTIo5L1FDNoEkzLG8QQnYK19vnl0/nH33ho9xRksTeVzn7w8PIvPXgSUx1kyyhSxpn/9Krdv7Dd5oNh04a/r3H7+fZQFlKLNJYJaqPijQlMBpN0Ka1msAkUo7DRcUKFQCQlMn60KN7z5W9ZRWktXKB0p42NBxeX3nXiLp+CSlLjOFmw1LlruX/31+81kppobId2gke+OxOS0/AXQIpQHUzwhRsPXNGeR0/R1Y888o1/d2+fk20UezR0XeBDL3zRO3ftwMg31T0X8B8rdzbZ1+VllWjEEGXBgsikAMNuyn9phLHWOgcixAiiVsm11co0QmsmqAMrTNEqKanLQepiZzdgSVizslEE68teK9VsZzBp0NS+b/HxllR8vHGijrApaZnk5aGrL/1cP4YHjmexOlq3/uAR+HaW0nIUE3Xh6jk9myz/+pM5qLY+vWPFHm8wJyfP1NPQIUcCrBhmlSSKZ1Jal9lXKBExg6gsclij4NI0xHqIR8hJlKgSY7yxsS3e1shpapCK2kFSFF0YD0SiYemoF7lB2LMXxIhpQgtqvU+XTXBu0Cy1AglIYBNkTTK1Ic9VIyQmG/RzVyI0gAjnQU1IAq6TGGsya5kzjA/LFx9BVu3AEZpAFbYGgyTNQlKk5bVp+h/2H2jLQFPzyGDwK48fKzH9im7yy3v35CbnRvrw+f7vPPZ0jey1rYWfe8FOI0WRBmv5MhYTs14UCDFiEtnEroN6EAFMHIGegmyZuQhvfZ0mSNKkskLBsCpV3rESavKsNHnFWU3KriUfiXkshamcFRZSDxZV0qiuRFh54e7L3rhvjvIcKe2PMx889szx5fyfXD31hkvTGMUgHprf85FjT9dFfsO25pt3pBgxnNqAFYhFuYRWBNpp3jQqZRJELGoPJR3n+khL2y9JYLPgUnhKYxw1ZqQXhUoYgRKMEcHFpOKkxFX9x3FiU5LSU4RLYVMIOS8kTcTQyZ0WIYQaRmKVInahqdYe+ZBKgikpQ6uaWq7EeUbdjzSiYOzPH5xpliaY+a+eOfvISj+6mcgB9fnXNdoHrrrSBmEVkAoQElsj/+rTRx8jA2pWqW/5pTftmpufSwLZbmlrG2Td89Oq22xIwStRyJyR8htHjz6Yl7E5HU0esgsoerAdbhkepRCYJhg9BGg2i9mEa4NKkkTrpIcYNJtHs2HybWBnP3bFlSgdWq1H9ss7Pn/Ho4kA4cWzU5+68ZoZl1IENIIValDNohX/bmbHP//6fRcaXOvw1ivmPnbwoLE9bzgZJMiw/mUaz18Y1TSS+luXXPKjX7rnqYBAZPImTOurp+v3fuuYJlUq2TOD3mLtbCP7/LN1IsOKorU4de7oaNCAST/39KBItFYT02DrOGKw7Z15wcJlV041Hs1r5PUPzO2cbXSxsoKogIA1EhTLNq/3L+yaTu0FL4AenL/U5gYh54wxCrVQsrY9YS0rzpvf/eISfHnJnn1z082nVjQhYxFy6w5HOfzod5Ax6ibYuLbaUB6u3eGHnoYtwMaUQVotmPjtUr797SdRZmjldkRd3xkZN/ul00sPLvapMaUpf/7sqVsWd10xv91UI9ao4GgUPPCY/9MnTp+ph2inKBp/+8ThH/z+Xfvj7shFOU0c2W95hSflSfp9/H4CURY2O+/4++Wj58+hPRWjYzVEpaOEkp2V5UTr2sQsVw5VmEKccmnRVTGhO7Ck8BGuGXkqNUmNKXrJgVdFDjNVfWRQnU1bcAZas1R7gIVu24SKNApRYIiNyJOjvWrQTJ3QVKVLaXmFzS5xVCRVMGy9QdzywMHr394AaMwq9tkzS8X5zIG5UyhRMmx4W1TwsW5FwIMalrtZSCSUEka1gYnsXUzdlENa1FU0Z4mjIiFc+gLrOdgOWYEJGgOJWk48UgSPGIAIBgzAjGhhLGywsWzUsbCz5GsvBZoADIJBjJsFoLVX8clhCJwgWLKJGs9atStfkw1UvTxt/9x1L0lp1CV7uO9/67Eji9R4fWv6PVfuFR62jbun3/+tI0/mcG/pzr/7qulAOkwTizQja8BWteIQjdqIppeUURFnSgpSZSVIEgTKQTkgDZwMnBiFOsdsFOBgbKBgZROYRhWkMAqoBlJmTkMN8TFqRSRkh46RqBR6dXfm7fOz6HtI44V77AefrOHDS+d2vGE2hRbQ+rKphQ8+dTj35fWze143l2FgYI1Fv+VZwStQFZCAQAEQoR7UTEALFBWhhACMYFFbqAFTtAUYECBQFETFGFqwUQKoQAQghUFU5Ml4i0ygCYkRWMQKSMAm6tCYfrS0ZDQ4RV4nvgddGeqQba0lN0WhWscati6d1EbtJ/bPjzLvZLuClQgQRgAF8AxgoZYUhECQQEZIWcQKvKHKULM2QkRKViGktZUk6tqL3PgjGFpTv6bmxGjwVSyMrDl18kSx3GdCbaBEUA6RTNYCOoZmGlWweQIOKxmhM90edGF8JSYXA2PK0AB2pFnJtiC97WeBFjRO5ryISFo70qxjaeLQMmmRjTgIWgffoFWPV6AysR1M7RGbn01Gn6jbNmsNesv33n13FAETLMOHncbdtGtHJ4ZM6ZlK7jl1euB4eyt52Y75qboikz02GN27fF6NuZTMzQvbUo2lgYWU8LzO9OsfaBVEYNoACtLne/6/KMMWAZggViSYWEGMiT5qIAmtdpusQR2hZCIx2zN1+VdPHiEV0qicctoE2cXS/9WRx5NYAC5kLU0yEJ0I1WeffkwZkdneFaldRrI81p6KbGKIVm2yxtsq4uN5xFDeANtQaGBkgXslGl5t9E97qbRWds88fTSUFYwBgBCEWY2F6yiP8WYxClEkQqLNbk1NACAHsVCISaTbgbEAUXPvC1yZRFOvgj3WePlHvMLT2ku1coyQVKxa1Aw7ajR9YCg0hAn3q8AR6NjcRErRVCxko1VwMKpGoEJCVgyUoolilKMByBYyW3ImKMd3DfCaC/3/CLAuBE28zmkIlKnAUUWALzOlESBr3ANQYgCkxKo8icNGAWFRKI3xT0oEUsgYCUIBRgSAZZMz1RePYGPN6fND8/4fBKDJ6g/slQlCgUolMSHG8fl8XWFhhSppNBrHefdolSBGgIioNhKUo1E1CigiGyGfRAVsjJyU0SdrIJy1LX8rnG2rSM8H5tnYqrDQCIXCghCfD0Fz8QC4eneYXB7GAUMRVKERYZVAJQKQAMP2zQvbhGCwGagUN/EPFQmrTK7GpY2XdQJtHWerzGsgHZqkKTbiwAAAzERE61F1kVd9ZIIpAimskn3LdDt3pht4PcMKxE2cKKJsOeesk0ABAiXg74amHLMicezZzBPor2yRgFYBw2vA4bB6KheRMeIm1bQRxDqO20sSJ5hYbBIxzSrecyvkaP1EGyXRyPK8DeuLvehl6006Jv4H50rDBtQNAIIQeds1tultwbqxDXZ1P1hXT7ROyA1yXFyya4bWdU2byTfsjJuJ6fmkhr2okgl1JAWr3QkqWpRdRBxNEFPRjsMqrePgewO7eYN/r7G7Nq+ucr9Bqu9irrUiNOmtqwcasZp4tddNz1V63oROtMQKUhUSKNjw6uhr2lqTck0XvElhdBFWvUYUVzFiWxn+h4tuOmXBk5rcxMRcaEkz1J2yUlPr1E57T2pvGs5E5DZSNOQqAOi1qe0jb3bJLbctHYNd1ri9uIAlTrry6n7yXfx7/S16tayB/ib1hrjX9Z2q3LUsoWEEBtmOT54//X8AgWl7HAkW5nwAAAAASUVORK5CYII=
// @match         *://www.bilibili.com/*
// @exclude       *://www.bilibili.com/all*
// @exclude       *://www.bilibili.com/anime*
// @exclude       *://www.bilibili.com/pgc*
// @exclude       *://t.bilibili.com/*
// @exclude       *://www.bilibili.com/opus*
// @exclude       *://www.bilibili.com/live*
// @exclude       *://www.bilibili.com/article*
// @exclude       *://www.bilibili.com/upuser*
// @exclude       *://www.bilibili.com/match*
// @exclude       *://www.bilibili.com/platform*
// @exclude       *://www.bilibili.com/bangumi*
// @exclude       *://www.bilibili.com/cheese*
// @grant         GM_setValue
// @grant         GM_getValue
// @grant         GM_registerMenuCommand
// @compatible    chrome
// @compatible    edge
// @compatible    firefox
// ==/UserScript==

(() => {
  "use strict";
  const info = {
      pageName: "",
      keyBase: "setting_",
      zoom: window.devicePixelRatio,
      homeClassList: {
        标题: "h3 a",
        作者: "bili-video-card__info--owner",
        分类: "floor-title",
        carousel: "recommended-swipe",
        vDom: ["container", "no-banner-container", "is-version8"],
        video: "feed-card",
        nav: "bili-header__bar",
        banner: "bili-header__banner",
        btn: "roll-btn",
        btn2: "flexible-roll-btn",
      },
      homeDelClassList: {
        广告: "bili-video-card__info--ad",
        推广: "bili-video-card__info--creative-ad",
        特殊: "floor-single-card",
        直播: "living",
        番剧: "分类=番剧",
        综艺: "分类=综艺",
        课堂: "分类=课堂",
        漫画: "分类=漫画",
        国创: "分类=国创",
        电影: "分类=电影",
        纪录片: "分类=纪录片",
        电视剧: "分类=电视剧",
      },
      apiUrl:
        "https://api.bilibili.com/x/web-interface/wbi/index/top/feed/rcmd",
      imgDetails: "@672w_378h_1c_!web-home-common-cover",
      marginTop1: 24,
      marginTop2: 24,
      errKeyArr: ["", 2, 3],
      errKeyInfo: {
        disNum: "setting_err_disNum",
        errNum: "setting_err_num",
        errTime: "setting_err_time",
        isTip: "setting_err_isTip",
      },
      disErrTipNum: 3,
      errTipNum: 15,
      errTipInterval: 2,
      errNumReset: 5,
      videoInfo: {
        startTime: 500,
        pathInterval: 500,
        interval: 1e3,
        timeout: 5,
        delDom: [
          { name: "几乎全部广告", pre: ".", str: "ad-report", type: "ad" },
          { name: "横幅广告", pre: "#", str: "bannerAd" },
          { name: "视频广告", pre: ".", str: "video-card-ad-small" },
          { name: "活动广告", pre: "#", str: "slide_ad", type: "ad" },
          { name: "活动推广", pre: "#", str: "activity_vote", type: "other" },
          { name: "横幅通告", pre: ".", str: "reply-notice", type: "other" },
          {
            name: "直播推广",
            pre: ".",
            str: "pop-live-small-mode",
            type: "other",
          },
        ],
      },
    },
    keyBase = info.keyBase,
    settings = {
      isCarousel: {
        value: !0,
        base: !0,
        key: keyBase + "isCarousel",
        txt: "是否显示轮播图 (修改后需要调整排列规则才能达到预期效果,轮播图占两个视频的宽度,所以每行显示视频数加减2即可)",
        type: "基础设置",
        valType: "boolean",
        compType: "radio",
        valueText: { true: "显示轮播图", false: "隐藏轮播图" },
      },
      isAutoLayout: {
        value: !0,
        base: !0,
        key: keyBase + "isAutoLayout",
        txt: "是否根据缩放自动调整视频布局",
        type: "基础设置",
        valType: "boolean",
        compType: "radio",
        valueText: {
          true: "缩放时自动调整布局",
          false: "仅窗口变化时调整布局",
        },
      },
      isClearAd: {
        value: !0,
        base: !0,
        key: keyBase + "isClearAd",
        txt: "是否删除广告, 若不删除则会将所有广告移至视频列表的最后",
        type: "基础设置",
        valType: "boolean",
        compType: "radio",
        valueText: { true: "删除广告", false: "广告后移" },
      },
      isTrueEnd: {
        value: !1,
        base: !1,
        key: keyBase + "isTrueEnd",
        txt: "是否将广告移至预加载视频的后面, 关闭后广告将放置在预加载视频的前面 一般视频的后面 (该设置仅在不删除广告时生效)",
        type: "基础设置",
        valType: "boolean",
        compType: "radio",
        valueText: { true: "放置页尾", false: "放置预加载视频前" },
      },
      isLoadOne: {
        value: !0,
        base: !0,
        key: keyBase + "isLoadOne",
        txt: "是否在进入网站时加载视口区域的全部视频, 开启时视频将会全部加载(不会出现空白视频)",
        type: "基础设置",
        valType: "boolean",
        compType: "radio",
        valueText: {
          true: "加载视频至充满视口",
          false: "保留视口的未加载视频",
        },
      },
      videoNumRule: {
        value: "0,1300,2\n1300,1800,3\n1800,3000,4\n3000,3700,5\n3700,6300,6",
        base: "0,1300,2\n1300,1800,3\n1800,3000,4\n3000,3700,5\n3700,6300,6",
        base2: "0,1300,4\n1300,1800,5\n1800,3000,6\n3000,3700,7\n3700,6300,8",
        key: keyBase + "videoNumRule",
        txt: "视频排列规则, 每条规则用 ; 分隔 或 换行书写. 未包含的尺寸将按照初始方式排列 (轮播图会影响视频的排列)\n示例: 1300,1800,3; 1800,3000,4 表示浏览器宽度在1300~1800像素时每行显示3个视频(前两行), 1800~3000像素每行4个视频",
        type: "排列规则",
        valType: "string",
        compType: "textarea",
        compH: "120px",
      },
      delClassArr: {
        value: "广告, 推广",
        base: "广告, 推广",
        key: keyBase + "delClassArr",
        txt: "屏蔽设置, 可根据需要自行修改, 可自定义, 每项用 , 分隔 或 换行书写\n例如: 广告, 推广, 直播\n----可选: ('特殊'包含了直播 番剧 课堂...)\n广告、推广、特殊、直播、番剧、综艺、课堂、漫画、国创、电影、纪录片、电视剧\n----自定义:\n1. 标题=xxx, 可屏蔽标题含xxx的视频, xxx部分支持&&运算符, 如: 标题=A&&B, 表示屏蔽标题同时含有A B内容的视频\n2. 作者=xxx, 可屏蔽作者名和发布日期中含xxx的视频",
        type: "屏蔽设置",
        valType: "string",
        compType: "textarea",
        compH: "100px",
      },
      video_isDelAd: {
        value: !0,
        base: !0,
        key: keyBase + "video_isDelAd",
        txt: "是否删除视频页的广告",
        type: "视频页",
        valType: "boolean",
        compType: "radio",
        valueText: { true: "删除广告", false: "保留广告" },
      },
      video_delSetting: {
        value: "部分广告",
        base: "部分广告",
        key: keyBase + "video_delSetting",
        title: "广告屏蔽设置",
        txt: "可根据需要自行修改, 每项用 , 分隔 (该设置仅在删除广告时生效)\n例如: 部分广告, 活动推广\n----可选:\n全部广告: 所有直接广告和间接广告\n部分广告: 所有直接广告 (横幅广告,视频广告,活动广告)\n横幅广告: 视频下方的横幅广告\n视频广告: 右侧视频列表上方的小视频广告\n活动广告: 右侧视频列表上方的广告\n活动推广: 评论区上方的活动推广\n横幅通告: 评论区上方的横幅通告\n直播推广: 右侧视频列表下方的直播推广",
        type: "视频页",
        valType: "string",
        compType: "textarea",
        compH: "30px",
      },
    };
  function getValue({
    base = null,
    key,
    valType = "string",
    isReSet = !0,
    getVal,
    setVal,
  } = {}) {
    let val = getVal ? getVal(key) : localStorage.getItem(key);
    return (
      null !== base &&
        null == val &&
        ((val = base),
        isReSet &&
          (setVal ? setVal(key, val) : localStorage.setItem(key, val))),
      "string" === valType
        ? val
        : "boolean" === valType || "number" === valType
        ? JSON.parse(val)
        : "object" === valType
        ? JSON.parse(val || {})
        : "array" === valType
        ? JSON.parse(val || [])
        : val
    );
  }
  function getData() {
    for (const valName in settings) {
      const setting = settings[valName];
      setting.value = getValue({
        base: setting.base,
        key: setting.key,
        valType: setting.valType,
        getVal: GM_getValue,
        setVal: GM_setValue,
      });
    }
  }
  const utils = {
      getW(isAutoLayout) {
        let width =
          window.innerWidth ||
          document.documentElement.clientWidth ||
          document.body.clientWidth;
        return (
          console.log("浏览器实际宽度:", width * window.devicePixelRatio),
          console.log("浏览器像素宽度:", width * info.zoom),
          !isAutoLayout && (width *= window.devicePixelRatio),
          width
        );
      },
      getValue(key, defa = null) {
        let value = GM_getValue(key);
        return null == value ? defa : value;
      },
      boolTxt: (val) => (val ? "是 (确定)" : "否 (取消)"),
      strToDom(str) {
        let tmpDom = document.createElement("div");
        tmpDom.innerHTML = str;
        const dom = tmpDom.children[0];
        return (tmpDom = null), dom;
      },
      formatDate(
        timestamp,
        { delimiter = "-", isYear = !1, isAlign = !0 } = {}
      ) {
        if (!timestamp) return -1;
        const date = new Date(timestamp),
          year = date.getFullYear();
        let month = (date.getMonth() + 1).toString(),
          day = date.getDate().toString();
        return (
          isAlign &&
            ((month = month.padStart(2, "0")), (day = day.padStart(2, "0"))),
          (isYear ? year + delimiter : "") + month + delimiter + day
        );
      },
      formatTime(time, { delimiter = ":", isAlign = !0 } = {}) {
        if (!time) return -1;
        let h = Math.floor(time / 60 / 60),
          m = Math.floor((time / 60) % 60),
          s = Math.ceil(time % 60);
        return (
          isAlign &&
            ((h = h ? h.toString().padStart(2, "0") : ""),
            (m = m.toString().padStart(2, "0")),
            (s = s.toString().padStart(2, "0"))),
          (h ? h + delimiter : "") + m + delimiter + s
        );
      },
      async request(url, options = {}) {
        options.method = options.method || "GET";
        try {
          const res = await fetch(url, options);
          if (!res.ok) throw new Error(`HTTP error! Status: ${res.status}`);
          return await res.json();
        } catch (error) {
          throw error;
        }
      },
      errHandle({ e = null, errTxt = "", logTxt = "", key = "" } = {}) {
        key && (key = "_" + key);
        let errNum = GM_getValue(info.errKeyInfo.errNum) || 0;
        if (errNum >= info.errTipNum) return;
        let disErrNum = GM_getValue(info.errKeyInfo.disNum + key) || 0;
        const curTime = Date.now();
        let disS =
          (curTime - (GM_getValue(info.errKeyInfo.errTime + key) || curTime)) /
          1e3;
        if (((disS = 0 === disS ? 5 : disS), disS < 5)) return;
        let flag = GM_getValue(info.errKeyInfo.isTip + key);
        (flag = void 0 === flag || flag),
          e && console.log(e),
          console.log(logTxt || errTxt),
          disS >= 60 * info.errTipInterval * 60 &&
            ((flag = !0),
            GM_setValue(info.errKeyInfo.isTip + key, !0),
            GM_setValue(info.errKeyInfo.disNum + key, 0)),
          flag &&
            disErrNum <= info.disErrTipNum &&
            disS < (info.errTipInterval / 10) * 60 * 60 &&
            (errNum++,
            disErrNum++,
            GM_setValue(info.errKeyInfo.errNum, errNum),
            GM_setValue(info.errKeyInfo.disNum + key, disErrNum),
            GM_setValue(info.errKeyInfo.errTime + key, curTime),
            alert(errTxt),
            disErrNum === info.disErrTipNum &&
              GM_setValue(info.errKeyInfo.isTip + key, !1));
      },
      resetErrInfo() {
        const curTime = Date.now();
        (curTime -
          info.errKeyArr.reduce((a, b) => {
            const t = +GM_getValue(info.errKeyInfo.errTime + b);
            return t < a ? t : a;
          }, curTime)) /
          1e3 >=
          24 * info.errNumReset * 60 * 60 &&
          (GM_setValue(info.errKeyInfo.errNum, 0),
          info.errKeyArr.forEach((key) => {
            key && (key = "_" + key),
              GM_setValue(info.errKeyInfo.disNum + key, 0);
          }));
      },
    },
    videoObj = {
      info: {
        isDelAd: null,
        delSetting: null,
        base_isDelAd: null,
        base_delSetting: null,
        startTime: info.videoInfo.startTime,
        pathInterval: info.videoInfo.pathInterval,
        interval: info.videoInfo.interval,
        timeout: info.videoInfo.timeout,
      },
      doms: { ad: [] },
      delDom: info.videoInfo.delDom,
      initValue() {
        (this.info.isDelAd = settings.video_isDelAd.value),
          (this.info.delSetting = settings.video_delSetting.value),
          (this.info.base_isDelAd = settings.video_isDelAd.base),
          (this.info.base_delSetting = settings.video_delSetting.base);
      },
      getAdInfo() {
        if (this.info.delSetting.includes("全部广告"))
          return this.delDom.filter(
            (item) => "ad" === item.type || "other" === item.type
          );
        if (this.info.delSetting.includes("部分广告"))
          return this.delDom.filter(
            (item) => "ad" === item.type || "other" !== item.type
          );
        {
          const arr = this.delDom.filter((item) =>
            this.info.delSetting.includes(item.name)
          );
          return 0 === arr.length
            ? (utils.errHandle({
                errTxt: `插件设置的广告屏蔽设置中 '${GM_getValue(
                  "setting_video_delSetting"
                )}' 格式书写错误`,
                key: info.errKeyArr[2],
              }),
              -1)
            : arr;
        }
      },
      getAd() {
        const ad = [],
          delAdInfo = this.getAdInfo();
        -1 !== delAdInfo
          ? (delAdInfo.forEach((item) => {
              let adList;
              if ("." === item.pre)
                adList = document.querySelectorAll(item.pre + item.str);
              else {
                adList = [];
                const ele = document.querySelector(item.pre + item.str);
                ele && adList.push(ele);
              }
              adList.length > 0 &&
                adList.forEach((adDom) => {
                  ad.push(adDom);
                });
            }),
            (this.doms.ad = this.info.isDelAd
              ? ad.filter((item) => "none" !== item.style.display)
              : ad))
          : (this.doms.ad = []);
      },
      delAd() {
        this.doms.ad.forEach((item) => {
          "none" !== item.style.display && (item.style.display = "none");
        });
      },
      showAd() {
        this.doms.ad.forEach((item) => {
          "none" === item.style.display && (item.style.display = "");
        });
      },
      updateData() {
        (this.info.isDelAd = settings.video_isDelAd.value),
          (this.info.delSetting = settings.video_delSetting.value);
      },
      init() {
        if ((this.initValue(), !this.info.isDelAd)) return;
        let i = 0;
        const timer = setInterval(() => {
          i++,
            this.getAd(),
            (0 === this.doms.ad.length || i > this.info.timeout) &&
              clearInterval(timer),
            this.delAd();
        }, this.info.interval);
        utils.resetErrInfo();
      },
    };
  const editArea_cfg = {
    isEditing: !1,
    isShowPage: !1,
    param: {
      id: "ll_edit_wrap",
      box: document.body,
      classBase: "ll_edit_",
      w: "450px",
      h: "",
      contentH: "450px",
      bg: "rgba(0, 0, 0, 0.12)",
      color: "#333",
      fontSize: "15px",
      fontFamily:
        "PingFang SC, HarmonyOS_Regular, Helvetica Neue, Microsoft YaHei, sans-serif",
      zIndex: 11e3,
      resetTt: "重置所有设置为默认值",
      isScrollStyle: !0,
      isResetBtn: !0,
      showPage: "0",
      page: [],
    },
    allData: {},
    baseData: {},
    oldData: {},
    controls: {},
    doms: { page: [] },
    editText: {},
    callback: { resetBefore: null, confirmBefore: null, finished: null },
  };
  const css = function getCss() {
    const param = editArea_cfg.param,
      cBase = (param.page, param.classBase),
      baseStart = `#${param.id} .${cBase}`,
      fSize = param.fontSize ? param.fontSize : "14px",
      css = `#${
        param.id
      } {\n  position: fixed;\n  left: 0;\n  top: 0;\n  width: 100%;\n  height: 100%;\n  z-index: ${
        param.zIndex || 11e3
      };\n  background: ${
        param.bg || "rgba(0, 0, 0, 0.12)"
      };\n  display: none;\n}\n${baseStart}box {\n  position: relative;\n  width: ${
        param.w || "450px"
      };\n  ${
        param.h ? "max-height:" + param.h : ""
      };\n  margin: auto;\n  color: ${
        param.color || "#333"
      };\n  background: #fff;\n  font-size: ${fSize};\n  line-height: normal;\n  font-family: ${
        param.fontFamily ||
        "PingFang SC, HarmonyOS_Regular, Helvetica Neue, Microsoft YaHei, sans-serif"
      };\n  border: 3px solid #dfedfe;\n  border-radius: 10px;\n  box-sizing: border-box;\n  padding: 10px 8px 10px 15px;\n  overflow: hidden;\n  overflow-y: auto;\n}\n${baseStart}menu {\n  font-weight: bold;\n  font-size: ${
        parseInt(fSize) + 1
      }px;\n  margin-bottom: 10px;\n  display: flex;\n  gap: 8px;\n}\n${baseStart}menu-item {\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: ${
        param.contentH || ""
      };\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: 0;\n}\n${baseStart}comp-tt {\n  font-weight: bold;\n}\n${baseStart}comp-desc {\n  line-height: 1.5;\n}\n${baseStart}title {\n  font-weight: bold;\n  font-size: ${
        parseInt(fSize) + 5
      }px;\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#${
        param.id
      } 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: ${
        parseInt(fSize) - 2
      }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#${
        param.id
      } 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`;
    return param.isScrollStyle
      ? css +
          "\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}"
      : css;
  };
  const editArea_html = function getHTML() {
      function getCompHTML({ info, active = "", id }) {
        let title,
          desc,
          ctrlTt,
          type = info.type;
        if (
          ((type = {
            menuTitle: "mtt",
            title: "tt",
            desc: "ds",
            radio: "rd",
            checkbox: "cb",
            textarea: "ta",
            mtt: "mtt",
            tt: "tt",
            ds: "ds",
            rd: "rd",
            cb: "cb",
            ta: "ta",
          }[type]),
          (id = 0 === id ? "0" : id || ""),
          0 === info.content
            ? (info.content = "0")
            : (info.content = info.content || ""),
          !type)
        )
          return console.log("不存在的组件类型"), !1;
        switch (
          ("tt" !== type &&
            "ds" !== type &&
            "mtt" !== type &&
            ((title = info.title
              ? `<div class="${cBase}comp-tt ${cBase}${type}-tt" title="${
                  info.tt || ""
                }">${info.title}</div>`
              : ""),
            (desc = info.desc
              ? `<div class="${cBase}comp-desc ${cBase}${type}-desc">${info.desc}</div>`
              : "")),
          type)
        ) {
          case "mtt":
            return info.content
              ? `<div class="${cBase}menu-item ${active || ""}" title="${
                  info.tt || ""
                }">${info.content}</div>`
              : "";
          case "tt":
            return info.content
              ? `<div class="${cBase}title ${cBase}comp" title="${
                  info.tt || ""
                }">${info.content}</div>`
              : "";
          case "ds":
            return info.content
              ? `<div class="${cBase}desc ${cBase}comp" title="${
                  info.tt || ""
                }">${info.content}</div>`
              : "";
          case "rd":
            const name = info.name || new Date().getTime();
            (ctrlTt = info.ctrlTt || ""),
              ctrlTt && (ctrlTt = `title="${ctrlTt}"`);
            let radio = `<div class="${cBase}rd ${cBase}rd-arr" ${ctrlTt}>`;
            if (void 0 === info.value && info.radioList[0]) {
              const obj = info.radioList[0];
              info.value = void 0 === obj.value ? obj.text : obj.value;
            }
            return (
              info.radioList.forEach((item) => {
                const value = void 0 === item.value ? item.text : item.value;
                let tt = item.tt || "";
                tt && (tt = `title="${tt}"`);
                let selected = "";
                info.value + "" == item.value + "" && (selected = "checked"),
                  (radio += `<label ${tt}><input ${selected} type="radio" name="${name}" data-val="${value}" data-cpid="${id}"><span>${item.text}</span></label>`);
              }),
              (radio += "</div>"),
              `<div class="${cBase}comp ${cBase}ctrl ${cBase}rd-box" data-type="${type}" data-cpid="${id}">${title}${desc}${radio}</div>`
            );
          case "cb":
            const name2 = info.name || new Date().getTime();
            if (
              ((ctrlTt = info.ctrlTt || ""),
              ctrlTt && (ctrlTt = `title="${ctrlTt}"`),
              void 0 === info.value && info.radioList[0])
            ) {
              const obj = info.radioList[0];
              info.value = void 0 === obj.value ? obj.text : obj.value;
            }
            let checkbox = `<div class="${cBase}cb ${cBase}rd-arr" ${ctrlTt}>`;
            return (
              info.radioList.forEach((item) => {
                const value = void 0 === item.value ? item.text : item.value;
                let tt = item.tt || "";
                tt && (tt = `title="${tt}"`);
                let selected = "";
                info.value + "" == item.value + "" && (selected = "checked"),
                  (checkbox += `<label ${tt}><input ${selected} type="checkbox" name="${name2}" data-val="${value}" data-cpid="${id}"><span>${item.text}</span></label>`);
              }),
              (checkbox += "</div>"),
              `<div class="${cBase}comp ${cBase}ctrl ${cBase}cb-box" data-type="${type}" data-cpid="${id}">${title}${desc}${checkbox}</div>`
            );
          case "ta":
            const style = `style="${
                info.width ? "width:" + info.width + ";" : ""
              }${info.height ? "height:" + info.height + ";" : ""}${
                info.fontSize ? "font-size:" + info.fontSize + ";" : ""
              }${
                info.fontFamily ? "font-family:" + info.fontFamily + ";" : ""
              }"`,
              textarea = `<textarea class="${cBase}ta" ${style} data-cpid="${id}" placeholder="${
                info.ph || ""
              }" title="${info.ctrlTt || "拖动右下角可调节宽高"}"></textarea>`;
            return `<div class="${cBase}comp ${cBase}ctrl ${cBase}ta-box" data-type="${type}"  data-cpid="${id}">${title}${desc}${textarea}</div>`;
        }
      }
      const param = editArea_cfg.param,
        page = param.page,
        cBase = param.classBase,
        isMenu = 1 !== page.length;
      let menu = `<div class="${cBase}menu">`,
        pageHTML = `<div class="${cBase}page-box ll-scroll-style-1 ll-scroll-style-1-size-2">`;
      page.forEach((curPage, index) => {
        let pageFlag,
          pgid = curPage.id || index;
        if (
          ((pgid += ""),
          (editArea_cfg.allData[pgid] = {}),
          (editArea_cfg.baseData[pgid] = {}),
          editArea_cfg.isShowPage ||
            (void 0 === param.showPage &&
              ((pageFlag = "curPage"), (editArea_cfg.isShowPage = !0)),
            pgid === param.showPage + ""
              ? ((pageFlag = "curPage"), (editArea_cfg.isShowPage = !0))
              : (pageFlag = "")),
          (pageHTML += `<div class="${cBase}page ${pageFlag}" data-pgid="${pgid}">`),
          curPage.components)
        ) {
          let compIndex = 0;
          if (isMenu) {
            let curMenu = curPage.components.find(
              (item) => "menuTitle" === item.type
            );
            curMenu || (curMenu = { type: "menuTitle", content: pgid }),
              (menu += getCompHTML({
                info: curMenu,
                active: pageFlag ? "active" : "",
              }));
          }
          curPage.components.forEach((item) => {
            const cpid = item.id || compIndex;
            "menuTitle" !== item.type &&
              (pageHTML += getCompHTML({ info: item, id: cpid })),
              "menuTitle" !== item.type &&
                "title" !== item.type &&
                "desc" !== item.type &&
                ((item.base = item.base || item.value),
                (editArea_cfg.allData[pgid][cpid] = item.value),
                (editArea_cfg.baseData[pgid][cpid] = item.base),
                compIndex++);
          });
        }
        pageHTML += "</div>";
      }),
        (pageHTML += "</div>"),
        isMenu ? (menu += "</div>") : (menu = "");
      const resetBtn = param.isResetBtn
        ? `<button class="${cBase}reset-btn" title="${
            editArea_cfg.resetTt || "重置所有设置为默认值"
          }">重置</button>`
        : "";
      return `<div class="${cBase}box ll-scroll-style-1 ll-scroll-style-1-size-3">\n${menu}\n${pageHTML}\n${`<div class="${cBase}btn-box">\n${resetBtn}\n<button class="${cBase}cancel-btn">取 消</button>\n<button class="${cBase}confirm-btn">确 认</button>\n</div>`}\n</div>`;
    },
    param = editArea_cfg.param,
    allData = editArea_cfg.allData,
    controls = editArea_cfg.controls,
    doms = editArea_cfg.doms,
    cBase = param.classBase;
  function createEditEle({
    id = param.id,
    box = param.box,
    classBase = param.classBase,
    w = param.w,
    h = param.h,
    contentH = param.contentH,
    bg = param.bg,
    color = param.color,
    fontSize = param.fontSize,
    fontFamily = param.fontFamily,
    zIndex = param.zIndex,
    resetTt = param.resetTt,
    isScrollStyle = param.isScrollStyle,
    isResetBtn = param.isResetBtn,
    showPage = param.showPage,
    page = [],
  } = {}) {
    (param.id = id),
      (param.box = box),
      (param.classBase = classBase),
      (param.w = w),
      (param.h = h),
      (param.contentH = contentH),
      (param.bg = bg),
      (param.color = color),
      (param.fontSize = fontSize),
      (param.fontFamily = fontFamily),
      (param.zIndex = zIndex),
      (param.resetTt = resetTt),
      (param.isScrollStyle = isScrollStyle),
      (param.isResetBtn = isResetBtn),
      (param.showPage = showPage),
      (param.page = page);
    const html = editArea_html();
    return (
      (function addCss(cssText, box = document.body, id = "") {
        const style = document.createElement("style");
        return (
          id && (style.id = id),
          box.appendChild(style),
          (style.innerHTML = cssText),
          style
        );
      })(css(), box),
      (doms.wrap = (function createEle({
        className = "",
        id = "",
        title = "",
        css,
        box = document.body,
        type = "div",
      } = {}) {
        const ele = document.createElement(type);
        return (
          id && (ele.id = id),
          className && (ele.className = className),
          title && (ele.title = title),
          css && (ele.style.cssText = css),
          box.appendChild(ele),
          ele
        );
      })({ className: id, id })),
      (doms.wrap.innerHTML = html),
      (function getDoms() {
        (doms.box = doms.wrap.querySelector(`.${cBase}box`)),
          (doms.cancel = doms.box.querySelector(`.${cBase}cancel-btn`)),
          (doms.confirm = doms.box.querySelector(`.${cBase}confirm-btn`));
        const isMenu = 1 !== param.page.length;
        isMenu &&
          ((doms.menu = doms.box.querySelector(`.${cBase}menu`)),
          (doms.menus = [].slice.call(
            doms.menu.querySelectorAll(`.${cBase}menu-item`)
          )));
        const pages = [].slice.call(doms.box.querySelectorAll(`.${cBase}page`));
        (doms.page = []),
          param.isResetBtn &&
            (doms.reset = doms.box.querySelector(`.${cBase}reset-btn`));
        pages.forEach((curPage, index) => {
          editArea_cfg.isShowPage ||
            (curPage.classList.add("curPage"), (editArea_cfg.isShowPage = !0));
          const page = {},
            pgid = curPage.dataset.pgid;
          (page.pgid = curPage.pgid = pgid),
            (page.controls = [].slice.call(
              curPage.querySelectorAll(`.${cBase}ctrl`)
            )),
            (page.ele = curPage),
            doms.page.push(page),
            isMenu && (doms.menus[index].settingsPage = curPage);
          const ctrls = {};
          (controls[pgid] = ctrls),
            page.controls.forEach((item, i) => {
              const cpid = item.dataset.cpid,
                cType = item.dataset.type;
              let dom;
              (item.cpid = cpid),
                "rd" === cType || "cb" === cType
                  ? ((dom = [].slice.call(item.querySelectorAll("input"))),
                    (dom.compType = cType))
                  : "ta" === cType &&
                    ((dom = item.querySelector("textarea")),
                    (dom.compType = cType),
                    (dom.value = allData[pgid][cpid])),
                (ctrls[cpid] = dom);
            });
        });
      })(),
      (function bindEvents() {
        function menuHandle(e) {
          const dom = e.target;
          if (dom.classList.contains(`${cBase}menu-item`)) {
            const old = doms.menu.querySelector(".active");
            old.classList.remove("active"),
              old.settingsPage.classList.remove("curPage"),
              dom.classList.add("active"),
              dom.settingsPage.classList.add("curPage");
          }
        }
        function cancelEdit(e) {
          (e.target.className !== `${cBase}wrap` &&
            e.target.className !== `${cBase}cancel-btn`) ||
            (showEditArea(!1), setCompValue(editArea_cfg.oldData));
        }
        function confirmEdit() {
          const callback = editArea_cfg.callback,
            data = getAllData();
          if (callback.confirmBefore) {
            let result;
            const func = callback.confirmBefore;
            if (
              (Array.isArray(func)
                ? func.curFn
                  ? ((result = func[curFn](data)), (func.curFn = null))
                  : func.forEach((fn) => {
                      result = fn(data);
                    })
                : (result = func(data)),
              !1 === result)
            )
              return;
          }
          if ((showEditArea(!1), callback.finished)) {
            const func = callback.finished;
            Array.isArray(func)
              ? func.curFn
                ? (func[curFn](data), (func.curFn = null))
                : func.forEach((fn) => {
                    fn(data);
                  })
              : func(data);
          }
        }
        function resetEdit() {
          const callback = editArea_cfg.callback,
            data = getAllData();
          if (callback.resetBefore) {
            let result;
            const func = callback.resetBefore;
            if (
              (Array.isArray(func)
                ? func.curFn
                  ? ((result = func[curFn](data)), (func.curFn = null))
                  : func.forEach((fn) => {
                      result = fn(data);
                    })
                : (result = func(data)),
              !1 === result)
            )
              return;
          }
          !(function resetEditData() {
            param.isResetBtn && setCompValue(editArea_cfg.baseData);
          })();
        }
        doms.menu && doms.menu.addEventListener("click", menuHandle),
          doms.wrap.addEventListener("click", cancelEdit),
          doms.cancel.addEventListener("click", cancelEdit),
          doms.confirm.addEventListener("click", confirmEdit),
          doms.reset && doms.reset.addEventListener("click", resetEdit);
      })(),
      editArea_cfg
    );
  }
  function getAllData() {
    function getCompItem(pgid, cpid) {
      if (!controls[pgid]) return;
      const ctrl = controls[pgid][cpid];
      if (ctrl) {
        if (!Array.isArray(ctrl)) return ctrl.value;
        if ("rd" === ctrl.compType) {
          return ctrl.find((item) => item.checked).dataset.val;
        }
        if ("cb" === ctrl.compType) {
          return ctrl
            .filter((item) => item.checked)
            .map((item) => item.dataset.val);
        }
      }
    }
    const data = {};
    if (0 === arguments.length) {
      for (const key in controls) {
        const page = controls[key];
        data[key] = {};
        for (const key2 in page) data[key][key2] = getCompItem(key, key2);
      }
      return data;
    }
    if (1 === arguments.length) {
      const ctrls = arguments[0];
      for (const pgid in ctrls) {
        data[pgid] = {};
        controls[pgid].forEach((cpid) => {
          data[pgid][cpid] = getCompItem(pgid, cpid);
        });
      }
      return allData;
    }
    return getCompItem(arguments[0], arguments[1]);
  }
  function setCompValue() {
    function setCompItem(pgid, cpid, value) {
      if (!controls[pgid]) return;
      const ctrl = controls[pgid][cpid];
      if (ctrl)
        if (Array.isArray(ctrl)) {
          if ("rd" === ctrl.compType) {
            const selected = ctrl.find((item) => item.checked);
            selected && (selected.checked = !1);
            const select = ctrl.find((item) => item.dataset.val === value + "");
            select && (select.checked = !0);
          } else if ("cb" === ctrl.compType) {
            if (
              (ctrl
                .filter((item) => item.checked)
                .forEach((item) => {
                  item.checked = !1;
                }),
              Array.isArray(value))
            )
              value.forEach((val) => {
                const select = ctrl.find(
                  (item) => item.dataset.val === val + ""
                );
                select && (select.checked = !0);
              });
            else {
              const select = ctrl.find(
                (item) => item.dataset.val === value + ""
              );
              select && (select.checked = !0);
            }
          }
        } else ctrl.value = value;
    }
    if (1 === arguments.length) {
      const data = arguments[0];
      for (const key in data) {
        const pageData = data[key];
        for (const key2 in pageData) {
          setCompItem(key, key2, pageData[key2]);
        }
      }
    } else {
      setCompItem(arguments[0], arguments[1], arguments[2]);
    }
  }
  function showEditArea(isShow = !0, callback = null) {
    if (
      isShow &&
      ((editArea_cfg.oldData = getAllData()), "function" == typeof callback)
    ) {
      if (!1 === callback(editArea_cfg.oldData)) return;
    }
    (editArea_cfg.isEditing = isShow),
      (doms.wrap.style.display = isShow ? "block" : "none"),
      isShow &&
        !doms.box.style.top &&
        (doms.box.style.top =
          window.innerHeight / 2 - doms.box.clientHeight / 2 + "px"),
      callback && (editArea_cfg.callback = callback);
  }
  function toPageObj(settings) {
    const pageArr = [],
      menuList = [];
    for (let key in settings) {
      const item = settings[key];
      menuList.includes(item.type) || menuList.push(item.type);
    }
    return (
      menuList.forEach((menuTt) => {
        const components = [],
          page = { id: menuTt, components },
          arr = [];
        for (let key in settings) {
          const item = settings[key];
          item.type === menuTt && arr.push(item);
        }
        arr.forEach((item) => {
          const comp = {
            id: item.key,
            type: item.compType,
            title: item.title || "",
            desc: item.txt.replaceAll("\n", "<br>").trim() || "",
            name: item.key,
            value: item.value,
            base: item.base,
          };
          if ("textarea" === comp.type)
            (comp.ph = item.base),
              (comp.width = item.compW),
              (comp.height = item.compH),
              (comp.ctrlTt = "默认: " + item.base);
          else if ("radio" === comp.type || "checkbox" === comp.type) {
            let str = "默认: ";
            if ("checkbox" === comp.type) {
              let arr = item.base;
              Array.isArray(arr) || (arr = arr.split(/,|,/)),
                arr.forEach((val, i) => {
                  0 !== i && (str += ", "), (val = val.trim());
                  let valTxt = item.valueText[val];
                  void 0 === valTxt && (valTxt = val), (str += valTxt);
                });
            } else {
              let val = item.valueText[item.base];
              void 0 === val && (val = item.base), (str += val);
            }
            comp.ctrlTt = str;
          }
          if (item.valueText) {
            comp.radioList = [];
            for (let key in item.valueText) {
              const rd = { text: item.valueText[key], value: key };
              comp.radioList.push(rd);
            }
          }
          components.push(comp);
        }),
          pageArr.push(page);
      }),
      pageArr
    );
  }
  const classList = info.homeClassList,
    delClassList = info.homeDelClassList;
  let vDom,
    nav,
    banner,
    carousel,
    base_videoNumRule,
    base_videoNumRule2,
    isClearAd,
    isTrueEnd,
    isAutoLayout,
    isLoadOne,
    isCarousel,
    videoNumRule,
    delClassArr;
  const apiUrl = info.apiUrl,
    imgDetails = info.imgDetails,
    queryNum = 0,
    marginTop1 = info.marginTop1,
    marginTop2 = info.marginTop2,
    zoom = info.zoom;
  let cssDom,
    cssText,
    oldCssText,
    w,
    isChange = !1,
    rowVideoNum = 3,
    videoNum = 0,
    newVideoNum = 0,
    firstAdIndex = 0,
    pageZoom = 1,
    loadNum = 0;
  function main(isLoads = !0) {
    if (isLoads && (loadNum++, loadNum > 3)) return;
    if (
      (updateData(),
      (function home_getDoms() {
        if (vDom && nav && banner && carousel)
          return void (isCarousel || showCarousel(!1));
        "string" == typeof classList.vDom
          ? (vDom = document.querySelector("." + classList.vDom))
          : classList.vDom.forEach((item) => {
              !vDom && (vDom = document.querySelector("." + item));
            });
        if (!vDom) {
          const dom = document.querySelector("." + classList.video);
          if ((dom && (vDom = dom.parentElement), !vDom)) return;
        }
        (carousel = vDom.querySelector("." + classList.carousel)),
          (nav = document.querySelector("." + classList.nav)),
          (banner = document.querySelector("." + classList.banner)),
          (videoNumRule = (function home_getValue(key, defa = "") {
            let value = GM_getValue(key);
            return null == value ? defa : value;
          })(
            "setting_videoNumRule",
            carousel && isCarousel ? base_videoNumRule2 : base_videoNumRule
          )),
          "string" == typeof videoNumRule &&
            (videoNumRule = getVideoNumRule(videoNumRule));
        isCarousel || showCarousel(!1);
      })(),
      !vDom && isLoads)
    )
      return void setTimeout(() => {
        main();
      }, 500);
    (w = utils.getW(isAutoLayout)),
      (videoNum = getVideoNum(vDom)),
      delAd(getAd(queryNum, delClassArr, newVideoNum, 1), vDom),
      setTimeout(() => {
        delAdFn();
      }, 1e3),
      zoomPage(),
      setStyle(),
      setTimeout(() => {
        loadTopVideo();
      }, 500),
      utils.resetErrInfo(),
      (function home_bindEvents() {
        let rollBtn, btnSvg, rollBtn2, timer, timer2, timer3;
        function handleClick() {
          if (!rollBtn) {
            let adArr = getAd(
              3 * rowVideoNum + (carousel ? 2 : 0),
              delClassArr,
              newVideoNum,
              1
            );
            delAd(adArr, vDom),
              (rollBtn = document.querySelector("button." + classList.btn)),
              (btnSvg = rollBtn && rollBtn.querySelector("svg")),
              btnSvg
                ? btnSvg.addEventListener("transitionend", () => {
                    (adArr = getAd(
                      3 * rowVideoNum + (carousel ? 2 : 0) + 3,
                      delClassArr,
                      newVideoNum,
                      1
                    )),
                      !isTrueEnd &&
                        adArr.forEach((item) => {
                          item.forEach((adItem) => {
                            adItem.style.display = "block";
                          });
                        }),
                      setTimeout(() => {
                        delAd(adArr, vDom);
                      }, 50);
                  })
                : rollBtn &&
                  rollBtn.addEventListener("click", () => {
                    setTimeout(() => {
                      (adArr = getAd(
                        3 * rowVideoNum + (carousel ? 2 : 0) + 3,
                        delClassArr,
                        newVideoNum,
                        1
                      )),
                        delAd(adArr, vDom);
                    }, 800);
                  });
          }
          if (!rollBtn2) {
            let adArr = getAd(queryNum, delClassArr, newVideoNum, 1);
            delAd(adArr, vDom),
              (rollBtn2 = document.querySelector("." + classList.btn2)),
              rollBtn2 &&
                rollBtn2.addEventListener("click", () => {
                  setTimeout(() => {
                    (videoNum = getVideoNum(vDom)),
                      (firstAdIndex = 0),
                      (adArr = getAd(queryNum, delClassArr, 0, 1, !!isTrueEnd)),
                      delAd(adArr, vDom, !0),
                      loadTopVideo();
                  }, 800);
                });
          }
          rollBtn &&
            rollBtn2 &&
            window.removeEventListener("click", handleClick);
        }
        window.addEventListener("click", handleClick),
          window.addEventListener("resize", () => {
            timer && clearTimeout(timer),
              (timer = setTimeout(() => {
                const newW = utils.getW(isAutoLayout);
                newW > w && delAdFn(), (w = newW), zoomPage(), setStyle();
              }, 400));
          }),
          window.addEventListener("wheel", () => {
            timer2 && clearTimeout(timer2),
              timer3 && clearTimeout(timer3),
              (timer2 = setTimeout(() => {
                delAdFn(timer3);
              }, 600)),
              (timer3 = setTimeout(() => {
                delAdFn();
              }, 1500));
          });
      })();
  }
  function zoomPage() {
    if (document.getBoxObjectFor) return;
    const rootDom = document.documentElement;
    let rate = rootDom.scrollWidth / getMainW();
    function getMainW() {
      let navW = nav ? nav.scrollWidth : 0;
      return navW > (banner ? banner.scrollWidth : 0)
        ? navW
        : rootDom.clientWidth;
    }
    !document.body.style.overflow &&
      (document.body.style.overflow = "hidden auto"),
      rate > 1
        ? ((pageZoom *= 1 / rate), (rootDom.style.zoom = pageZoom))
        : ((pageZoom = 1),
          (rootDom.style.zoom = 1),
          (rate = rootDom.scrollWidth / getMainW()),
          rate > 1 &&
            ((pageZoom *= 1 / rate), (rootDom.style.zoom = pageZoom)));
  }
  function getAd(queryNum, delClassArr, vNum, startIndex = 1, isAll = !1) {
    const arr = [];
    delClassArr.forEach(() => {
      arr.push([]);
    });
    const vList = [].slice.call(vDom.children);
    let len = vNum || vList.length;
    (len = len > vList.length ? vList.length : len),
      (queryNum = queryNum || len),
      (queryNum += startIndex) > len && (queryNum = len);
    for (let i = startIndex; i < queryNum; i++) {
      const vItem = vList[i];
      if (!isAll && !vItem.querySelector("a")) break;
      for (let j = 0; j < delClassArr.length; j++)
        if (isChecked(vItem, delClassArr[j])) {
          arr[j].push(vItem);
          break;
        }
    }
    return arr;
  }
  function delAd(adArr, dom = vDom, isDel = !1) {
    for (let i = adArr.length - 1; i >= 0; i--)
      adArr[i].forEach((item) => {
        isClearAd || isDel
          ? (item.remove(), newVideoNum--, videoNum--)
          : isTrueEnd
          ? (newVideoNum--, videoNum--, dom.appendChild(item))
          : dom.insertBefore(item, dom.children[newVideoNum]);
      });
  }
  function delAdFn(timer = null) {
    if ((getVideoNum(vDom), newVideoNum > videoNum)) {
      delAd(
        getAd(
          queryNum,
          delClassArr,
          newVideoNum,
          isTrueEnd ? videoNum : firstAdIndex
        ),
        vDom
      ),
        (videoNum = newVideoNum),
        timer && clearTimeout(timer);
    }
  }
  function setStyle() {
    if (
      ((isChange = !1),
      videoNumRule.forEach((item) => {
        !(function setVideoNum(vRule) {
          const min =
              (vRule = vRule.map((i) => +i.trim()))[0] /
              (isAutoLayout ? zoom : 1),
            max = vRule[1] / (isAutoLayout ? zoom : 1),
            num = vRule[2];
          (0 === min || min) && max && num
            ? (w >= min &&
                w < max &&
                ((cssText = carousel
                  ? `.container {grid-template-columns: repeat(${
                      num + 2
                    },1fr) !important}\n.container>div:nth-child(n){margin-top:${marginTop2}px !important}\n.container>div:nth-child(-n+${
                      3 * num + 2 + 1
                    }){margin-top:${marginTop1}px !important;display:block !important}\n.container>div:first-child{display:${
                      isCarousel ? "block" : "none"
                    } !important}\n.container>div:nth-child(-n+${
                      2 * (num + 1) - 1
                    }){margin-top:0px !important}`
                  : `.container {grid-template-columns: repeat(${num},1fr) !important}\n.container>div:nth-child(n){margin-top:${marginTop2}px !important}\n      `),
                (isChange = !0),
                (rowVideoNum = num)),
              isChange || ((cssText = ""), (rowVideoNum = carousel ? 5 : 3)))
            : utils.errHandle({
                errTxt: `插件设置的视频排列规则设置中 '${vRule.join(
                  ""
                )}' 格式书写错误`,
                key: info.errKeyArr[1],
              });
        })(item);
      }),
      isChange)
    ) {
      let isCssDom = !!cssDom;
      isCssDom ||
        ((cssDom = document.createElement("style")),
        cssDom.setAttribute("type", "text/css")),
        oldCssText !== cssText && (cssDom.innerHTML = cssText),
        (oldCssText = cssText),
        !isCssDom && vDom.parentElement.insertBefore(cssDom, vDom);
    } else !isChange && cssDom && ((oldCssText = ""), (cssDom.innerHTML = ""));
  }
  function getVideoNum(dom) {
    const arr = [].slice.call(dom.children),
      len = arr.length;
    let i,
      isGetAdIndex = !1;
    for (i = 1; i < len; i++) {
      const item = arr[i];
      if (!isTrueEnd && !isGetAdIndex) {
        const vItem = dom.children[i];
        for (let j = 0; j < delClassArr.length; j++)
          if (isChecked(vItem, delClassArr[j])) {
            (isGetAdIndex = !0), (firstAdIndex = i);
            break;
          }
      }
      if (!item.querySelector("a")) return (newVideoNum = i), i;
    }
    return (newVideoNum = i), i;
  }
  function isChecked(vEle, delStr) {
    let flag = !1;
    const map = classList;
    function custom(txt, type, selector) {
      const dom = vEle.querySelector(selector);
      if (!dom) return;
      const domTxt = dom.innerText,
        txtArr = txt.replace(type, "").split("&&");
      if (!txtArr[0]) return;
      let f = !1;
      txtArr.forEach((item) => {
        f = f || domTxt.includes(item, "");
      }),
        (flag = flag || f);
    }
    if (
      ((delStr = delStr.trim()),
      (delStr = delClassList[delStr] || delStr).includes("标题="))
    )
      custom(delStr, "标题=", map.标题);
    else if (delStr.includes("作者=")) custom(delStr, "作者=", "." + map.作者);
    else if (delStr.includes("分类=")) custom(delStr, "分类=", "." + map.分类);
    else {
      flag = flag || vEle.classList.contains(delStr);
      try {
        flag = flag || vEle.querySelector("." + delStr);
      } catch (e) {
        utils.errHandle({
          errTxt: `插件设置的屏蔽设置中 '${delStr}' 格式书写错误, 自定义格式应以 '标题=' 或 '作者=' 开头`,
          e,
        });
      }
    }
    return flag;
  }
  function createVideoDom(data) {
    function formatNum(num) {
      return num > 1e8
        ? (num / 1e8).toFixed(1) + "亿"
        : num > 1e4
        ? (num / 1e4).toFixed(1) + "万"
        : "" + num;
    }
    function videoDom(item, reportStr) {
      if (item.business_info) return -1;
      const like = Math.floor(item.stat.like / 1e4),
        likeHTML =
          like > 1
            ? `<div class="bili-video-card__info--icon-text">${like}万点赞</div>`
            : "",
        upIconHTML = likeHTML
          ? ""
          : '<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>',
        html = `<div data-v-7ae03d4e="" class="bili-video-card is-rcmd" data-report="tianma.${reportStr}.click"\n  style="--cover-radio: 56.25%;">\n  <div class="bili-video-card__skeleton hide">\n    <div class="bili-video-card__skeleton--cover"></div>\n    <div class="bili-video-card__skeleton--info">\n      <div class="bili-video-card__skeleton--right">\n        <p class="bili-video-card__skeleton--text"></p>\n        <p class="bili-video-card__skeleton--text short"></p>\n        <p class="bili-video-card__skeleton--light"></p>\n      </div>\n    </div>\n  </div>\n  <div class="bili-video-card__wrap __scale-wrap"><a href="${
          item.uri
        }" 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(
          "http:",
          ""
        )}${imgDetails}.avif"\n              type="image/avif">\n            <source\n              srcset="${item.pic.replace(
          "http:",
          ""
        )}${imgDetails}.webp"\n              type="image/webp"><img\n              src="${item.pic.replace(
          "http:",
          ""
        )}${imgDetails}"\n              alt="${
          item.title
        }" 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(
          item.stat.view
        )}</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(
          item.stat.danmaku
        )}</span></span></div><span\n              class="bili-video-card__stats__duration">${utils.formatTime(
          item.duration
        )}</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="${
          item.title
        }">\n          <a href="${
          item.uri
        }?spm_id_from=333.1007.tianma.${reportStr}.click" target="_blank" data-spmid="333.1007"\n            data-mod="tianma.${reportStr}" data-idx="click">${
          item.title
        }\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/${
          item.owner.mid
        }" 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="${
          item.owner.name
        }">${
          item.owner.name
        }</span>\n            <span class="bili-video-card__info--date">· ${(function formatDate(
          t
        ) {
          const date = new Date(),
            oldDate = new Date(1e3 * t),
            dis = Math.floor(date.getTime() / 1e3) - t;
          return date.getFullYear() !== oldDate.getFullYear()
            ? utils.formatDate(1e3 * t, { isYear: !0, isAlign: !1 })
            : dis < 60
            ? "刚刚"
            : dis < 3600
            ? Math.floor(dis / 60 / 60) + "分钟前"
            : dis < 86400
            ? Math.floor(dis / 60 / 60) + "小时前"
            : dis < 172800
            ? "昨天"
            : utils.formatDate(1e3 * t, { isAlign: !1 });
        })(
          item.pubdate
        )}</span>\n          </a>\n        </div>\n      </div>\n    </div>\n  </div>\n</div>`;
      return utils.strToDom(html);
    }
    const videoList = [];
    let num = 10;
    return (
      data.forEach((item, index) => {
        num++;
        const dom = videoDom(item, `4-${index + 1}-${num}`);
        -1 !== dom && videoList.push(dom);
      }),
      videoList
    );
  }
  async function loadTopVideo() {
    if (isLoadOne)
      try {
        const row = 4,
          newNum = (function addVideoNum() {
            return isCarousel
              ? 3 * rowVideoNum +
                  2 -
                  newVideoNum +
                  (isClearAd || isTrueEnd ? 0 : 1)
              : 3 * rowVideoNum -
                  newVideoNum +
                  (isClearAd || isTrueEnd ? 0 : 1);
          })();
        if (newNum <= 0) return;
        const params = new URLSearchParams({
            web_location: 1430650,
            y_num: 4,
            fresh_type: 4,
            feed_version: "V8",
            fresh_idx_1h: 1,
            fetch_row: row,
            fresh_idx: 1,
            brush: 1,
            homepage_ver: 1,
            ps: newNum,
            last_y_num: 5,
            screen: window.innerWidth + "-" + window.innerHeight,
            wts: Math.floor(new Date().getTime() / 1e3),
          }),
          data = await utils.request(`${apiUrl}?${params}`);
        let videoList = [];
        if (data.data.item) {
          (videoList = createVideoDom(data.data.item)), getVideoNum(vDom);
          for (let i = videoList.length - 1; i >= 0; i--)
            vDom.insertBefore(videoList[i], vDom.children[newVideoNum]);
        }
      } catch (e) {
        console.log(e),
          setTimeout(() => {
            document.documentElement.scrollTo(0, 400),
              setTimeout(() => {
                document.documentElement.scrollTo(0, 0),
                  setTimeout(() => {
                    delAdFn();
                  }, 800);
              }, 20);
          }, 1e3);
      }
  }
  function getDelClassArr(value) {
    return (value = value
      .replaceAll(";", ",")
      .replaceAll(";", ",")
      .replaceAll(",", ",")
      .replaceAll(",\n", "\n")
      .replaceAll("\n", ",\n")).split(",");
  }
  function getVideoNumRule(value) {
    return (value = (value = value
      .replaceAll(";", ";")
      .replaceAll(";\n", ";")
      .replaceAll("\n", ";\n")).split(";")).map((item) => item.split(/,|,/));
  }
  function updateData() {
    (isClearAd = settings.isClearAd.value),
      (isTrueEnd = settings.isTrueEnd.value),
      (isAutoLayout = settings.isAutoLayout.value),
      (isLoadOne = settings.isLoadOne.value),
      (isCarousel = settings.isCarousel.value),
      (videoNumRule = getVideoNumRule(settings.videoNumRule.value)),
      (delClassArr = getDelClassArr(settings.delClassArr.value)),
      (base_videoNumRule = getVideoNumRule(settings.videoNumRule.base)),
      (base_videoNumRule2 = getVideoNumRule(settings.videoNumRule.base2));
  }
  function showCarousel(isShow = !0) {
    carousel || (carousel = vDom.querySelector("." + classList.carousel)),
      carousel && (carousel.style.display = isShow ? "block" : "none"),
      isShow || (carousel = !1);
  }
  function setValue({
    value,
    base,
    key,
    verification = null,
    getValue = null,
    setValue = null,
  } = {}) {
    let newVal = value,
      val = getValue ? getValue(key) : localStorage.getItem(key);
    return (
      null == val &&
        ((val = base),
        setValue ? setValue(key, base) : localStorage.setItem(key, base)),
      null !== newVal &&
        ("function" != typeof verification ||
          ((newVal = verification(newVal, val)), null !== newVal)) &&
        newVal !== val &&
        (setValue ? setValue(key, newVal) : localStorage.setItem(key, newVal),
        !0)
    );
  }
  function showSettings() {
    info.settingsArea ||
      (info.settingsArea = createEditEle(
        (function getEditInfo() {
          const editInfo = {
            w: "500px",
            contentH: "450px",
            resetTT: "重置所有设置项为默认值",
            page: toPageObj(settings),
          };
          return (
            "首页" === info.pageName
              ? (editInfo.showPage = "基础设置")
              : "视频" === info.pageName && (editInfo.showPage = "视频页"),
            editInfo
          );
        })()
      )),
      getData(),
      updateData(),
      videoObj.updateData();
    const callback = {
      resetBefore: () => confirm("是否重置所有设置项为默认值?"),
      confirmBefore: () => {},
      finished: (data) => {
        console.log(data);
        if (
          !(function isValueChange() {
            const curData = getAllData();
            return (
              JSON.stringify(curData) !== JSON.stringify(editArea_cfg.oldData)
            );
          })()
        )
          return;
        const changeObj = {
          isCarousel: !1,
          isAutoLayout: !1,
          isClearAd: !1,
          isTrueEnd: !1,
          isLoadOne: !1,
          videoNumRule: !1,
          delClassArr: !1,
          video_isDelAd: !1,
          video_delSetting: !1,
        };
        for (const pageName in data) {
          const page = data[pageName];
          for (const key in page) {
            const value = page[key];
            let item, verifyFn;
            const flag = key.replace(info.keyBase, "");
            switch (key) {
              case settings.isCarousel.key:
                item = settings.isCarousel;
                break;
              case settings.isAutoLayout.key:
                item = settings.isAutoLayout;
                break;
              case settings.isClearAd.key:
                item = settings.isClearAd;
                break;
              case settings.isTrueEnd.key:
                item = settings.isTrueEnd;
                break;
              case settings.isLoadOne.key:
                item = settings.isLoadOne;
                break;
              case settings.videoNumRule.key:
                (item = settings.videoNumRule),
                  (verifyFn = (newVal) =>
                    newVal.replaceAll(" ", "").toLowerCase());
                break;
              case settings.delClassArr.key:
                (item = settings.delClassArr),
                  (verifyFn = (newVal) =>
                    newVal.replaceAll(" ", "").toLowerCase());
                break;
              case settings.video_isDelAd.key:
                item = settings.video_isDelAd;
                break;
              case settings.video_delSetting.key:
                (item = settings.video_delSetting),
                  (verifyFn = (newVal) =>
                    newVal.replaceAll(" ", "").toLowerCase());
            }
            if (!item) return void console.log("设置的数据对应的对象获取失败");
            changeObj[flag] = setValue({
              value,
              base: item.base,
              key,
              verification: verifyFn,
              getValue: GM_getValue,
              setValue: GM_setValue,
            });
          }
        }
        getData();
        const changeArr = (function getTrueArr(obj) {
          const arr = [];
          for (const key in obj) obj[key] && arr.push(key);
          return arr;
        })(changeObj);
        if ("视频" === info.pageName)
          (changeArr.includes("video_delSetting") ||
            changeArr.includes("video_isDelAd")) &&
            (videoObj.updateData(),
            videoObj.getAd(),
            settings.video_isDelAd.value
              ? videoObj.delAd()
              : videoObj.showAd());
        else if ("首页" === info.pageName) {
          (function hasCommonItems(arr1, arr2) {
            for (let i = 0; i < arr1.length; i++)
              if (arr2.includes(arr1[i])) return !0;
            return !1;
          })(changeArr, [
            "isCarousel",
            "isAutoLayout",
            "isClearAd",
            "isTrueEnd",
            "isLoadOne",
          ])
            ? main(!1)
            : (updateData(),
              changeArr.includes("videoNumRule") &&
                (function rearrange(rule) {
                  (videoNumRule = getVideoNumRule(rule)),
                    zoomPage(),
                    setStyle();
                })(settings.videoNumRule.value),
              changeArr.includes("delClassArr") &&
                (function updateVideo(delClass) {
                  (delClassArr = getDelClassArr(delClass)),
                    delAd(getAd(queryNum, delClassArr, newVideoNum, 1), vDom);
                })(settings.delClassArr.value));
        }
      },
    };
    showEditArea(!0, callback);
  }
  let pageName = (function getBiliPageType(location) {
    const url = location.href;
    return ("www.bilibili.com" !== location.host &&
      "www.bilibili.com" !== location.hostname) ||
      ("/" !== location.pathname && "/index.html" !== location.pathname)
      ? url.includes("www.bilibili.com/video")
        ? "视频"
        : url.includes("space.bilibili.com")
        ? "主页"
        : url.includes("t.bilibili.com") ||
          url.includes("www.bilibili.com/opus")
        ? "动态"
        : url.includes("www.bilibili.com/read")
        ? "专栏"
        : url.includes("www.bilibili.com/bangumi")
        ? "番剧"
        : url.includes("live.bilibili.com")
        ? "直播"
        : ("message.bilibili.com" !== url.host &&
            "message.bilibili.com" !== location.hostname) ||
          "/" !== location.pathname
        ? "其他"
        : "消息"
      : "首页";
  })(window.location);
  if (
    ((info.pageName = pageName),
    ("首页" !== pageName && "视频" !== pageName) ||
      (getData(),
      GM_registerMenuCommand("设置", () => {
        showSettings();
      })),
    "首页" === pageName)
  )
    main();
  else if ("视频" === pageName) {
    setTimeout(() => {
      videoObj.init();
    }, videoObj.info.startTime);
    let url = window.location.href;
    const pathInterval = videoObj.info.pathInterval;
    setInterval(() => {
      url !== window.location.href &&
        ((url = window.location.href),
        setTimeout(() => {
          videoObj.init();
        }, videoObj.info.startTime));
    }, pathInterval);
  }
})();