劫持自动跳转登录,修复用户主页正确跳转,伪装客户端,可查看名人堂日程表,解锁视频清晰度(1080p、2K、2K-60、4K、4K-60)
// ==UserScript== // @name 【移动端】微博优化 // @namespace https://github.com/WhiteSevs/TamperMonkeyScript // @version 2025.3.18 // @author WhiteSevs // @description 劫持自动跳转登录,修复用户主页正确跳转,伪装客户端,可查看名人堂日程表,解锁视频清晰度(1080p、2K、2K-60、4K、4K-60) // @license GPL-3.0-only // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAAAXNSR0IArs4c6QAAFxNJREFUeF7tXQl4XMWR/uu9kQ+N5IDQSPNGskZ2DBhzfuFcwhKbw9xXbI8xBMIVYJ0EkgCBJeyGLARCwgKLsUkAh2O5JAUwJsByBTYsy9rchMtgbI0szxsdFgmWhCXNvFq1ZuSMNMfrd4wkS9Pfp898vKrqqup/+vWrrq4mFNqE9gBNaOsLxqMAgAkOggIACgCY4B6Y4OYXZoACACa4Bya4+YUZoACACe6BCW5+YQYoAGCCe2CCm1+YAQoAmOAemODmF2aAAgAmuAdcNv+rR/y1cTU+lxi7AZgGoJQIpQBPY1AHMzUrqrEJTM0xpmaPGttUvKCj2WU1pMUVZgBpV2Un7K73LWbC4WAcDmAvOyKJ8Lhh0BPUa7zkPatdtyPDDk8BAHa8luTpqqs4FcTXANjfgZg0VmY8pyj8AhP9ybuw7R03ZQ+XVQCATe/2/KFin5jBzwOotClClu1xI87LSpe0vyLLYIWuAAAr3kqh7az3XUXAjTbZrbMx7uE4LSs5o/V968zZOQoAsOnNrjrf0yAcb5PdLttXzLxMIb69OLRls10hqXwFANj0YndDxS3M/GOb7I7YCPgcoCuKQ61POBIEFFLC7Dqwq6H8RDA9ZZffFT7ia72L2n/hRFZhBnDgvc66ioeJeIkDEW6wPuENtX3brqACAOx6Lsm3ta78WkXBQjDtmfxfHwNYA9BaYrwf53gHGWrHJ1tbO3bzVU1TYrEAiDUwB0DQiPkggOYC2MmuKuKVUBxqm2WHvwAAO17LA093XcU3SeHDjUQw6VirXTC4oyTUvotVvgIArHpsBOi76yoWGMTfJ2Cele6Y+aGSxe3fscJTAIAVb40wbWed77sEfB+EA+W7pqXeUOudsvQFAMh6ahTpOuvLHyDQWfIq8CneUPtqGfoCAGS8NAZouhp8y8FYKqOKWA8QMN8ban/LjH6HBkAkEChWiugQMHvjCrwqoxgMr6HAS4xOVVWeq9jQ/JmZE3aU51315RcC9DsZfRl4oSTUNt+MdocDQKRG218hHMOAMO5bZgYCeIeAV4piyi27bN48avvuEnpKkWxrqJgfZ35Oihjm64EdAgD6dP+BpNKZzDgKwOD3tpwP/k7VDualWlO0wSrjWKPvbCg/k5geNNOLCBt4Gx+WK79gTAMgMl07nIjOA/F3zYyVfU6g8/3hyO9l6e3QffHETjtN6p00lxT+FjMOosSWsfgjBtog/hhvQOFnizn+KoW++JvVfgYCUEQ/N+Nj0C0lodbLstGNSQBEpgfmE+F8EIfMDLTznMg4xN/YssYOrxlP58MVlfDw8wTsY0abfB4xmO9WPPidd4G1TKDOuvIHiehMs34U4B+nhtr+JxPdmAJA4hfPl4HoZDOjHD5fo4X1QxzKyMjeVe/7I4ATbMiOQKHrvAtbfyvL2/t4xb59MawFeFJuHlrtDbWeMqYBoNcErgT4ehA8sg5wQsfAnEBYF3F7V1tXvY+dCDSYf1G6uP1aWRmy29Kqqnx9yoKWDcPljvoMEK2u3JsVun4EfvVDbCemS/1NkdtlHS1L5xQAA/0Qn+Rd1C5mEtP2t3rfLA9oDcBluYiJcEnxorZlYwoAkRrtIiJcB8BnaqnLBOKXVtUUlf6lyXbfVedbDkoL2PQBWAeCAcauAKaaySMYBxeHtqw1oxPPuxoq/g3M/2JC+6w31JaWwTQqM8DG2topU4ze37q5updxVCpNvgAg+hArdPGvouBNVVE/Gj71bqsv390gOpUZv8qh97u9RX3zdj7tr381s+3LR8t3UxVaZ0bXg9hOZcO+OEYcAK21Pn+cPffa2fI0M9DKcyJc7W/URy6pM4NyWx8pn6uoVJ9tBiTCbcWL2qTSzrobKl5k5iNz+UABnT011PqfqTQjCoBIbWA2mJ8kDJyaGd1GfK7WGL1vdJVI9N7VUP5BSkLJEJUYOK4k1PZfZnp211VczsS/yUnHeMy7uG3hqAAgWlt5CLPyupkhI/VcUeiYyo0Rkdc/6q17Vdl07lWbMinCzDeXLG6/wkzJrkfKA1DJLFP4bW+obcghlhGZAaK1gSXM/LCZESP6nHiG1hhtHNE+c3TWXe/7AQNpq3QAaYOWTUx3g+9lZoj0soyNiMPFi9prR3QGiAS16wgQx6fGUuvSwnqJFYX0WX4fYtgTjDmAsifAc5L7Etu/YAgcAeGtuIG3CfRUoEk33Y4d1EEcKjXU+MZMOhWjbTKF0Gumr1mSKgGdxaG20hEDQKRGu40Il5opPuLPCW9ojfpBZv3qNf45BhBSiMR7084m1McALdfCkeVmfYnnnfW+jwjYYzgtxeM1xUs6NpnJ6K6ruJlFJDVHKy752hQ6fn3PIEneXgF60L8SoPPMlB6l569oYT1jvl3bjMDusThOIeKT+/fUv+mGfrKfnF31PvF1dE5anwof6F3Y/qaZLp115ZcR0c056eJc5V3SHskrAPSgJj5tFpkpPIrPG7WwPmOw/9bq6lmGYhzHxMf1p3SLP/cbc8hsK7qrznc3CBekdW4YB3lP3/KGmVLddeVLmCjnWouh7FMSavlL3gCgB7VnR/sb38xRyeeJ07aEXcDYW5LHIRmfoIWjz2QT0tXgew+cvouoxNUZU5eYL1iTcYWXcylpxHle6kljV18B0VrteWYc7dBL45adgLv9Yf3CTAZyffXUbvR0Z3q2dZtS4j+7pcvMMV0N5ReA6e7cdHxAaq6gawDQg9ofACwwU3KCP2/fRpN3ndHYmBbezfHr3egNtc2U8VtnXflNRPTTXLSqwbtPOb39U1dfAdGg/3YG/VBGyYlOw0SnBRojq4b7ISsAGPd4F7d9T8ZvXfW+xwDkPieociA18cTxDKDXBH4K4ptkFCzQANm+CLIBgJnPKFnc/oiM7zrrfOuIcofZu7fyNN/57VtdmQEiwcAZBH5IRrkCTcIDuT4Juxt8i5ghvqC208omh7StLC8tLqUvzfzsDbUN+dHbngH0Wn8tmMSKc0ho0UyBif6cgcsCYf2WbH7oavAdZxh8MBGtKgm1vSvrL5kvAABveUNtB6TKtA+AmsC9IE4PWshqPEHpFKbDKpsir7ltvlQQCHSXN9R6kWMA6LX+c8AkolaFZs0DX24u18sPeAsiQ8jVJpcmzhd5Q+13OQJAYep3Mm70tBaOnOhEQvZXR8VSMJvsOQyNAQhZll8BYzzGnw/fuiaTiE73N0bqXBOYIqinvmxODOqH2WVnTg23BIBIUDut/8DD4/kwQEYmY2BL9C9EHIGhbAFxBwMdRNxhgDs8hrqFgakMo4wU2tlgKiMYOzPEv9g5uWBN222T6dsFmje1sG7hnL/1Hrvqyu8E0cXpnLQ2HvOcMO2MSPvwZ9IA4LnwRDdq4nTJwdZVs8URBvARQB+BjA/ipL5TvXHze7YkpTBtqq6e6imK7U2GsheY92bivQESewEVTmXn5Ge6UmuK/DqvfSQTUhUiETgKDBxBA+7yKMaDkxdu+SRT39IAiAa1nzFwfZ4N+BjEqxVWVleGI/+b576GiB+Y3QingnGaqPDtdt9EdIa/MSIV0HHad/SBSm/ppNgcmR1EKQA0z6jaVzWMV/PhGABRIqyGYTzlb2qROgzh1EG5+DdVV1d5VONUwDgNoJxZtlb0YGAdEV+sNUbzUvPXii6ptFIAiAS1hwlwtR4egd4n4hVFyrZHyzZYPx1r12ArfPoM/0Fk0IUMnG+Fz4RWHM96ixmroeLVwEZdvOpGrZkCIFpTdSST8aJ7GvJ6JlqhebwraP3fU5Pck+++pEhN4DAQL3X7R5DQlJczKXcEGiMZ39HuWzNUojkAgv6V7EpqF0cYtKKPi1YEm5q+yLdh+ZAvjq0PAIGQ8aStgz63EuOOPkNdPr252Sy120E36aw5AdA6s3rXeDwuypNPcdIrMZ4kjl9Wuan1cydyxgpvtFb7ETNudV8f+pzBVwTCuuMi0LK65QTA5hq/VBWKXJ0xcEMgrP9MViGLdDUeYGYMEO/VjAcrLMqTJo9OD5wMhe/iPFwYIZtEKq1sDsKsAOBZsyZH+7rEr9/2MS4D+F5VWL/HqaKTgVkxYD8C9gWwX1InkSWTWksghgQQxCHJNQy8VwR8uA3ImGvvVKdBfr1WWwu2UshRrueRAkFWALTUaGcZhAfk1E2nMpiOrmqKOFo8FmHAsZcz4KRUjJhO74gBf7JrixmfGzNlpj5GAgRZAaAHNfP0omyeYb5Wa4o6qWO/kwe4qj+wJQ45uFIxhIF7FeA/+gDH0cRMZuu12v1gnG0GFqvPmXBsoFGXLAtnVXqWzaBN1dW7etS4KJ+iWheJx7SwPuQEqhUZKnAqAaL6lZjq3W4iHeaqPiAvVcL0oCaCZYe5rPSbk4p6jtxlfYdpto+dfjPOAHrQfzlAuY8aZ+qN8KrWqIty57aaBwMr6x/ZYrbAxMCKuCjC7HJrml7x9UmK8mcGiTi8a42BawJh/ZeuCUwRlAUA1pEsDkbGFeWIqo0R00oVmQwpAup5BE8TEdDQ52xtkXE88rRj+qk/ru5Hzc1fuQ2CNABEZmhBMmD52LSTBctID/6gE/MFAj2oiVzJrMe07QwiE/4p0KhLl5CT7SMNAK212rFxhjjeJd3Er19F7ABf2FqhQ9GBBwN1cq6U7sx9wptiiQWna21zMHC+Anb8+TtUIX5UC0dd3Y8R8tMAoAf9lwEmJ0yHucrur1985vUXfRbbvq6s9G2OYIyAQ/sA08OXsvI/nDNnUlnXFyKj18XkE/pcC0ds3QuUS+/0V4DFnT8nv/4ioM7hN77smOSkI6C+D1jsirCkkEhQu5oAVxduHvQF7MyylgCgB/3vASRb51ZMIU/4w7rla8uKgP0ZMD3z7uagmMg6Nga49r3dFtS+EQOkK4RI2Uk8z+18ggyvAE0cG7JQPoWXa+HoD6QMSCHyJN77uerkWRUJBu4j4H5OXMH27wRIHapMvgsf7gNMCy/LKhWtrPTyFEVUAbcTS8ncTb4B0DKjotIw1KiskQOOs1lvz5OIyEnPNGY6EfBQH7D9xixPYhUuyqtNNuMdfB5LAMdy6fZs8vWgJvb4d5ft35Qu3wDYHAwcqoCtnVqxV2+v3JNIWJRtYo9clDURhZm8mZgYOCkODEkp8wDihpAq2U4YOCEOZC3gICtnkE4Pak8DLl4wnW8ARGq0s8jiBpCdenueRO2djPXrU5zcRcA/K8AzPQOXJSfaJGAfcb6OkRZ3nxcDUvPtaj0WdwKFzDgwpJKm1UFPpdeDgV8DbFrjT7YPQ6HZdgNt2foYsgaws6vFwMJAWBcbR9KtCDiPgZU5GJ5RgUt7gPXZaIqAIXX1CLikL6XOXv93pajXa3qjRqp8An7SlwhHu9J0l89Pdnh3nrznRx+ZlouzovwQANg780c/1MKRO6x06gFEFYtsNQW6FOCQXuADM5lFwMX9CRmplyRewYB47y6gTNW2zAQC18Rc/HTTg/7XAXLrYopmLaxPNzfBGsVwAMxNHvmWlkKMG/1N+tXSDIll8bcJyDZr3BADpDOIPBiIWlq+azeTvgQs7RsKKCtmpdHqQa3VtVL4DjfapF4BkUCgnIrYyuJMxBIf0Bp1S5c6ife4kWVfXgH26QW2lzEzG4EiYCkDUoUYzWT1zx6nxwFXzu4lD9G6l41kw89m9ornmSKB66xV8+aXtHBUXOdmpU3tfw1kqoj1RQzIefPF8E48wD8gEU52ox0dAxxlMQ0qEa2pPJFJecoNpYQMu+F2s/4zBYJEGpiFe2ohAjCWF4L9AyeibsNvtnwlZvHGbGGgZ0AFx21LDCh3LCUpwFFGVQYlPAYO9G3SXY+cpgGgJagtMABR8s1Ke1kL60dYYSgCxImb4degjuYMcGsM+IkVG7LR6rV+y2up3P3yei0cFVfNuN7SAPDm/iiqah+IYEmHUQe0Ij5Ha4zeL6vhlEQ6d9o5gdFaAxCwn1v5gu7nB/IyLRy9RNa3VugyZgRFg9r1bGElngCAXAXuVOU8idPGw1f8t8UAqWtSktO/G18Bv4y5VNI+Ml07gBT3tpYT/uLjtXDUUo6GLAgyAqB5ZtVuStx4lyRut0rtiIB7/GFdqqhhkk8sBv8bifTv7S2WCPdmLJuaSpchDiBrdyrdG7HEJdSupFtFa7XnmNPWNnb0SvLQdVo48q8OBORkzZ4WXqPdCUKGahO5VSHgBr+Fk0AqcEr/9Du8cuZbKrA4NQQ8vFc7kb5MmjNwahx40g0H68HAbwC+3A1ZiUmVX9/iLZvrdvRv2I82s7ptu5eXxrYViVWnjZNB1qasIuAiBtLy3ZL/b40KrO0FmjzAPuJOXk58pRzq1NEiGSUOuHKbeKRGu5AobVHrUMXc1cUdCk++uXNIEbd8EbOt61W1sG568njYesD1/IBcDiLggr7c+xHS/m2pCRxlEL8gzSBByMCtgbDuyleJiR9ya9NaEzgsTiwOPFhvzHtpTdEclauGilQT8fufU56rjxJwUR8wpF6edeMSHHqN/1cgcjuptUEL606Ow0mbI/UrFXfngEh6IIe8Y6yXRqtVEyDIRxXSPyd3/BynavXXS/K0BLVnGbAaBTUbnBEb/MQ6Q7IlQSDuss2YkJFbjPWVrAqcSIC4XOEkSRVzkb3CwP1xwJWLIpNVU1bYWx/ltGZEB98SAJLTnZgJRJ1A62lOxE8phnJ7pcUTwwIIyYso5lp5NXAil0B8Yv4xnv6VYQtTn82aNbk01v1jZhZ5Bo6KZmRQYMQH3zIABkHARA+JyJktLzLdZxAvqwrrb1vlL0r0OdcA9hAJnwzMTP67gYAN/Rk9GxTgAwJe6h2oMehei9Ro3yEaCFB9wz2pCUl2ttTd0kH6FZDa4WezyqaVxCb9DJz7epJsShKoj8HLQLxsLN3emUnfgbi+iEwyneyW01PkfNJf/fTqkSwJM9wGWwAYFLK5JnCUQixCuXbPwbX038ApLkh4Nl+hTjuDtqm6ukxV4wNXyJGLqeJDdCE8EIupV490UShXATAoLHkKRgCh2I7DEzws3tki3j0qYEgd9OTAW8pLkLWbgM0MulH2NlFZuXbpHM0AqZ2KTRAQrnGnhBqvByuvEfidOOjNqjxcsCAinfFt6oHM6oEgPoCBI8hiMoo1p9PnRLyym+K/n7mxtcUab/6oXQNAymvhaJX4HAbOcE1tRqe4RRsK/x+R8lrc4GaFuKPT09uxa47KGQwoeiBQ5pmi7GwYfWUGK7MIfDBA4t7gkSp6/SETVk729KzMV5UPJ352HQCDykRrKw82DOVcooGAjvTpHKvGJBeUHQASpeMTn2dlAJcB9DWr8lyjZ6yFwvf5i8tWksup3K7paCUQZLfTSFDbg0DnAgP3C22/at2uvDHO10SEVWDjSX+4JW9Vydz0Qd5mgOFKNldVVatF8ZPAJG7tFn+u5d+56RAbsnpBtIoZT6IPqwKRiGkeg40+8sYyYgBIteBlwDM76J/PTPMVonkMdu2QaN48lSK4f30jrl59VQG9Thx/ubKpRRSo3CHbqABguKdEDj0bdAwIxyjAviLCN8a82cbAiwroJWbjda0p6mqUcTRtHRMAGO4AEXOfFv9qNjPPjhvGHgowm4lmEzA7nwtKANsA/hQgcTZincH41FCV9924qmY0BzlX32MSALkUDtdUzpwMzwxD4VLV4BLxLwyllIlLFUaJQSglolIwlxJoMoN7GOgh5h5A2UYK9/Dgfw88oxY28Ck8vG60L28YDZDscAAYDSeN5z4LABjPoythWwEAEk4azyQFAIzn0ZWwrQAACSeNZ5ICAMbz6ErYVgCAhJPGM0kBAON5dCVsKwBAwknjmaQAgPE8uhK2FQAg4aTxTFIAwHgeXQnbCgCQcNJ4JikAYDyProRtBQBIOGk8kxQAMJ5HV8K2/wdoY6Xq8vNo+AAAAABJRU5ErkJggg== // @supportURL https://github.com/WhiteSevs/TamperMonkeyScript/issues // @match *://m.weibo.cn/* // @match *://huati.weibo.cn/* // @match *://h5.video.weibo.com/* // @match *://card.weibo.com/* // @match *://weibo.com/l/wblive/m/show/* // @require https://fastly.jsdelivr.net/gh/WhiteSevs/TamperMonkeyScript@86be74b83fca4fa47521cded28377b35e1d7d2ac/lib/CoverUMD/index.js // @require https://fastly.jsdelivr.net/npm/@whitesev/[email protected]/dist/index.umd.js // @require https://fastly.jsdelivr.net/npm/@whitesev/[email protected]/dist/index.umd.js // @require https://fastly.jsdelivr.net/npm/@whitesev/[email protected]/dist/index.umd.js // @require https://fastly.jsdelivr.net/npm/[email protected]/dist/index.umd.js // @connect * // @connect m.weibo.cn // @connect www.weibo.com // @connect passport.weibo.com // @grant GM_getResourceText // @grant GM_getValue // @grant GM_info // @grant GM_registerMenuCommand // @grant GM_setValue // @grant GM_unregisterMenuCommand // @grant GM_xmlhttpRequest // @grant unsafeWindow // @run-at document-start // ==/UserScript== (function (Qmsg, DOMUtils, Utils, pops) { 'use strict'; var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); var _a; var _GM_getResourceText = /* @__PURE__ */ (() => typeof GM_getResourceText != "undefined" ? GM_getResourceText : void 0)(); var _GM_getValue = /* @__PURE__ */ (() => typeof GM_getValue != "undefined" ? GM_getValue : void 0)(); var _GM_info = /* @__PURE__ */ (() => typeof GM_info != "undefined" ? GM_info : void 0)(); var _GM_registerMenuCommand = /* @__PURE__ */ (() => typeof GM_registerMenuCommand != "undefined" ? GM_registerMenuCommand : void 0)(); var _GM_setValue = /* @__PURE__ */ (() => typeof GM_setValue != "undefined" ? GM_setValue : void 0)(); var _GM_unregisterMenuCommand = /* @__PURE__ */ (() => typeof GM_unregisterMenuCommand != "undefined" ? GM_unregisterMenuCommand : void 0)(); var _GM_xmlhttpRequest = /* @__PURE__ */ (() => typeof GM_xmlhttpRequest != "undefined" ? GM_xmlhttpRequest : void 0)(); var _unsafeWindow = /* @__PURE__ */ (() => typeof unsafeWindow != "undefined" ? unsafeWindow : void 0)(); var _monkeyWindow = /* @__PURE__ */ (() => window)(); const HttpxCookieManager = { $data: { /** 是否启用 */ get enable() { return PopsPanel.getValue("httpx-use-cookie-enable"); }, /** 是否使用document.cookie */ get useDocumentCookie() { return PopsPanel.getValue("httpx-use-document-cookie"); }, cookieRule: [ { key: "httpx-cookie-weibo.com", hostname: /weibo.com/g } ] }, /** * 补充cookie末尾分号 */ fixCookieSplit(str) { if (utils.isNotNull(str) && !str.trim().endsWith(";")) { str += ";"; } return str; }, /** * 合并两个cookie */ concatCookie(targetCookie, newCookie) { if (utils.isNull(targetCookie)) { return newCookie; } targetCookie = targetCookie.trim(); newCookie = newCookie.trim(); targetCookie = this.fixCookieSplit(targetCookie); if (newCookie.startsWith(";")) { newCookie = newCookie.substring(1); } return targetCookie.concat(newCookie); }, /** * 处理cookie * @param details * @returns */ handle(details) { if (details.fetch) { return; } if (!this.$data.enable) { return; } let ownCookie = ""; let url = details.url; if (url.startsWith("//")) { url = window.location.protocol + url; } let urlObj = new URL(url); if (this.$data.useDocumentCookie && urlObj.hostname.endsWith( window.location.hostname.split(".").slice(-2).join(".") )) { ownCookie = this.concatCookie(ownCookie, document.cookie.trim()); } for (let index = 0; index < this.$data.cookieRule.length; index++) { let rule = this.$data.cookieRule[index]; if (urlObj.hostname.match(rule.hostname)) { let cookie = PopsPanel.getValue(rule.key); if (utils.isNull(cookie)) { break; } ownCookie = this.concatCookie(ownCookie, cookie); } } if (utils.isNotNull(ownCookie)) { if (details.headers && details.headers["Cookie"]) { details.headers.Cookie = this.concatCookie( details.headers.Cookie, ownCookie ); } else { details.headers["Cookie"] = ownCookie; } log.info("Httpx => 设置cookie:", details); } if (details.headers && details.headers.Cookie != null && utils.isNull(details.headers.Cookie)) { delete details.headers.Cookie; } } }; const CommonUtil = { /** * 添加屏蔽CSS * @param args * @example * addBlockCSS("") * addBlockCSS("","") * addBlockCSS(["",""]) */ addBlockCSS(...args) { let selectorList = []; if (args.length === 0) { return; } if (args.length === 1 && typeof args[0] === "string" && args[0].trim() === "") { return; } args.forEach((selector) => { if (Array.isArray(selector)) { selectorList = selectorList.concat(selector); } else { selectorList.push(selector); } }); return addStyle(`${selectorList.join(",\n")}{display: none !important;}`); }, /** * 设置GM_getResourceText的style内容 * @param resourceMapData 资源数据 * @example * setGMResourceCSS({ * keyName: "ViewerCSS", * url: "https://example.com/example.css", * }) */ setGMResourceCSS(resourceMapData) { let cssText = typeof _GM_getResourceText === "function" ? _GM_getResourceText(resourceMapData.keyName) : ""; if (typeof cssText === "string" && cssText) { addStyle(cssText); } else { CommonUtil.loadStyleLink(resourceMapData.url); } }, /** * 添加<link>标签 * @param url * @example * loadStyleLink("https://example.com/example.css") */ async loadStyleLink(url) { let $link = document.createElement("link"); $link.rel = "stylesheet"; $link.type = "text/css"; $link.href = url; domUtils.ready(() => { document.head.appendChild($link); }); }, /** * 添加<script>标签 * @param url * @example * loadStyleLink("https://example.com/example.js") */ async loadScript(url) { let $script = document.createElement("script"); $script.src = url; return new Promise((resolve) => { $script.onload = () => { resolve(null); }; (document.head || document.documentElement).appendChild($script); }); }, /** * 将url修复,例如只有search的链接修复为完整的链接 * * 注意:不包括http转https * @param url 需要修复的链接 * @example * 修复前:`/xxx/xxx?ss=ssss` * 修复后:`https://xxx.xxx.xxx/xxx/xxx?ss=ssss` * @example * 修复前:`//xxx/xxx?ss=ssss` * 修复后:`https://xxx.xxx.xxx/xxx/xxx?ss=ssss` * @example * 修复前:`https://xxx.xxx.xxx/xxx/xxx?ss=ssss` * 修复后:`https://xxx.xxx.xxx/xxx/xxx?ss=ssss` * @example * 修复前:`xxx/xxx?ss=ssss` * 修复后:`https://xxx.xxx.xxx/xxx/xxx?ss=ssss` */ fixUrl(url) { url = url.trim(); if (url.match(/^http(s|):\/\//i)) { return url; } else { if (!url.startsWith("/")) { url += "/"; } url = window.location.origin + url; return url; } }, /** * http转https * @param url 需要修复的链接 * @example * 修复前: * 修复后: * @example * 修复前: * 修复后: */ fixHttps(url) { if (url.startsWith("https://")) { return url; } if (!url.startsWith("http://")) { return url; } let urlObj = new URL(url); urlObj.protocol = "https:"; return urlObj.toString(); } }; const _SCRIPT_NAME_ = "【移动端】微博优化"; const utils = Utils.noConflict(); const domUtils = DOMUtils.noConflict(); const __pops = pops; const log = new utils.Log( _GM_info, _unsafeWindow.console || _monkeyWindow.console ); const SCRIPT_NAME = ((_a = _GM_info == null ? void 0 : _GM_info.script) == null ? void 0 : _a.name) || _SCRIPT_NAME_; const DEBUG = false; log.config({ debug: DEBUG, logMaxCount: 2e4, autoClearConsole: true, tag: true }); Qmsg.config( Object.defineProperties( { html: true, autoClose: true, showClose: false }, { position: { get() { return PopsPanel.getValue("qmsg-config-position", "bottom"); } }, maxNums: { get() { return PopsPanel.getValue("qmsg-config-maxnums", 5); } }, showReverse: { get() { return PopsPanel.getValue("qmsg-config-showreverse", true); } }, zIndex: { get() { let maxZIndex = Utils.getMaxZIndex(); let popsMaxZIndex = pops.config.InstanceUtils.getPopsMaxZIndex(maxZIndex).zIndex; return Utils.getMaxValue(maxZIndex, popsMaxZIndex) + 100; } } } ) ); const GM_Menu = new utils.GM_Menu({ GM_getValue: _GM_getValue, GM_setValue: _GM_setValue, GM_registerMenuCommand: _GM_registerMenuCommand, GM_unregisterMenuCommand: _GM_unregisterMenuCommand }); const httpx = new utils.Httpx(_GM_xmlhttpRequest); httpx.interceptors.request.use((data) => { HttpxCookieManager.handle(data); return data; }); httpx.interceptors.response.use(void 0, (data) => { log.error("拦截器-请求错误", data); if (data.type === "onabort") { Qmsg.warning("请求取消"); } else if (data.type === "onerror") { Qmsg.error("请求异常"); } else if (data.type === "ontimeout") { Qmsg.error("请求超时"); } else { Qmsg.error("其它错误"); } return data; }); httpx.config({ logDetails: DEBUG }); ({ Object: { defineProperty: _unsafeWindow.Object.defineProperty }, Function: { apply: _unsafeWindow.Function.prototype.apply, call: _unsafeWindow.Function.prototype.call }, Element: { appendChild: _unsafeWindow.Element.prototype.appendChild }, setTimeout: _unsafeWindow.setTimeout }); const addStyle = utils.addStyle.bind(utils); const $ = document.querySelector.bind(document); const $$ = document.querySelectorAll.bind(document); const KEY = "GM_Panel"; const ATTRIBUTE_INIT = "data-init"; const ATTRIBUTE_KEY = "data-key"; const ATTRIBUTE_DEFAULT_VALUE = "data-default-value"; const ATTRIBUTE_INIT_MORE_VALUE = "data-init-more-value"; const PROPS_STORAGE_API = "data-storage-api"; const WeiBoApi = { /** * 获取组件播放信息 * @param oid 格式:xxxx:xxxxxxxxxxx */ async component(oid) { let postParams = { page: "/tv/show/" + oid }; let postData = { data: JSON.stringify({ Component_Play_Playinfo: { oid } }) }; let api = `https://www.weibo.com/tv/api/component?${utils.toSearchParamsStr( postParams )}`; let response = await httpx.post(api, { data: utils.toSearchParamsStr(postData), headers: { Accept: "application/json, text/plain, */*", "Content-Type": "application/x-www-form-urlencoded", Host: "www.weibo.com", Origin: "https://www.weibo.com", "Page-Referer": postParams.page, Referer: "https://www.weibo.com" + postParams.page, "User-Agent": utils.getRandomPCUA() } }); if (!response.status) { return; } let data = utils.toJSON(response.data.responseText); if (data["code"] !== "100000") { log.info(`获取播放信息失败`, response); Qmsg.error("获取播放信息失败"); return; } let Component_Play_Playinfo = data["data"]["Component_Play_Playinfo"]; return Component_Play_Playinfo; } }; const VueUtils = { /** * 获取vue2实例 * @param element * @returns */ getVue(element) { if (element == null) { return; } return element["__vue__"] || element["__Ivue__"] || element["__IVue__"]; }, /** * 获取vue3实例 * @param element * @returns */ getVue3(element) { if (element == null) { return; } return element["__vueParentComponent"]; }, /** * 等待vue属性并进行设置 * @param $target 目标对象 * @param needSetList 需要设置的配置 */ waitVuePropToSet($target, needSetList) { if (!Array.isArray(needSetList)) { VueUtils.waitVuePropToSet($target, [needSetList]); return; } function getTarget() { let __target__ = null; if (typeof $target === "string") { __target__ = document.querySelector($target); } else if (typeof $target === "function") { __target__ = $target(); } else if ($target instanceof HTMLElement) { __target__ = $target; } return __target__; } needSetList.forEach((needSetOption) => { if (typeof needSetOption.msg === "string") { log.info(needSetOption.msg); } function checkVue() { let target = getTarget(); if (target == null) { return false; } let vueInstance = VueUtils.getVue(target); if (vueInstance == null) { return false; } let needOwnCheck = needSetOption.check(vueInstance); return Boolean(needOwnCheck); } utils.waitVueByInterval( () => { return getTarget(); }, checkVue, 250, 1e4 ).then((r###lt) => { if (!r###lt) { if (typeof needSetOption.failWait === "function") { needSetOption.failWait(true); } return; } let target = getTarget(); let vueInstance = VueUtils.getVue(target); if (vueInstance == null) { if (typeof needSetOption.failWait === "function") { needSetOption.failWait(false); } return; } needSetOption.set(vueInstance); }); }); }, /** * 观察vue属性的变化 * @param $target 目标对象 * @param key 需要观察的属性 * @param callback 监听回调 * @param watchConfig 监听配置 * @param failWait 当检测失败/超时触发该回调 */ watchVuePropChange($target, key, callback, watchConfig, failWait) { let config = utils.assign( { immediate: true, deep: false }, watchConfig || {} ); return new Promise((resolve) => { VueUtils.waitVuePropToSet($target, { check(vueInstance) { return typeof (vueInstance == null ? void 0 : vueInstance.$watch) === "function"; }, set(vueInstance) { let removeWatch = null; if (typeof key === "function") { removeWatch = vueInstance.$watch( () => { return key(vueInstance); }, (newValue, oldValue) => { callback(vueInstance, newValue, oldValue); }, config ); } else { removeWatch = vueInstance.$watch( key, (newValue, oldValue) => { callback(vueInstance, newValue, oldValue); }, config ); } resolve(removeWatch); }, failWait }); }); }, /** * 前往网址 * @param $vueNode 包含vue属性的元素 * @param path 需要跳转的路径 * @param [useRouter=false] 是否强制使用Vue的Router来进行跳转 */ goToUrl($vueNode, path, useRouter = false) { if ($vueNode == null) { Qmsg.error("跳转Url: $vueNode为空"); log.error("跳转Url: $vueNode为空:" + path); return; } let vueObj = VueUtils.getVue($vueNode); if (vueObj == null) { Qmsg.error("获取vue属性失败", { consoleLogContent: true }); return; } let $router = vueObj.$router; let isBlank = true; log.info("即将跳转URL:" + path); if (useRouter) { isBlank = false; } if (isBlank) { window.open(path, "_blank"); } else { if (path.startsWith("http") || path.startsWith("//")) { if (path.startsWith("//")) { path = window.location.protocol + path; } let urlObj = new URL(path); if (urlObj.origin === window.location.origin) { path = urlObj.pathname + urlObj.search + urlObj.hash; } else { log.info("不同域名,直接本页打开,不用Router:" + path); window.location.href = path; return; } } log.info("$router push跳转Url:" + path); $router.push(path); } }, /** * 手势返回 * @param option 配置 */ hookGestureReturnByVueRouter(option) { function popstateEvent() { log.success("触发popstate事件"); r###meBack(true); } function banBack() { log.success("监听地址改变"); option.vueInstance.$router.history.push(option.hash); domUtils.on(_unsafeWindow, "popstate", popstateEvent); } async function r###meBack(isFromPopState = false) { domUtils.off(_unsafeWindow, "popstate", popstateEvent); let callbackR###lt = option.callback(isFromPopState); if (callbackR###lt) { return; } while (1) { if (option.vueInstance.$router.history.current.hash === option.hash) { log.info("后退!"); option.vueInstance.$router.back(); await utils.sleep(250); } else { return; } } } banBack(); return { r###meBack }; } }; const VideoQualityMap_Mobile = { "流畅 360P": { label: "流畅", sign: 1, name: "mp4_ld_mp4" }, "标清 480P": { label: "标清", sign: 2, name: "mp4_hd_mp4" }, "高清 720P": { label: "高清", sign: 3, name: "mp4_720p_mp4" } }; const VideoQualityMap_PC = { "高清 1080P": { label: "超清", sign: 4, name: "mp4_1080p_mp4" }, "超清 2K": { label: "2K", sign: 5, name: "mp4_1440p_mp4" }, "超清 2K60": { label: "2K-60", sign: 6, name: "mp4_1440p_60fps_mp4" }, "超清 4K": { label: "4K", sign: 7, name: "mp4_2160p_mp4" }, "超清 4K60": { label: "4K-60", sign: 7, name: "mp4_2160p_60fps_mp4" } }; const VideoQualityMap = { ...VideoQualityMap_Mobile, ...VideoQualityMap_PC }; class WeiBoUnlockQuality { constructor() { __publicField(this, "$src", VideoQualityMap_PC); __publicField(this, "$data", { newQualityNameList: [], videoQualityMap: new utils.Dictionary() }); this.$data.newQualityNameList = []; this.$data.newQualityNameList.push(...Object.keys(this.$src)); } /** * 锁定视频清晰度 */ lockVideoQuality() { let that = this; log.info("锁定视频清晰度"); VueUtils.waitVuePropToSet(".video-player .mwb-video", [ { msg: "等待获取属性 __vue__.player.controlBar.addChild", check(vueObj) { return typeof vueObj.player.controlBar.addChild === "function"; }, set(vueObj) { let oldAddChild = vueObj.player.controlBar.addChild; let userSetQuality = PopsPanel.getValue( "weibo-common-lockVideoQuality" ); let userSetQualitySign = -1; Object.keys(VideoQualityMap).find((key) => { if (VideoQualityMap[key].name === userSetQuality) { userSetQualitySign = VideoQualityMap[key].sign; return true; } else { return false; } }); let ownAddChild = function(...args) { let name = args[0]; if (name === "qualityButton") { let qualityInfo = args[1]; log.info("锁定视频清晰度", qualityInfo); qualityInfo["qualityList"].find((item) => { if (!(item.sign === 1 && that.$data.videoQualityMap.has(item.src))) { return false; } that.$data.videoQualityMap.get(item.src).forEach((videoQualityMapInfo) => { let findIndex = qualityInfo["qualityList"].findIndex( (qualityItem) => { return qualityItem.sign === videoQualityMapInfo.sign; } ); if (findIndex === -1) { let newQuality = { label: videoQualityMapInfo.label, sign: videoQualityMapInfo.sign, src: videoQualityMapInfo.src }; log.success("添加新的视频清晰度", newQuality); qualityInfo["qualityList"].push(newQuality); } }); return true; }); if (userSetQualitySign !== -1) { let findSign = qualityInfo["qualityList"].find( (item) => item["sign"] === userSetQualitySign ); if (findSign) { qualityInfo["defaultSign"] = userSetQualitySign; } else { let signList = qualityInfo["qualityList"].map((item) => { if (item.sign <= userSetQualitySign) { return item.sign; } }).filter((item) => item); let userSetQualitySignLower = utils.getMaxValue(...signList); qualityInfo["defaultSign"] = userSetQualitySignLower; log.error( "该清晰度不存在,选择比该画质低的清晰度:" + userSetQualitySignLower ); } } else { let signList = qualityInfo["qualityList"].map( (item) => item.sign ); let maxSign = utils.getMaxValue(...signList); qualityInfo["defaultSign"] = maxSign; } } return oldAddChild.apply(this, args); }; if (oldAddChild == ownAddChild) { return; } vueObj.player.controlBar.addChild = ownAddChild; log.success("成功覆盖属性 __vue__.player.controlBar.addChild"); } } ]); } /** * 解锁更多视频清晰度 */ async unlockVideoHigherQuality() { let that = this; let taskQueue = []; $$(".weibo-media-wraps:not([data-unlock-quality])").forEach( ($ele) => { $ele.setAttribute("data-unlock-quality", "true"); let taskFunc = function() { return new Promise((resolve, reject) => { VueUtils.waitVuePropToSet($ele, [ { check(vueObj) { var _a2, _b, _c; if (typeof ((_a2 = vueObj == null ? void 0 : vueObj.item) == null ? void 0 : _a2.type) === "string" && ((_b = vueObj == null ? void 0 : vueObj.item) == null ? void 0 : _b.type) !== "video") { return true; } return typeof ((_c = vueObj == null ? void 0 : vueObj.item) == null ? void 0 : _c.object_id) === "string"; }, failWait() { resolve(); }, async set(vueObj) { try { if (vueObj.item.type !== "video") { return; } let object_id = vueObj.item.object_id; let urls = vueObj.item.urls; let componentInfo = await WeiBoApi.component(object_id); if (!componentInfo) { return; } if (!componentInfo.urls) { log.error("获取组件信息urls失败"); Qmsg.error("获取组件信息urls失败"); return; } if (typeof componentInfo.urls !== "object") { log.error("组件信息urls不是一个对象"); Qmsg.error("组件信息urls不是一个对象"); return; } if (!Object.keys(componentInfo.urls).length) { log.error("组件信息urls为空"); Qmsg.error("组件信息urls为空"); return; } Object.keys(componentInfo.urls).forEach((srcName) => { let src = componentInfo.urls[srcName]; if (that.$data.newQualityNameList.includes(srcName)) { let mapInfo = { label: that.$src[srcName].label, name: that.$src[srcName].name, sign: that.$src[srcName].sign, src }; let ld_mp4_url = urls["mp4_ld_mp4"]; if (ld_mp4_url) { if (!that.$data.videoQualityMap.has(ld_mp4_url)) { that.$data.videoQualityMap.set(ld_mp4_url, [ mapInfo ]); } else { let currentMapInfo = that.$data.videoQualityMap.get(ld_mp4_url); currentMapInfo.push(mapInfo); that.$data.videoQualityMap.set( ld_mp4_url, currentMapInfo ); } } } if (srcName in VideoQualityMap) { let newSrcInfo = VideoQualityMap[srcName]; if (newSrcInfo.name in urls) { } else { log.success("新增清晰度:", newSrcInfo); urls[newSrcInfo.name] = src; } } else { log.error("视频清晰度映射尚未补充", { srcName, src }); } }); } catch (error) { log.error(error); } finally { resolve(); } } } ]); }); }; taskQueue.push(taskFunc); } ); for (const taskIterator of taskQueue) { taskIterator(); await utils.sleep(100); } } } const UISelect = function(text, key, defaultValue, data, callback, description) { let selectData = []; if (typeof data === "function") { selectData = data(); } else { selectData = data; } let r###lt = { text, type: "select", description, attributes: {}, props: {}, getValue() { return this.props[PROPS_STORAGE_API].get(key, defaultValue); }, callback(event, isSelectedValue, isSelectedText) { let value = isSelectedValue; log.info(`选择:${isSelectedText}`); this.props[PROPS_STORAGE_API].set(key, value); if (typeof callback === "function") { callback(event, value, isSelectedText); } }, data: selectData }; Reflect.set(r###lt.attributes, ATTRIBUTE_KEY, key); Reflect.set(r###lt.attributes, ATTRIBUTE_DEFAULT_VALUE, defaultValue); Reflect.set(r###lt.props, PROPS_STORAGE_API, { get(key2, defaultValue2) { return PopsPanel.getValue(key2, defaultValue2); }, set(key2, value) { PopsPanel.setValue(key2, value); } }); return r###lt; }; const UISwitch = function(text, key, defaultValue, clickCallBack, description, afterAddToUListCallBack) { let r###lt = { text, type: "switch", description, attributes: {}, props: {}, getValue() { return Boolean( this.props[PROPS_STORAGE_API].get(key, defaultValue) ); }, callback(event, __value) { let value = Boolean(__value); log.success(`${value ? "开启" : "关闭"} ${text}`); this.props[PROPS_STORAGE_API].set(key, value); }, afterAddToUListCallBack }; Reflect.set(r###lt.attributes, ATTRIBUTE_KEY, key); Reflect.set(r###lt.attributes, ATTRIBUTE_DEFAULT_VALUE, defaultValue); Reflect.set(r###lt.props, PROPS_STORAGE_API, { get(key2, defaultValue2) { return PopsPanel.getValue(key2, defaultValue2); }, set(key2, value) { PopsPanel.setValue(key2, value); } }); return r###lt; }; const UITextArea = function(text, key, defaultValue, description, changeCallBack, placeholder = "", disabled) { let r###lt = { text, type: "textarea", attributes: {}, props: {}, description, placeholder, disabled, getValue() { return this.props[PROPS_STORAGE_API].get(key, defaultValue); }, callback(event, value) { this.props[PROPS_STORAGE_API].set(key, value); } }; Reflect.set(r###lt.attributes, ATTRIBUTE_KEY, key); Reflect.set(r###lt.attributes, ATTRIBUTE_DEFAULT_VALUE, defaultValue); Reflect.set(r###lt.props, PROPS_STORAGE_API, { get(key2, defaultValue2) { return PopsPanel.getValue(key2, defaultValue2); }, set(key2, value) { PopsPanel.setValue(key2, value); } }); return r###lt; }; const SettingUICommon = { id: "weibo-panel-config-currency", title: "通用", forms: [ { text: "", type: "forms", forms: [ { type: "deepMenu", text: "Toast配置", forms: [ { text: "", type: "forms", forms: [ UISelect( "Toast位置", "qmsg-config-position", "bottom", [ { value: "topleft", text: "左上角" }, { value: "top", text: "顶部" }, { value: "topright", text: "右上角" }, { value: "left", text: "左边" }, { value: "center", text: "中间" }, { value: "right", text: "右边" }, { value: "bottomleft", text: "左下角" }, { value: "bottom", text: "底部" }, { value: "bottomright", text: "右下角" } ], (event, isSelectValue, isSelectText) => { log.info("设置当前Qmsg弹出位置" + isSelectText); }, "Toast显示在页面九宫格的位置" ), UISelect( "最多显示的数量", "qmsg-config-maxnums", 3, [ { value: 1, text: "1" }, { value: 2, text: "2" }, { value: 3, text: "3" }, { value: 4, text: "4" }, { value: 5, text: "5" } ], void 0, "限制Toast显示的数量" ), UISwitch( "逆序弹出", "qmsg-config-showreverse", false, void 0, "修改Toast弹出的顺序" ) ] } ] }, { type: "deepMenu", text: "Cookie配置", forms: [ { text: "", type: "forms", forms: [ UISwitch( "启用", "httpx-use-cookie-enable", false, void 0, "启用后,将根据下面的配置进行添加cookie" ), UISwitch( "使用document.cookie", "httpx-use-document-cookie", false, void 0, "自动根据请求的域名来获取对应的cookie" ), UITextArea( "weibo.com", "httpx-cookie-weibo.com", "", void 0, void 0, "Cookie格式:xxx=xxxx;xxx=xxxx" ) ] } ] } ] }, { type: "forms", text: "", forms: [ { text: "功能", type: "deepMenu", forms: [ { text: "", type: "forms", forms: [ UISelect( "视频清晰度", "weibo-common-lockVideoQuality", "", [ { value: "", text: "自动" }, ...(() => { let r###lt = []; Object.keys(VideoQualityMap).forEach((name) => { let value = VideoQualityMap[name]; r###lt.push({ value: value.name, text: name }); }); return r###lt; })() ], void 0, "设置视频清晰度,默认自动,其它的清晰度将自动被删除(强制固定选择的清晰度)" ), UISwitch( "解锁更多清晰度", "weibo-common-unlockVideoHigherQuality", true, void 0, "自动请求PC端的视频清晰度,如果请求成功,将解锁更多的清晰度,如1080p、2K、2K-60、4K-60" ), UISwitch( "点击图片关闭预览", "weibo-common-clickImageToClosePreviewImage", false, void 0, "当点击图片进入预览模式时,再点击当前预览的图片可退出预览" ) ] }, { text: "函数禁用", type: "forms", forms: [ UISwitch( "navigator.serviceWorker.register", "weibo_hijack_navigator_service_worker_register", true, void 0, "禁止注册serviceWorker" ) ] } ] }, { text: "屏蔽", type: "deepMenu", forms: [ { text: "", type: "forms", forms: [ UISwitch( "【屏蔽】广告", "weibo_remove_ads", true, void 0, "包括【登录/注册按钮】、【小程序横幅推荐】" ), UISwitch( "【屏蔽】底部工具栏", "weibo_shield_bottom_bar", false, void 0, "屏蔽聊天/关注按钮" ) ] } ] }, { text: "拦截跳转", type: "deepMenu", forms: [ { text: "注意:已登录的情况下请关闭下面的功能", type: "forms", forms: [ UISwitch( "api/attitudes/create", "weibo_apply_attitudes_create", true ), UISwitch( "点赞", "weibo_apply_likes_update", true, void 0, "未登录时,拦截点赞跳转登录" ), UISwitch( "评论", "weibo_apply_comments_create", true, void 0, "未登录时,拦截评论跳转登录" ), UISwitch( "关注", "weibo_apply_friendships_create", true, void 0, "未登录时,拦截关注跳转登录" ), UISwitch( "转发", "weibo_apply_statuses_repostTimeline", true, void 0, "未登录时,拦截查看转发数据" ), UISwitch( "回复", "weibo_apply_comments_reply", true, void 0, "未登录时,拦截回复跳转登录" ), UISwitch( "优化跳转主页", "weibo_apply_profile_info", true, void 0, "未登录时,正确跳转至用户主页" ), UISwitch( "下拉加载更多评论", "weibo_apply_comments_hotflow", true, void 0, "未登录时,拦截下拉加载更多评论跳转登录" ), UISwitch( "楼中楼下拉加载更多评论", "weibo_apply_comments_hotFlowChild", true, void 0, "未登录时,拦截下拉加载更多评论跳转登录" ) ] } ] }, { text: "网络请求", type: "deepMenu", forms: [ { text: "", type: "forms", forms: [ UISwitch( "/api/config", "weibo_request_api_config", true, void 0, "Api为获取用户数据,未登录时伪装为已登录" ), UISwitch( "/comments/hot", "weibo_request_comments_hot", true, void 0, "Api为获取评论数据,未登录时伪装为成功获取评论数据" ), UISwitch( "/status/push", "weibo_request_status_push", true, void 0, "Api为获取顶部的热点新闻信息流,这里是直接清空json" ) ] } ] }, { text: "Vue-Router路由", type: "deepMenu", forms: [ { text: "", type: "forms", forms: [ UISwitch( "监听路由改变", "weibo-listenRouterChange", true, void 0, "监听路由改变,动态加载功能" ), UISwitch( "修复用户主页正确跳转", "weibo_router_profile_to_user_home", true, void 0, "可以正确跳转至用户主页" ) ] } ] } ] } ] }; const SettingUIHuaTi = { id: "weibo-panel-config-huati", title: "话题", forms: [ { text: "功能", type: "forms", forms: [ UISwitch( "伪装微博客户端", "huati_weibo_masquerade_weibo_client_app", true, void 0, "可以隐藏底部的【在微博内打开】" ) ] }, { text: "网络请求(不一定能劫持到)", type: "forms", forms: [ UISwitch( "/ajax/super/starschedule", "huati_weibo_get_more_celebrity_calendar_information", true, void 0, "Api为获取日程数据,开启后可获取正常日程数据" ) ] } ] }; const SettingUIVideo = { id: "weibo-panel-config-video", title: "视频", forms: [ { text: "功能", type: "forms", forms: [ UISelect( "视频清晰度", "weibo-video-quality", "", [ { value: "", text: "自动" }, { value: "mp4_ld_mp4", text: "流畅360p" }, { value: "mp4_hd_mp4", text: "标清480p" }, { value: "mp4_720p_mp4", text: "高清720p" }, { value: "mp4_1080p_mp4", text: "超清1080p" } ], void 0, "设置视频清晰度,默认自动,其它的清晰度将自动被删除(强制固定选择的清晰度)" ), UISwitch( "解锁1080p", "weibo-video-unlockVideo1080p", true, void 0, "请求PC端的视频1080p链接,开启该功能↑选择的1080p才会生效" ) ] }, { text: "屏蔽", type: "forms", forms: [ UISwitch( "【屏蔽】底部工具栏", "weibo_video_shield_bottom_toolbar", true ), UISwitch("【屏蔽】相关推荐", "weibo_video_shield_recommend", true), UISwitch("【屏蔽】热门评论", "weibo_video_shield_hot_comments", true) ] }, { text: "webpack", type: "forms", forms: [ UISwitch( "gotoApp", "weibo_video_webpack_gotoApp", true, void 0, "开启后阻止唤醒Scheme" ) ] } ] }; const SettingUIDetail = { id: "weibo-panel-config-detail", title: "正文", forms: [ { text: "功能", type: "forms", forms: [ UISwitch( "修改发布时间显示为绝对时间", "weibo-detail-setArticleAbsoluteTime", false, void 0, "该功能全局生效包括但不限于微博正文、首页等" ) ] } ] }; const SettingUISearch = { id: "weibo-panel-config-u", title: "搜索", forms: [ { text: "功能", type: "forms", forms: [ UISwitch("自动聚焦搜索框", "weibo-search-autoFocusSearchInput", void 0), UISwitch( "新增【新标签页打开】按钮", "weibo-search-addOpenBlankBtn", false, void 0, "在每个card下面的按钮区域添加该按钮,方便快速在新标签页中打开" ) ] } ] }; const SettingUICardArticle = { id: "weibo-panel-config-card-article", title: "头条文章", forms: [ { text: "功能", type: "forms", forms: [ UISwitch( "自动展开全文", "card_weibo_com__autoExpandFullArticle", true, void 0, "自动展开全文,屏蔽展开按钮" ), UISwitch( "修复文章作者主页正确跳转", "card_weibo_com__repairArticleUserHomeJump", true, void 0, "避免跳转至用户主页时需登录" ) ] }, { text: "屏蔽", type: "forms", forms: [ UISwitch( "【屏蔽】评论", "card_weibo_com__blockComment", false, void 0, "屏蔽评论区" ) ] } ] }; const SettingUIHome = { id: "weibo-panel-config-card-article", title: "首页", forms: [ { text: "功能", type: "forms", forms: [ UISwitch( "新增超话Tab", "weibo-home-addSupertalkTab", false, void 0, "在首页添加超话Tab,方便快速查看超话" ), UISwitch( "新增【新标签页打开】按钮", "weibo-home-addOpenBlankBtn", false, void 0, "在每个card下面的按钮区域添加该按钮,方便快速在新标签页中打开" ) ] }, { text: "网络拦截", type: "forms", forms: [ UISwitch( "过滤掉信息流广告", "weibo-request-blockArticleAds", true, void 0, '夹杂在文章中间的"微博广告"' ) ] }, { text: "屏蔽", type: "forms", forms: [ UISwitch( "屏蔽消息数量", "weibo-home-blockMessageCount", false, void 0, "即登录后右上角的消息提示数" ) ] } ] }; const SettingUIOther = { id: "weibo-panel-config-other", title: "其它", forms: [ { text: "微博热搜", type: "forms", forms: [ UISwitch( "新标签页打开", "weibo-hot-search-openBlank", false, void 0, "新标签页打开链接" ) ] } ] }; const PanelUISize = { /** * 一般设置界面的尺寸 */ setting: { get width() { return window.innerWidth < 550 ? "88vw" : "550px"; }, get height() { return window.innerHeight < 450 ? "70vh" : "450px"; } } }; const __PopsPanel__ = { data: null, on###ccessExecMenu: null, onceExec: null, listenData: null }; const PopsPanel = { /** 数据 */ $data: { /** * 菜单项的默认值 */ get data() { if (__PopsPanel__.data == null) { __PopsPanel__.data = new utils.Dictionary(); } return __PopsPanel__.data; }, /** * 成功只执行了一次的项 */ get on###ccessExecMenu() { if (__PopsPanel__.on###ccessExecMenu == null) { __PopsPanel__.on###ccessExecMenu = new utils.Dictionary(); } return __PopsPanel__.on###ccessExecMenu; }, /** * 成功只执行了一次的项 */ get onceExec() { if (__PopsPanel__.onceExec == null) { __PopsPanel__.onceExec = new utils.Dictionary(); } return __PopsPanel__.onceExec; }, /** 脚本名,一般用在设置的标题上 */ get scriptName() { return SCRIPT_NAME; }, /** 菜单项的总值在本地数据配置的键名 */ key: KEY, /** 菜单项在attributes上配置的菜单键 */ attributeKeyName: ATTRIBUTE_KEY, /** 菜单项在attributes上配置的菜单默认值 */ attributeDefaultValueName: ATTRIBUTE_DEFAULT_VALUE }, /** 监听器 */ $listener: { /** * 值改变的监听器 */ get listenData() { if (__PopsPanel__.listenData == null) { __PopsPanel__.listenData = new utils.Dictionary(); } return __PopsPanel__.listenData; } }, init() { this.initPanelDefaultValue(); this.initExtensionsMenu(); }, /** 判断是否是顶层窗口 */ isTopWindow() { return _unsafeWindow.top === _unsafeWindow.self; }, initExtensionsMenu() { if (!this.isTopWindow()) { return; } GM_Menu.add([ { key: "show_pops_panel_setting", text: "⚙ 设置", autoReload: false, isStoreValue: false, showText(text) { return text; }, callback: () => { this.showPanel(); } } ]); }, /** 初始化本地设置默认的值 */ initPanelDefaultValue() { let that = this; function initDefaultValue(config) { if (!config.attributes) { return; } let needInitConfig = {}; let key = config.attributes[ATTRIBUTE_KEY]; if (key != null) { needInitConfig[key] = config.attributes[ATTRIBUTE_DEFAULT_VALUE]; } let __attr_init__ = config.attributes[ATTRIBUTE_INIT]; if (typeof __attr_init__ === "function") { let __attr_r###lt__ = __attr_init__(); if (typeof __attr_r###lt__ === "boolean" && !__attr_r###lt__) { return; } } let initMoreValue = config.attributes[ATTRIBUTE_INIT_MORE_VALUE]; if (initMoreValue && typeof initMoreValue === "object") { Object.assign(needInitConfig, initMoreValue); } let needInitConfigList = Object.keys(needInitConfig); if (!needInitConfigList.length) { log.warn("请先配置键", config); return; } needInitConfigList.forEach((__key) => { let __defaultValue = needInitConfig[__key]; if (that.$data.data.has(__key)) { log.warn("请检查该key(已存在): " + __key); } that.$data.data.set(__key, __defaultValue); }); } function loopInitDefaultValue(configList) { for (let index = 0; index < configList.length; index++) { let configItem = configList[index]; initDefaultValue(configItem); let childForms = configItem.forms; if (childForms && Array.isArray(childForms)) { loopInitDefaultValue(childForms); } } } let contentConfigList = this.getPanelContentConfig(); for (let index = 0; index < contentConfigList.length; index++) { let leftContentConfigItem = contentConfigList[index]; if (!leftContentConfigItem.forms) { continue; } let rightContentConfigList = leftContentConfigItem.forms; if (rightContentConfigList && Array.isArray(rightContentConfigList)) { loopInitDefaultValue(rightContentConfigList); } } }, /** * 设置值 * @param key 键 * @param value 值 */ setValue(key, value) { let locaData = _GM_getValue(KEY, {}); let oldValue = locaData[key]; locaData[key] = value; _GM_setValue(KEY, locaData); if (this.$listener.listenData.has(key)) { this.$listener.listenData.get(key).callback(key, oldValue, value); } }, /** * 获取值 * @param key 键 * @param defaultValue 默认值 */ getValue(key, defaultValue) { let locaData = _GM_getValue(KEY, {}); let localValue = locaData[key]; if (localValue == null) { if (this.$data.data.has(key)) { return this.$data.data.get(key); } return defaultValue; } return localValue; }, /** * 删除值 * @param key 键 */ deleteValue(key) { let locaData = _GM_getValue(KEY, {}); let oldValue = locaData[key]; Reflect.deleteProperty(locaData, key); _GM_setValue(KEY, locaData); if (this.$listener.listenData.has(key)) { this.$listener.listenData.get(key).callback(key, oldValue, void 0); } }, /** * 监听调用setValue、deleteValue * @param key 需要监听的键 * @param callback */ addValueChangeListener(key, callback) { let listenerId = Math.random(); this.$listener.listenData.set(key, { id: listenerId, key, callback }); return listenerId; }, /** * 移除监听 * @param listenerId 监听的id */ removeValueChangeListener(listenerId) { let deleteKey = null; for (const [key, value] of this.$listener.listenData.entries()) { if (value.id === listenerId) { deleteKey = key; break; } } if (typeof deleteKey === "string") { this.$listener.listenData.delete(deleteKey); } else { console.warn("没有找到对应的监听器"); } }, /** * 主动触发菜单值改变的回调 * @param key 菜单键 * @param newValue 想要触发的新值,默认使用当前值 * @param oldValue 想要触发的旧值,默认使用当前值 */ triggerMenuValueChange(key, newValue, oldValue) { if (this.$listener.listenData.has(key)) { let listenData = this.$listener.listenData.get(key); if (typeof listenData.callback === "function") { let value = this.getValue(key); let __newValue = value; let __oldValue = value; if (typeof newValue !== "undefined" && arguments.length > 1) { __newValue = newValue; } if (typeof oldValue !== "undefined" && arguments.length > 2) { __oldValue = oldValue; } listenData.callback(key, __oldValue, __newValue); } } }, /** * 判断该键是否存在 * @param key 键 */ hasKey(key) { let locaData = _GM_getValue(KEY, {}); return key in locaData; }, /** * 自动判断菜单是否启用,然后执行回调 * @param key * @param callback 回调 * @param [isReverse=false] 逆反判断菜单启用 */ execMenu(key, callback, isReverse = false) { if (!(typeof key === "string" || typeof key === "object" && Array.isArray(key))) { throw new TypeError("key 必须是字符串或者字符串数组"); } let runKeyList = []; if (typeof key === "object" && Array.isArray(key)) { runKeyList = [...key]; } else { runKeyList.push(key); } let value = void 0; for (let index = 0; index < runKeyList.length; index++) { const runKey = runKeyList[index]; if (!this.$data.data.has(runKey)) { log.warn(`${key} 键不存在`); return; } let runValue = PopsPanel.getValue(runKey); if (isReverse) { runValue = !runValue; } if (!runValue) { break; } value = runValue; } if (value) { callback(value); } }, /** * 自动判断菜单是否启用,然后执行回调,只会执行一次 * @param key * @param callback 回调 * @param getValueFn 自定义处理获取当前值,值true是启用并执行回调,值false是不执行回调 * @param handleValueChangeFn 自定义处理值改变时的回调,值true是启用并执行回调,值false是不执行回调 */ execMenuOnce(key, callback, getValueFn, handleValueChangeFn) { if (typeof key !== "string") { throw new TypeError("key 必须是字符串"); } if (!this.$data.data.has(key)) { log.warn(`${key} 键不存在`); return; } if (this.$data.on###ccessExecMenu.has(key)) { return; } this.$data.on###ccessExecMenu.set(key, 1); let __getValue = () => { let localValue = PopsPanel.getValue(key); return typeof getValueFn === "function" ? getValueFn(key, localValue) : localValue; }; let r###ltStyleList = []; let dynamicPushStyleNode = ($style) => { let __value = __getValue(); let dynamicR###ltList = []; if ($style instanceof HTMLStyleElement) { dynamicR###ltList = [$style]; } else if (Array.isArray($style)) { dynamicR###ltList = [ ...$style.filter( (item) => item != null && item instanceof HTMLStyleElement ) ]; } if (__value) { r###ltStyleList = r###ltStyleList.concat(dynamicR###ltList); } else { for (let index = 0; index < dynamicR###ltList.length; index++) { let $css = dynamicR###ltList[index]; $css.remove(); dynamicR###ltList.splice(index, 1); index--; } } }; let changeCallBack = (currentValue) => { let r###ltList = []; if (currentValue) { let r###lt = callback(currentValue, dynamicPushStyleNode); if (r###lt instanceof HTMLStyleElement) { r###ltList = [r###lt]; } else if (Array.isArray(r###lt)) { r###ltList = [ ...r###lt.filter( (item) => item != null && item instanceof HTMLStyleElement ) ]; } } for (let index = 0; index < r###ltStyleList.length; index++) { let $css = r###ltStyleList[index]; $css.remove(); r###ltStyleList.splice(index, 1); index--; } r###ltStyleList = [...r###ltList]; }; this.addValueChangeListener( key, (__key, oldValue, newValue) => { let __newValue = newValue; if (typeof handleValueChangeFn === "function") { __newValue = handleValueChangeFn(__key, newValue, oldValue); } changeCallBack(__newValue); } ); let value = __getValue(); if (value) { changeCallBack(value); } }, /** * 父子菜单联动,自动判断菜单是否启用,然后执行回调,只会执行一次 * @param key 菜单键 * @param childKey 子菜单键 * @param callback 回调 * @param replaceValueFn 用于修改mainValue,返回undefined则不做处理 */ execInheritMenuOnce(key, childKey, callback, replaceValueFn) { let that = this; const handleInheritValue = (key2, childKey2) => { let mainValue = that.getValue(key2); let childValue = that.getValue(childKey2); if (typeof replaceValueFn === "function") { let changedMainValue = replaceValueFn(mainValue, childValue); if (changedMainValue !== void 0) { return changedMainValue; } } return mainValue; }; this.execMenuOnce( key, callback, () => { return handleInheritValue(key, childKey); }, () => { return handleInheritValue(key, childKey); } ); this.execMenuOnce( childKey, () => { }, () => false, () => { this.triggerMenuValueChange(key); return false; } ); }, /** * 根据key执行一次 * @param key */ onceExec(key, callback) { if (typeof key !== "string") { throw new TypeError("key 必须是字符串"); } if (this.$data.onceExec.has(key)) { return; } callback(); this.$data.onceExec.set(key, 1); }, /** * 显示设置面板 */ showPanel() { __pops.panel({ title: { text: `${SCRIPT_NAME}-设置`, position: "center", html: false, style: "" }, content: this.getPanelContentConfig(), mask: { enable: true, clickEvent: { toClose: true, toHide: false } }, width: PanelUISize.setting.width, height: PanelUISize.setting.height, drag: true, only: true, style: ( /*css*/ ` aside.pops-panel-aside{ width: auto !important; } .pops-panel-textarea textarea{ height: 100px; } ` ) }); }, /** * 获取配置内容 */ getPanelContentConfig() { let configList = [ SettingUICommon, SettingUIHome, SettingUIDetail, // SettingUIUserHome, SettingUISearch, SettingUIHuaTi, SettingUIVideo, SettingUICardArticle, SettingUIOther ]; return configList; } }; const blockAdsCSS$1 = "/* 底部中间的 登录/注册按钮 */\r\n#app div.main-wrap div.login-box,\r\n/* 主内容底部的小程序横幅推荐 */\r\n#app > div.lite-page-wrap > div > div.main > div > div.wrap,\r\n/* 底部悬浮的在微博内打开 */\r\n#app .woo-frame.blog-config-page div.weibo-btn-box,\r\n/* 顶部的新闻信息流 */\r\n#app .woo-frame div.woo-panel-container.news-banner,\r\n/* 夹杂在card中间的图片横幅,不确定是否会误伤其它正常内容 */\r\n.card .card-main .m-img-box > ul {\r\n display: none !important;\r\n}\r\n/* 搜索域名下的 */\r\n.card.m-panel:has(+ .simple),\r\n.card.m-panel.simple {\r\n display: none !important;\r\n}\r\n"; let _ajaxHooker_ = null; const WeiBoNetWorkHook = { get ajaxHooker() { if (_ajaxHooker_ == null) { log.info("启用ajaxHooker拦截网络"); _ajaxHooker_ = utils.ajaxHooker(); _ajaxHooker_.protect(); } return _ajaxHooker_; } }; const WeiBoHook = { /** * 劫持Function.prototype.apply; */ hookApply() { log.info("劫持Function.prototype.apply"); let originApply = _unsafeWindow.Function.prototype.apply; _unsafeWindow.Function.prototype.apply = function(...args) { var _a2, _b; let target = originApply; if (args.length !== 2) { return Reflect.apply(target, this, args); } if (args.length === 2 && !Array.isArray(args[1])) { return Reflect.apply(target, this, args); } if (typeof args[1][0] !== "string") { return Reflect.apply(target, this, args); } const ApiPath = args[1][0]; const ApiSearchParams = (_b = (_a2 = args[1]) == null ? void 0 : _a2[1]) == null ? void 0 : _b["params"]; if (ApiPath === "api/attitudes/create" && PopsPanel.getValue("weibo_apply_attitudes_create")) { log.success("拦截跳转登录"); return new Promise((resolve) => { resolve({ data: {} }); }); } else if (ApiPath === "api/likes/update" && PopsPanel.getValue("weibo_apply_likes_update")) { log.success("拦截点赞跳转登录"); return new Promise((resolve) => { resolve({ data: {} }); }); } else if (ApiPath === "api/comments/create" && PopsPanel.getValue("weibo_apply_comments_create")) { log.success("拦截评论跳转登录"); return new Promise((resolve) => { resolve({ data: {} }); }); } else if (ApiPath === "api/friendships/create" && PopsPanel.getValue("weibo_apply_friendships_create")) { log.success("拦截关注跳转登录"); return new Promise((resolve) => { resolve({ data: {} }); }); } else if (ApiPath === "api/comments/reply" && PopsPanel.getValue("weibo_apply_comments_reply")) { log.success("拦截回复跳转登录"); return new Promise((resolve, reject) => { resolve({ data: { ok: 200 } }); }); } else if (ApiPath.startsWith("profile/info") && PopsPanel.getValue("weibo_apply_profile_info")) { log.success("优化跳转xx微博主页", ApiSearchParams); let uidHomeUrl = `https://weibo.com/${ApiSearchParams["uid"]}`; log.success("跳转微博主页:" + uidHomeUrl); window.location.href = uidHomeUrl; return null; } else if (ApiPath === "comments/hotflow" && PopsPanel.getValue("weibo_apply_comments_hotflow")) { if (!("id" in ApiSearchParams && "max_id_type" in ApiSearchParams && "mid" in ApiSearchParams) || "id" in ApiSearchParams && "max_id" in ApiSearchParams && "max_id_type" in ApiSearchParams && "mid" in ApiSearchParams) { log.success("拦截下拉加载更多评论跳转登录", ApiSearchParams); return new Promise((resolve) => { resolve({ ok: 1, data: { data: [], total_number: 0 } }); }); } } else if (ApiPath === "comments/hotFlowChild" && PopsPanel.getValue("weibo_apply_comments_hotFlowChild")) { if ("max_id" in ApiSearchParams && ApiSearchParams["max_id"] !== 0) { log.success( "拦截评论中的评论下拉加载更多评论跳转登录", ApiSearchParams ); return new Promise((resolve) => { resolve({ data: { ok: 1, data: [], rootComment: [], total_number: 0 } }); }); } } else if (ApiPath === "api/statuses/repostTimeline" && PopsPanel.getValue("weibo_apply_statuses_repostTimeline")) { log.success("拦截查看转发数据,因为需登录", ApiSearchParams); return new Promise((resolve) => { resolve({ data: { ok: 1, data: { data: [], total_number: 0 } } }); }); } else ; return Reflect.apply(target, this, args); }; }, /** * 拦截网络 */ hookNetWork() { WeiBoNetWorkHook.ajaxHooker.hook(function(request) { let requestUrl = CommonUtil.fixUrl(request.url); log.info("[ajaxHookr] " + requestUrl); if (requestUrl.startsWith("https://m.weibo.cn/api/config") && PopsPanel.getValue("weibo_request_api_config")) { request.response = function(originResponse) { let originResponseData = utils.toJSON(originResponse.responseText); if (!originResponseData.data.login) { log.error("由于未登录,伪装为已登录状态"); originResponseData.data.login = true; originResponseData.data.uid = ""; originResponseData.preferQuickapp = 0; Reflect.deleteProperty(originResponseData.data, "loginUrl"); Reflect.deleteProperty(originResponseData.data, "wx_callback"); Reflect.deleteProperty(originResponseData.data, "wx_authorize"); Reflect.deleteProperty( originResponseData.data, "passport_login_url" ); originResponse.responseText = JSON.stringify(originResponseData); } }; } else if (requestUrl.startsWith("https://m.weibo.cn/comments/hot") && PopsPanel.getValue("weibo_request_comments_hot")) { request.response = function(originResponse) { let originResponseData = utils.toJSON(originResponse.responseText); if (originResponseData.ok !== 1) { log.error("由于尚未登录,获取不到更多评论数据", originResponseData); originResponseData = { ok: 1 }; originResponse.responseText = JSON.stringify(originResponseData); } }; } else if (requestUrl.startsWith("https://m.weibo.cn/status/push?") && PopsPanel.getValue("weibo_request_status_push")) { request.response = function(originResponse) { let originResponseData = utils.toJSON(originResponse.responseText); Reflect.set(originResponse, "json", {}); log.info(`重构/status/push响应`, originResponseData); originResponse.responseText = JSON.stringify(originResponseData); }; } else if (requestUrl.startsWith("https://m.weibo.cn/api/container/getIndex") && PopsPanel.getValue("weibo-request-blockArticleAds")) { request.response = function(originResponse) { var _a2; let originResponseData = utils.toJSON(originResponse.responseText); let cards = originResponseData["data"]["cards"]; if (Array.isArray(cards)) { for (let index = 0; index < cards.length; index++) { const card = cards[index]; let mblog = card == null ? void 0 : card.mblog; if (mblog) { let id = mblog.id; let ad_state = mblog == null ? void 0 : mblog.ad_state; let cardText = mblog == null ? void 0 : mblog.text; (_a2 = mblog == null ? void 0 : mblog.page_info) == null ? void 0 : _a2.page_title; if (ad_state) { cards.splice(index, 1); index--; log.info(`移除广告url:https://m.weibo.cn/detail/` + id); log.info(`移除广告card:` + cardText); } } } } originResponse.responseText = JSON.stringify(originResponseData); }; } }); }, /** * 劫持webpack * @param webpackName 当前全局变量的webpack名 * @param mainCoreData 需要劫持的webpack的顶部core,例如:(window.webpackJsonp = window.webpackJsonp || []).push([["core:0"],{}]) * @param checkCallBack 如果mainCoreData匹配上,则调用此回调函数 */ hookWebpack(webpackName = "webpackJsonp", mainCoreData, checkCallBack) { let originObject = void 0; Object.defineProperty(_unsafeWindow, webpackName, { get() { return originObject; }, set(newValue) { log.success("成功劫持webpack,当前webpack名:" + webpackName); originObject = newValue; const originPush = originObject.push; originObject.push = function(...args) { let _mainCoreData = args[0][0]; if (mainCoreData == _mainCoreData || Array.isArray(mainCoreData) && Array.isArray(_mainCoreData) && JSON.stringify(mainCoreData) === JSON.stringify(_mainCoreData)) { Object.keys(args[0][1]).forEach((keyName) => { let originSwitchFunc = args[0][1][keyName]; args[0][1][keyName] = function(..._args) { let r###lt = originSwitchFunc.call(this, ..._args); _args[0] = checkCallBack(_args[0]); return r###lt; }; }); } return originPush.call(this, ...args); }; } }); }, /** * 拦截Vue Router跳转 */ hookVueRouter() { VueUtils.waitVuePropToSet("#app", [ { msg: "等待获取属性 __vue__.$router", check(vueIns) { var _a2; return typeof ((_a2 = vueIns == null ? void 0 : vueIns.$router) == null ? void 0 : _a2.push) === "function"; }, set(vueIns) { log.success("拦截Vue路由跳转"); let beforeEachFn = (to, from, next) => { var _a2; if (to.name === "profile") { if (PopsPanel.getValue("weibo_router_profile_to_user_home")) { let uid = (_a2 = to == null ? void 0 : to.params) == null ? void 0 : _a2.uid; if (uid == null) { log.error("获取uid失败"); Qmsg.error("获取uid失败"); return; } log.success(`修复跳转${uid}微博主页`); let uidHomeUrl = `https://m.weibo.cn/u/${uid}`; window.location.href = uidHomeUrl; return; } } else if ((to == null ? void 0 : to.name) === "detail") ; next(); }; vueIns.$router.beforeEach(beforeEachFn); vueIns.$router.afterEach((to, from) => { PopsPanel.execMenu("weibo-listenRouterChange", () => { log.info("路由更新,重载功能"); WeiBo.init(); }); }); let ownHookIndex = vueIns.$router.beforeHooks.findIndex( (item) => item == beforeEachFn ); if (ownHookIndex !== -1) { let ownHook = vueIns.$router.beforeHooks.splice(ownHookIndex, 1); vueIns.$router.beforeHooks.splice(0, 0, ...ownHook); } else { log.error("$router未在beforeHooks内找到自定义的beforeEach"); } } } ]); }, /** * 禁止Service Worker注册 */ hookServiceWorkerRegister() { log.info("hook => navigator.serviceWorker.register"); _unsafeWindow.Object.defineProperty( _unsafeWindow.navigator.serviceWorker, "register", { get() { return function(...args) { log.success("劫持navigator.serviceWorker.register: ", args); }; } } ); } }; const WeiBoRouter = { /** * 移动端微博 * @returns */ isMWeiBo() { return window.location.hostname === "m.weibo.cn"; }, /** * 移动端微博-首页 */ isMWeiBoHome() { return this.isMWeiBo() && window.location.pathname === "/"; }, /** * 移动端微博-微博正文 */ isMWeiBo_detail() { return this.isMWeiBo() && window.location.pathname.startsWith("/detail/"); }, /** * 移动端微博-微博正文 */ isMWeiBo_status() { return this.isMWeiBo() && window.location.pathname.startsWith("/status/"); }, /** * 移动端微博-用户主页 */ isMWeiBo_userHome() { return this.isMWeiBo() && window.location.pathname.startsWith("/u/"); }, /** * 移动端微博-搜索 */ isMWeiBo_search() { return this.isMWeiBo() && window.location.pathname.startsWith("/search"); }, /** * 移动端微博-微博热搜 */ isMWeiBo_HotSearch() { let searchParams = new URLSearchParams(globalThis.location.search); let containerid = searchParams.get("containerid"); return this.isMWeiBo() && window.location.pathname.startsWith("/p/index") && typeof containerid === "string" && containerid.startsWith("106003"); }, /** * 话题 */ isHuaTi() { return window.location.hostname === "huati.weibo.cn"; }, /** * 视频页 */ isVideo() { return window.location.hostname === "h5.video.weibo.com"; }, /** * 头条 */ isCard() { return window.location.hostname === "card.weibo.com"; }, /** * 头条文章 */ isCardArticle() { return this.isCard() && window.location.pathname.startsWith("/article/"); }, /** * 微博直播页面 */ isLive() { return window.location.hostname === "weibo.com" && window.location.pathname.startsWith("/l/wblive/m/show/"); } }; const WeiBoHuaTi = { init() { PopsPanel.execMenu("huati_weibo_masquerade_weibo_client_app", () => { this.isWeibo(); }); PopsPanel.execMenuOnce( "huati_weibo_get_more_celebrity_calendar_information", () => { this.hookNetWorkWithGetMoreCelebrityCalendarInformation(); } ); }, /** * 伪装微博 */ isWeibo() { log.info("伪装微博"); VueUtils.waitVuePropToSet("#loadMore", [ { msg: "等待设置属性 __vue__.isWeibo", check(vueObj) { return typeof vueObj.isWeibo === "boolean"; }, set(vueObj) { vueObj.isWeibo = true; log.success("成功设置属性 __vue__.isWeibo=true"); } } ]); }, /** * 劫持请求让获取更多名人日历信息 */ hookNetWorkWithGetMoreCelebrityCalendarInformation() { WeiBoNetWorkHook.ajaxHooker.hook((request) => { log.info("ajaxHookr: ", request.url); if (!request.url.startsWith("/ajax/super/starschedule?")) { return; } request.response = async (res) => { let getResp = await httpx.get(request.url, { headers: { Host: globalThis.location.hostname, Accept: "application/json, text/plain, */*", "X-Requested-With": "XMLHttpRequest", "sec-ch-ua-mobile": "?1", "User-Agent": utils.getRandomAndroidUA() + " Weibo (__weibo__)", "sec-ch-ua-platform": "Android", "Sec-Fetch-Site": "same-origin", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Dest": "empty", Referer: globalThis.location.href, "Accept-Encoding": "gzip, deflate, br", "Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7" } }); res.response = getResp.data.responseText; res.responseText = getResp.data.responseText; }; }); } }; const WeiBoVideoHook = { init() { this.hookWebpack(); }, /** * 劫持webpack */ hookWebpack() { log.info("劫持webpack"); WeiBoHook.hookWebpack("webpackJsonp", "chunk-common", (webpackExports) => { if (typeof (webpackExports == null ? void 0 : webpackExports.exports) === "object" && typeof webpackExports.exports["a"] === "object" && typeof webpackExports.exports["a"]["gotoApp"] === "function" && PopsPanel.getValue("weibo_video_webpack_gotoApp")) { log.success("成功劫持webpack调用函数", webpackExports); webpackExports.exports["a"]["gotoApp"] = function(...args) { log.info("阻止唤醒App:", args); }; return webpackExports; } }); } }; const WeiBoVideo = { init() { PopsPanel.onceExec("weibo-video-init-hook", () => { WeiBoVideoHook.init(); }); PopsPanel.execMenuOnce("weibo_video_shield_bottom_toolbar", () => { return this.shieldBottomToolBar(); }); PopsPanel.execMenuOnce("weibo_video_shield_hot_comments", () => { return this.shieldHotComments(); }); PopsPanel.execMenuOnce("weibo_video_shield_recommend", () => { return this.shieldRecommend(); }); }, /** 【屏蔽】底部工具栏 */ shieldBottomToolBar() { log.info("【屏蔽】底部工具栏"); return CommonUtil.addBlockCSS(".woo-toolBar"); }, /** 【屏蔽】相关推荐 */ shieldRecommend() { log.info("【屏蔽】相关推荐"); return CommonUtil.addBlockCSS( '#app .woo-panel[class*="Playdetail_card_"]:nth-child(2)' ); }, /** 【屏蔽】热门评论 */ shieldHotComments() { log.info("【屏蔽】热门评论"); return CommonUtil.addBlockCSS( '#app .woo-panel[class*="Playdetail_card_"]:nth-child(3)' ); } }; const blockAdsCSS = "/* 文章内容的底部的广告 */\r\n#app .ad-wrap {\r\n display: none !important;\r\n}\r\n"; const WeiBoDetail = { init() { PopsPanel.onceExec("weibo-detail-blockAds", () => { return addStyle(blockAdsCSS); }); }, /** * 设置正文显示的时间为绝对时间 */ setArticleAbsoluteTime() { log.info(`监听并设置正文显示的时间为绝对时间`); utils.mutationObserver(document.documentElement, { config: { subtree: true, childList: true }, immediate: true, callback: () => { function handleCardMainTime() { Array.from( $$( ".card.m-panel .m-text-cut .time:not([data-gm-absolute-time])" ) ).forEach(($time) => { var _a2; let $card = $time.closest(".card.m-panel"); let cardVueIns = VueUtils.getVue($card); if (!cardVueIns) { return; } let createTime = (_a2 = cardVueIns == null ? void 0 : cardVueIns.item) == null ? void 0 : _a2.created_at; if (typeof createTime !== "string") { return; } if ($time.innerText.includes("编辑")) { return; } let createTimeObj = new Date(createTime); let formatCreateTime = utils.formatTime( createTimeObj, "yyyy-MM-dd HH:mm:ss" ); $time.innerText = formatCreateTime; $time.setAttribute("data-gm-absolute-time", "true"); }); } function handleCardLzlTime() { let $litePageWrap = $(".lite-page-wrap"); let litePageWrapVueIns = VueUtils.getVue($litePageWrap); if (litePageWrapVueIns) { let curWeiboData = litePageWrapVueIns == null ? void 0 : litePageWrapVueIns.curWeiboData; let $timeList = Array.from( $$( ".lite-page-comment .card .card-main .m-box .time" ) ); if ($timeList.length === curWeiboData.commentLists.length + 1) { $timeList.forEach(($time, index) => { if ($time.hasAttribute("data-gm-absolute-time")) { return; } if (index === 0) { let createTimeObj = new Date( curWeiboData.rootComment.created_at ); let formatCreateTime = utils.formatTime( createTimeObj, "yyyy-MM-dd HH:mm:ss" ); $time.innerText = formatCreateTime; } else { let createTimeObj = new Date( curWeiboData.commentLists[index - 1].created_at ); let formatCreateTime = utils.formatTime( createTimeObj, "yyyy-MM-dd HH:mm:ss" ); $time.innerText = formatCreateTime; } $time.setAttribute("data-gm-absolute-time", "true"); }); } else { if ($timeList.length !== 0) { log.warn("楼中楼时间设置失败,数量不一致"); } } } } function handleCardCommentTime() { Array.from( $$( ".comment-content .card .m-box .time:not([data-gm-absolute-time])" ) ).forEach(($time) => { var _a2, _b; let $card = $time.closest(".card"); let $cardParent = $card.parentElement; let cardVueIns = VueUtils.getVue($card) || VueUtils.getVue($cardParent); if (!cardVueIns) { return; } let createTime = (_a2 = cardVueIns == null ? void 0 : cardVueIns.item) == null ? void 0 : _a2.created_at; if (typeof createTime !== "string") { return; } let createTimeObj = new Date(createTime); let formatCreateTime = utils.formatTime( createTimeObj, "yyyy-MM-dd HH:mm:ss" ); $time.innerText = `${formatCreateTime} ${((_b = cardVueIns == null ? void 0 : cardVueIns.item) == null ? void 0 : _b.source) || ""}`; $time.setAttribute("data-gm-absolute-time", "true"); }); } let searchParams = new URLSearchParams(window.location.search); if (WeiBoRouter.isMWeiBo_detail() || WeiBoRouter.isMWeiBo_status()) { if (searchParams.has("cid")) { handleCardLzlTime(); } else { handleCardMainTime(); handleCardCommentTime(); } } else { handleCardMainTime(); } } }); } }; const WeiBoSearch = { init() { PopsPanel.execMenuOnce("weibo-search-addOpenBlankBtn", () => { this.addOpenBlankBtn(); }); domUtils.ready(() => { PopsPanel.execMenu("weibo-search-autoFocusSearchInput", () => { this.autoFocusSearchInput(); }); }); }, /** * 自动聚焦搜索框 */ autoFocusSearchInput() { log.info(`自动聚焦搜索框`); utils.waitNode(`.ntop-nav input[type="search"]`).then(($input) => { if (!$input) { log.error("未找到搜索框"); Qmsg.error("未找到搜索框"); return; } let searchParams = new URLSearchParams(window.location.search); if (!searchParams.has("containerid")) { log.warn("不存在containerid参数"); return; } let containeridSearchParams = new URLSearchParams( searchParams.get("containerid") ); if (containeridSearchParams.has("q")) { log.warn("containerid参数中存在q参数,是搜索结果页面"); return; } log.success( "containerid参数中不存在q参数,所以是主搜索页面,聚焦输入框" ); setTimeout(() => { $input.focus(); }, 250); }); }, /** * 新增新标签页打开按钮 */ addOpenBlankBtn() { utils.mutationObserver(document.documentElement, { config: { subtree: true, childList: true }, immediate: true, callback() { if (!WeiBoRouter.isMWeiBo_search()) { return; } document.querySelectorAll( ".card footer.m-ctrl-box:not(:has(.gm-open-blank))" ).forEach(($footerCtrl) => { if ($footerCtrl.querySelector(".gm-open-blank")) { return; } let $ownDiyBtn = domUtils.createElement("div", { innerHTML: ( /*html*/ ` <h4>新标签页打开</h4> ` ) }); $ownDiyBtn.classList.add( "m-diy-btn", "m-box-col", "m-box-center", "m-box-center-a", "gm-open-blank" ); domUtils.on($ownDiyBtn, "click", (event) => { var _a2; utils.preventEvent(event); let vueIns = VueUtils.getVue($footerCtrl); if (!vueIns) { Qmsg.error("没有找到对应的Vue实例"); return; } let id = (_a2 = vueIns == null ? void 0 : vueIns.item) == null ? void 0 : _a2.id; if (typeof id !== "string") { Qmsg.error("没有找到对应的id"); return; } let url = `${window.location.origin}/detail/${id}`; log.info(`新标签页打开:${url}`); window.open(url, "_blank"); }); let $diyBtnList = $footerCtrl.querySelectorAll(".m-diy-btn"); if ($diyBtnList.length) { domUtils.after($diyBtnList[$diyBtnList.length - 1], $ownDiyBtn); } else { domUtils.append($footerCtrl, $ownDiyBtn); } }); } }); } }; const WeiBoCardArticle = { init() { PopsPanel.execMenuOnce("card_weibo_com__autoExpandFullArticle", () => { return this.autoExpandFullArticle(); }); PopsPanel.execMenuOnce("card_weibo_com__blockComment", () => { return this.blockComment(); }); PopsPanel.execMenuOnce("card_weibo_com__repairArticleUserHomeJump", () => { this.repairArticleUserHomeJump(); }); }, /** * 自动展开全文 */ autoExpandFullArticle() { log.info("自动展开全文"); return [ addStyle( /*css*/ ` .m-container-max .f-art, .m-container-max .art-con-new{ height: unset !important; overflow: unset !important; } ` ), CommonUtil.addBlockCSS(".m-container-max .f-art-opt") ]; }, /** * 屏蔽评论 */ blockComment() { log.info("【屏蔽】评论"); return CommonUtil.addBlockCSS(".m-container-max .m-panel1"); }, /** * 修复文章用户主页跳转 */ repairArticleUserHomeJump() { log.info("修复文章用户主页跳转"); domUtils.on( document, "click", ".m-feed .f-art-user-v2", (event) => { let $click = event.target; let jQueryEventName = Object.keys($click).find( (key) => key.startsWith("jQuery") ); if (!jQueryEventName) { return; } utils.preventEvent(event); let jQueryEvent = $click[jQueryEventName]; let data = jQueryEvent["events"]["click"][0]["data"]; log.success("跳转信息:", data); let url = data["url"] || data["target_url"]; window.open(url, "_blank"); }, { capture: true } ); } }; const WeiBoHome = { init() { PopsPanel.execMenuOnce("weibo-home-blockMessageCount", () => { return this.blockMessageCount(); }); PopsPanel.execMenuOnce("weibo-home-addOpenBlankBtn", () => { this.addOpenBlankBtn(); }); domUtils.ready(() => { PopsPanel.execMenuOnce("weibo-home-addSupertalkTab", () => { this.addSupertalkTab(); }); }); }, /** * 屏蔽右上角的信息红点(登录后) */ blockMessageCount() { log.info(`屏蔽右上角的信息红点(登录后)`); return CommonUtil.addBlockCSS(".nav-right .m-bubble"); }, /** * 新增Tab - 超话 */ addSupertalkTab() { VueUtils.waitVuePropToSet(".main-top", { check(vueObj) { return Array.isArray(vueObj == null ? void 0 : vueObj.tabs); }, set(vueObj) { var _a2; log.success(`添加顶部Tab - 超话`); (_a2 = vueObj == null ? void 0 : vueObj.tabs) == null ? void 0 : _a2.push({ children: [ { api: "api/container/getIndex?containerid=100803", gid: "100803", name: "超话社区", type: 1 } ] }); return; } }); }, /** * 新增新标签页打开按钮 */ addOpenBlankBtn() { utils.mutationObserver(document.documentElement, { config: { subtree: true, childList: true }, immediate: true, callback() { if (!WeiBoRouter.isMWeiBoHome()) { return; } document.querySelectorAll( ".main-wrap .wb-item .card .f-footer-ctrl:not(:has(.gm-open-blank))" ).forEach(($footerCtrl) => { if ($footerCtrl.querySelector(".gm-open-blank")) { return; } let $ownDiyBtn = domUtils.createElement("div", { innerHTML: ( /*html*/ ` <h4>新标签页打开</h4> ` ) }); $ownDiyBtn.classList.add( "m-diy-btn", "m-box-center-a", "gm-open-blank" ); domUtils.on($ownDiyBtn, "click", (event) => { var _a2; utils.preventEvent(event); let vueIns = VueUtils.getVue($footerCtrl); if (!vueIns) { Qmsg.error("没有找到对应的Vue实例"); return; } let id = (_a2 = vueIns == null ? void 0 : vueIns.item) == null ? void 0 : _a2.id; if (typeof id !== "string") { Qmsg.error("没有找到对应的id"); return; } let url = `${window.location.origin}/detail/${id}`; log.info(`新标签页打开:${url}`); window.open(url, "_blank"); }); let $diyBtnList = $footerCtrl.querySelectorAll(".m-diy-btn"); if ($diyBtnList.length) { domUtils.after($diyBtnList[$diyBtnList.length - 1], $ownDiyBtn); } else { domUtils.append($footerCtrl, $ownDiyBtn); } }); } }); } }; const WeiBoHotSearch = { init() { PopsPanel.execMenuOnce("weibo-hot-search-openBlank", () => { this.openBlank(); }); }, /** * 新标签页打开链接 */ openBlank() { DOMUtils.on( document, "click", ".card-list .card", (event) => { utils.preventEvent(event); let vueIns = VueUtils.getVue(event.target); if (!vueIns) { log.error("没有找到对应的Vue实例", vueIns); Qmsg.error("没有找到对应的Vue实例"); return; } let carddata = vueIns == null ? void 0 : vueIns.carddata; if (typeof (carddata == null ? void 0 : carddata.scheme) !== "string") { log.error("没有找到对应的scheme", vueIns); Qmsg.error("没有找到对应的scheme"); return; } let scheme = carddata.scheme; log.success(`新标签页打开:` + scheme); window.open(scheme, "_blank"); }, { capture: true } ); } }; const blockCSS = "#app .bottombtn {\r\n display: none !important;\r\n}\r\n"; const WeiBoLive = { init() { addStyle(blockCSS); } }; const WeiBo = { $data: { weiBoUnlockQuality: new WeiBoUnlockQuality() }, init() { PopsPanel.execMenuOnce( "weibo_hijack_navigator_service_worker_register", () => { WeiBoHook.hookServiceWorkerRegister(); } ); PopsPanel.execMenuOnce("weibo-common-clickImageToClosePreviewImage", () => { this.clickImageToClosePreviewImage(); }); if (WeiBoRouter.isMWeiBo()) { log.info("Router: 移动端微博"); PopsPanel.onceExec("weibo-m-init", () => { WeiBoHook.hookNetWork(); WeiBoHook.hookApply(); WeiBoHook.hookVueRouter(); }); PopsPanel.execMenuOnce("weibo_remove_ads", () => { return this.blockAds(); }); PopsPanel.execMenuOnce("weibo_shield_bottom_bar", () => { return this.shieldBottomBar(); }); this.$data.weiBoUnlockQuality.lockVideoQuality(); domUtils.ready(() => { PopsPanel.execMenuOnce("weibo-common-unlockVideoHigherQuality", () => { this.unlockVideoHigherQuality(); }); PopsPanel.execMenuOnce("weibo-detail-setArticleAbsoluteTime", () => { WeiBoDetail.setArticleAbsoluteTime(); }); }); if (WeiBoRouter.isMWeiBoHome()) { log.info(`Router: 移动端微博-首页`); WeiBoHome.init(); } else if (WeiBoRouter.isMWeiBo_detail() || WeiBoRouter.isMWeiBo_status()) { log.info("Router: 移动端微博-正文"); WeiBoDetail.init(); } else if (WeiBoRouter.isMWeiBo_userHome()) { log.info("Router: 移动端微博-用户主页"); } else if (WeiBoRouter.isMWeiBo_search()) { log.info("Router: 移动端微博-搜索"); WeiBoSearch.init(); } else if (WeiBoRouter.isMWeiBo_HotSearch()) { log.info(`Router: 移动端微博-微博热搜`); WeiBoHotSearch.init(); } else { log.error("Router: 移动端微博未适配链接 => " + window.location.href); } } else if (WeiBoRouter.isHuaTi()) { log.info("Router: 话题"); WeiBoHuaTi.init(); } else if (WeiBoRouter.isVideo()) { log.info("Router: 视频页"); WeiBoVideo.init(); } else if (WeiBoRouter.isCard()) { log.info("Router: 头条"); if (WeiBoRouter.isCardArticle()) { log.info("Router: 头条文章"); WeiBoCardArticle.init(); } else { log.error("Router: 头条未适配链接 => " + window.location.href); } } else if (WeiBoRouter.isLive()) { log.info(`Router: 直播`); WeiBoLive.init(); } else { log.error("Router: 未适配 => " + window.location.href); } }, /** * 屏蔽 广告 */ blockAds() { log.info(`屏蔽 广告`); return addStyle(blockAdsCSS$1); }, /** * 【屏蔽】底部工具栏 */ shieldBottomBar() { log.info("【屏蔽】底部工具栏"); return CommonUtil.addBlockCSS( "#app div.m-tab-bar.m-bar-panel.m-container-max" ); }, /** * 解锁微博视频高画质 **/ unlockVideoHigherQuality() { let lock = new utils.LockFunction(() => { this.$data.weiBoUnlockQuality.unlockVideoHigherQuality(); }, 15); utils.mutationObserver(document.body, { config: { subtree: true, childList: true }, immediate: true, callback: () => { lock.run(); } }); }, /** * 设置监听事件,监听点击预览中的图片,从而关闭预览 */ clickImageToClosePreviewImage() { let selectorList = [".pswp .pswp__item"]; selectorList.forEach((selector) => { domUtils.on(document, "click", selector, (event) => { event.target; let $closeButton = $(".pswp .pswp__button--close"); if ($closeButton) { $closeButton.click(); } else { log.warn("未找到关闭预览按钮,使用history.back()"); window.history.back(); } }); }); } }; PopsPanel.init(); WeiBo.init(); })(Qmsg, DOMUtils, Utils, pops);