├── .clang-format ├── .editorconfig ├── .gitignore ├── .prettierignore ├── .prettierrc.json ├── .vscode ├── extensions.json ├── launch.json └── settings.json ├── LICENSE ├── buf.gen.yaml ├── buf.yaml ├── dist ├── 12306.request.js ├── bilibili.airborne.js ├── bilibili.json.js ├── bilibili.protobuf.js ├── missav.html.js └── zhihu.json.js ├── eslint.config.js ├── jq ├── bilibili.mine.jq └── bilibili.tab.jq ├── package.json ├── proto └── bilibili │ ├── app │ ├── card │ │ └── v1 │ │ │ └── card.proto │ ├── dynamic │ │ └── v2 │ │ │ └── dynamic.proto │ ├── interface │ │ └── v1 │ │ │ ├── search.proto │ │ │ └── teenagers.proto │ ├── playerunite │ │ ├── pgcanymodel │ │ │ └── pgcanymodel.proto │ │ └── v1 │ │ │ └── player.proto │ ├── playurl │ │ └── v1 │ │ │ └── playurl.proto │ ├── show │ │ └── popular │ │ │ └── v1 │ │ │ └── popular.proto │ ├── view │ │ └── v1 │ │ │ └── view.proto │ └── viewunite │ │ └── v1 │ │ └── view.proto │ ├── community │ └── service │ │ └── dm │ │ └── v1 │ │ └── dm.proto │ ├── main │ └── community │ │ └── reply │ │ └── v1 │ │ └── reply.proto │ ├── pgc │ └── gateway │ │ └── player │ │ └── v2 │ │ └── playurl.proto │ ├── playershared │ └── playershared.proto │ └── polymer │ └── app │ └── search │ └── v1 │ └── search.proto ├── release ├── loon │ └── plugin │ │ └── bilibili.plugin └── surge │ └── module │ ├── 12306.sgmodule │ ├── bilibili-manga.sgmodule │ ├── bilibili.sgmodule │ ├── block-ad.sgmodule │ ├── block.sgmodule │ ├── boxjs.sgmodule │ ├── dev.sgmodule │ ├── extra.sgmodule │ ├── general.sgmodule │ ├── missav.sgmodule │ ├── redirect.sgmodule │ ├── safari-search.sgmodule │ ├── scheduled-tasks.sgmodule │ ├── substore.sgmodule │ ├── weibo-intl.sgmodule │ └── youtube.sgmodule ├── src ├── script │ ├── 12306 │ │ └── 12306.request.ts │ ├── bilibili │ │ ├── bilibili.airborne.ts │ │ ├── bilibili.json.ts │ │ └── handler.ts │ ├── missav │ │ ├── missav.html │ │ ├── missav.html.ts │ │ └── missav.plugin.js │ └── zhihu │ │ └── zhihu.json.ts └── util │ └── bilibili.js └── tsconfig.json /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Google 2 | IndentWidth: 4 3 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules 3 | package-lock.json 4 | 5 | jq/test 6 | src/lib 7 | src/proto 8 | src/script/ehentai 9 | src/script/missav/input.html 10 | src/script/missav/output.html 11 | src/types 12 | src/util 13 | 14 | *.dev.ts 15 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | **/dist 2 | **/node_modules 3 | 4 | src/lib 5 | src/proto 6 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120, 3 | "tabWidth": 4, 4 | "useTabs": false, 5 | "semi": true, 6 | "singleQuote": true, 7 | "trailingComma": "es5", 8 | "bracketSpacing": true, 9 | "arrowParens": "avoid", 10 | "endOfLine": "lf", 11 | "overrides": [ 12 | { 13 | "files": ["*.yaml"], 14 | "options": { 15 | "tabWidth": 2 16 | } 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "xaver.clang-format", 4 | "dbaeumer.vscode-eslint", 5 | "christian-kohler.npm-intellisense", 6 | "christian-kohler.path-intellisense", 7 | "esbenp.prettier-vscode", 8 | "zxh404.vscode-proto3" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Debug", 6 | "type": "node", 7 | "request": "launch", 8 | "program": "${file}", 9 | "runtimeExecutable": "tsx", 10 | "runtimeArgs": ["watch"], 11 | "skipFiles": ["/**"] 12 | }, 13 | { 14 | "name": "Bilibili Protobuf", 15 | "type": "node", 16 | "request": "launch", 17 | "program": "${workspaceFolder}/src/script/bilibili/bilibili.protobuf.ts", 18 | "runtimeExecutable": "tsx", 19 | "runtimeArgs": ["watch"], 20 | "skipFiles": ["/**"] 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.rulers": [80], 3 | "editor.formatOnSave": true, 4 | "javascript.suggest.paths": false, 5 | "typescript.suggest.paths": false, 6 | "protoc": { 7 | "options": ["--proto_path=${workspaceRoot}/proto"] 8 | }, 9 | "eslint.run": "onSave", 10 | "editor.codeActionsOnSave": { 11 | "source.fixAll.eslint": "explicit" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . -------------------------------------------------------------------------------- /buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v2 2 | inputs: 3 | - directory: proto 4 | plugins: 5 | - local: protoc-gen-ts 6 | opt: 7 | - long_type_string 8 | - output_javascript 9 | out: src/proto 10 | - local: protoc-gen-es 11 | opt: 12 | - target=js+dts 13 | - import_extension=js 14 | out: src/proto 15 | -------------------------------------------------------------------------------- /buf.yaml: -------------------------------------------------------------------------------- 1 | version: v2 2 | modules: 3 | - path: proto 4 | lint: 5 | use: 6 | - BASIC 7 | -------------------------------------------------------------------------------- /dist/12306.request.js: -------------------------------------------------------------------------------- 1 | // Build: 2025/4/4 21:33:21 2 | (()=>{$done(o($request)||{});function o({url:e,headers:r,body:n}){let s={"/getAdList":()=>({response:{body:i(JSON.parse(n))}}),"/mgw.htm":()=>({abort:a(r["operation-type"])})};try{for(let t in s)if(e.endsWith(t))return s[t]();return null}catch(t){return console.log(t.toString()),null}}function i({placementNo:e}){return e==="0007"?'{"materialsList":[{"billMaterialsId":"1","filePath":"#","creativeType":1}],"advertParam":{"skipTime":1}}':e==="G0054"?'{"code":"00","materialsList":[{}]}':'{"code":"00","message":"0"}'}function a(e){return["com.cars.otsmobile.newHomePageBussData"].includes(e)}})(); 3 | -------------------------------------------------------------------------------- /dist/bilibili.airborne.js: -------------------------------------------------------------------------------- 1 | // Build: 2025/5/9 20:52:01 2 | (()=>{function U(s){let e=typeof s;if(e=="object"){if(Array.isArray(s))return"array";if(s===null)return"null"}return e}function S(s){return s!==null&&typeof s=="object"&&!Array.isArray(s)}var x="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split(""),j=[];for(let s=0;s>4,a=i,r=2;break;case 2:t[n++]=(a&15)<<4|(i&60)>>2,a=i,r=3;break;case 3:t[n++]=(a&3)<<6|i,r=0;break}}if(r==1)throw Error("invalid base64 string.");return t.subarray(0,n)}function at(s){let e="",t=0,n,r=0;for(let i=0;i>2],r=(n&3)<<4,t=1;break;case 1:e+=x[r|n>>4],r=(n&15)<<2,t=2;break;case 2:e+=x[r|n>>6],e+=x[n&63],t=0;break}return t&&(e+=x[r],e+="=",t==1&&(e+="=")),e}var p;(function(s){s.symbol=Symbol.for("protobuf-ts/unknown"),s.onRead=(t,n,r,i,a)=>{(e(n)?n[s.symbol]:n[s.symbol]=[]).push({no:r,wireType:i,data:a})},s.onWrite=(t,n,r)=>{for(let{no:i,wireType:a,data:o}of s.list(n))r.tag(i,a).raw(o)},s.list=(t,n)=>{if(e(t)){let r=t[s.symbol];return n?r.filter(i=>i.no==n):r}return[]},s.last=(t,n)=>s.list(t,n).slice(-1)[0];let e=t=>t&&Array.isArray(t[s.symbol])})(p||(p={}));var u;(function(s){s[s.Varint=0]="Varint",s[s.Bit64=1]="Bit64",s[s.LengthDelimited=2]="LengthDelimited",s[s.StartGroup=3]="StartGroup",s[s.EndGroup=4]="EndGroup",s[s.Bit32=5]="Bit32"})(u||(u={}));function lt(){let s=0,e=0;for(let n=0;n<28;n+=7){let r=this.buf[this.pos++];if(s|=(r&127)<>4,(t&128)==0)return this.assertBounds(),[s,e];for(let n=3;n<=31;n+=7){let r=this.buf[this.pos++];if(e|=(r&127)<>>i,o=!(!(a>>>7)&&e==0),l=(o?a|128:a)&255;if(t.push(l),!o)return}let n=s>>>28&15|(e&7)<<4,r=e>>3!=0;if(t.push((r?n|128:n)&255),!!r){for(let i=3;i<31;i=i+7){let a=e>>>i,o=!!(a>>>7),l=(o?a|128:a)&255;if(t.push(l),!o)return}t.push(e>>>31&1)}}var M=65536*65536;function ue(s){let e=s[0]=="-";e&&(s=s.slice(1));let t=1e6,n=0,r=0;function i(a,o){let l=Number(s.slice(a,o));r*=t,n=n*t+l,n>=M&&(r=r+(n/M|0),n=n%M)}return i(-24,-18),i(-18,-12),i(-12,-6),i(-6),[e,n,r]}function K(s,e){if(e>>>0<=2097151)return""+(M*e+(s>>>0));let t=s&16777215,n=(s>>>24|e<<8)>>>0&16777215,r=e>>16&65535,i=t+n*6777216+r*6710656,a=n+r*8147497,o=r*2,l=1e7;i>=l&&(a+=Math.floor(i/l),i%=l),a>=l&&(o+=Math.floor(a/l),a%=l);function f(h,g){let y=h?String(h):"";return g?"0000000".slice(y.length)+y:y}return f(o,0)+f(a,o)+f(i,1)}function he(s,e){if(s>=0){for(;s>127;)e.push(s&127|128),s=s>>>7;e.push(s)}else{for(let t=0;t<9;t++)e.push(s&127|128),s=s>>7;e.push(1)}}function ft(){let s=this.buf[this.pos++],e=s&127;if((s&128)==0)return this.assertBounds(),e;if(s=this.buf[this.pos++],e|=(s&127)<<7,(s&128)==0)return this.assertBounds(),e;if(s=this.buf[this.pos++],e|=(s&127)<<14,(s&128)==0)return this.assertBounds(),e;if(s=this.buf[this.pos++],e|=(s&127)<<21,(s&128)==0)return this.assertBounds(),e;s=this.buf[this.pos++],e|=(s&15)<<28;for(let t=5;(s&128)!==0&&t<10;t++)s=this.buf[this.pos++];if((s&128)!=0)throw new Error("invalid varint");return this.assertBounds(),e>>>0}var w;function Dt(){let s=new DataView(new ArrayBuffer(8));w=globalThis.BigInt!==void 0&&typeof s.getBigInt64=="function"&&typeof s.getBigUint64=="function"&&typeof s.setBigInt64=="function"&&typeof s.setBigUint64=="function"?{MIN:BigInt("-9223372036854775808"),MAX:BigInt("9223372036854775807"),UMIN:BigInt("0"),UMAX:BigInt("18446744073709551615"),C:BigInt,V:s}:void 0}Dt();function ct(s){if(!s)throw new Error("BigInt unavailable, see https://github.com/timostamm/protobuf-ts/blob/v1.0.8/MANUAL.md#bigint-support")}var ut=/^-?[0-9]+$/,G=4294967296,J=2147483648,X=class{constructor(e,t){this.lo=e|0,this.hi=t|0}isZero(){return this.lo==0&&this.hi==0}toNumber(){let e=this.hi*G+(this.lo>>>0);if(!Number.isSafeInteger(e))throw new Error("cannot convert to safe number");return e}},N=class s extends X{static from(e){if(w)switch(typeof e){case"string":if(e=="0")return this.ZERO;if(e=="")throw new Error("string is no integer");e=w.C(e);case"number":if(e===0)return this.ZERO;e=w.C(e);case"bigint":if(!e)return this.ZERO;if(ew.UMAX)throw new Error("ulong too large");return w.V.setBigUint64(0,e,!0),new s(w.V.getInt32(0,!0),w.V.getInt32(4,!0))}else switch(typeof e){case"string":if(e=="0")return this.ZERO;if(e=e.trim(),!ut.test(e))throw new Error("string is no integer");let[t,n,r]=ue(e);if(t)throw new Error("signed value for ulong");return new s(n,r);case"number":if(e==0)return this.ZERO;if(!Number.isSafeInteger(e))throw new Error("number is no integer");if(e<0)throw new Error("signed value for ulong");return new s(e,e/G)}throw new Error("unknown value "+typeof e)}toString(){return w?this.toBigInt().toString():K(this.lo,this.hi)}toBigInt(){return ct(w),w.V.setInt32(0,this.lo,!0),w.V.setInt32(4,this.hi,!0),w.V.getBigUint64(0,!0)}};N.ZERO=new N(0,0);var k=class s extends X{static from(e){if(w)switch(typeof e){case"string":if(e=="0")return this.ZERO;if(e=="")throw new Error("string is no integer");e=w.C(e);case"number":if(e===0)return this.ZERO;e=w.C(e);case"bigint":if(!e)return this.ZERO;if(ew.MAX)throw new Error("signed long too large");return w.V.setBigInt64(0,e,!0),new s(w.V.getInt32(0,!0),w.V.getInt32(4,!0))}else switch(typeof e){case"string":if(e=="0")return this.ZERO;if(e=e.trim(),!ut.test(e))throw new Error("string is no integer");let[t,n,r]=ue(e);if(t){if(r>J||r==J&&n!=0)throw new Error("signed long too small")}else if(r>=J)throw new Error("signed long too large");let i=new s(n,r);return t?i.negate():i;case"number":if(e==0)return this.ZERO;if(!Number.isSafeInteger(e))throw new Error("number is no integer");return e>0?new s(e,e/G):new s(-e,-e/G).negate()}throw new Error("unknown value "+typeof e)}isNegative(){return(this.hi&J)!==0}negate(){let e=~this.hi,t=this.lo;return t?t=~t+1:e+=1,new s(t,e)}toString(){if(w)return this.toBigInt().toString();if(this.isNegative()){let e=this.negate();return"-"+K(e.lo,e.hi)}return K(this.lo,this.hi)}toBigInt(){return ct(w),w.V.setInt32(0,this.lo,!0),w.V.setInt32(4,this.hi,!0),w.V.getBigInt64(0,!0)}};k.ZERO=new k(0,0);var ht={readUnknownField:!0,readerFactory:s=>new pe(s)};function pt(s){return s?Object.assign(Object.assign({},ht),s):ht}var pe=class{constructor(e,t){this.varint64=lt,this.uint32=ft,this.buf=e,this.len=e.length,this.pos=0,this.view=new DataView(e.buffer,e.byteOffset,e.byteLength),this.textDecoder=t??new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0})}tag(){let e=this.uint32(),t=e>>>3,n=e&7;if(t<=0||n<0||n>5)throw new Error("illegal tag: field no "+t+" wire type "+n);return[t,n]}skip(e){let t=this.pos;switch(e){case u.Varint:for(;this.buf[this.pos++]&128;);break;case u.Bit64:this.pos+=4;case u.Bit32:this.pos+=4;break;case u.LengthDelimited:let n=this.uint32();this.pos+=n;break;case u.StartGroup:let r;for(;(r=this.tag()[1])!==u.EndGroup;)this.skip(r);break;default:throw new Error("cant skip wire type "+e)}return this.assertBounds(),this.buf.subarray(t,this.pos)}assertBounds(){if(this.pos>this.len)throw new RangeError("premature EOF")}int32(){return this.uint32()|0}sint32(){let e=this.uint32();return e>>>1^-(e&1)}int64(){return new k(...this.varint64())}uint64(){return new N(...this.varint64())}sint64(){let[e,t]=this.varint64(),n=-(e&1);return e=(e>>>1|(t&1)<<31)^n,t=t>>>1^n,new k(e,t)}bool(){let[e,t]=this.varint64();return e!==0||t!==0}fixed32(){return this.view.getUint32((this.pos+=4)-4,!0)}sfixed32(){return this.view.getInt32((this.pos+=4)-4,!0)}fixed64(){return new N(this.sfixed32(),this.sfixed32())}sfixed64(){return new k(this.sfixed32(),this.sfixed32())}float(){return this.view.getFloat32((this.pos+=4)-4,!0)}double(){return this.view.getFloat64((this.pos+=8)-8,!0)}bytes(){let e=this.uint32(),t=this.pos;return this.pos+=e,this.assertBounds(),this.buf.subarray(t,t+e)}string(){return this.textDecoder.decode(this.bytes())}};function b(s,e){if(!s)throw new Error(e)}var At=34028234663852886e22,Lt=-34028234663852886e22,Wt=4294967295,_t=2147483647,Ct=-2147483648;function O(s){if(typeof s!="number")throw new Error("invalid int 32: "+typeof s);if(!Number.isInteger(s)||s>_t||sWt||s<0)throw new Error("invalid uint 32: "+s)}function V(s){if(typeof s!="number")throw new Error("invalid float 32: "+typeof s);if(Number.isFinite(s)&&(s>At||snew de};function mt(s){return s?Object.assign(Object.assign({},dt),s):dt}var de=class{constructor(e){this.stack=[],this.textEncoder=e??new TextEncoder,this.chunks=[],this.buf=[]}finish(){this.chunks.push(new Uint8Array(this.buf));let e=0;for(let r=0;r>>0)}raw(e){return this.buf.length&&(this.chunks.push(new Uint8Array(this.buf)),this.buf=[]),this.chunks.push(e),this}uint32(e){for(F(e);e>127;)this.buf.push(e&127|128),e=e>>>7;return this.buf.push(e),this}int32(e){return O(e),he(e,this.buf),this}bool(e){return this.buf.push(e?1:0),this}bytes(e){return this.uint32(e.byteLength),this.raw(e)}string(e){let t=this.textEncoder.encode(e);return this.uint32(t.byteLength),this.raw(t)}float(e){V(e);let t=new Uint8Array(4);return new DataView(t.buffer).setFloat32(0,e,!0),this.raw(t)}double(e){let t=new Uint8Array(8);return new DataView(t.buffer).setFloat64(0,e,!0),this.raw(t)}fixed32(e){F(e);let t=new Uint8Array(4);return new DataView(t.buffer).setUint32(0,e,!0),this.raw(t)}sfixed32(e){O(e);let t=new Uint8Array(4);return new DataView(t.buffer).setInt32(0,e,!0),this.raw(t)}sint32(e){return O(e),e=(e<<1^e>>31)>>>0,he(e,this.buf),this}sfixed64(e){let t=new Uint8Array(8),n=new DataView(t.buffer),r=k.from(e);return n.setInt32(0,r.lo,!0),n.setInt32(4,r.hi,!0),this.raw(t)}fixed64(e){let t=new Uint8Array(8),n=new DataView(t.buffer),r=N.from(e);return n.setInt32(0,r.lo,!0),n.setInt32(4,r.hi,!0),this.raw(t)}int64(e){let t=k.from(e);return v(t.lo,t.hi,this.buf),this}sint64(e){let t=k.from(e),n=t.hi>>31,r=t.lo<<1^n,i=(t.hi<<1|t.lo>>>31)^n;return v(r,i,this.buf),this}uint64(e){let t=N.from(e);return v(t.lo,t.hi,this.buf),this}};var bt={emitDefaultValues:!1,enumAsInteger:!1,useProtoFieldName:!1,prettySpaces:0},yt={ignoreUnknownFields:!1};function me(s){return s?Object.assign(Object.assign({},yt),s):yt}function D(s){return s?Object.assign(Object.assign({},bt),s):bt}var Y=Symbol.for("protobuf-ts/message-type");function be(s){let e=!1,t=[];for(let n=0;n!r.includes(a))||!n&&r.some(a=>!i.known.includes(a)))return!1;if(t<1)return!0;for(let a of i.oneofs){let o=e[a];if(!wt(o))return!1;if(o.oneofKind===void 0)continue;let l=this.fields.find(f=>f.localName===o.oneofKind);if(!l||!this.field(o[o.oneofKind],l,n,t))return!1}for(let a of this.fields)if(a.oneof===void 0&&!this.field(e[a.localName],a,n,t))return!1;return!0}field(e,t,n,r){let i=t.repeat;switch(t.kind){case"scalar":return e===void 0?t.opt:i?this.scalars(e,t.T,r,t.L):this.scalar(e,t.T,t.L);case"enum":return e===void 0?t.opt:i?this.scalars(e,c.INT32,r):this.scalar(e,c.INT32);case"message":return e===void 0?!0:i?this.messages(e,t.T(),n,r):this.message(e,t.T(),n,r);case"map":if(typeof e!="object"||e===null)return!1;if(r<2)return!0;if(!this.mapKeys(e,t.K,r))return!1;switch(t.V.kind){case"scalar":return this.scalars(Object.values(e),t.V.T,r,t.V.L);case"enum":return this.scalars(Object.values(e),c.INT32,r);case"message":return this.messages(Object.values(e),t.V.T(),n,r)}break}return!0}message(e,t,n,r){return n?t.isAssignable(e,r):t.is(e,r)}messages(e,t,n,r){if(!Array.isArray(e))return!1;if(r<2)return!0;if(n){for(let i=0;iparseInt(i)),t,n);case c.BOOL:return this.scalars(r.slice(0,n).map(i=>i=="true"?!0:i=="false"?!1:i),t,n);default:return this.scalars(r,t,n,T.STRING)}}};function I(s,e){switch(e){case T.BIGINT:return s.toBigInt();case T.NUMBER:return s.toNumber();default:return s.toString()}}var q=class{constructor(e){this.info=e}prepare(){var e;if(this.fMap===void 0){this.fMap={};let t=(e=this.info.fields)!==null&&e!==void 0?e:[];for(let n of t)this.fMap[n.name]=n,this.fMap[n.jsonName]=n,this.fMap[n.localName]=n}}assert(e,t,n){if(!e){let r=U(n);throw(r=="number"||r=="boolean")&&(r=n.toString()),new Error(`Cannot parse JSON ${r} for ${this.info.typeName}#${t}`)}}read(e,t,n){this.prepare();let r=[];for(let[i,a]of Object.entries(e)){let o=this.fMap[i];if(!o){if(!n.ignoreUnknownFields)throw new Error(`Found unknown field while reading ${this.info.typeName} from JSON format. JSON key: ${i}`);continue}let l=o.localName,f;if(o.oneof){if(a===null&&(o.kind!=="enum"||o.T()[0]!=="google.protobuf.NullValue"))continue;if(r.includes(o.oneof))throw new Error(`Multiple members of the oneof group "${o.oneof}" of ${this.info.typeName} are present in JSON.`);r.push(o.oneof),f=t[o.oneof]={oneofKind:l}}else f=t;if(o.kind=="map"){if(a===null)continue;this.assert(S(a),o.name,a);let h=f[l];for(let[g,y]of Object.entries(a)){this.assert(y!==null,o.name+" map value",null);let E;switch(o.V.kind){case"message":E=o.V.T().internalJsonRead(y,n);break;case"enum":if(E=this.enum(o.V.T(),y,o.name,n.ignoreUnknownFields),E===!1)continue;break;case"scalar":E=this.scalar(y,o.V.T,o.V.L,o.name);break}this.assert(E!==void 0,o.name+" map value",y);let B=g;o.K==c.BOOL&&(B=B=="true"?!0:B=="false"?!1:B),B=this.scalar(B,o.K,T.STRING,o.name).toString(),h[B]=E}}else if(o.repeat){if(a===null)continue;this.assert(Array.isArray(a),o.name,a);let h=f[l];for(let g of a){this.assert(g!==null,o.name,null);let y;switch(o.kind){case"message":y=o.T().internalJsonRead(g,n);break;case"enum":if(y=this.enum(o.T(),g,o.name,n.ignoreUnknownFields),y===!1)continue;break;case"scalar":y=this.scalar(g,o.T,o.L,o.name);break}this.assert(y!==void 0,o.name,a),h.push(y)}}else switch(o.kind){case"message":if(a===null&&o.T().typeName!="google.protobuf.Value"){this.assert(o.oneof===void 0,o.name+" (oneof member)",null);continue}f[l]=o.T().internalJsonRead(a,n,f[l]);break;case"enum":if(a===null)continue;let h=this.enum(o.T(),a,o.name,n.ignoreUnknownFields);if(h===!1)continue;f[l]=h;break;case"scalar":if(a===null)continue;f[l]=this.scalar(a,o.T,o.L,o.name);break}}}enum(e,t,n,r){if(e[0]=="google.protobuf.NullValue"&&b(t===null||t==="NULL_VALUE",`Unable to parse field ${this.info.typeName}#${n}, enum ${e[0]} only accepts null.`),t===null)return 0;switch(typeof t){case"number":return b(Number.isInteger(t),`Unable to parse field ${this.info.typeName}#${n}, enum can only be integral number, got ${t}.`),t;case"string":let i=t;e[2]&&t.substring(0,e[2].length)===e[2]&&(i=t.substring(e[2].length));let a=e[1][i];return typeof a>"u"&&r?!1:(b(typeof a=="number",`Unable to parse field ${this.info.typeName}#${n}, enum ${e[0]} has no value for "${t}".`),a)}b(!1,`Unable to parse field ${this.info.typeName}#${n}, cannot parse enum value from ${typeof t}".`)}scalar(e,t,n,r){let i;try{switch(t){case c.DOUBLE:case c.FLOAT:if(e===null)return 0;if(e==="NaN")return Number.NaN;if(e==="Infinity")return Number.POSITIVE_INFINITY;if(e==="-Infinity")return Number.NEGATIVE_INFINITY;if(e===""){i="empty string";break}if(typeof e=="string"&&e.trim().length!==e.length){i="extra whitespace";break}if(typeof e!="string"&&typeof e!="number")break;let a=Number(e);if(Number.isNaN(a)){i="not a number";break}if(!Number.isFinite(a)){i="too large or small";break}return t==c.FLOAT&&V(a),a;case c.INT32:case c.FIXED32:case c.SFIXED32:case c.SINT32:case c.UINT32:if(e===null)return 0;let o;if(typeof e=="number"?o=e:e===""?i="empty string":typeof e=="string"&&(e.trim().length!==e.length?i="extra whitespace":o=Number(e)),o===void 0)break;return t==c.UINT32?F(o):O(o),o;case c.INT64:case c.SFIXED64:case c.SINT64:if(e===null)return I(k.ZERO,n);if(typeof e!="number"&&typeof e!="string")break;return I(k.from(e),n);case c.FIXED64:case c.UINT64:if(e===null)return I(N.ZERO,n);if(typeof e!="number"&&typeof e!="string")break;return I(N.from(e),n);case c.BOOL:if(e===null)return!1;if(typeof e!="boolean")break;return e;case c.STRING:if(e===null)return"";if(typeof e!="string"){i="extra whitespace";break}try{encodeURIComponent(e)}catch(l){l="invalid UTF8";break}return e;case c.BYTES:if(e===null||e==="")return new Uint8Array(0);if(typeof e!="string")break;return ot(e)}}catch(a){i=a.message}this.assert(!1,r+(i?" - "+i:""),e)}};var z=class{constructor(e){var t;this.fields=(t=e.fields)!==null&&t!==void 0?t:[]}write(e,t){let n={},r=e;for(let i of this.fields){if(!i.oneof){let f=this.field(i,r[i.localName],t);f!==void 0&&(n[t.useProtoFieldName?i.name:i.jsonName]=f);continue}let a=r[i.oneof];if(a.oneofKind!==i.localName)continue;let o=i.kind=="scalar"||i.kind=="enum"?Object.assign(Object.assign({},t),{emitDefaultValues:!0}):t,l=this.field(i,a[i.localName],o);b(l!==void 0),n[t.useProtoFieldName?i.name:i.jsonName]=l}return n}field(e,t,n){let r;if(e.kind=="map"){b(typeof t=="object"&&t!==null);let i={};switch(e.V.kind){case"scalar":for(let[l,f]of Object.entries(t)){let h=this.scalar(e.V.T,f,e.name,!1,!0);b(h!==void 0),i[l.toString()]=h}break;case"message":let a=e.V.T();for(let[l,f]of Object.entries(t)){let h=this.message(a,f,e.name,n);b(h!==void 0),i[l.toString()]=h}break;case"enum":let o=e.V.T();for(let[l,f]of Object.entries(t)){b(f===void 0||typeof f=="number");let h=this.enum(o,f,e.name,!1,!0,n.enumAsInteger);b(h!==void 0),i[l.toString()]=h}break}(n.emitDefaultValues||Object.keys(i).length>0)&&(r=i)}else if(e.repeat){b(Array.isArray(t));let i=[];switch(e.kind){case"scalar":for(let l=0;l0||n.emitDefaultValues)&&(r=i)}else switch(e.kind){case"scalar":r=this.scalar(e.T,t,e.name,e.opt,n.emitDefaultValues);break;case"enum":r=this.enum(e.T(),t,e.name,e.opt,n.emitDefaultValues,n.enumAsInteger);break;case"message":r=this.message(e.T(),t,e.name,n);break}return r}enum(e,t,n,r,i,a){if(e[0]=="google.protobuf.NullValue")return!i&&!r?void 0:null;if(t===void 0){b(r);return}if(!(t===0&&!i&&!r))return b(typeof t=="number"),b(Number.isInteger(t)),a||!e[1].hasOwnProperty(t)?t:e[2]?e[2]+e[1][t]:e[1][t]}message(e,t,n,r){return t===void 0?r.emitDefaultValues?null:void 0:e.internalJsonWrite(t,r)}scalar(e,t,n,r,i){if(t===void 0){b(r);return}let a=i||r;switch(e){case c.INT32:case c.SFIXED32:case c.SINT32:return t===0?a?0:void 0:(O(t),t);case c.FIXED32:case c.UINT32:return t===0?a?0:void 0:(F(t),t);case c.FLOAT:V(t);case c.DOUBLE:return t===0?a?0:void 0:(b(typeof t=="number"),Number.isNaN(t)?"NaN":t===Number.POSITIVE_INFINITY?"Infinity":t===Number.NEGATIVE_INFINITY?"-Infinity":t);case c.STRING:return t===""?a?"":void 0:(b(typeof t=="string"),t);case c.BOOL:return t===!1?a?!1:void 0:(b(typeof t=="boolean"),t);case c.UINT64:case c.FIXED64:b(typeof t=="number"||typeof t=="string"||typeof t=="bigint");let o=N.from(t);return o.isZero()&&!a?void 0:o.toString();case c.INT64:case c.SFIXED64:case c.SINT64:b(typeof t=="number"||typeof t=="string"||typeof t=="bigint");let l=k.from(t);return l.isZero()&&!a?void 0:l.toString();case c.BYTES:return b(t instanceof Uint8Array),t.byteLength?at(t):a?"":void 0}}};function L(s,e=T.STRING){switch(s){case c.BOOL:return!1;case c.UINT64:case c.FIXED64:return I(N.ZERO,e);case c.INT64:case c.SFIXED64:case c.SINT64:return I(k.ZERO,e);case c.DOUBLE:case c.FLOAT:return 0;case c.BYTES:return new Uint8Array(0);case c.STRING:return"";default:return 0}}var H=class{constructor(e){this.info=e}prepare(){var e;if(!this.fieldNoToField){let t=(e=this.info.fields)!==null&&e!==void 0?e:[];this.fieldNoToField=new Map(t.map(n=>[n.no,n]))}}read(e,t,n,r){this.prepare();let i=r===void 0?e.len:e.pos+r;for(;e.post.no-n.no)}}write(e,t,n){this.prepare();for(let i of this.fields){let a,o,l=i.repeat,f=i.localName;if(i.oneof){let h=e[i.oneof];if(h.oneofKind!==f)continue;a=h[f],o=!0}else a=e[f],o=!1;switch(i.kind){case"scalar":case"enum":let h=i.kind=="enum"?c.INT32:i.T;if(l)if(b(Array.isArray(a)),l==A.PACKED)this.packed(t,h,i.no,a);else for(let g of a)this.scalar(t,h,i.no,g,!0);else a===void 0?b(i.opt):this.scalar(t,h,i.no,a,o||i.opt);break;case"message":if(l){b(Array.isArray(a));for(let g of a)this.message(t,n,i.T(),i.no,g)}else this.message(t,n,i.T(),i.no,a);break;case"map":b(typeof a=="object"&&a!==null);for(let[g,y]of Object.entries(a))this.mapEntry(t,n,i,g,y);break}}let r=n.writeUnknownFields;r!==!1&&(r===!0?p.onWrite:r)(this.info.typeName,e,t)}mapEntry(e,t,n,r,i){e.tag(n.no,u.LengthDelimited),e.fork();let a=r;switch(n.K){case c.INT32:case c.FIXED32:case c.UINT32:case c.SFIXED32:case c.SINT32:a=Number.parseInt(r);break;case c.BOOL:b(r=="true"||r=="false"),a=r=="true";break}switch(this.scalar(e,n.K,1,a,!0),n.V.kind){case"scalar":this.scalar(e,n.V.T,2,i,!0);break;case"enum":this.scalar(e,c.INT32,2,i,!0);break;case"message":this.message(e,t,n.V.T(),2,i);break}e.join()}message(e,t,n,r,i){i!==void 0&&(n.internalBinaryWrite(i,e.tag(r,u.LengthDelimited).fork(),t),e.join())}scalar(e,t,n,r,i){let[a,o,l]=this.scalarInfo(t,r);(!l||i)&&(e.tag(n,a),e[o](r))}packed(e,t,n,r){if(!r.length)return;b(t!==c.BYTES&&t!==c.STRING),e.tag(n,u.LengthDelimited),e.fork();let[,i]=this.scalarInfo(t);for(let a=0;aye}])}create(e){let t=globalThis.Object.create(this.messagePrototype);return t.streamList=[],e!==void 0&&d(this,t,e),t}internalBinaryRead(e,t,n,r){let i=r??this.create(),a=e.pos+t;for(;e.posge}])}create(e){let t=globalThis.Object.create(this.messagePrototype);return e!==void 0&&d(this,t,e),t}internalBinaryRead(e,t,n,r){let i=r??this.create(),a=e.pos+t;for(;e.poste}}])}create(e){let t=globalThis.Object.create(this.messagePrototype);return t.arcConfs={},e!==void 0&&d(this,t,e),t}internalBinaryRead(e,t,n,r){let i=r??this.create(),a=e.pos+t;for(;e.poswe},{no:4,name:"unsupport_scene",kind:"scalar",repeat:1,T:5}])}create(e){let t=globalThis.Object.create(this.messagePrototype);return t.isSupport=!1,t.disabled=!1,t.unsupportScene=[],e!==void 0&&d(this,t,e),t}internalBinaryRead(e,t,n,r){let i=r??this.create(),a=e.pos+t;for(;e.pos["bilibili.playershared.BizType",W,"BIZ_TYPE_"]}])}create(e){let t=globalThis.Object.create(this.messagePrototype);return t.videoType=0,e!==void 0&&d(this,t,e),t}internalBinaryRead(e,t,n,r){let i=r??this.create(),a=e.pos+t;for(;e.posl.typeName===n);if(!i)throw new globalThis.Error("Unable to convert google.protobuf.Any with typeUrl '"+e.typeUrl+"' to JSON. The specified type "+n+" is not available in the type registry.");let a=i.fromBinary(e.value,{readUnknownField:!1}),o=i.internalJsonWrite(a,r);return(n.startsWith("google.protobuf.")||!S(o))&&(o={value:o}),o["@type"]=e.typeUrl,o}internalJsonRead(e,t,n){if(!S(e))throw new globalThis.Error("Unable to parse google.protobuf.Any from JSON "+U(e)+".");if(typeof e["@type"]!="string"||e["@type"]=="")return this.create();let r=this.typeUrlToName(e["@type"]),i=t?.typeRegistry?.find(o=>o.typeName==r);if(!i)throw new globalThis.Error("Unable to parse google.protobuf.Any from JSON. The specified type "+r+" is not available in the type registry.");let a;if(r.startsWith("google.protobuf.")&&e.hasOwnProperty("value"))a=i.fromJson(e.value,t);else{let o=Object.assign({},e);delete o["@type"],a=i.fromJson(o,t)}return n===void 0&&(n=this.create()),n.typeUrl=e["@type"],n.value=i.toBinary(a),n}typeNameToUrl(e){if(!e.length)throw new Error("invalid type name: "+e);return"type.googleapis.com/"+e}typeUrlToName(e){if(!e.length)throw new Error("invalid type url: "+e);let t=e.lastIndexOf("/"),n=t>0?e.substring(t+1):e;if(!n.length)throw new Error("invalid type url: "+e);return n}create(e){let t=globalThis.Object.create(this.messagePrototype);return t.typeUrl="",t.value=new Uint8Array(0),e!==void 0&&d(this,t,e),t}internalBinaryRead(e,t,n,r){let i=r??this.create(),a=e.pos+t;for(;e.posne},{no:5,name:"bvid",kind:"scalar",T:9}])}create(e){let t=globalThis.Object.create(this.messagePrototype);return t.bvid="",e!==void 0&&d(this,t,e),t}internalBinaryRead(e,t,n,r){let i=r??this.create(),a=e.pos+t;for(;e.posie},{no:2,name:"play_arc_conf",kind:"message",T:()=>re},{no:5,name:"supplement",kind:"message",T:()=>ae},{no:6,name:"play_arc",kind:"message",T:()=>se},{no:9,name:"view_info",kind:"message",T:()=>oe}])}create(e){let t=globalThis.Object.create(this.messagePrototype);return e!==void 0&&d(this,t,e),t}internalBinaryRead(e,t,n,r){let i=r??this.create(),a=e.pos+t;for(;e.posPe},{no:6,name:"play_ext_conf",kind:"message",T:()=>R}])}create(e){let t=globalThis.Object.create(this.messagePrototype);return e!==void 0&&d(this,t,e),t}internalBinaryRead(e,t,n,r){let i=r??this.create(),a=e.pos+t;for(;e.posDe}])}create(e){let t=globalThis.Object.create(this.messagePrototype);return t.allowCloseSubtitle=!1,e!==void 0&&d(this,t,e),t}internalBinaryRead(e,t,n,r){let i=r??this.create(),a=e.pos+t;for(;e.posAe},{no:16,name:"vip_status",kind:"scalar",T:5},{no:18,name:"episode_info",kind:"message",T:()=>Le},{no:20,name:"user_status",kind:"message",T:()=>_e}])}create(e){let t=globalThis.Object.create(this.messagePrototype);return t.clipInfo=[],t.vipStatus=0,e!==void 0&&d(this,t,e),t}internalBinaryRead(e,t,n,r){let i=r??this.create(),a=e.pos+t;for(;e.pos["bilibili.pgc.gateway.player.v2.ClipType",_]}])}create(e){let t=globalThis.Object.create(this.messagePrototype);return t.start=0,t.end=0,t.clipType=0,e!==void 0&&d(this,t,e),t}internalBinaryRead(e,t,n,r){let i=r??this.create(),a=e.pos+t;for(;e.posWe}])}create(e){let t=globalThis.Object.create(this.messagePrototype);return t.epId=0,t.cid="0",t.aid="0",t.epStatus="0",e!==void 0&&d(this,t,e),t}internalBinaryRead(e,t,n,r){let i=r??this.create(),a=e.pos+t;for(;e.posCe}])}create(e){let t=globalThis.Object.create(this.messagePrototype);return e!==void 0&&d(this,t,e),t}internalBinaryRead(e,t,n,r){let i=r??this.create(),a=e.pos+t;for(;e.posle},{no:6,name:"play_ext_conf",kind:"message",T:()=>R}])}create(e){let t=globalThis.Object.create(this.messagePrototype);return e!==void 0&&d(this,t,e),t}internalBinaryRead(e,t,n,r){let i=r??this.create(),a=e.pos+t;for(;e.posze}])}create(e){let t=globalThis.Object.create(this.messagePrototype);return t.activityMeta=[],e!==void 0&&d(this,t,e),t}internalBinaryRead(e,t,n,r){let i=r??this.create(),a=e.pos+t;for(;e.posHe}])}create(e){let t=globalThis.Object.create(this.messagePrototype);return t.elems=[],e!==void 0&&d(this,t,e),t}internalBinaryRead(e,t,n,r){let i=r??this.create(),a=e.pos+t;for(;e.pos["bilibili.community.service.dm.v1.DmColorfulType",C]},{no:25,name:"type",kind:"scalar",T:5},{no:26,name:"oid",kind:"scalar",T:3},{no:27,name:"dm_from",kind:"scalar",T:5}])}create(e){let t=globalThis.Object.create(this.messagePrototype);return t.id="0",t.progress=0,t.mode=0,t.fontsize=0,t.color=0,t.midHash="",t.content="",t.ctime="0",t.weight=0,t.action="",t.pool=0,t.idStr="",t.attr=0,t.animation="",t.extra="",t.colorful=0,t.type=0,t.oid="0",t.dmFrom=0,e!==void 0&&d(this,t,e),t}internalBinaryRead(e,t,n,r){let i=r??this.create(),a=e.pos+t;for(;e.pos0;)e[t]=vt[Number(n%BigInt(Ut))],n=n/Ut,t-=1;return[e[3],e[9]]=[e[9],e[3]],[e[4],e[7]]=[e[7],e[4]],e.join("")}var Ft=$request.url,Kt=globalThis.$environment?.["device-model"]||globalThis.$loon,Jt=Kt?.includes("iPad");Ft.endsWith("/PlayViewUnite")?Gt($request):Ft.endsWith("/DmSegMobile")&&Jt?Xt($request):$done({});function Gt({url:s,headers:e,body:t}){let n=fe(t),r=Bt.fromBinary(n),{vod:i,bvid:a}=r,{aid:o,cid:l}=i||{},f=a||st(o);Promise.all([Rt(s,e,t),St(f,l!=="0"?l:"")]).then(([{headers:h,body:g},y])=>{$done({response:{headers:h,body:Vt(Yt(g,y,f))}})}).catch(h=>{console.log(h?.toString()),$done({})})}function Xt({url:s,headers:e,body:t}){let n=fe(t),r=Ot.fromBinary(n),{pid:i,oid:a}=r,o=st(i);Promise.all([Rt(s,e,t),St(o,a!=="0"?a:"")]).then(([{headers:l,body:f},h])=>{h.length?(console.log(`${o}: ${JSON.stringify(h)}`),$done({response:{headers:l,body:Vt(zt(f,h))}})):$done({response:{headers:l,body:f}})}).catch(l=>{console.log(l?.toString()),$done({})})}function Rt(s,e,t){let n={url:s,headers:e,body:t,"binary-mode":!0};return new Promise((r,i)=>{$httpClient.post(n,(a,o,l)=>{o?.status!==200?i("Fetch Original Request Failed"):r({headers:o.headers,body:l})})})}function St(s,e){let t={url:`https://bsbsb.top/api/skipSegments?videoID=${s}&cid=${e}&category=sponsor`,headers:{origin:"https://github.com/kokoryh/Sparkle/blob/master/release/surge/module/bilibili.sgmodule","x-ext-version":"1.0.0"}};return new Promise(n=>{$httpClient.get(t,(r,i,a)=>{if(i?.status!==200)n([]);else{let l=JSON.parse(a).reduce((f,h)=>(h.actionType==="skip"&&f.push(h.segment),f),[]);n(l)}})})}function Yt(s,e,t){let n=new Uint8Array(0),r=fe(s),i=Ve.fromBinary(r);if(i.viewInfo&&(i.viewInfo.promptBar=n),!e.length&&i.playArcConf?.arcConfs&&Object.values(i.playArcConf.arcConfs).forEach(a=>{a.isSupport&&a.disabled&&(a.disabled=!1,a.extraContent=void 0,a.unsupportScene.length=0)}),e.length){console.log(`${t}: ${JSON.stringify(e)}`);let a=i.playArcConf?.arcConfs||{};[P.SKIPOPED].forEach(o=>{a[o]={isSupport:!0,disabled:!1,unsupportScene:[]}}),[P.FREYAENTER,P.FREYAFULLENTER].forEach(o=>{a[o]={isSupport:!1,disabled:!0,unsupportScene:[]}}),i.vodInfo&&i.vodInfo.streamList.forEach(o=>{delete o.streamInfo?.needVip}),i.playArc&&(i.playArc.videoType=W.PGC),i.supplement={typeUrl:"type.googleapis.com/bilibili.app.playerunite.pgcanymodel.PGCAnyModel",value:xt.toBinary(Zt(e))}}return Ve.toBinary(i)}function Zt(s){return{business:{clipInfo:qt(s),vipStatus:1,episodeInfo:{epId:1231523,cid:"27730904912",aid:"113740078909891",epStatus:"2",seasonInfo:{seasonId:73081,seasonType:1,seasonStatus:13,mode:2}},userStatus:{watchProgress:{lastEpId:1231523,lastEpIndex:"OP",progress:"1",lastPlayAid:"113740078909891",lastPlayCid:"27730904912"}}},playExtConf:{allowCloseSubtitle:!0}}}function qt(s){return s.map(([e,t])=>({start:Math.floor(e),end:Math.ceil(t),clipType:_.CLIP_TYPE_OP}))}function zt(s,e){let t=fe(s),n=rt.fromBinary(t);return n.elems.unshift(...Ht(e)),rt.toBinary(n)}function Ht(s){return s.map((e,t)=>{let n=(t+1).toString(),r=Math.max(Math.floor(e[0]*1e3-2e3),1),i=Math.floor(e[1]*1e3);return{id:n,progress:r,mode:5,fontsize:50,color:16777215,midHash:"1948dd5d",content:"\u70B9\u51FB\u7A7A\u964D\u5E7F\u544A\u7ED3\u675F",ctime:"1735660800",weight:11,action:`airborne:${i}`,pool:0,idStr:n,attr:1310724,animation:"",extra:"",colorful:C.NONE_TYPE,type:1,oid:"212364987",dmFrom:1}})}function fe(s){let e=s.slice(0,5),t=s.slice(5);return e[0]&&(t=$utils.ungzip(t)),t}function Vt(s){let e=Qt(s.length),t=new Uint8Array(5+s.length);return t[0]=0,t.set(e,1),t.set(s,5),t}function Qt(s){let e=new ArrayBuffer(4);return new DataView(e).setUint32(0,s,!1),new Uint8Array(e)}})(); 4 | -------------------------------------------------------------------------------- /dist/bilibili.json.js: -------------------------------------------------------------------------------- 1 | // Build: 2025/6/1 12:53:23 2 | (()=>{$done(o($response,$request,globalThis.$argument)||{});function o({body:e},{url:t},i){let a={"/resource/show/tab/v2?":l,"/v2/splash":s,"/feed/index?":b,"/feed/index/story?":r,"/account/mine":f,"/account/myinfo?":_};try{if(e=JSON.parse(e),!e?.data)return null;let c=typeof i=="string"?JSON.parse(i):typeof i=="object"&&i!==null?i:{};for(let n in a)if(t.includes(n))return{body:JSON.stringify(a[n](e,c))};return null}catch(c){return console.log(c.toString()),null}}function l(e){return e.data.tab=[{pos:1,id:731,name:"\u76F4\u64AD",tab_id:"\u76F4\u64ADtab",uri:"bilibili://live/home"},{pos:2,id:477,name:"\u63A8\u8350",tab_id:"\u63A8\u8350tab",uri:"bilibili://pegasus/promo",default_selected:1},{pos:3,id:478,name:"\u70ED\u95E8",tab_id:"\u70ED\u95E8tab",uri:"bilibili://pegasus/hottopic"},{pos:4,id:545,name:"\u52A8\u753B",tab_id:"bangumi",uri:"bilibili://pgc/home"},{pos:5,id:151,name:"\u5F71\u89C6",tab_id:"film",uri:"bilibili://pgc/cinema-tab"}],e.data.top=[{pos:1,id:176,name:"\u6D88\u606F",tab_id:"\u6D88\u606FTop",uri:"bilibili://link/im_home",icon:"http://i0.hdslb.com/bfs/archive/d43047538e72c9ed8fd8e4e34415fbe3a4f632cb.png"}],e.data.bottom=[{pos:1,id:177,name:"\u9996\u9875",tab_id:"home",uri:"bilibili://main/home/",icon:"http://i0.hdslb.com/bfs/archive/63d7ee88d471786c1af45af86e8cb7f607edf91b.png",icon_selected:"http://i0.hdslb.com/bfs/archive/e5106aa688dc729e7f0eafcbb80317feb54a43bd.png"},{pos:2,id:179,name:"\u52A8\u6001",tab_id:"dynamic",uri:"bilibili://following/home/",icon:"http://i0.hdslb.com/bfs/archive/86dfbe5fa32f11a8588b9ae0fccb77d3c27cedf6.png",icon_selected:"http://i0.hdslb.com/bfs/archive/25b658e1f6b6da57eecba328556101dbdcb4b53f.png"},{pos:5,id:181,name:"\u6211\u7684",tab_id:"\u6211\u7684Bottom",uri:"bilibili://user_center/",icon:"http://i0.hdslb.com/bfs/archive/4b0b2c49ffeb4f0c2e6a4cceebeef0aab1c53fe1.png",icon_selected:"http://i0.hdslb.com/bfs/archive/a54a8009116cb896e64ef14dcf50e5cade401e00.png"}],e}function s(e){return["show","event_list"].forEach(i=>{e.data[i]&&(e.data[i]=[])}),e}function b(e){if(Array.isArray(e.data.items)){let t=new Set(["small_cover_v2","large_cover_single_v9","large_cover_v1"]);e.data.items=e.data.items.filter(i=>!i.banner_item&&!i.ad_info&&i.card_goto==="av"&&t.has(i.card_type))}return e}function r(e){return Array.isArray(e.data.items)&&(e.data.items=e.data.items.reduce((t,i)=>(!i.ad_info&&!i.card_goto?.startsWith("ad")&&(delete i.story_cart_icon,delete i.free_flow_toast,t.push(i)),t),[])),e}function f(e,t){let i={sections_v2:[{items:[{id:396,title:"\u79BB\u7EBF\u7F13\u5B58",uri:"bilibili://user_center/download",icon:"http://i0.hdslb.com/bfs/archive/5fc84565ab73e716d20cd2f65e0e1de9495d56f8.png",common_op_item:{}},{id:397,title:"\u5386\u53F2\u8BB0\u5F55",uri:"bilibili://user_center/history",icon:"http://i0.hdslb.com/bfs/archive/8385323c6acde52e9cd52514ae13c8b9481c1a16.png",common_op_item:{}},{id:3072,title:"\u6211\u7684\u6536\u85CF",uri:"bilibili://user_center/favourite",icon:"http://i0.hdslb.com/bfs/archive/d79b19d983067a1b91614e830a7100c05204a821.png",common_op_item:{}},{id:2830,title:"\u7A0D\u540E\u518D\u770B",uri:"bilibili://user_center/watch_later_v2",icon:"http://i0.hdslb.com/bfs/archive/63bb768caa02a68cb566a838f6f2415f0d1d02d6.png",need_login:1,common_op_item:{}}],style:1,button:{}},{title:"\u63A8\u8350\u670D\u52A1",items:[{id:402,title:"\u4E2A\u6027\u88C5\u626E",uri:"https://www.bilibili.com/h5/mall/home?navhide=1&f_source=shop&from=myservice",icon:"http://i0.hdslb.com/bfs/archive/0bcad10661b50f583969b5a188c12e5f0731628c.png",common_op_item:{}},{id:622,title:"\u4F1A\u5458\u8D2D",uri:"bilibili://mall/home",icon:"http://i0.hdslb.com/bfs/archive/19c794f01def1a267b894be84427d6a8f67081a9.png",common_op_item:{}},{id:404,title:"\u6211\u7684\u94B1\u5305",uri:"bilibili://bilipay/mine_wallet",icon:"http://i0.hdslb.com/bfs/archive/f416634e361824e74a855332b6ff14e2e7c2e082.png",common_op_item:{}},{id:406,title:"\u6211\u7684\u76F4\u64AD",uri:"bilibili://user_center/live_center",icon:"http://i0.hdslb.com/bfs/archive/1db5791746a0112890b77a0236baf263d71ecb27.png",common_op_item:{}}],style:1,button:{}},{title:"\u66F4\u591A\u670D\u52A1",items:[{id:407,title:"\u8054\u7CFB\u5BA2\u670D",uri:"bilibili://user_center/feedback",icon:"http://i0.hdslb.com/bfs/archive/7ca840cf1d887a45ee1ef441ab57845bf26ef5fa.png",common_op_item:{}},{id:410,title:"\u8BBE\u7F6E",uri:"bilibili://user_center/setting",icon:"http://i0.hdslb.com/bfs/archive/e932404f2ee62e075a772920019e9fbdb4b5656a.png",common_op_item:{}}],style:2,button:{}}],ipad_sections:[{id:747,title:"\u79BB\u7EBF\u7F13\u5B58",uri:"bilibili://user_center/download",icon:"http://i0.hdslb.com/bfs/feed-admin/9bd72251f7366c491cfe78818d453455473a9678.png",mng_resource:{icon_id:0,icon:""}},{id:748,title:"\u5386\u53F2\u8BB0\u5F55",uri:"bilibili://user_center/history",icon:"http://i0.hdslb.com/bfs/feed-admin/83862e10685f34e16a10cfe1f89dbd7b2884d272.png",mng_resource:{icon_id:0,icon:""}},{id:749,title:"\u6211\u7684\u6536\u85CF",uri:"bilibili://user_center/favourite",icon:"http://i0.hdslb.com/bfs/feed-admin/6ae7eff6af627590fc4ed80c905e9e0a6f0e8188.png",mng_resource:{icon_id:0,icon:""}},{id:750,title:"\u7A0D\u540E\u518D\u770B",uri:"bilibili://user_center/watch_later",icon:"http://i0.hdslb.com/bfs/feed-admin/928ba9f559b02129e51993efc8afe95014edec94.png",mng_resource:{icon_id:0,icon:""}}],ipad_upper_sections:[{id:752,title:"\u521B\u4F5C\u9996\u9875",uri:"/uper/homevc",icon:"http://i0.hdslb.com/bfs/feed-admin/d20dfed3b403c895506b1c92ecd5874abb700c01.png",mng_resource:{icon_id:0,icon:""}}],ipad_recommend_sections:[{id:755,title:"\u6211\u7684\u5173\u6CE8",uri:"bilibili://user_center/myfollows",icon:"http://i0.hdslb.com/bfs/feed-admin/fdd7f676030c6996d36763a078442a210fc5a8c0.png",mng_resource:{icon_id:0,icon:""}},{id:756,title:"\u6211\u7684\u6D88\u606F",uri:"bilibili://link/im_home",icon:"http://i0.hdslb.com/bfs/feed-admin/e1471740130a08a48b02a4ab29ed9d5f2281e3bf.png",mng_resource:{icon_id:0,icon:""}}],ipad_more_sections:[{id:763,title:"\u6211\u7684\u5BA2\u670D",uri:"bilibili://user_center/feedback",icon:"http://i0.hdslb.com/bfs/feed-admin/7801a6180fb67cf5f8ee05a66a4668e49fb38788.png",mng_resource:{icon_id:0,icon:""}},{id:764,title:"\u8BBE\u7F6E",uri:"bilibili://user_center/setting",icon:"http://i0.hdslb.com/bfs/feed-admin/34e8faea00b3dd78977266b58d77398b0ac9410b.png",mng_resource:{icon_id:0,icon:""}}]};return Object.keys(i).forEach(a=>{e.data[a]&&(e.data[a]=i[a])}),t.showUperCenter&&e.data.sections_v2&&e.data.sections_v2.splice(1,0,{title:"\u521B\u4F5C\u4E2D\u5FC3",items:[{id:171,title:"\u521B\u4F5C\u4E2D\u5FC3",uri:"bilibili://uper/homevc",icon:"http://i0.hdslb.com/bfs/archive/d3aad2d07538d2d43805f1fa14a412d7a45cc861.png",need_login:1,global_red_dot:0,display:1,is_up_anchor:!0},{id:533,title:"\u6570\u636E\u4E2D\u5FC3",uri:"https://member.bilibili.com/york/data-center?navhide=1&from=profile",icon:"http://i0.hdslb.com/bfs/feed-admin/367204ba56004b1a78211ba27eefbf5b4cc53a35.png",need_login:1,global_red_dot:0,display:1},{id:707,title:"\u4E3B\u64AD\u4E2D\u5FC3",uri:"https://live.bilibili.com/p/html/live-app-anchor-center/index.html?is_live_webview=1#/",icon:"http://i0.hdslb.com/bfs/feed-admin/48e17ccd0ce0cfc9c7826422d5e47ce98f064c2a.png",need_login:1,display:1},{id:2647,title:"\u76F4\u64AD\u6570\u636E",uri:"https://live.bilibili.com/p/html/live-app-data/index.html?source_tag=0&foreground=pink&is_live_webview=1&hybrid_set_header=2#/",icon:"https://i0.hdslb.com/bfs/legacy/0566b128c51d85b7ec545f318e1fd437d172dfea.png",display:1}],style:1,button:{text:"\u53D1\u5E03",url:"bilibili://uper/user_center/archive_selection",icon:"http://i0.hdslb.com/bfs/archive/205f47675eaaca7912111e0e9b1ac94cb985901f.png",style:1},type:1,up_title:"\u521B\u4F5C\u4E2D\u5FC3"}),delete e.data.answer,delete e.data.live_tip,delete e.data.vip_section,delete e.data.vip_section_v2,delete e.data.modular_vip_section,e.data.vip_type=2,e.data.vip=d(),e}function _(e){return e.data.vip=d(),e}function d(){let e=p();return{status:1,type:2,vip_pay_type:0,due_date:90052704e5,tv_vip_status:1,tv_vip_pay_type:0,tv_due_date:90052704e5,role:15,theme_type:0,nickname_color:"#FB7299",avatar_subscript:1,avatar_subscript_url:"",avatar_icon:{icon_resource:{}},label:{path:"",text:"\u767E\u5E74\u5927\u4F1A\u5458",label_theme:"hundred_annual_vip",text_color:"#FFFFFF",bg_style:1,bg_color:"#FB7299",border_color:"",use_img_label:!0,image:e,img_label_uri_hans:"",img_label_uri_hant:"",img_label_uri_hans_static:e,img_label_uri_hant_static:e}}}function p(){let e=new Date,t=e.getMonth()+1,i=e.getDate();switch(`${t}/${i}`){case"6/1":return"https://i0.hdslb.com/bfs/bangumi/kt/629e28d4426f1b44af1131ade99d27741cc61d4b.png";default:return"https://i0.hdslb.com/bfs/vip/52f60c8bdae8d4440edbb96dad72916022adf126.png"}}})(); 3 | -------------------------------------------------------------------------------- /dist/zhihu.json.js: -------------------------------------------------------------------------------- 1 | // Build: 2025/4/4 17:02:04 2 | (()=>{function E(e){return oe.test(e)}var oe=/^-?[0-9]+$/;function $(e){return ie.test(e)}var ie=/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/;function q(e,t){let i=Number.parseFloat(e),r=String(i),s=L(e),m=L(r);return!!(s===m||t?.approx===!0&&!E(e)&&m.length>=14&&s.startsWith(m.substring(0,14)))}var w=function(e){return e.underflow="underflow",e.overflow="overflow",e.truncate_integer="truncate_integer",e.truncate_float="truncate_float",e}({});function j(e){if(q(e,{approx:!1}))return;if(E(e))return w.truncate_integer;let t=Number.parseFloat(e);return Number.isFinite(t)?t===0?w.underflow:w.truncate_float:w.overflow}function L(e){return e.replace(se,"").replace(fe,"").replace(ue,"").replace(ce,"")}var se=/[eE][+-]?\d+$/,ce=/^-?(0*)?/,fe=/\./,ue=/0+$/;var O=class{isLosslessNumber=!0;constructor(t){if(!$(t))throw new Error(`Invalid number (value: "${t}")`);this.value=t}valueOf(){let t=j(this.value);if(t===void 0||t===w.truncate_float)return Number.parseFloat(this.value);if(E(this.value))return BigInt(this.value);throw new Error(`Cannot safely convert to number: the value '${this.value}' would ${t} and become ${Number.parseFloat(this.value)}`)}toString(){return this.value}};function B(e){return e&&typeof e=="object"&&e.isLosslessNumber===!0||!1}function F(e){return new O(e)}function P(e,t){return T({"":e},"",e,t)}function T(e,t,i,r){return Array.isArray(i)?r.call(e,t,de(i,r)):i&&typeof i=="object"&&!B(i)?r.call(e,t,ae(i,r)):r.call(e,t,i)}function ae(e,t){for(let i of Object.keys(e)){let r=T(e,i,e[i],t);r!==void 0?e[i]=r:delete e[i]}return e}function de(e,t){for(let i=0;i2&&arguments[2]!==void 0?arguments[2]:F,r=0,s=N();return d(s),g(),t?P(s,t):s;function m(){if(e.charCodeAt(r)===ye){r++,h();let n={},f=!0;for(;rn)return i(e.slice(n,r))}function a(){if(e.charCodeAt(r)!==Ce)throw new SyntaxError(`Comma ',' expected after value ${p()}`);r++}function c(){if(e.charCodeAt(r)!==Oe)throw new SyntaxError(`Colon ':' expected after property name ${p()}`);r++}function d(n){if(n===void 0)throw new SyntaxError(`JSON value expected ${p()}`)}function l(n){if(n===void 0)throw new SyntaxError(`Array item expected ${p()}`)}function g(){if(r=V&&e<=X||e>=Ie&&e<=ke||e>=_e&&e<=Le}function D(e){return e>=V&&e<=X}function pe(e){return e>=Se&&e<=X}function he(e){return e>=32&&e<=1114111}function U(e,t){return e===t?!0:Array.isArray(e)&&Array.isArray(t)?e.length===t.length&&e.every((i,r)=>U(i,t[r])):Z(e)&&Z(t)?[...new Set([...Object.keys(e),...Object.keys(t)])].every(r=>U(e[r],t[r])):!1}function Z(e){return typeof e=="object"&&e!==null}var me={'"':'"',"\\":"\\","/":"/",b:"\b",f:"\f",n:` 3 | `,r:"\r",t:" "},ge=92,ye=123,K=125,we=91,Q=93,be=32,Ae=10,Ee=9,Ne=13,G=34,xe=43,M=45,V=48,Se=49,X=57,Ce=44,$e=46,Oe=58,Ie=65,_e=97,De=69,Re=101,ke=70,Le=102;function R(e,t,i,r){let s=je(i),m=typeof t=="function"?t.call({"":e},"",e):e;return b(m,"");function b(o,u){if(Array.isArray(r)){let a=r.find(c=>c.test(o));if(a){let c=a.stringify(o);if(typeof c!="string"||!$(c))throw new Error(`Invalid JSON number: output of a number stringifier must be a string containing a JSON number (output: ${c})`);return c}}if(typeof o=="boolean"||typeof o=="number"||typeof o=="string"||o===null||o instanceof Date||o instanceof Boolean||o instanceof Number||o instanceof String)return JSON.stringify(o);if(o?.isLosslessNumber||typeof o=="bigint")return o.toString();if(Array.isArray(o))return N(o,u);if(o&&typeof o=="object")return x(o,u)}function N(o,u){if(o.length===0)return"[]";let a=s?u+s:void 0,c=s?`[ 4 | `:"[";for(let d=0;d!t?.target?.answer_type?.includes("paid"))),e}})(); 10 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import eslint from '@eslint/js'; 2 | import tseslint from 'typescript-eslint'; 3 | import { globalIgnores } from 'eslint/config'; 4 | 5 | export default tseslint.config( 6 | eslint.configs.recommended, 7 | tseslint.configs.recommended, 8 | globalIgnores(['dist', 'src/proto']) 9 | ); 10 | -------------------------------------------------------------------------------- /jq/bilibili.mine.jq: -------------------------------------------------------------------------------- 1 | .data |= ( 2 | del(.answer, .live_tip, .vip_section, .vip_section_v2, .modular_vip_section) | 3 | .vip_type = 2 | 4 | .vip |= if . != null and .status == 0 5 | then . + { status: 1, type: 2, due_date: 9005270400000, role: 15 } 6 | else . 7 | end | 8 | if .sections_v2 then .sections_v2 = 9 | [ 10 | { 11 | "items": [ 12 | { 13 | "id": 396, 14 | "title": "离线缓存", 15 | "uri": "bilibili://user_center/download", 16 | "icon": "http://i0.hdslb.com/bfs/archive/5fc84565ab73e716d20cd2f65e0e1de9495d56f8.png", 17 | "common_op_item": {} 18 | }, 19 | { 20 | "id": 397, 21 | "title": "历史记录", 22 | "uri": "bilibili://user_center/history", 23 | "icon": "http://i0.hdslb.com/bfs/archive/8385323c6acde52e9cd52514ae13c8b9481c1a16.png", 24 | "common_op_item": {} 25 | }, 26 | { 27 | "id": 3072, 28 | "title": "我的收藏", 29 | "uri": "bilibili://user_center/favourite", 30 | "icon": "http://i0.hdslb.com/bfs/archive/d79b19d983067a1b91614e830a7100c05204a821.png", 31 | "common_op_item": {} 32 | }, 33 | { 34 | "id": 2830, 35 | "title": "稍后再看", 36 | "uri": "bilibili://user_center/watch_later_v2", 37 | "icon": "http://i0.hdslb.com/bfs/archive/63bb768caa02a68cb566a838f6f2415f0d1d02d6.png", 38 | "need_login": 1, 39 | "common_op_item": {} 40 | } 41 | ], 42 | "style": 1, 43 | "button": {} 44 | }, 45 | { 46 | "title": "推荐服务", 47 | "items": [ 48 | { 49 | "id": 402, 50 | "title": "个性装扮", 51 | "uri": "https://www.bilibili.com/h5/mall/home?navhide=1&f_source=shop&from=myservice", 52 | "icon": "http://i0.hdslb.com/bfs/archive/0bcad10661b50f583969b5a188c12e5f0731628c.png", 53 | "common_op_item": {} 54 | }, 55 | { 56 | "id": 622, 57 | "title": "会员购", 58 | "uri": "bilibili://mall/home", 59 | "icon": "http://i0.hdslb.com/bfs/archive/19c794f01def1a267b894be84427d6a8f67081a9.png", 60 | "common_op_item": {} 61 | }, 62 | { 63 | "id": 404, 64 | "title": "我的钱包", 65 | "uri": "bilibili://bilipay/mine_wallet", 66 | "icon": "http://i0.hdslb.com/bfs/archive/f416634e361824e74a855332b6ff14e2e7c2e082.png", 67 | "common_op_item": {} 68 | }, 69 | { 70 | "id": 406, 71 | "title": "我的直播", 72 | "uri": "bilibili://user_center/live_center", 73 | "icon": "http://i0.hdslb.com/bfs/archive/1db5791746a0112890b77a0236baf263d71ecb27.png", 74 | "common_op_item": {}, 75 | } 76 | ], 77 | "style": 1, 78 | "button": {} 79 | }, 80 | { 81 | "title": "更多服务", 82 | "items": [ 83 | { 84 | "id": 407, 85 | "title": "联系客服", 86 | "uri": "bilibili://user_center/feedback", 87 | "icon": "http://i0.hdslb.com/bfs/archive/7ca840cf1d887a45ee1ef441ab57845bf26ef5fa.png", 88 | "common_op_item": {} 89 | }, 90 | { 91 | "id": 410, 92 | "title": "设置", 93 | "uri": "bilibili://user_center/setting", 94 | "icon": "http://i0.hdslb.com/bfs/archive/e932404f2ee62e075a772920019e9fbdb4b5656a.png", 95 | "common_op_item": {} 96 | } 97 | ], 98 | "style": 2, 99 | "button": {} 100 | } 101 | ] 102 | end | 103 | if .ipad_sections then .ipad_sections = 104 | [ 105 | { 106 | "id": 747, 107 | "title": "离线缓存", 108 | "uri": "bilibili://user_center/download", 109 | "icon": "http://i0.hdslb.com/bfs/feed-admin/9bd72251f7366c491cfe78818d453455473a9678.png", 110 | "mng_resource": { "icon_id": 0, "icon": "" } 111 | }, 112 | { 113 | "id": 748, 114 | "title": "历史记录", 115 | "uri": "bilibili://user_center/history", 116 | "icon": "http://i0.hdslb.com/bfs/feed-admin/83862e10685f34e16a10cfe1f89dbd7b2884d272.png", 117 | "mng_resource": { "icon_id": 0, "icon": "" } 118 | }, 119 | { 120 | "id": 749, 121 | "title": "我的收藏", 122 | "uri": "bilibili://user_center/favourite", 123 | "icon": "http://i0.hdslb.com/bfs/feed-admin/6ae7eff6af627590fc4ed80c905e9e0a6f0e8188.png", 124 | "mng_resource": { "icon_id": 0, "icon": "" } 125 | }, 126 | { 127 | "id": 750, 128 | "title": "稍后再看", 129 | "uri": "bilibili://user_center/watch_later", 130 | "icon": "http://i0.hdslb.com/bfs/feed-admin/928ba9f559b02129e51993efc8afe95014edec94.png", 131 | "mng_resource": { "icon_id": 0, "icon": "" } 132 | } 133 | ] 134 | end | 135 | if .ipad_upper_sections then .ipad_upper_sections = 136 | [ 137 | { 138 | "id": 752, 139 | "title": "创作首页", 140 | "uri": "/uper/homevc", 141 | "icon": "http://i0.hdslb.com/bfs/feed-admin/d20dfed3b403c895506b1c92ecd5874abb700c01.png", 142 | "mng_resource": { "icon_id": 0, "icon": "" } 143 | } 144 | ] 145 | end | 146 | if .ipad_recommend_sections then .ipad_recommend_sections = 147 | [ 148 | { 149 | "id": 755, 150 | "title": "我的关注", 151 | "uri": "bilibili://user_center/myfollows", 152 | "icon": "http://i0.hdslb.com/bfs/feed-admin/fdd7f676030c6996d36763a078442a210fc5a8c0.png", 153 | "mng_resource": { "icon_id": 0, "icon": "" } 154 | }, 155 | { 156 | "id": 756, 157 | "title": "我的消息", 158 | "uri": "bilibili://link/im_home", 159 | "icon": "http://i0.hdslb.com/bfs/feed-admin/e1471740130a08a48b02a4ab29ed9d5f2281e3bf.png", 160 | "mng_resource": { "icon_id": 0, "icon": "" } 161 | } 162 | ] 163 | end | 164 | if .ipad_more_sections then .ipad_more_sections = 165 | [ 166 | { 167 | "id": 763, 168 | "title": "我的客服", 169 | "uri": "bilibili://user_center/feedback", 170 | "icon": "http://i0.hdslb.com/bfs/feed-admin/7801a6180fb67cf5f8ee05a66a4668e49fb38788.png", 171 | "mng_resource": { "icon_id": 0, "icon": "" } 172 | }, 173 | { 174 | "id": 764, 175 | "title": "设置", 176 | "uri": "bilibili://user_center/setting", 177 | "icon": "http://i0.hdslb.com/bfs/feed-admin/34e8faea00b3dd78977266b58d77398b0ac9410b.png", 178 | "mng_resource": { "icon_id": 0, "icon": "" } 179 | } 180 | ] 181 | end 182 | ) 183 | -------------------------------------------------------------------------------- /jq/bilibili.tab.jq: -------------------------------------------------------------------------------- 1 | .data.tab = [ 2 | { 3 | pos: 1, 4 | id: 731, 5 | name: "\u76F4\u64AD", 6 | tab_id: "\u76F4\u64ADtab", 7 | uri: "bilibili://live/home" 8 | }, 9 | { 10 | pos: 2, 11 | id: 477, 12 | name: "\u63A8\u8350", 13 | tab_id: "\u63A8\u8350tab", 14 | uri: "bilibili://pegasus/promo", 15 | default_selected: 1 16 | }, 17 | { 18 | pos: 3, 19 | id: 478, 20 | name: "\u70ED\u95E8", 21 | tab_id: "\u70ED\u95E8tab", 22 | uri: "bilibili://pegasus/hottopic" 23 | }, 24 | { 25 | pos: 4, 26 | id: 545, 27 | name: "\u52A8\u753B", 28 | tab_id: "bangumi", 29 | uri: "bilibili://pgc/home" 30 | }, 31 | { 32 | pos: 5, 33 | id: 151, 34 | name: "\u5F71\u89C6", 35 | tab_id: "film", 36 | uri: "bilibili://pgc/cinema-tab" 37 | } 38 | ] | 39 | .data.top = [ 40 | { 41 | pos: 1, 42 | id: 176, 43 | name: "\u6D88\u606F", 44 | tab_id: "\u6D88\u606FTop", 45 | uri: "bilibili://link/im_home", 46 | icon: "http://i0.hdslb.com/bfs/archive/d43047538e72c9ed8fd8e4e34415fbe3a4f632cb.png" 47 | } 48 | ] | 49 | .data.bottom = [ 50 | { 51 | pos: 1, 52 | id: 177, 53 | name: "\u9996\u9875", 54 | tab_id: "home", 55 | uri: "bilibili://main/home/", 56 | icon: "http://i0.hdslb.com/bfs/archive/63d7ee88d471786c1af45af86e8cb7f607edf91b.png", 57 | icon_selected: "http://i0.hdslb.com/bfs/archive/e5106aa688dc729e7f0eafcbb80317feb54a43bd.png" 58 | }, 59 | { 60 | pos: 2, 61 | id: 179, 62 | name: "\u52A8\u6001", 63 | tab_id: "dynamic", 64 | uri: "bilibili://following/home/", 65 | icon: "http://i0.hdslb.com/bfs/archive/86dfbe5fa32f11a8588b9ae0fccb77d3c27cedf6.png", 66 | icon_selected: "http://i0.hdslb.com/bfs/archive/25b658e1f6b6da57eecba328556101dbdcb4b53f.png" 67 | }, 68 | { 69 | pos: 5, 70 | id: 181, 71 | name: "\u6211\u7684", 72 | tab_id: "\u6211\u7684Bottom", 73 | uri: "bilibili://user_center/", 74 | icon: "http://i0.hdslb.com/bfs/archive/4b0b2c49ffeb4f0c2e6a4cceebeef0aab1c53fe1.png", 75 | icon_selected: "http://i0.hdslb.com/bfs/archive/a54a8009116cb896e64ef14dcf50e5cade401e00.png" 76 | } 77 | ] 78 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sparkle", 3 | "author": "kokoryh", 4 | "type": "module", 5 | "scripts": { 6 | "build": "node build.js", 7 | "generate": "buf generate", 8 | "jq": "jq -f ./jq/test/index.jq --indent 4 < ./jq/test/input.json > ./jq/test/output.json" 9 | }, 10 | "dependencies": { 11 | "@bufbuild/protobuf": "2.2.5", 12 | "@protobuf-ts/plugin": "2.9.6", 13 | "cheerio": "1.0.0", 14 | "fflate": "0.8.2", 15 | "lossless-json": "4.0.2" 16 | }, 17 | "devDependencies": { 18 | "@bufbuild/buf": "1.51.0", 19 | "@bufbuild/protoc-gen-es": "2.2.5", 20 | "@eslint/js": "9.24.0", 21 | "@types/node": "22.14.0", 22 | "esbuild": "0.25.2", 23 | "eslint": "9.24.0", 24 | "tsx": "4.19.3", 25 | "typescript": "5.8.3", 26 | "typescript-eslint": "8.29.0" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /proto/bilibili/app/card/v1/card.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package bilibili.app.card.v1; 4 | 5 | message Card { 6 | oneof item { 7 | SmallCoverV5 small_cover_v5 = 1; 8 | bytes rcmd_one_item = 10; 9 | bytes small_cover_v5_ad = 11; 10 | bytes topic_list = 12; 11 | } 12 | } 13 | 14 | message SmallCoverV5 { 15 | Base base = 1; 16 | } 17 | 18 | message Base { 19 | bytes ad_info = 12; 20 | string from_type = 14; 21 | } 22 | -------------------------------------------------------------------------------- /proto/bilibili/app/dynamic/v2/dynamic.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package bilibili.app.dynamic.v2; 4 | 5 | message DynAllReply { 6 | DynamicList dynamic_list = 1; 7 | CardVideoUpList up_list = 2; 8 | bytes topic_list = 3; 9 | } 10 | 11 | message DynamicList { 12 | repeated DynamicItem list = 1; 13 | } 14 | 15 | message DynamicItem { 16 | DynamicType card_type = 1; 17 | } 18 | 19 | enum DynamicType { 20 | DYN_NONE = 0; 21 | AD = 15; 22 | LIVE_RCMD = 18; 23 | } 24 | 25 | message CardVideoUpList { 26 | repeated UpListItem list = 2; 27 | int32 show_live_num = 4; 28 | repeated UpListItem list_second = 10; 29 | } 30 | 31 | message UpListItem { 32 | bool separator = 11; 33 | } 34 | -------------------------------------------------------------------------------- /proto/bilibili/app/interface/v1/search.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package bilibili.app.interface.v1; 4 | 5 | message DefaultWordsReply { 6 | string show = 3; 7 | string word = 4; 8 | int64 show_front = 5; 9 | string goto = 7; 10 | string value = 8; 11 | string uri = 9; 12 | } 13 | -------------------------------------------------------------------------------- /proto/bilibili/app/interface/v1/teenagers.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package bilibili.app.interface.v1; 4 | 5 | message ModeStatusReply { 6 | repeated UserModel user_models = 1; 7 | } 8 | 9 | message UserModel { 10 | string mode = 2; 11 | Policy policy = 5; 12 | } 13 | 14 | message Policy { 15 | int64 interval = 1; 16 | } 17 | -------------------------------------------------------------------------------- /proto/bilibili/app/playerunite/pgcanymodel/pgcanymodel.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package bilibili.app.playerunite.pgcanymodel; 4 | 5 | import "bilibili/pgc/gateway/player/v2/playurl.proto"; 6 | 7 | message PGCAnyModel { 8 | bilibili.pgc.gateway.player.v2.PlayViewBusinessInfo business = 3; 9 | bilibili.pgc.gateway.player.v2.PlayAbilityExtConf play_ext_conf = 6; 10 | } 11 | -------------------------------------------------------------------------------- /proto/bilibili/app/playerunite/v1/player.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package bilibili.app.playerunite.v1; 4 | 5 | import "google/protobuf/any.proto"; 6 | import "bilibili/playershared/playershared.proto"; 7 | 8 | message PlayViewUniteReq { 9 | bilibili.playershared.VideoVod vod = 1; 10 | string bvid = 5; 11 | } 12 | 13 | message PlayViewUniteReply { 14 | bilibili.playershared.VodInfo vod_info = 1; 15 | bilibili.playershared.PlayArcConf play_arc_conf = 2; 16 | google.protobuf.Any supplement = 5; 17 | bilibili.playershared.PlayArc play_arc = 6; 18 | bilibili.playershared.ViewInfo view_info = 9; 19 | } 20 | -------------------------------------------------------------------------------- /proto/bilibili/app/playurl/v1/playurl.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package bilibili.app.playurl.v1; 4 | 5 | message PlayViewReply { 6 | PlayArcConf play_arc = 5; 7 | } 8 | 9 | message PlayArcConf { 10 | ArcConf background_play_conf = 1; 11 | ArcConf cast_conf = 3; 12 | } 13 | 14 | message ArcConf { 15 | bool is_support = 1; 16 | bool disabled = 2; 17 | ExtraContent extra_content = 3; 18 | repeated int64 unsupport_scene = 4; 19 | } 20 | 21 | message ExtraContent { 22 | string disabled_reason = 1; 23 | int64 disabled_code = 2; 24 | } 25 | -------------------------------------------------------------------------------- /proto/bilibili/app/show/popular/v1/popular.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package bilibili.app.show.popular.v1; 4 | 5 | import "bilibili/app/card/v1/card.proto"; 6 | 7 | message PopularReply { 8 | repeated bilibili.app.card.v1.Card items = 1; 9 | } 10 | -------------------------------------------------------------------------------- /proto/bilibili/app/view/v1/view.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package bilibili.app.view.v1; 4 | 5 | message ViewReply { 6 | ReqUser req_user = 4; 7 | repeated Relate relates = 10; 8 | bytes label = 23; 9 | repeated bytes cms = 30; 10 | bytes cm_config = 31; 11 | bytes cm_ipad = 41; 12 | repeated bytes special_cell_new = 50; 13 | } 14 | 15 | message ReqUser { 16 | bytes elec_plus_btn = 9; 17 | } 18 | 19 | message Relate { 20 | bytes cm = 28; 21 | } 22 | 23 | message ViewProgressReply { 24 | bytes video_guide = 1; 25 | } 26 | 27 | message TFInfoReply { 28 | int64 tips_id = 1; 29 | bytes tf_toast = 2; 30 | bytes tf_panel_customized = 3; 31 | } 32 | -------------------------------------------------------------------------------- /proto/bilibili/app/viewunite/v1/view.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package bilibili.app.viewunite.v1; 4 | 5 | message ViewReply { 6 | ReqUser req_user = 3; 7 | Tab tab = 5; 8 | bytes cm = 7; 9 | } 10 | 11 | message ReqUser { 12 | bytes elec_plus_btn = 7; 13 | } 14 | 15 | message Tab { 16 | repeated TabModule tab_module = 1; 17 | } 18 | 19 | message TabModule { 20 | TabType tab_type = 1; 21 | oneof tab { 22 | IntroductionTab introduction = 2; 23 | } 24 | } 25 | 26 | enum TabType { 27 | TAB_NONE = 0; 28 | TAB_INTRODUCTION = 1; 29 | } 30 | 31 | message IntroductionTab { 32 | repeated Module modules = 2; 33 | } 34 | 35 | message Module { 36 | ModuleType type = 1; 37 | oneof data { 38 | Headline head_line = 5; 39 | Relates relates = 22; 40 | } 41 | } 42 | 43 | enum ModuleType { 44 | UNKNOWN = 0; 45 | UGC_HEADLINE = 3; 46 | ACTIVITY = 18; 47 | RELATED_RECOMMEND = 28; 48 | PAY_BAR = 29; 49 | SPECIALTAG = 37; 50 | MERCHANDISE = 55; 51 | } 52 | 53 | message Headline { 54 | bytes label = 1; 55 | } 56 | 57 | message Relates { 58 | repeated RelateCard cards = 1; 59 | } 60 | 61 | message RelateCard { 62 | RelateCardType relate_card_type = 1; 63 | bytes cm_stock = 11; 64 | CardBasicInfo basic_info = 12; 65 | } 66 | 67 | enum RelateCardType { 68 | CARD_TYPE_UNKNOWN = 0; 69 | AV = 1; 70 | GAME = 4; 71 | CM_TYPE = 5; 72 | LIVE = 6; 73 | AI_RECOMMEND = 7; 74 | COURSE = 11; 75 | } 76 | 77 | message CardBasicInfo { 78 | string unique_id = 6; 79 | } 80 | 81 | message ViewProgressReply { 82 | bytes dm = 4; 83 | } 84 | 85 | message RelatesFeedReply { 86 | repeated RelateCard relates = 1; 87 | } 88 | -------------------------------------------------------------------------------- /proto/bilibili/community/service/dm/v1/dm.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package bilibili.community.service.dm.v1; 4 | 5 | message DmViewReply { 6 | repeated string activity_meta = 18; 7 | Command command = 22; 8 | } 9 | 10 | message Command { 11 | repeated bytes command_dms = 1; 12 | } 13 | 14 | message DmSegMobileReq { 15 | int64 pid = 1; 16 | int64 oid = 2; 17 | } 18 | 19 | message DmSegMobileReply { 20 | repeated DanmakuElem elems = 1; 21 | } 22 | 23 | message DanmakuElem { 24 | int64 id = 1; 25 | int32 progress = 2; 26 | int32 mode = 3; 27 | int32 fontsize = 4; 28 | int32 color = 5; 29 | string mid_hash = 6; 30 | string content = 7; 31 | int64 ctime = 8; 32 | int32 weight = 9; 33 | string action = 10; 34 | int32 pool = 11; 35 | string id_str = 12; 36 | int32 attr = 13; 37 | string animation = 22; 38 | string extra = 23; 39 | DmColorfulType colorful = 24; 40 | int32 type = 25; 41 | int64 oid = 26; 42 | int32 dm_from = 27; 43 | } 44 | 45 | enum DmColorfulType { 46 | NONE_TYPE = 0; 47 | VIP_GRADUAL_COLOR = 60001; 48 | } 49 | -------------------------------------------------------------------------------- /proto/bilibili/main/community/reply/v1/reply.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package bilibili.main.community.reply.v1; 4 | 5 | message MainListReply { 6 | bytes cm = 11; 7 | repeated ReplyInfo top_replies = 14; 8 | } 9 | 10 | message ReplyInfo { 11 | Content content = 12; 12 | } 13 | 14 | message Content { 15 | string message = 1; 16 | map urls = 5; 17 | } 18 | 19 | message Url { 20 | string title = 1; 21 | string app_name = 5; 22 | string app_package_name = 6; 23 | } 24 | -------------------------------------------------------------------------------- /proto/bilibili/pgc/gateway/player/v2/playurl.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package bilibili.pgc.gateway.player.v2; 4 | 5 | message PlayViewReply { 6 | ViewInfo view_info = 5; 7 | PlayAbilityExtConf play_ext_conf = 6; 8 | } 9 | 10 | message ViewInfo { 11 | bytes try_watch_prompt_bar = 8; 12 | } 13 | 14 | message PlayAbilityExtConf { 15 | bool allow_close_subtitle = 1; 16 | CastTips cast_tips = 3; 17 | } 18 | 19 | message CastTips { 20 | int32 code = 1; 21 | string message = 2; 22 | } 23 | 24 | message PlayViewBusinessInfo { 25 | repeated ClipInfo clip_info = 6; 26 | int32 vip_status = 16; 27 | EpisodeInfo episode_info = 18; 28 | UserStatus user_status = 20; 29 | } 30 | 31 | message ClipInfo { 32 | int32 start = 2; 33 | int32 end = 3; 34 | ClipType clip_type = 4; 35 | } 36 | 37 | enum ClipType { 38 | NT_UNKNOWN = 0; 39 | CLIP_TYPE_OP = 1; 40 | CLIP_TYPE_ED = 2; 41 | } 42 | 43 | message EpisodeInfo { 44 | int32 ep_id = 1; 45 | int64 cid = 2; 46 | int64 aid = 3; 47 | int64 ep_status = 4; 48 | SeasonInfo season_info = 5; 49 | } 50 | 51 | message SeasonInfo { 52 | int32 season_id = 1; 53 | int32 season_type = 2; 54 | int32 season_status = 3; 55 | int32 mode = 7; 56 | } 57 | 58 | message UserStatus { 59 | WatchProgress watch_progress = 3; 60 | } 61 | 62 | message WatchProgress { 63 | int32 last_ep_id = 1; 64 | string last_ep_index = 2; 65 | int64 progress = 3; 66 | int64 last_play_cid = 4; 67 | int64 last_play_aid = 7; 68 | } 69 | -------------------------------------------------------------------------------- /proto/bilibili/playershared/playershared.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package bilibili.playershared; 4 | 5 | message VideoVod { 6 | int64 aid = 1; 7 | int64 cid = 2; 8 | } 9 | 10 | message VodInfo { 11 | repeated Stream stream_list = 5; 12 | } 13 | 14 | message Stream { 15 | StreamInfo stream_info = 1; 16 | } 17 | 18 | message StreamInfo { 19 | optional bool need_vip = 6; 20 | } 21 | 22 | message PlayArcConf { 23 | map arc_confs = 1; 24 | } 25 | 26 | enum ConfType { 27 | NO_TYPE = 0; 28 | BACKGROUNDPLAY = 9; 29 | SMALLWINDOW = 23; 30 | FREYAENTER = 31; 31 | FREYAFULLENTER = 32; 32 | SKIPOPED = 33; 33 | } 34 | 35 | message ArcConf { 36 | bool is_support = 1; 37 | bool disabled = 2; 38 | ExtraContent extra_content = 3; 39 | repeated int32 unsupport_scene = 4; 40 | } 41 | 42 | message ExtraContent { 43 | string disable_reason = 1; 44 | int64 disable_code = 2; 45 | } 46 | 47 | message PlayArc { 48 | BizType video_type = 1; 49 | } 50 | 51 | enum BizType { 52 | BIZ_TYPE_UNKNOWN = 0; 53 | BIZ_TYPE_UGC = 1; 54 | BIZ_TYPE_PGC = 2; 55 | BIZ_TYPE_PUGV = 3; 56 | } 57 | 58 | message ViewInfo { 59 | bytes prompt_bar = 2; 60 | } 61 | -------------------------------------------------------------------------------- /proto/bilibili/polymer/app/search/v1/search.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package bilibili.polymer.app.search.v1; 4 | 5 | message SearchAllResponse { 6 | repeated Item item = 4; 7 | } 8 | 9 | message Item { 10 | string linktype = 4; 11 | } 12 | -------------------------------------------------------------------------------- /release/loon/plugin/bilibili.plugin: -------------------------------------------------------------------------------- 1 | #!name=哔哩哔哩增强 2 | #!desc=拜托,没有广告的哔哩哔哩真的超酷的 3 | #!openUrl=https://apps.apple.com/app/id736536022 4 | #!tag=Enhancement 5 | #!system=iOS,iPadOS 6 | #!system_version=15 7 | #!loon_version=3.2.9(837) 8 | #!icon=https://raw.githubusercontent.com/luestr/IconResource/main/App_icon/120px/Bilibili.png 9 | #!date=2025-05-03 10 | 11 | [Argument] 12 | showUpList=select,"auto","true","false",tag=[动态]中[最常访问]的显示方式,desc=true: 始终显示\n- false: 始终隐藏\n- auto: 仅当列表中存在直播状态时显示 13 | filterTopReplies=switch,true,tag=[评论区]过滤置顶评论广告,desc=true: 开启\n- false: 关闭 14 | enableAirborne=switch,true,tag=空降助手,desc=true: 开启\n- false: 关闭 15 | enableAirborneDm=switch,false,tag=空降助手弹幕版(仅限Ipad开启),desc=true: 开启\n- false: 关闭 16 | 17 | [Rule] 18 | DOMAIN,api.biliapi.com,REJECT 19 | DOMAIN,app.biliapi.com,REJECT 20 | DOMAIN,api.biliapi.net,REJECT 21 | DOMAIN,app.biliapi.net,REJECT 22 | 23 | [Rewrite] 24 | ^https:\/\/api\.live\.bilibili\.com\/xlive\/e-commerce-interface\/v1\/ecommerce-user\/get_shopping_info\? reject-dict 25 | ^https:\/\/ap[ip]\.bilibili\.com\/x\/(?:resource\/(?:top\/activity|patch\/tab)|v2\/search\/square|vip\/ads\/materials)\? mock-response-body data-type=text status-code=200 data="{"code":-404,"message":"-404","ttl":1,"data":null}" 26 | ^https:\/\/api\.bilibili\.com\/pgc\/activity\/deliver\/material\/receive\? mock-response-body data-type=text status-code=200 data="{"code":0,"data":{"closeType":"close_win","container":[],"showTime":""},"message":"success"}" 27 | ^https:\/\/(?:grpc\.biliapi\.net|app\.bilibili\.com)\/bilibili\.app\.interface\.v1\.Teenagers\/ModeStatus$ mock-response-body data-type=base64 data="AAAAABMKEQgCEgl0ZWVuYWdlcnMgAioA" mock-data-is-base64=true 28 | ^https:\/\/(?:grpc\.biliapi\.net|app\.bilibili\.com)\/bilibili\.app\.interface\.v1\.Search\/DefaultWords$ mock-response-body data-type=base64 data="AAAAACkaHeaQnOe0ouinhumikeOAgeeVquWJp+aIlnVw5Li7IgAoAToAQgBKAA==" mock-data-is-base64=true 29 | ^https:\/\/(?:grpc\.biliapi\.net|app\.bilibili\.com)\/bilibili\.app\.view\.v1\.View\/TFInfo$ mock-response-body data-type=base64 data="AAAAAAIIAQ==" mock-data-is-base64=true 30 | 31 | ^https:\/\/api\.bilibili\.com\/pgc\/view\/v2\/app\/season\? response-body-json-jq 'del(.data.payment)' 32 | ^https:\/\/api\.bilibili\.com\/pgc\/page\/(?:bangumi|cinema\/tab)\? response-body-json-jq '.result.modules |= if . then map(if (.style | startswith("tip")) or (.module_id | IN(241, 1283, 1441, 1284)) then .items = [] elif .style | startswith("banner") then .items |= if . then map(select(.link | contains("play"))) else [] end elif .style | startswith("function") then .items |= if . then map(select(.blink | startswith("bilibili"))) else [] end end) end' 33 | ^https:\/\/api\.live\.bilibili\.com\/xlive\/(?:app-interface\/v2\/index\/feed|app-room\/v1\/index\/getInfoBy(?:Room|User))\? response-body-json-jq '.data |= (del(.play_together_info, .play_together_info_v2, .activity_banner_info) | if .function_card then .function_card[] = null end | if .new_tab_info.outer_list then .new_tab_info.outer_list |= map(select(.biz_id != 33)) end | if .card_list then .card_list |= map(select(.card_type | IN("banner_v2", "activity_card_v1") | not)) end | reduce ([["show_reserve_status"], false], [["reserve_info", "show_reserve_status"], false], [["shopping_info", "is_show"], 0]) as [$path, $value] (.; if getpath($path) then setpath($path; $value) end))' 34 | 35 | ^https:\/\/app\.bilibili\.com\/x\/resource\/show\/skin\? response-body-json-del data.common_equip 36 | ^https:\/\/app\.bilibili\.com\/x\/resource\/show\/tab\/v2\? response-body-json-jq jq-path="https://raw.githubusercontent.com/kokoryh/Sparkle/refs/heads/master/jq/bilibili.tab.jq" 37 | ^https:\/\/app\.bilibili\.com\/x\/v2\/splash\/(?:list|show|event\/list2)\? response-body-json-jq '.data |= with_entries(if .key | IN("show", "event_list") then .value = [] else . end)' 38 | ^https:\/\/app\.bilibili\.com\/x\/v2\/feed\/index\? response-body-json-jq 'if .data.items then .data.items |= map(select((.banner_item == null) and (.ad_info == null) and (.card_goto == "av") and (.card_type | IN("small_cover_v2", "large_cover_single_v9", "large_cover_v1")))) end' 39 | ^https:\/\/app\.bilibili\.com\/x\/v2\/feed\/index\/story\? response-body-json-jq 'if .data.items then .data.items |= map(select((.ad_info == null) and (.card_goto | startswith("ad") | not)) | del(.story_cart_icon, .free_flow_toast)) end' 40 | ^https:\/\/app\.bilibili\.com\/x\/v2\/account\/mine(?:\/ipad)?\? response-body-json-jq jq-path="https://raw.githubusercontent.com/kokoryh/Sparkle/refs/heads/master/jq/bilibili.mine.jq" 41 | ^https:\/\/app\.bilibili\.com\/x\/v2\/account\/myinfo\? response-body-json-jq '.data.vip |= if . != null and .status == 0 then . + { status: 1, type: 2, due_date: 9005270400000, role: 15 } else . end' 42 | 43 | [Script] 44 | http-request ^https:\/\/(?:grpc\.biliapi\.net|app\.bilibili\.com)\/bilibili\.app\.playerunite\.v1\.Player\/PlayViewUnite$ script-path=https://raw.githubusercontent.com/kokoryh/Sparkle/refs/heads/master/dist/bilibili.airborne.js, requires-body=true, binary-body-mode=true, enable={enableAirborne}, tag=bilibili.airborne 45 | http-request ^https:\/\/(?:grpc\.biliapi\.net|app\.bilibili\.com)\/bilibili\.community\.service\.dm\.v1\.DM\/DmSegMobile$ script-path=https://raw.githubusercontent.com/kokoryh/Sparkle/refs/heads/master/dist/bilibili.airborne.js, requires-body=true, binary-body-mode=true, enable={enableAirborneDm}, tag=bilibili.airborneDm 46 | http-response ^https:\/\/(?:grpc\.biliapi\.net|app\.bilibili\.com)\/bilibili\.(?:app\.(?:show\.v1\.Popular\/Index|dynamic\.v2\.Dynamic\/DynAll|view(?:unite)?\.v1\.View\/(?:View|ViewProgress|RelatesFeed)|playurl\.v1\.PlayURL\/PlayView|playerunite\.v1\.Player\/PlayViewUnite)|polymer\.app\.search\.v1\.Search\/SearchAll|community\.service\.dm\.v1\.DM\/DmView|main\.community\.reply\.v1\.Reply\/MainList|pgc\.gateway\.player\.v2\.PlayURL\/PlayView)$ script-path=https://raw.githubusercontent.com/kokoryh/Sparkle/refs/heads/master/dist/bilibili.protobuf.js, argument=[{showUpList}, {filterTopReplies}], requires-body=true, binary-body-mode=true, tag=bilibili.protobuf 47 | 48 | [MitM] 49 | hostname = grpc.biliapi.net, app.bilibili.com, api.bilibili.com, api.live.bilibili.com 50 | -------------------------------------------------------------------------------- /release/surge/module/12306.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=12306去广告 2 | #!desc=移除开屏广告和首页广告 3 | #!category=Block 4 | 5 | [Script] 6 | 12306.request = type=http-request,pattern=^https:\/\/ad\.12306\.cn\/ad\/ser\/getAdList$,requires-body=1,engine=webview,script-path=https://raw.githubusercontent.com/kokoryh/Sparkle/refs/heads/master/dist/12306.request.js 7 | 12306.request = type=http-request,pattern=^https:\/\/mobile\.12306\.cn\/otsmobile\/app\/mgs\/mgw\.htm$,requires-body=1,engine=webview,script-path=https://raw.githubusercontent.com/kokoryh/Sparkle/refs/heads/master/dist/12306.request.js 8 | 9 | [MITM] 10 | hostname = %APPEND% ad.12306.cn, mobile.12306.cn 11 | -------------------------------------------------------------------------------- /release/surge/module/bilibili-manga.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=哔哩哔哩漫画去广告 2 | #!desc=适用于哔哩哔哩漫画HD 3 | #!category=Block 4 | 5 | [Map Local] 6 | ^https:\/\/manga\.bilibili\.com\/twirp\/comic\.v1\.Comic\/(?:Flash|ListFlash|GetActivityTab|GetBubbles)\? header="content-type: application/json" data-type=text data="{}" 7 | 8 | [Body Rewrite] 9 | http-response-jq ^https:\/\/manga\.bilibili\.com\/twirp\/comic\.v1\.(?:Comic\/AppInit|Home\/HomeFeed)\? '.data as $data | .data[("activity_tab", "flash", "operate") | select($data[.])] = null | if .data.feeds then .data.feeds |= map(select(.type | IN(15, 30) | not)) end' 10 | 11 | [MITM] 12 | hostname = %APPEND% manga.bilibili.com 13 | -------------------------------------------------------------------------------- /release/surge/module/bilibili.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=Bilibili增强 2 | #!desc=拜托,没有广告的哔哩哔哩真的超酷的 3 | #!category=Enhancement 4 | #!arguments=动态最常访问:auto,创作中心:0,过滤置顶评论广告:1,空降助手:bilibili.airborne,空降助手弹幕版:#,替换鉴权字段:#,Authorization:identify_v1 xxx 5 | #!arguments-desc=动态最常访问: [true, false, auto]\n- true: 始终显示\n- false: 始终隐藏\n- auto: 仅当列表中存在直播状态时显示\n\n创作中心: [1, 0]\n- 1: 显示\n- 0: 隐藏\n\n过滤置顶评论广告: [1, 0]\n- 1: 开启\n- 0: 关闭\n\n空降助手: 默认开启,配置为"#"时关闭\n\n空降助手弹幕版: 默认关闭,仅限Ipad开启\n\n替换鉴权字段: 默认关闭,配置为"h"时开启,需填写Authorization 6 | 7 | [Rule] 8 | DOMAIN,api.biliapi.com,REJECT,pre-matching 9 | DOMAIN,app.biliapi.com,REJECT,pre-matching 10 | DOMAIN,api.biliapi.net,REJECT,pre-matching 11 | DOMAIN,app.biliapi.net,REJECT,pre-matching 12 | 13 | [Map Local] 14 | ^https:\/\/ap[ip]\.bilibili\.com\/x\/(?:resource\/(?:top\/activity|patch\/tab)|v2\/search\/square|vip\/ads\/materials)\? header="content-type: application/json" data-type=text data="{"code":-404,"message":"-404","ttl":1,"data":null}" 15 | ^https:\/\/api\.bilibili\.com\/pgc\/activity\/deliver\/material\/receive\? header="content-type: application/json" data-type=text data="{"code":0,"data":{"closeType":"close_win","container":[],"showTime":""},"message":"success"}" 16 | ^https:\/\/api\.live\.bilibili\.com\/xlive\/e-commerce-interface\/v1\/ecommerce-user\/get_shopping_info\? header="content-type: application/json" data-type=text data="{}" 17 | ^https:\/\/(?:grpc\.biliapi\.net|app\.bilibili\.com)\/bilibili\.app\.interface\.v1\.Teenagers\/ModeStatus$ header="content-type: application/grpc" data-type=base64 data="AAAAABMKEQgCEgl0ZWVuYWdlcnMgAioA" 18 | ^https:\/\/(?:grpc\.biliapi\.net|app\.bilibili\.com)\/bilibili\.app\.interface\.v1\.Search\/DefaultWords$ header="content-type: application/grpc" data-type=base64 data="AAAAACkaHeaQnOe0ouinhumikeOAgeeVquWJp+aIlnVw5Li7IgAoAToAQgBKAA==" 19 | ^https:\/\/(?:grpc\.biliapi\.net|app\.bilibili\.com)\/bilibili\.app\.view\.v1\.View\/TFInfo$ header="content-type: application/grpc" data-type=base64 data="AAAAAAIIAQ==" 20 | 21 | [Header Rewrite] 22 | {{{替换鉴权字段}}}ttp-request ^https:\/\/(?:grpc\.biliapi\.net|app\.bilibili\.com)\/bilibili\.app\.(?:playerunite\.v1\.Player\/PlayViewUnite|pgc\.gateway\.player\.v2\.PlayURL\/PlayView)$ header-replace authorization "{{{Authorization}}}" 23 | 24 | [Body Rewrite] 25 | http-response-jq ^https:\/\/api\.bilibili\.com\/pgc\/view\/v2\/app\/season\? 'del(.data.payment)' 26 | http-response-jq ^https:\/\/api\.bilibili\.com\/pgc\/page\/(?:bangumi|cinema\/tab)\? '.result.modules |= if . then map(if (.style | startswith("tip")) or (.module_id | IN(241, 1283, 1441, 1284)) then .items = [] elif .style | startswith("banner") then .items |= if . then map(select(.link | contains("play"))) else [] end elif .style | startswith("function") then .items |= if . then map(select(.blink | startswith("bilibili"))) else [] end end) end' 27 | http-response-jq ^https:\/\/api\.live\.bilibili\.com\/xlive\/(?:app-interface\/v2\/index\/feed|app-room\/v1\/index\/getInfoBy(?:Room|User))\? '.data |= (del(.play_together_info, .play_together_info_v2, .activity_banner_info) | if .function_card then .function_card[] = null end | if .new_tab_info.outer_list then .new_tab_info.outer_list |= map(select(.biz_id != 33)) end | if .card_list then .card_list |= map(select(.card_type | IN("banner_v2", "activity_card_v1") | not)) end | reduce ([["show_reserve_status"], false], [["reserve_info", "show_reserve_status"], false], [["shopping_info", "is_show"], 0]) as [$path, $value] (.; if getpath($path) then setpath($path; $value) end))' 28 | 29 | [Script] 30 | {{{空降助手}}} = type=http-request,pattern=^https:\/\/(?:grpc\.biliapi\.net|app\.bilibili\.com)\/bilibili\.app\.playerunite\.v1\.Player\/PlayViewUnite$,requires-body=1,binary-body-mode=1,max-size=-1,engine=webview,script-path=https://raw.githubusercontent.com/kokoryh/Sparkle/refs/heads/master/dist/bilibili.airborne.js 31 | {{{空降助手弹幕版}}} = type=http-request,pattern=^https:\/\/(?:grpc\.biliapi\.net|app\.bilibili\.com)\/bilibili\.community\.service\.dm\.v1\.DM\/DmSegMobile$,requires-body=1,binary-body-mode=1,max-size=-1,engine=webview,script-path=https://raw.githubusercontent.com/kokoryh/Sparkle/refs/heads/master/dist/bilibili.airborne.js 32 | bilibili.skin = type=http-response,pattern=^https:\/\/app\.bilibili\.com\/x\/resource\/show\/skin\?,requires-body=1,max-size=-1,engine=webview,script-path=https://raw.githubusercontent.com/kokoryh/Script/master/js/bili-suit-diy.js 33 | bilibili.json = type=http-response,pattern=^https:\/\/app\.bilibili\.com\/x\/(?:resource\/show\/tab\/v2|v2\/(?:splash\/(?:list|show|event\/list2)|feed\/index(?:\/story)?|account\/(?:mine(?:\/ipad)?|myinfo)))\?,argument="{"showUperCenter":{{{创作中心}}}}",requires-body=1,max-size=-1,engine=webview,script-path=https://raw.githubusercontent.com/kokoryh/Sparkle/refs/heads/master/dist/bilibili.json.js 34 | bilibili.protobuf = type=http-response,pattern=^https:\/\/(?:grpc\.biliapi\.net|app\.bilibili\.com)\/bilibili\.(?:app\.(?:show\.v1\.Popular\/Index|dynamic\.v2\.Dynamic\/DynAll|view(?:unite)?\.v1\.View\/(?:View|ViewProgress|RelatesFeed)|playurl\.v1\.PlayURL\/PlayView|playerunite\.v1\.Player\/PlayViewUnite)|polymer\.app\.search\.v1\.Search\/SearchAll|community\.service\.dm\.v1\.DM\/DmView|main\.community\.reply\.v1\.Reply\/MainList|pgc\.gateway\.player\.v2\.PlayURL\/PlayView)$,argument="{"showUpList":"{{{动态最常访问}}}","filterTopReplies":{{{过滤置顶评论广告}}}}",requires-body=1,binary-body-mode=1,max-size=-1,engine=webview,script-path=https://raw.githubusercontent.com/kokoryh/Sparkle/refs/heads/master/dist/bilibili.protobuf.js 35 | 36 | [MITM] 37 | hostname = %APPEND% grpc.biliapi.net, app.bilibili.com, api.bilibili.com, api.live.bilibili.com 38 | -------------------------------------------------------------------------------- /release/surge/module/block-ad.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=AD Block 2 | #!desc=去广告规则合集 3 | #!category=Block 4 | 5 | [URL Rewrite] 6 | # 百度网盘广告 7 | ^https?:\/\/pan\.baidu\.com\/(act\/(api\/activityentry|v2\/(bchannel|welfare)\/list)|rest\/2\.0\/pcs\/ad) - reject 8 | 9 | # 中国移动开屏 10 | ^https?:\/\/client\.app\.coc\.10086\.cn\/biz-orange\/DN\/(?:init\/startInit|emotionMarket) - reject 11 | 12 | # 浙里办开屏 13 | ^https?:\/\/portal\.zjzwfw\.gov\.cn\/app_api\/appHome\/selectStartPic - reject 14 | 15 | [Map Local] 16 | 17 | [Script] 18 | 19 | [MITM] 20 | hostname = %APPEND% pan.baidu.com, client.app.coc.10086.cn, portal.zjzwfw.gov.cn 21 | -------------------------------------------------------------------------------- /release/surge/module/block.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=Block 2 | #!desc=屏蔽特定协议 & 端口 & 域名 3 | #!category=Block 4 | #!arguments=STUN:PROTOCOL,Bilibili:DEST-PORT,通用域名:DOMAIN,系统更新:# 5 | #!arguments-desc=系统更新: DOMAIN 6 | 7 | [Rule] 8 | {{{STUN}}},STUN,REJECT 9 | 10 | {{{Bilibili}}},4480,REJECT-NO-DROP 11 | {{{Bilibili}}},4483,REJECT-NO-DROP 12 | {{{Bilibili}}},9102,REJECT-NO-DROP 13 | 14 | {{{通用域名}}},www.googleadservices.com,REJECT,pre-matching 15 | {{{通用域名}}},googleads.g.doubleclick.net,REJECT,pre-matching 16 | 17 | {{{系统更新}}},mesu.apple.com,REJECT-DROP 18 | {{{系统更新}}},gdmf.apple.com,REJECT-DROP 19 | {{{系统更新}}},updates-http.cdn-apple.com,REJECT-DROP 20 | {{{系统更新}}},xp.apple.com,REJECT-DROP 21 | -------------------------------------------------------------------------------- /release/surge/module/boxjs.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=BoxJs 2 | #!desc=https://boxjs.com 3 | #!category=Plugin 4 | #!author=chavyleung[https://github.com/chavyleung/scripts] 5 | 6 | [General] 7 | force-http-engine-hosts = %APPEND% boxjs.com 8 | 9 | [Script] 10 | boxjs = type=http-request,pattern=https?:\/\/boxjs\.com,requires-body=true,timeout=120,script-path=https://raw.githubusercontent.com/chavyleung/scripts/master/box/chavy.boxjs.js 11 | 12 | [MITM] 13 | hostname = %APPEND% boxjs.com 14 | -------------------------------------------------------------------------------- /release/surge/module/dev.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=Development Mode 2 | #!desc=Redirect to the specified refName 3 | #!category=General 4 | #!arguments=refname:refs/heads/dev 5 | 6 | [URL Rewrite] 7 | ^https:\/\/raw\.githubusercontent\.com\/kokoryh\/Sparkle\/refs\/heads\/master https://raw.githubusercontent.com/kokoryh/Sparkle/{{{refname}}} 302 8 | 9 | [MITM] 10 | hostname = %APPEND% raw.githubusercontent.com 11 | -------------------------------------------------------------------------------- /release/surge/module/extra.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=Extra 2 | #!desc=Optional configuration 3 | #!category=General 4 | #!arguments=allow-wifi-access:allow-wifi-access,allow-hotspot-access:allow-hotspot-access,external-controller-access:external-controller-access,http-api:http-api 5 | 6 | [General] 7 | {{{allow-wifi-access}}} = true 8 | {{{allow-hotspot-access}}} = true 9 | {{{external-controller-access}}} = kokoryh@0.0.0.0:25505 10 | {{{http-api}}} = kokoryh@0.0.0.0:25500 11 | {{{http-api}}}-tls = false 12 | {{{http-api}}}-web-dashboard = true 13 | -------------------------------------------------------------------------------- /release/surge/module/general.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=General 2 | #!desc=Basic configuration 3 | #!category=General 4 | #!arguments=skip-proxy:skip-proxy,always-real-ip:always-real-ip,hide-vpn-icon:hide-vpn-icon 5 | 6 | [General] 7 | {{{skip-proxy}}} = %APPEND% localhost, *.local, captive.apple.com, e.crashlytics.com, www.baidu.com, www.abchina.com.cn, id6.me, 10.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.168.0.0/16, 224.0.0.0/4, fe80::/10 8 | {{{always-real-ip}}} = %APPEND% cable.auth.com, *.cmpassport.com, id6.me, open.e.189.cn, localhost.ptlogin2.qq.com, localhost.sec.qq.com, localhost.work.weixin.qq.com 9 | {{{hide-vpn-icon}}} = true 10 | -------------------------------------------------------------------------------- /release/surge/module/missav.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=MissAV去广告 2 | #!desc=适用于 missav.ai, missav.ws 3 | #!category=Block 4 | 5 | [Rule] 6 | DOMAIN-SUFFIX,creative.myavlive.com,REJECT,pre-matching 7 | DOMAIN-SUFFIX,trackwilltrk.com,REJECT,pre-matching 8 | DOMAIN-SUFFIX,tsyndicate.com,REJECT,pre-matching 9 | 10 | [Script] 11 | missav.html = type=http-response,pattern=^https:\/\/missav\.(?:ai|ws)\/(?!(build|fonts|img|js|api|cdn-cgi)\/).,requires-body=1,max-size=-1,engine=webview,script-path=https://raw.githubusercontent.com/kokoryh/Sparkle/refs/heads/master/dist/missav.html.js 12 | 13 | [MITM] 14 | hostname = %APPEND% missav.ai, missav.ws 15 | -------------------------------------------------------------------------------- /release/surge/module/redirect.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=Redirect 2 | #!desc=URL Redirect 3 | #!category=General 4 | 5 | [URL Rewrite] 6 | ^https?:\/\/(www.)?(g|google)\.cn https://www.google.com 307 7 | ^https?:\/\/exhentai\.org https://e-hentai.org 307 8 | 9 | [MITM] 10 | hostname = %APPEND% www.google.cn, exhentai.org 11 | -------------------------------------------------------------------------------- /release/surge/module/safari-search.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=Safari搜索拓展 2 | #!desc=搜索引擎设置为DuckDuckGo 3 | #!category=Enhancement 4 | 5 | [URL Rewrite] 6 | ^https:\/\/duckduckgo.com\/\?q=([^+]+)\+trc.+ https://translate.google.com/?op=translate&sl=auto&tl=zh-CN&text=$1 302 7 | ^https:\/\/duckduckgo.com\/\?q=([^+]+)\+tre.+ https://translate.google.com/?op=translate&sl=auto&tl=en&text=$1 302 8 | ^https:\/\/duckduckgo.com\/\?q=([^+]+)\+trj.+ https://translate.google.com/?op=translate&sl=auto&tl=ja&text=$1 302 9 | 10 | ^https:\/\/duckduckgo.com\/\?q=([^+]+)\+gh.+ https://github.com/search?q=$1 302 11 | ^https:\/\/duckduckgo.com\/\?q=([^+]+)\+gu.+ https://github.com/search?type=users&q=$1 302 12 | ^https:\/\/duckduckgo.com\/\?q=([^+]+)\+so.+ https://stackoverflow.com/search?q=$1 302 13 | ^https:\/\/duckduckgo.com\/\?q=([^+]+)\+se.+ https://stackexchange.com/search?q=$1 302 14 | ^https:\/\/duckduckgo.com\/\?q=([^+]+)\+tw.+ https://twitter.com/search?q=$1 302 15 | ^https:\/\/duckduckgo.com\/\?q=([^+]+)\+zh.+ http://www.zhihu.com/search?q=$1 302 16 | ^https:\/\/duckduckgo.com\/\?q=([^+]+)\+wb.+ https://s.weibo.com/weibo/$1 302 17 | 18 | ^https:\/\/duckduckgo.com\/\?q=([^+]+)\+tb.+ taobao://s.taobao.com?q=$1 302 19 | ^https:\/\/duckduckgo.com\/\?q=([^+]+)\+jd.+ openapp.jdmobile://virtual?params={"des":"productList","keyWord":"$1","from":"search","category":"jump"} 302 20 | ^https:\/\/duckduckgo.com\/\?q=([^+]+)\+zdm.+ https://search.m.smzdm.com/?v=b&s=$1 302 21 | 22 | ^https:\/\/duckduckgo.com\/\?q=([^+]+)\+yt.+ https://www.youtube.com/results?search_query=$1 302 23 | ^https:\/\/duckduckgo.com\/\?q=([^+]+)\+bli.+ https://m.bilibili.com/search?keyword=$1 302 24 | 25 | ^https:\/\/duckduckgo.com\/\?q=cn&.+ https://itunes.apple.com/WebObjects/MZStore.woa/wa/resetAndRedirect?dsf=143465&mt=8&url=/WebObjects/MZStore.woa/wa/viewSoftware?mt=8&id=1108187390&cc=cn&urlDesc= 302 26 | ^https:\/\/duckduckgo.com\/\?q=hk&.+ https://itunes.apple.com/WebObjects/MZStore.woa/wa/resetAndRedirect?dsf=143463&mt=8&url=/WebObjects/MZStore.woa/wa/viewSoftware?mt=8&id=1108187390&cc=hk&urlDesc= 302 27 | ^https:\/\/duckduckgo.com\/\?q=tw&.+ https://itunes.apple.com/WebObjects/MZStore.woa/wa/resetAndRedirect?dsf=143470&mt=8&url=/WebObjects/MZStore.woa/wa/viewSoftware?mt=8&id=1108187390&cc=tw&urlDesc= 302 28 | ^https:\/\/duckduckgo.com\/\?q=us&.+ https://itunes.apple.com/WebObjects/MZStore.woa/wa/resetAndRedirect?dsf=143441&mt=8&url=/WebObjects/MZStore.woa/wa/viewSoftware?mt=8&id=1108187390&cc=us&urlDesc= 302 29 | ^https:\/\/duckduckgo.com\/\?q=jp&.+ https://itunes.apple.com/WebObjects/MZStore.woa/wa/resetAndRedirect?dsf=143462&mt=8&url=/WebObjects/MZStore.woa/wa/viewSoftware?mt=8&id=1108187390&cc=jp&urlDesc= 302 30 | ^https:\/\/duckduckgo.com\/\?q=tr&.+ https://itunes.apple.com/WebObjects/MZStore.woa/wa/resetAndRedirect?dsf=143480&mt=8&url=/WebObjects/MZStore.woa/wa/viewSoftware?mt=8&id=1108187390&cc=tr&urlDesc= 302 31 | 32 | ^https:\/\/duckduckgo.com\/\?q=([^+]+)\+bd.+ https://www.baidu.com/s?wd=$1 302 33 | ^https:\/\/duckduckgo.com\/\?q=([^+]+)\+wk.+ https://zh.wikipedia.org/wiki/$1 302 34 | ^https:\/\/duckduckgo.com\/\?q=([^+]+)\+bi.+ https://cn.bing.com/search?q=$1 302 35 | ^https:\/\/duckduckgo.com\/\?q=([^&]+).+ https://www.google.com/search?q=$1 302 36 | 37 | [MITM] 38 | hostname = %APPEND% duckduckgo.com 39 | -------------------------------------------------------------------------------- /release/surge/module/scheduled-tasks.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=定时任务 2 | #!desc=Scheduled tasks 3 | #!category=General 4 | #!arguments=SubStore同步:0 5 * * *,毛怪俱乐部签到:55 2 * * * 5 | #!arguments-desc=定时任务执行时间: [Cron表达式, #]\n- #: 停用定时任务 6 | 7 | [Script] 8 | {{{SubStore同步}}} substore = type=cron,cronexp={{{SubStore同步}}},wake-system=1,timeout=120,script-path=https://raw.githubusercontent.com/sub-store-org/Sub-Store/release/cron-sync-artifacts.min.js 9 | {{{毛怪俱乐部签到}}} mgclub = type=cron,cronexp={{{毛怪俱乐部签到}}},wake-system=1,script-path=https://raw.githubusercontent.com/kokoryh/Script/master/js/ihan.js, 10 | -------------------------------------------------------------------------------- /release/surge/module/substore.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=Sub-Store 2 | #!desc=https://sub.store 3 | #!category=Plugin 4 | #!author=sub-store-org[https://github.com/sub-store-org/Sub-Store] 5 | 6 | [Script] 7 | substore.core = type=http-request,pattern=^https?:\/\/sub\.store\/((download)|api\/(preview|sync|(utils\/node-info))),requires-body=true,timeout=120,script-path=https://raw.githubusercontent.com/sub-store-org/Sub-Store/release/sub-store-1.min.js 8 | substore.simple = type=http-request,pattern=^https?:\/\/sub\.store,requires-body=true,timeout=120,script-path=https://raw.githubusercontent.com/sub-store-org/Sub-Store/release/sub-store-0.min.js 9 | 10 | [MITM] 11 | hostname = %APPEND% sub.store 12 | -------------------------------------------------------------------------------- /release/surge/module/weibo-intl.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=微博轻享版去广告 2 | #!desc=极简体验 3 | #!category=Block 4 | 5 | [Rule] 6 | DOMAIN-SUFFIX,biz.weibo.com,REJECT,pre-matching 7 | 8 | [Map Local] 9 | ^https?:\/\/api\.weibo\.cn\/2\/ad\/weibointl\? header="content-type: application/json" data-type=text data="{}" 10 | ^https?:\/\/weibointl\.api\.weibo\.cn\/portal\.php\?a=get_searching_info& header="content-type: text/html" data-type=text data="{"retcode":0,"info":"","data":{"expiration_time":"86400","cards":[{"tip":"搜索微博","word":""}]}}" 11 | ^https?:\/\/weibointl\.api\.weibo\.cn\/portal\.php\?ct=feed&a=search_topic& header="content-type: text/html" data-type=text data="{"retcode":0,"info":"","data":[],"ext":{}}" 12 | 13 | [Body Rewrite] 14 | http-response-jq ^https?:\/\/api\.weibo\.cn\/2\/statuses\/unread_hot_timeline$ 'del(.ad, .advertises, .trends) | if .statuses then .statuses |= map(select(((.promotion.type == "ad") or (.mblogtypename | IN("广告", "廣告", "热推", "熱推"))) | not)) end' 15 | http-response-jq ^https?:\/\/weibointl\.api\.weibo\.cn\/portal\.php\?a=get_coopen_ads& '.data |= . + {"ad_list":[],"pic_ad":[],"gdt_video_ad_ios":[],"display_ad":0,"ad_ios_id":null,"app_ad_ios_id":null,"reserve_ad_ios_id":"","reserve_app_ad_ios_id":"","ad_duration":604800,"ad_cd_interval":604800}' 16 | http-response-jq ^https?:\/\/weibointl\.api\.weibo\.cn\/portal\.php\?a=trends& 'if .data.order then .data.order = ["search_topic"] end' 17 | http-response-jq ^https?:\/\/weibointl\.api\.weibo\.cn\/portal\.php\?a=search_topic& 'if .data.search_topic.cards[0].type == "searchtop" then del(.data.search_topic.cards[0]) end' 18 | http-response-jq ^https?:\/\/weibointl\.api\.weibo\.cn\/portal\.php\?a=user_center& 'if .data.cards then .data.cards[].items |= map(select(.type != "personal_vip")) | .data.cards |= map(select((.items | length) > 0)) end' 19 | 20 | [MITM] 21 | hostname = %APPEND% api.weibo.cn, weibointl.api.weibo.cn 22 | -------------------------------------------------------------------------------- /release/surge/module/youtube.sgmodule: -------------------------------------------------------------------------------- 1 | #!name=YouTube增强 2 | #!desc=适用于 YouTube & YouTube Music 3 | #!category=Enhancement 4 | #!arguments=屏蔽上传按钮:true,屏蔽选段按钮:true,屏蔽Shorts按钮:true,字幕翻译语言:off,歌词翻译语言:off,脚本执行引擎:auto,启用调试模式:false 5 | #!arguments-desc=- 屏蔽参数:[true, false] \n- 翻译参数:[语言代码, off] \n- 脚本引擎:[auto, jsc, webview]\n\n1. 语言代码遵循 Google Translate Languages Codes, 当填入 off 时关闭翻译\n2. 推荐使用 jsc 引擎,但你仍可以切换成 webview 体验 Surge 新特性\n3. 开启调试模式用于输出更多日志 6 | #!author=Maasea[https://github.com/Maasea/sgmodule/tree/master] 7 | 8 | [Rule] 9 | AND,((DOMAIN-SUFFIX,googlevideo.com), (PROTOCOL,UDP)),REJECT 10 | AND,((DOMAIN,youtubei.googleapis.com), (PROTOCOL,UDP)),REJECT 11 | 12 | [Map Local] 13 | ^https?:\/\/[\w-]+\.googlevideo\.com\/initplayback.+&oad data-type=text data="" status-code=502 14 | 15 | [Script] 16 | youtube.response = type=http-response,pattern=^https:\/\/youtubei\.googleapis\.com\/youtubei\/v1\/(browse|next|player|search|reel\/reel_watch_sequence|guide|account\/get_setting|get_watch),argument="{"lyricLang":"{{{歌词翻译语言}}}","captionLang":"{{{字幕翻译语言}}}","blockUpload":{{{屏蔽上传按钮}}},"blockImmersive":{{{屏蔽选段按钮}}},"blockShorts":{{{屏蔽Shorts按钮}}},"debug":{{{启用调试模式}}}}",requires-body=1,binary-body-mode=1,max-size=-1,engine={{{脚本执行引擎}}},script-path=https://raw.githubusercontent.com/Maasea/sgmodule/master/Script/Youtube/youtube.response.js 17 | 18 | [MITM] 19 | hostname = %APPEND% *.googlevideo.com, youtubei.googleapis.com 20 | -------------------------------------------------------------------------------- /src/script/12306/12306.request.ts: -------------------------------------------------------------------------------- 1 | $done(handleRequest($request) || {}); 2 | 3 | function handleRequest({ url, headers, body }) { 4 | const routeHandlers = { 5 | '/getAdList': () => ({ 6 | response: { 7 | body: getResponseBody(JSON.parse(body)), 8 | }, 9 | }), 10 | '/mgw.htm': () => ({ 11 | abort: shouldAbortRequest(headers['operation-type']), 12 | }), 13 | }; 14 | try { 15 | for (const route in routeHandlers) { 16 | if (url.endsWith(route)) { 17 | return routeHandlers[route](); 18 | } 19 | } 20 | return null; 21 | } catch (e) { 22 | console.log(e.toString()); 23 | return null; 24 | } 25 | } 26 | 27 | function getResponseBody({ placementNo }) { 28 | if (placementNo === '0007') { 29 | return '{"materialsList":[{"billMaterialsId":"1","filePath":"#","creativeType":1}],"advertParam":{"skipTime":1}}'; 30 | } else if (placementNo === 'G0054') { 31 | return '{"code":"00","materialsList":[{}]}'; 32 | } else { 33 | return '{"code":"00","message":"0"}'; 34 | } 35 | } 36 | 37 | function shouldAbortRequest(type) { 38 | const filter = ['com.cars.otsmobile.newHomePageBussData']; 39 | return filter.includes(type); 40 | } 41 | -------------------------------------------------------------------------------- /src/script/bilibili/bilibili.airborne.ts: -------------------------------------------------------------------------------- 1 | import { PlayViewUniteReply, PlayViewUniteReq } from '@proto/bilibili/app/playerunite/v1/player'; 2 | import { PGCAnyModel } from '@proto/bilibili/app/playerunite/pgcanymodel/pgcanymodel'; 3 | import { BizType, ConfType } from '@proto/bilibili/playershared/playershared'; 4 | import { ClipInfo, ClipType } from '@proto/bilibili/pgc/gateway/player/v2/playurl'; 5 | import { 6 | DanmakuElem, 7 | DmColorfulType, 8 | DmSegMobileReply, 9 | DmSegMobileReq, 10 | } from '@proto/bilibili/community/service/dm/v1/dm'; 11 | import { av2bv } from '@util/bilibili'; 12 | 13 | const url = $request.url; 14 | const device = globalThis.$environment?.['device-model'] || globalThis.$loon; 15 | const isIpad = device?.includes('iPad'); 16 | if (url.endsWith('/PlayViewUnite')) { 17 | handlePlayViewUniteReq($request); 18 | } else if (url.endsWith('/DmSegMobile') && isIpad) { 19 | handleDmSegMobileReq($request); 20 | } else { 21 | $done({}); 22 | } 23 | 24 | function handlePlayViewUniteReq({ url, headers, body }) { 25 | const binaryBody = getBinaryBody(body); 26 | const message = PlayViewUniteReq.fromBinary(binaryBody); 27 | const { vod, bvid } = message; 28 | const { aid, cid } = vod || {}; 29 | const videoId = bvid || av2bv(aid); 30 | Promise.all([fetchOriginalRequest(url, headers, body), fetchSponsorBlock(videoId, cid !== '0' ? cid : '')]) 31 | .then(([{ headers, body }, segments]) => { 32 | $done({ response: { headers, body: newRawBody(handlePlayViewUniteReply(body, segments, videoId)) } }); 33 | }) 34 | .catch(err => { 35 | console.log(err?.toString()); 36 | $done({}); 37 | }); 38 | } 39 | 40 | function handleDmSegMobileReq({ url, headers, body }) { 41 | const binaryBody = getBinaryBody(body); 42 | const message = DmSegMobileReq.fromBinary(binaryBody); 43 | const { pid, oid } = message; 44 | const videoId = av2bv(pid); 45 | Promise.all([fetchOriginalRequest(url, headers, body), fetchSponsorBlock(videoId, oid !== '0' ? oid : '')]) 46 | .then(([{ headers, body }, segments]) => { 47 | if (segments.length) { 48 | console.log(`${videoId}: ${JSON.stringify(segments)}`); 49 | $done({ response: { headers, body: newRawBody(handleDmSegMobileReply(body, segments)) } }); 50 | } else { 51 | $done({ response: { headers, body } }); 52 | } 53 | }) 54 | .catch(err => { 55 | console.log(err?.toString()); 56 | $done({}); 57 | }); 58 | } 59 | 60 | function fetchOriginalRequest(url, headers, body): Promise<{ headers; body }> { 61 | const params = { 62 | url, 63 | headers, 64 | body, 65 | 'binary-mode': true, 66 | }; 67 | return new Promise((resolve, reject) => { 68 | $httpClient.post(params, (error, response, data) => { 69 | if (response?.status !== 200) { 70 | reject('Fetch Original Request Failed'); 71 | } else { 72 | resolve({ 73 | headers: response.headers, 74 | body: data, 75 | }); 76 | } 77 | }); 78 | }); 79 | } 80 | 81 | function fetchSponsorBlock(videoId, cid): Promise { 82 | const params = { 83 | url: `https://bsbsb.top/api/skipSegments?videoID=${videoId}&cid=${cid}&category=sponsor`, 84 | headers: { 85 | origin: 'https://github.com/kokoryh/Sparkle/blob/master/release/surge/module/bilibili.sgmodule', 86 | 'x-ext-version': '1.0.0', 87 | }, 88 | }; 89 | return new Promise(resolve => { 90 | $httpClient.get(params, (error, response, data) => { 91 | if (response?.status !== 200) { 92 | resolve([]); 93 | } else { 94 | const body: any[] = JSON.parse(data as string); 95 | const segments = body.reduce((result, element) => { 96 | if (element.actionType === 'skip') { 97 | result.push(element.segment); 98 | } 99 | return result; 100 | }, []); 101 | resolve(segments); 102 | } 103 | }); 104 | }); 105 | } 106 | 107 | function handlePlayViewUniteReply(body, segments: number[][], videoId: string) { 108 | const emptyBytes = new Uint8Array(0); 109 | const binaryBody = getBinaryBody(body); 110 | const message = PlayViewUniteReply.fromBinary(binaryBody); 111 | if (message.viewInfo) { 112 | message.viewInfo.promptBar = emptyBytes; 113 | } 114 | if (!segments.length && message.playArcConf?.arcConfs) { 115 | Object.values(message.playArcConf.arcConfs).forEach(item => { 116 | if (item.isSupport && item.disabled) { 117 | item.disabled = false; 118 | item.extraContent = undefined; 119 | item.unsupportScene.length = 0; 120 | } 121 | }); 122 | } 123 | if (segments.length) { 124 | console.log(`${videoId}: ${JSON.stringify(segments)}`); 125 | 126 | const arcConfs = message.playArcConf?.arcConfs || {}; 127 | [ConfType.SKIPOPED].forEach(i => { 128 | arcConfs[i] = { 129 | isSupport: true, 130 | disabled: false, 131 | unsupportScene: [], 132 | }; 133 | }); 134 | [ConfType.FREYAENTER, ConfType.FREYAFULLENTER].forEach(i => { 135 | arcConfs[i] = { 136 | isSupport: false, 137 | disabled: true, 138 | unsupportScene: [], 139 | }; 140 | }); 141 | 142 | if (message.vodInfo) { 143 | message.vodInfo.streamList.forEach(item => { 144 | delete item.streamInfo?.needVip; 145 | }); 146 | } 147 | 148 | if (message.playArc) { 149 | message.playArc.videoType = BizType.PGC; 150 | } 151 | 152 | message.supplement = { 153 | typeUrl: 'type.googleapis.com/bilibili.app.playerunite.pgcanymodel.PGCAnyModel', 154 | value: PGCAnyModel.toBinary(getPGCAnyModel(segments)), 155 | }; 156 | } 157 | return PlayViewUniteReply.toBinary(message); 158 | } 159 | 160 | function getPGCAnyModel(segments: number[][]): PGCAnyModel { 161 | return { 162 | business: { 163 | clipInfo: getClipInfo(segments), 164 | vipStatus: 1, 165 | episodeInfo: { 166 | epId: 1231523, 167 | cid: '27730904912', 168 | aid: '113740078909891', 169 | epStatus: '2', 170 | seasonInfo: { 171 | seasonId: 73081, 172 | seasonType: 1, 173 | seasonStatus: 13, 174 | mode: 2, 175 | }, 176 | }, 177 | userStatus: { 178 | watchProgress: { 179 | lastEpId: 1231523, 180 | lastEpIndex: 'OP', 181 | progress: '1', 182 | lastPlayAid: '113740078909891', 183 | lastPlayCid: '27730904912', 184 | }, 185 | }, 186 | }, 187 | playExtConf: { 188 | allowCloseSubtitle: true, 189 | }, 190 | }; 191 | } 192 | 193 | function getClipInfo(segments: number[][]): ClipInfo[] { 194 | return segments.map(([start, end]) => ({ 195 | start: Math.floor(start), 196 | end: Math.ceil(end), 197 | clipType: ClipType.CLIP_TYPE_OP, 198 | })); 199 | } 200 | 201 | function handleDmSegMobileReply(body, segments: number[][]) { 202 | const binaryBody = getBinaryBody(body); 203 | const message = DmSegMobileReply.fromBinary(binaryBody); 204 | message.elems.unshift(...getAirBorneDms(segments)); 205 | return DmSegMobileReply.toBinary(message); 206 | } 207 | 208 | function getAirBorneDms(segments: number[][]): DanmakuElem[] { 209 | return segments.map((segment, index) => { 210 | const id = (index + 1).toString(); 211 | const start = Math.max(Math.floor(segment[0] * 1000 - 2000), 1); 212 | const end = Math.floor(segment[1] * 1000); 213 | return { 214 | id, 215 | progress: start, 216 | mode: 5, 217 | fontsize: 50, 218 | color: 16777215, 219 | midHash: '1948dd5d', 220 | content: '点击空降广告结束', 221 | ctime: '1735660800', 222 | weight: 11, 223 | action: `airborne:${end}`, 224 | pool: 0, 225 | idStr: id, 226 | attr: 1310724, 227 | animation: '', 228 | extra: '', 229 | colorful: DmColorfulType.NONE_TYPE, 230 | type: 1, 231 | oid: '212364987', 232 | dmFrom: 1, 233 | }; 234 | }); 235 | } 236 | 237 | function getBinaryBody(body) { 238 | const header = body.slice(0, 5); 239 | let binaryBody = body.slice(5); 240 | if (header[0]) { 241 | binaryBody = $utils.ungzip(binaryBody); 242 | } 243 | return binaryBody; 244 | } 245 | 246 | function newRawBody(body) { 247 | const checksum = Checksum(body.length); 248 | const rawBody = new Uint8Array(5 + body.length); 249 | 250 | rawBody[0] = 0; // 直接置protobuf 为未压缩状态 251 | rawBody.set(checksum, 1); // 1-4位: 校验值(4位) 252 | rawBody.set(body, 5); // 5-end位:protobuf数据 253 | return rawBody; 254 | } 255 | 256 | function Checksum(num) { 257 | const arr = new ArrayBuffer(4); // an Int32 takes 4 bytes 258 | const view = new DataView(arr); 259 | view.setUint32(0, num, false); // byteOffset = 0; litteEndian = false 260 | return new Uint8Array(arr); 261 | } 262 | -------------------------------------------------------------------------------- /src/script/bilibili/bilibili.json.ts: -------------------------------------------------------------------------------- 1 | $done(handleResponse($response, $request, globalThis.$argument) || {}); 2 | 3 | function handleResponse({ body }, { url }, argument) { 4 | const routeHandlers = { 5 | '/resource/show/tab/v2?': handleLayout, 6 | '/v2/splash': handleSplash, 7 | '/feed/index?': handleFeedIndex, 8 | '/feed/index/story?': handleFeedIndexStory, 9 | '/account/mine': handleAccountMine, 10 | '/account/myinfo?': handleAccountMyInfo, 11 | }; 12 | try { 13 | body = JSON.parse(body); 14 | if (!body?.data) return null; 15 | const options = 16 | typeof argument === 'string' 17 | ? JSON.parse(argument) 18 | : typeof argument === 'object' && argument !== null 19 | ? argument 20 | : {}; 21 | for (const route in routeHandlers) { 22 | if (url.includes(route)) { 23 | return { body: JSON.stringify(routeHandlers[route](body, options)) }; 24 | } 25 | } 26 | return null; 27 | } catch (e) { 28 | console.log(e.toString()); 29 | return null; 30 | } 31 | } 32 | 33 | function handleLayout(body) { 34 | body.data.tab = [ 35 | { 36 | pos: 1, 37 | id: 731, 38 | name: '直播', 39 | tab_id: '直播tab', 40 | uri: 'bilibili://live/home', 41 | }, 42 | { 43 | pos: 2, 44 | id: 477, 45 | name: '推荐', 46 | tab_id: '推荐tab', 47 | uri: 'bilibili://pegasus/promo', 48 | default_selected: 1, 49 | }, 50 | { 51 | pos: 3, 52 | id: 478, 53 | name: '热门', 54 | tab_id: '热门tab', 55 | uri: 'bilibili://pegasus/hottopic', 56 | }, 57 | { 58 | pos: 4, 59 | id: 545, 60 | name: '动画', 61 | tab_id: 'bangumi', 62 | uri: 'bilibili://pgc/home', 63 | }, 64 | { 65 | pos: 5, 66 | id: 151, 67 | name: '影视', 68 | tab_id: 'film', 69 | uri: 'bilibili://pgc/cinema-tab', 70 | }, 71 | ]; 72 | body.data.top = [ 73 | { 74 | pos: 1, 75 | id: 176, 76 | name: '消息', 77 | tab_id: '消息Top', 78 | uri: 'bilibili://link/im_home', 79 | icon: 'http://i0.hdslb.com/bfs/archive/d43047538e72c9ed8fd8e4e34415fbe3a4f632cb.png', 80 | }, 81 | ]; 82 | body.data.bottom = [ 83 | { 84 | pos: 1, 85 | id: 177, 86 | name: '首页', 87 | tab_id: 'home', 88 | uri: 'bilibili://main/home/', 89 | icon: 'http://i0.hdslb.com/bfs/archive/63d7ee88d471786c1af45af86e8cb7f607edf91b.png', 90 | icon_selected: 'http://i0.hdslb.com/bfs/archive/e5106aa688dc729e7f0eafcbb80317feb54a43bd.png', 91 | }, 92 | { 93 | pos: 2, 94 | id: 179, 95 | name: '动态', 96 | tab_id: 'dynamic', 97 | uri: 'bilibili://following/home/', 98 | icon: 'http://i0.hdslb.com/bfs/archive/86dfbe5fa32f11a8588b9ae0fccb77d3c27cedf6.png', 99 | icon_selected: 'http://i0.hdslb.com/bfs/archive/25b658e1f6b6da57eecba328556101dbdcb4b53f.png', 100 | }, 101 | { 102 | pos: 5, 103 | id: 181, 104 | name: '我的', 105 | tab_id: '我的Bottom', 106 | uri: 'bilibili://user_center/', 107 | icon: 'http://i0.hdslb.com/bfs/archive/4b0b2c49ffeb4f0c2e6a4cceebeef0aab1c53fe1.png', 108 | icon_selected: 'http://i0.hdslb.com/bfs/archive/a54a8009116cb896e64ef14dcf50e5cade401e00.png', 109 | }, 110 | ]; 111 | return body; 112 | } 113 | 114 | function handleSplash(body) { 115 | const keys = ['show', 'event_list']; 116 | keys.forEach(key => { 117 | if (body.data[key]) { 118 | body.data[key] = []; 119 | } 120 | }); 121 | return body; 122 | } 123 | 124 | function handleFeedIndex(body) { 125 | if (Array.isArray(body.data.items)) { 126 | const types = new Set([ 127 | 'small_cover_v2', // ios double column mode 128 | 'large_cover_single_v9', // ios single column mode 129 | 'large_cover_v1', // ipad 130 | ]); 131 | body.data.items = body.data.items.filter(item => { 132 | return ( 133 | !item.banner_item && // remove header banner 134 | !item.ad_info && 135 | item.card_goto === 'av' && 136 | types.has(item.card_type) 137 | ); 138 | }); 139 | } 140 | return body; 141 | } 142 | 143 | function handleFeedIndexStory(body) { 144 | if (Array.isArray(body.data.items)) { 145 | body.data.items = body.data.items.reduce((res, item) => { 146 | if (!item.ad_info && !item.card_goto?.startsWith('ad')) { 147 | delete item.story_cart_icon; 148 | delete item.free_flow_toast; 149 | res.push(item); 150 | } 151 | return res; 152 | }, []); 153 | } 154 | return body; 155 | } 156 | 157 | function handleAccountMine(body, options) { 158 | const sectionMap = { 159 | sections_v2: [ 160 | { 161 | items: [ 162 | { 163 | id: 396, 164 | title: '离线缓存', 165 | uri: 'bilibili://user_center/download', 166 | icon: 'http://i0.hdslb.com/bfs/archive/5fc84565ab73e716d20cd2f65e0e1de9495d56f8.png', 167 | common_op_item: {}, 168 | }, 169 | { 170 | id: 397, 171 | title: '历史记录', 172 | uri: 'bilibili://user_center/history', 173 | icon: 'http://i0.hdslb.com/bfs/archive/8385323c6acde52e9cd52514ae13c8b9481c1a16.png', 174 | common_op_item: {}, 175 | }, 176 | { 177 | id: 3072, 178 | title: '我的收藏', 179 | uri: 'bilibili://user_center/favourite', 180 | icon: 'http://i0.hdslb.com/bfs/archive/d79b19d983067a1b91614e830a7100c05204a821.png', 181 | common_op_item: {}, 182 | }, 183 | { 184 | id: 2830, 185 | title: '稍后再看', 186 | uri: 'bilibili://user_center/watch_later_v2', 187 | icon: 'http://i0.hdslb.com/bfs/archive/63bb768caa02a68cb566a838f6f2415f0d1d02d6.png', 188 | need_login: 1, 189 | common_op_item: {}, 190 | }, 191 | ], 192 | style: 1, 193 | button: {}, 194 | }, 195 | { 196 | title: '推荐服务', 197 | items: [ 198 | { 199 | id: 402, 200 | title: '个性装扮', 201 | uri: 'https://www.bilibili.com/h5/mall/home?navhide=1&f_source=shop&from=myservice', 202 | icon: 'http://i0.hdslb.com/bfs/archive/0bcad10661b50f583969b5a188c12e5f0731628c.png', 203 | common_op_item: {}, 204 | }, 205 | { 206 | id: 622, 207 | title: '会员购', 208 | uri: 'bilibili://mall/home', 209 | icon: 'http://i0.hdslb.com/bfs/archive/19c794f01def1a267b894be84427d6a8f67081a9.png', 210 | common_op_item: {}, 211 | }, 212 | { 213 | id: 404, 214 | title: '我的钱包', 215 | uri: 'bilibili://bilipay/mine_wallet', 216 | icon: 'http://i0.hdslb.com/bfs/archive/f416634e361824e74a855332b6ff14e2e7c2e082.png', 217 | common_op_item: {}, 218 | }, 219 | { 220 | id: 406, 221 | title: '我的直播', 222 | uri: 'bilibili://user_center/live_center', 223 | icon: 'http://i0.hdslb.com/bfs/archive/1db5791746a0112890b77a0236baf263d71ecb27.png', 224 | common_op_item: {}, 225 | }, 226 | ], 227 | style: 1, 228 | button: {}, 229 | }, 230 | { 231 | title: '更多服务', 232 | items: [ 233 | { 234 | id: 407, 235 | title: '联系客服', 236 | uri: 'bilibili://user_center/feedback', 237 | icon: 'http://i0.hdslb.com/bfs/archive/7ca840cf1d887a45ee1ef441ab57845bf26ef5fa.png', 238 | common_op_item: {}, 239 | }, 240 | { 241 | id: 410, 242 | title: '设置', 243 | uri: 'bilibili://user_center/setting', 244 | icon: 'http://i0.hdslb.com/bfs/archive/e932404f2ee62e075a772920019e9fbdb4b5656a.png', 245 | common_op_item: {}, 246 | }, 247 | ], 248 | style: 2, 249 | button: {}, 250 | }, 251 | ], 252 | ipad_sections: [ 253 | { 254 | id: 747, 255 | title: '离线缓存', 256 | uri: 'bilibili://user_center/download', 257 | icon: 'http://i0.hdslb.com/bfs/feed-admin/9bd72251f7366c491cfe78818d453455473a9678.png', 258 | mng_resource: { 259 | icon_id: 0, 260 | icon: '', 261 | }, 262 | }, 263 | { 264 | id: 748, 265 | title: '历史记录', 266 | uri: 'bilibili://user_center/history', 267 | icon: 'http://i0.hdslb.com/bfs/feed-admin/83862e10685f34e16a10cfe1f89dbd7b2884d272.png', 268 | mng_resource: { 269 | icon_id: 0, 270 | icon: '', 271 | }, 272 | }, 273 | { 274 | id: 749, 275 | title: '我的收藏', 276 | uri: 'bilibili://user_center/favourite', 277 | icon: 'http://i0.hdslb.com/bfs/feed-admin/6ae7eff6af627590fc4ed80c905e9e0a6f0e8188.png', 278 | mng_resource: { 279 | icon_id: 0, 280 | icon: '', 281 | }, 282 | }, 283 | { 284 | id: 750, 285 | title: '稍后再看', 286 | uri: 'bilibili://user_center/watch_later', 287 | icon: 'http://i0.hdslb.com/bfs/feed-admin/928ba9f559b02129e51993efc8afe95014edec94.png', 288 | mng_resource: { 289 | icon_id: 0, 290 | icon: '', 291 | }, 292 | }, 293 | ], 294 | ipad_upper_sections: [ 295 | { 296 | id: 752, 297 | title: '创作首页', 298 | uri: '/uper/homevc', 299 | icon: 'http://i0.hdslb.com/bfs/feed-admin/d20dfed3b403c895506b1c92ecd5874abb700c01.png', 300 | mng_resource: { 301 | icon_id: 0, 302 | icon: '', 303 | }, 304 | }, 305 | ], 306 | ipad_recommend_sections: [ 307 | { 308 | id: 755, 309 | title: '我的关注', 310 | uri: 'bilibili://user_center/myfollows', 311 | icon: 'http://i0.hdslb.com/bfs/feed-admin/fdd7f676030c6996d36763a078442a210fc5a8c0.png', 312 | mng_resource: { 313 | icon_id: 0, 314 | icon: '', 315 | }, 316 | }, 317 | { 318 | id: 756, 319 | title: '我的消息', 320 | uri: 'bilibili://link/im_home', 321 | icon: 'http://i0.hdslb.com/bfs/feed-admin/e1471740130a08a48b02a4ab29ed9d5f2281e3bf.png', 322 | mng_resource: { 323 | icon_id: 0, 324 | icon: '', 325 | }, 326 | }, 327 | ], 328 | ipad_more_sections: [ 329 | { 330 | id: 763, 331 | title: '我的客服', 332 | uri: 'bilibili://user_center/feedback', 333 | icon: 'http://i0.hdslb.com/bfs/feed-admin/7801a6180fb67cf5f8ee05a66a4668e49fb38788.png', 334 | mng_resource: { 335 | icon_id: 0, 336 | icon: '', 337 | }, 338 | }, 339 | { 340 | id: 764, 341 | title: '设置', 342 | uri: 'bilibili://user_center/setting', 343 | icon: 'http://i0.hdslb.com/bfs/feed-admin/34e8faea00b3dd78977266b58d77398b0ac9410b.png', 344 | mng_resource: { 345 | icon_id: 0, 346 | icon: '', 347 | }, 348 | }, 349 | ], 350 | }; 351 | 352 | Object.keys(sectionMap).forEach(key => { 353 | if (body.data[key]) { 354 | body.data[key] = sectionMap[key]; 355 | } 356 | }); 357 | 358 | if (options.showUperCenter && body.data.sections_v2) { 359 | body.data.sections_v2.splice(1, 0, { 360 | title: '创作中心', 361 | items: [ 362 | { 363 | id: 171, 364 | title: '创作中心', 365 | uri: 'bilibili://uper/homevc', 366 | icon: 'http://i0.hdslb.com/bfs/archive/d3aad2d07538d2d43805f1fa14a412d7a45cc861.png', 367 | need_login: 1, 368 | global_red_dot: 0, 369 | display: 1, 370 | is_up_anchor: true, 371 | }, 372 | { 373 | id: 533, 374 | title: '数据中心', 375 | uri: 'https://member.bilibili.com/york/data-center?navhide=1&from=profile', 376 | icon: 'http://i0.hdslb.com/bfs/feed-admin/367204ba56004b1a78211ba27eefbf5b4cc53a35.png', 377 | need_login: 1, 378 | global_red_dot: 0, 379 | display: 1, 380 | }, 381 | { 382 | id: 707, 383 | title: '主播中心', 384 | uri: 'https://live.bilibili.com/p/html/live-app-anchor-center/index.html?is_live_webview=1#/', 385 | icon: 'http://i0.hdslb.com/bfs/feed-admin/48e17ccd0ce0cfc9c7826422d5e47ce98f064c2a.png', 386 | need_login: 1, 387 | display: 1, 388 | }, 389 | { 390 | id: 2647, 391 | title: '直播数据', 392 | uri: 'https://live.bilibili.com/p/html/live-app-data/index.html?source_tag=0&foreground=pink&is_live_webview=1&hybrid_set_header=2#/', 393 | icon: 'https://i0.hdslb.com/bfs/legacy/0566b128c51d85b7ec545f318e1fd437d172dfea.png', 394 | display: 1, 395 | }, 396 | ], 397 | style: 1, 398 | button: { 399 | text: '发布', 400 | url: 'bilibili://uper/user_center/archive_selection', 401 | icon: 'http://i0.hdslb.com/bfs/archive/205f47675eaaca7912111e0e9b1ac94cb985901f.png', 402 | style: 1, 403 | }, 404 | type: 1, 405 | up_title: '创作中心', 406 | }); 407 | } 408 | 409 | delete body.data.answer; 410 | delete body.data.live_tip; 411 | delete body.data.vip_section; 412 | delete body.data.vip_section_v2; 413 | delete body.data.modular_vip_section; 414 | 415 | body.data.vip_type = 2; 416 | body.data.vip = getHundredAnnualVipData(); 417 | 418 | return body; 419 | } 420 | 421 | function handleAccountMyInfo(body) { 422 | body.data.vip = getHundredAnnualVipData(); 423 | return body; 424 | } 425 | 426 | function getHundredAnnualVipData() { 427 | const image = getVipLabelImage(); 428 | return { 429 | status: 1, 430 | type: 2, 431 | vip_pay_type: 0, 432 | due_date: 9005270400000, 433 | tv_vip_status: 1, 434 | tv_vip_pay_type: 0, 435 | tv_due_date: 9005270400000, 436 | role: 15, 437 | theme_type: 0, 438 | nickname_color: '#FB7299', 439 | avatar_subscript: 1, 440 | avatar_subscript_url: '', 441 | avatar_icon: { 442 | icon_resource: {}, 443 | }, 444 | label: { 445 | path: '', 446 | text: '百年大会员', 447 | label_theme: 'hundred_annual_vip', 448 | text_color: '#FFFFFF', 449 | bg_style: 1, 450 | bg_color: '#FB7299', 451 | border_color: '', 452 | use_img_label: true, 453 | image, 454 | img_label_uri_hans: '', 455 | img_label_uri_hant: '', 456 | img_label_uri_hans_static: image, 457 | img_label_uri_hant_static: image, 458 | }, 459 | }; 460 | } 461 | 462 | function getVipLabelImage(): string { 463 | const date = new Date(); 464 | const month = date.getMonth() + 1; 465 | const day = date.getDate(); 466 | switch (`${month}/${day}`) { 467 | case '6/1': 468 | return 'https://i0.hdslb.com/bfs/bangumi/kt/629e28d4426f1b44af1131ade99d27741cc61d4b.png'; 469 | default: 470 | return 'https://i0.hdslb.com/bfs/vip/52f60c8bdae8d4440edbb96dad72916022adf126.png'; 471 | } 472 | } 473 | -------------------------------------------------------------------------------- /src/script/bilibili/handler.ts: -------------------------------------------------------------------------------- 1 | import { modifyBody } from '../../util/utils.js'; 2 | import { DynAllReply, DynamicType } from '@proto/bilibili/app/dynamic/v2/dynamic.js'; 3 | import { DefaultWordsReply } from '@proto/bilibili/app/interface/v1/search.js'; 4 | import { ModeStatusReply } from '@proto/bilibili/app/interface/v1/teenagers.js'; 5 | import { PlayViewUniteReply } from '@proto/bilibili/app/playerunite/v1/player.js'; 6 | import { PlayViewReply } from '@proto/bilibili/app/playurl/v1/playurl.js'; 7 | import { PopularReply } from '@proto/bilibili/app/show/popular/v1/popular.js'; 8 | import { 9 | TFInfoReply, 10 | ViewReply as IpadViewReply, 11 | ViewProgressReply as IpadViewProgressReply, 12 | } from '@proto/bilibili/app/view/v1/view.js'; 13 | import { 14 | Module, 15 | ModuleType, 16 | RelateCardType, 17 | RelatesFeedReply, 18 | ViewReply, 19 | ViewProgressReply, 20 | } from '@proto/bilibili/app/viewunite/v1/view.js'; 21 | import { DmViewReply } from '@proto/bilibili/community/service/dm/v1/dm.js'; 22 | import { MainListReply } from '@proto/bilibili/main/community/reply/v1/reply.js'; 23 | import { PlayViewReply as IpadPlayViewReply } from '@proto/bilibili/pgc/gateway/player/v2/playurl.js'; 24 | import { SearchAllResponse } from '@proto/bilibili/polymer/app/search/v1/search.js'; 25 | 26 | const emptyBytes = new Uint8Array(0); 27 | 28 | export function handleDynAllReply(grpcBody, options) { 29 | const message = DynAllReply.fromBinary(grpcBody); 30 | message.topicList = emptyBytes; 31 | if (message.dynamicList) { 32 | message.dynamicList.list = message.dynamicList.list.filter( 33 | item => ![DynamicType.AD, DynamicType.LIVE_RCMD].includes(item.cardType) 34 | ); 35 | } 36 | if (options.showUpList === 'false') { 37 | delete message.upList; 38 | } else if (!options.isIPad && options.showUpList !== 'true') { 39 | if (message.upList?.showLiveNum) { 40 | const { list, listSecond } = message.upList; 41 | const lastItem = listSecond.at(-1); 42 | if (lastItem) { 43 | lastItem.separator = true; 44 | list.unshift(...listSecond); 45 | listSecond.length = 0; 46 | } 47 | } else { 48 | delete message.upList; 49 | } 50 | } 51 | modifyBody(DynAllReply, message); 52 | } 53 | 54 | export function handleDefaultWordsReply(grpcBody) { 55 | const message = DefaultWordsReply.fromBinary(grpcBody); 56 | message.show = '搜索视频、番剧或up主'; 57 | message.word = ''; 58 | message.goto = ''; 59 | message.value = ''; 60 | message.uri = ''; 61 | modifyBody(DefaultWordsReply, message); 62 | } 63 | 64 | export function handleModeStatusReply(grpcBody) { 65 | const message = ModeStatusReply.fromBinary(grpcBody); 66 | const teenagersModel = message.userModels.find(item => item.mode === 'teenagers'); 67 | if (teenagersModel?.policy?.interval && teenagersModel.policy.interval !== '0') { 68 | teenagersModel.policy.interval = '0'; 69 | modifyBody(ModeStatusReply, message); 70 | } 71 | } 72 | 73 | export function handlePlayViewUniteReply(grpcBody) { 74 | const message = PlayViewUniteReply.fromBinary(grpcBody); 75 | if (message.viewInfo) { 76 | message.viewInfo.promptBar = emptyBytes; 77 | } 78 | if (message.playArcConf?.arcConfs) { 79 | Object.values(message.playArcConf.arcConfs).forEach(item => { 80 | if (item.isSupport && item.disabled) { 81 | item.disabled = false; 82 | item.extraContent = undefined; 83 | item.unsupportScene.length = 0; 84 | } 85 | }); 86 | } 87 | modifyBody(PlayViewUniteReply, message); 88 | } 89 | 90 | export function handlePlayViewReply(grpcBody) { 91 | const message = PlayViewReply.fromBinary(grpcBody); 92 | const { backgroundPlayConf, castConf } = message.playArc || {}; 93 | [backgroundPlayConf, castConf].forEach(arcConf => { 94 | if (arcConf && (!arcConf.isSupport || arcConf.disabled)) { 95 | arcConf.isSupport = true; 96 | arcConf.disabled = false; 97 | arcConf.extraContent = undefined; 98 | arcConf.unsupportScene.length = 0; 99 | } 100 | }); 101 | modifyBody(PlayViewReply, message); 102 | } 103 | 104 | export function handlePopularReply(grpcBody) { 105 | const message = PopularReply.fromBinary(grpcBody); 106 | message.items = message.items.filter(item => { 107 | if (item.item.oneofKind === 'smallCoverV5') { 108 | const card = item.item.smallCoverV5; 109 | return card.base?.fromType === 'recommend' && !card.base.adInfo.length; 110 | } 111 | return !['rcmdOneItem', 'smallCoverV5Ad', 'topicList'].includes(item.item.oneofKind as string); 112 | }); 113 | modifyBody(PopularReply, message); 114 | } 115 | 116 | export function handleTFInfoReply(grpcBody) { 117 | const message = TFInfoReply.fromBinary(grpcBody); 118 | if (message.tipsId !== '0') { 119 | message.tfToast = emptyBytes; 120 | message.tfPanelCustomized = emptyBytes; 121 | modifyBody(TFInfoReply, message); 122 | } 123 | } 124 | 125 | export function handleIpadViewReply(grpcBody) { 126 | const message = IpadViewReply.fromBinary(grpcBody); 127 | message.label = emptyBytes; 128 | message.cmIpad = emptyBytes; 129 | message.cmConfig = emptyBytes; 130 | if (message.reqUser) { 131 | message.reqUser.elecPlusBtn = emptyBytes; 132 | } 133 | message.cms.length = 0; 134 | message.specialCellNew.length = 0; 135 | message.relates = message.relates.filter(item => !item.cm.length); 136 | modifyBody(IpadViewReply, message); 137 | } 138 | 139 | export function handleIpadViewProgressReply(grpcBody) { 140 | const message = IpadViewProgressReply.fromBinary(grpcBody); 141 | message.videoGuide = emptyBytes; 142 | modifyBody(IpadViewProgressReply, message); 143 | } 144 | 145 | const filterRelateCardType = [ 146 | RelateCardType.GAME, 147 | RelateCardType.CM_TYPE, 148 | RelateCardType.LIVE, 149 | RelateCardType.AI_RECOMMEND, 150 | RelateCardType.COURSE, 151 | ]; 152 | 153 | const filterRelateCard = card => { 154 | return !filterRelateCardType.includes(card.relateCardType) && !card.cmStock.length && !card.basicInfo?.uniqueId; 155 | }; 156 | 157 | export function handleRelatesFeedReply(grpcBody) { 158 | const message = RelatesFeedReply.fromBinary(grpcBody); 159 | message.relates = message.relates.filter(filterRelateCard); 160 | modifyBody(RelatesFeedReply, message); 161 | } 162 | 163 | export function handleViewReply(grpcBody) { 164 | const message = ViewReply.fromBinary(grpcBody); 165 | message.cm = emptyBytes; 166 | if (message.reqUser) { 167 | message.reqUser.elecPlusBtn = emptyBytes; 168 | } 169 | 170 | message.tab?.tabModule.forEach(tabModule => { 171 | if (tabModule.tab.oneofKind !== 'introduction') return; 172 | 173 | tabModule.tab.introduction.modules = tabModule.tab.introduction.modules.reduce((modules: Module[], module) => { 174 | if ( 175 | [ModuleType.ACTIVITY, ModuleType.PAY_BAR, ModuleType.SPECIALTAG, ModuleType.MERCHANDISE].includes( 176 | module.type 177 | ) 178 | ) { 179 | return modules; 180 | } 181 | if (module.type === ModuleType.UGC_HEADLINE && module.data.oneofKind === 'headLine') { 182 | module.data.headLine.label = emptyBytes; 183 | } else if (module.type === ModuleType.RELATED_RECOMMEND && module.data.oneofKind === 'relates') { 184 | module.data.relates.cards = module.data.relates.cards.filter(filterRelateCard); 185 | } 186 | modules.push(module); 187 | return modules; 188 | }, []); 189 | }); 190 | modifyBody(ViewReply, message); 191 | } 192 | 193 | export function handleViewProgressReply(grpcBody) { 194 | const message = ViewProgressReply.fromBinary(grpcBody); 195 | message.dm = emptyBytes; 196 | modifyBody(ViewProgressReply, message); 197 | } 198 | 199 | export function handleDmViewReply(grpcBody) { 200 | const message = DmViewReply.fromBinary(grpcBody); 201 | message.activityMeta.length = 0; 202 | if (message.command?.commandDms.length) { 203 | message.command.commandDms.length = 0; 204 | } 205 | modifyBody(DmViewReply, message); 206 | } 207 | 208 | export function handleMainListReply(grpcBody, options) { 209 | const message = MainListReply.fromBinary(grpcBody); 210 | message.cm = emptyBytes; 211 | if (options.filterTopReplies) { 212 | const pattern = /https:\/\/b23\.tv\/(cm|mall)/; 213 | message.topReplies = message.topReplies.filter(reply => { 214 | const urls = reply.content?.urls || {}; 215 | const message = reply.content?.message || ''; 216 | return !Object.keys(urls).some(url => pattern.test(url)) && !pattern.test(message); 217 | }); 218 | } 219 | modifyBody(MainListReply, message); 220 | } 221 | 222 | export function handleIpadPlayViewReply(grpcBody) { 223 | const message = IpadPlayViewReply.fromBinary(grpcBody); 224 | if (message.viewInfo) { 225 | message.viewInfo.tryWatchPromptBar = emptyBytes; 226 | } 227 | if (message.playExtConf?.castTips) { 228 | message.playExtConf.castTips = { code: 0, message: '' }; 229 | } 230 | modifyBody(IpadPlayViewReply, message); 231 | } 232 | 233 | export function handleSearchAllResponse(grpcBody) { 234 | const message = SearchAllResponse.fromBinary(grpcBody); 235 | message.item = message.item.filter(item => !item.linktype.endsWith('_ad')); 236 | modifyBody(SearchAllResponse, message); 237 | } 238 | -------------------------------------------------------------------------------- /src/script/missav/missav.html: -------------------------------------------------------------------------------- 1 | 17 | 18 | 31 | -------------------------------------------------------------------------------- /src/script/missav/missav.html.ts: -------------------------------------------------------------------------------- 1 | import * as cheerio from 'cheerio'; 2 | 3 | // import * as fs from 'fs'; 4 | // import path from 'path'; 5 | // import { fileURLToPath } from 'url'; 6 | // const __dirname = path.dirname(fileURLToPath(import.meta.url)); 7 | // const $response = { 8 | // headers: { 'content-type': 'text/html' }, 9 | // body: fs.readFileSync(path.join(__dirname, './input.html'), 'utf-8'), 10 | // }; 11 | // const $done = ({ body }) => { 12 | // fs.writeFileSync(path.join(__dirname, './output.html'), body); 13 | // }; 14 | 15 | $done(handleResponse($response) || {}); 16 | 17 | function handleResponse({ headers, body }) { 18 | const contentType = headers['content-type']; 19 | if (!contentType?.includes('text/html')) return null; 20 | 21 | const scriptElement = ``; 22 | const styleElement = ``; 23 | const scriptElementFilter = (i, element) => { 24 | if (element.attribs?.src?.includes('tsyndicate.com')) { 25 | return true; 26 | } 27 | if (element.children?.[0]?.data?.includes('TSOutstreamVideo')) { 28 | return true; 29 | } 30 | if (element.children?.[0]?.data?.includes('htmlAds')) { 31 | return true; 32 | } 33 | return false; 34 | }; 35 | try { 36 | const $ = cheerio.load(body); 37 | $('script').filter(scriptElementFilter).remove(); 38 | $('head').append(scriptElement, styleElement); 39 | return { body: $.html() }; 40 | } catch (e) { 41 | console.log(e.toString()); 42 | return null; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/script/missav/missav.plugin.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name Missav 3 | // @namespace http://tampermonkey.net/ 4 | // @version 2025-03-15 5 | // @description try to take over the world! 6 | // @author kokoryh 7 | // @match https://missav.ai/* 8 | // @match https://missav.ws/* 9 | // @icon https://www.google.com/s2/favicons?sz=64&domain=missav.ai 10 | // @grant none 11 | // ==/UserScript== 12 | 13 | const style = ` 14 | .lg\\:block, 15 | .lg\\:hidden, 16 | a[href*="//bit.ly/"], 17 | div[x-init*="#genki-counter'"], 18 | div:has(a[href*='go.myavlive.com']), 19 | [x-show$="video_details'"] > div > ul, 20 | div[style*='width: 300px; height: 250px;'], 21 | .relative > div[x-init*='campaignId=under_player'], 22 | div[x-show^='recommendItems'] ~ div[class]:has(> div > div.mx-auto > div.flex > a[rel^='sponsored']) { 23 | display: none !important; 24 | } 25 | `; 26 | 27 | (function () { 28 | 'use strict'; 29 | document.addEventListener('ready', () => { 30 | window.open = () => {}; 31 | if (window.player?.pause) { 32 | const pause = window.player.pause; 33 | window.player.pause = () => { 34 | if (document.hasFocus()) { 35 | pause(); 36 | } 37 | }; 38 | } 39 | 40 | const styleElement = document.createElement('style'); 41 | styleElement.innerHTML = style; 42 | document.querySelector('head').appendChild(styleElement); 43 | }); 44 | })(); 45 | -------------------------------------------------------------------------------- /src/script/zhihu/zhihu.json.ts: -------------------------------------------------------------------------------- 1 | import { parse, stringify } from 'lossless-json'; 2 | 3 | $done(handleResponse($response) || {}); 4 | 5 | function handleResponse({ body }) { 6 | try { 7 | return { body: stringify(handleQuestions(parse(body))) }; 8 | } catch (e) { 9 | console.log(e.toString()); 10 | return null; 11 | } 12 | } 13 | 14 | function handleQuestions(body) { 15 | delete body.ad_info; 16 | delete body.query_info; 17 | if (Object.prototype.toString.call(body.data) === '[object Object]') { 18 | delete body.data.ad_info; 19 | } else if (Array.isArray(body.data)) { 20 | body.data = body.data.filter(item => !item?.target?.answer_type?.includes('paid')); 21 | } 22 | return body; 23 | } 24 | -------------------------------------------------------------------------------- /src/util/bilibili.js: -------------------------------------------------------------------------------- 1 | const XOR_CODE = 23442827791579n; 2 | const MASK_CODE = 2251799813685247n; 3 | const MAX_AID = 1n << 51n; 4 | const BASE = 58n; 5 | 6 | const data = 'FcwAPNKTMug3GV5Lj7EJnHpWsx4tb8haYeviqBz6rkCy12mUSDQX9RdoZf'; 7 | 8 | export function av2bv(avid) { 9 | const bytes = ['B', 'V', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0']; 10 | let bvIndex = bytes.length - 1; 11 | let tmp = (MAX_AID | BigInt(avid)) ^ XOR_CODE; 12 | while (tmp > 0) { 13 | bytes[bvIndex] = data[Number(tmp % BigInt(BASE))]; 14 | tmp = tmp / BASE; 15 | bvIndex -= 1; 16 | } 17 | [bytes[3], bytes[9]] = [bytes[9], bytes[3]]; 18 | [bytes[4], bytes[7]] = [bytes[7], bytes[4]]; 19 | return bytes.join(''); 20 | } 21 | 22 | export function bv2av(bvid) { 23 | const bvidArr = Array.from(bvid); 24 | [bvidArr[3], bvidArr[9]] = [bvidArr[9], bvidArr[3]]; 25 | [bvidArr[4], bvidArr[7]] = [bvidArr[7], bvidArr[4]]; 26 | bvidArr.splice(0, 3); 27 | const tmp = bvidArr.reduce((pre, bvidChar) => pre * BASE + BigInt(data.indexOf(bvidChar)), 0n); 28 | return Number((tmp & MASK_CODE) ^ XOR_CODE); 29 | } 30 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "lib": ["ESNext", "DOM"], 5 | "baseUrl": "./", 6 | "rootDir": "./", 7 | "outDir": "./dist", 8 | "module": "ESNext", 9 | "moduleResolution": "bundler", 10 | "typeRoots": ["./node_modules/@types"], 11 | "paths": { 12 | "@proto/*": ["src/proto/*"], 13 | "@util/*": ["src/util/*"] 14 | }, 15 | "allowJs": true, 16 | "checkJs": true, 17 | "strict": true, 18 | "noImplicitAny": false, 19 | "alwaysStrict": false 20 | } 21 | } 22 | --------------------------------------------------------------------------------